Using the REST API
The REST API is a thin HTTP adapter over the Mock Machines facade. It exposes
scenarios and experiments as resources, so any HTTP client can browse a
deployed scenario, run an experiment, and read back the results. It is a sibling
of the MCP server — both drive the same
Lab → Workbench → Scenario → Experiment facade, and neither holds engine logic of
its own.
The hosted API
Section titled “The hosted API”The live API is served at https://api.mockmachines.dev — no local build or
server to run. Every endpoint below hangs off that base.
- A liveness probe is at
/health. - The MCP connector is the sibling adapter, served
at
https://mcp.mockmachines.dev. - The read-only studio is a browser UI over this
same API — open a preset at
https://app.mockmachines.dev/paymentprocessor.
Access
Section titled “Access”The API is open for reading the curated preset scenarios anonymously — no token required. Creating, running, and deploying scenarios needs a bearer token, which scopes the work to your own private workbench.
| Tier | Token | Can |
|---|---|---|
| Anonymous | none | List presets; read their pre-seeded experiments — entities, events, dataset, DuckDB bundle. |
| Authenticated | Authorization: Bearer <token> | Everything above, plus deploy scenarios and create / run experiments in your own workbench. |
The resource model
Section titled “The resource model”Everything hangs off two nested resources:
- A scenario is a deployed config. Deploys are additive — each
POST /scenariosmints a new id, and the name is display-only. The curated presets have stable ids; the PaymentProcessor preset ispaymentprocessor. - An experiment is one run of a scenario. It owns its dataset (entity tables,
event log, exports) and is rehydrated from disk on demand, so an experiment is
its on-disk dataset rather than a live in-process object. Each preset ships a
pre-run default experiment,
<scenario>-default— e.g.paymentprocessor-default.
Browse the PaymentProcessor preset
Section titled “Browse the PaymentProcessor preset”The PaymentProcessor preset models a European payment processor — merchants onboard through verification and run recurring payments routed onto SEPA, BACS, and AUTOGIRO settlement schemes across eight linked tables. Its default experiment is pre-run, so you can read populated data straight away — no token:
API=https://api.mockmachines.dev
# The scenario's metadata, and its pre-run default experimentcurl -s $API/scenarios/paymentprocessor | jqcurl -s $API/scenarios/paymentprocessor/experiments/paymentprocessor-default | jq
# Entity types with counts, then all merchants, then one merchantcurl -s $API/scenarios/paymentprocessor/experiments/paymentprocessor-default/entities | jqcurl -s $API/scenarios/paymentprocessor/experiments/paymentprocessor-default/entities/Merchant | jqcurl -s $API/scenarios/paymentprocessor/experiments/paymentprocessor-default/entities/Merchant/Merchant-00000001 | jq
# The append-only event log, and the dataset manifestcurl -s "$API/scenarios/paymentprocessor/experiments/paymentprocessor-default/events?from=0&limit=20" | jqcurl -s $API/scenarios/paymentprocessor/experiments/paymentprocessor-default/dataset | jq
# Download the whole world as a DuckDB database + OSI semantic model (a zip)curl -s -o paymentprocessor.zip \ $API/scenarios/paymentprocessor/experiments/paymentprocessor-default/dbEndpoints
Section titled “Endpoints”Scenarios
| Method | Path | Purpose |
|---|---|---|
GET | /scenarios | List deployed scenarios (presets included). |
GET | /scenarios/{id} | One scenario’s metadata. |
POST | /scenarios | Deploy a scenario from a YAML request body; returns the new id. (auth) |
DELETE | /scenarios/{id} | Delete a scenario and all its experiments. (auth) |
Experiments (under /scenarios/{id}/experiments)
| Method | Path | Purpose |
|---|---|---|
GET | /experiments | List a scenario’s experiments. |
GET | /experiments/{eid} | An experiment’s status, turn, and entity counts — poll this after a run. |
POST | /experiments | Create (seed) an experiment at turn 0. Body: {"seed_count": N, "event_log": bool, "decision_log": bool, "flushing": bool}. (auth) |
DELETE | /experiments/{eid} | Delete an experiment. (auth) |
POST | /experiments/{eid}/run | Advance the experiment (see below). (auth) |
POST | /experiments/{eid}/persist | Checkpoint at the current closed-turn boundary. (auth) |
POST | /experiments/{eid}/load | Resume a named checkpoint into a new experiment. (auth) |
POST | /experiments/{eid}/export | Export tables to CSV or Parquet. (auth) |
GET | /experiments/{eid}/db | Download the DuckDB database + OSI model as a zip. |
GET | /experiments/{eid}/events | Paginated event log (?from=&limit=). |
GET | /experiments/{eid}/dataset | Dataset metadata (status, counts, file list). |
Browsing a ready experiment (under .../experiments/{eid})
| Method | Path | Purpose |
|---|---|---|
GET | /entities | Machine types with counts. |
GET | /entities/{type} | All instances of a type, fields decoded. |
GET | /entities/{type}/{id} | One instance’s field map. |
GET | /entities/{type}/{id}/actions | The instance’s current state and available events, each with condition verdicts. |
Run your own experiment
Section titled “Run your own experiment”To run a fresh experiment you deploy (or reuse) a scenario in your own
workbench and drive it with a bearer token. POST .../run with {"turns": N}
starts a background run and returns 202 Accepted immediately — poll
GET .../experiments/{eid} until its status is ready and current_turn
reaches the target:
API=https://api.mockmachines.devAUTH="Authorization: Bearer $TOKEN"
# Deploy a config → seed → run → poll → read entitiesSID=$(curl -s -H "$AUTH" -X POST $API/scenarios \ --data-binary @PaymentProcessor.yaml | jq -r .id)
EID=$(curl -s -H "$AUTH" -X POST $API/scenarios/$SID/experiments \ -d '{"seed_count":100}' | jq -r .id)
curl -s -H "$AUTH" -X POST $API/scenarios/$SID/experiments/$EID/run \ -d '{"turns":50}' # → 202 Accepted
until [ "$(curl -s -H "$AUTH" $API/scenarios/$SID/experiments/$EID | jq -r .status)" = ready ]; do sleep 1done
curl -s -H "$AUTH" $API/scenarios/$SID/experiments/$EID/entities | jqThen export the tables, or pull the DuckDB + OSI bundle:
curl -s -H "$AUTH" -X POST $API/scenarios/$SID/experiments/$EID/export -d '{"format":"parquet"}'curl -s -H "$AUTH" -o experiment.zip $API/scenarios/$SID/experiments/$EID/dbInteractive control
Section titled “Interactive control”The same run endpoint can drive one entity for one step instead of N turns —
pass a target and event rather than turns:
curl -H "$AUTH" -X POST $API/scenarios/$SID/experiments/$EID/run \ -d '{"target":{"type":"Merchant","id":"Merchant-00000001"},"event":"activate"}'It returns the step outcome — fired, or stayed if the event’s conditions did not
hold (a requested event is a no-op when masked, never a fall-through to a different
event). Call .../entities/{type}/{id}/actions first to see which events are
eligible.
Authentication
Section titled “Authentication”Anonymous reads of the preset scenarios work out of the box. Authenticated
requests present a bearer token in the Authorization: Bearer <token> header,
verified as a Firebase ID token; the caller then operates in their own per-user
workbench. The admin route POST /admin/reset-presets is separately gated (an
MM_ADMIN_TOKEN bearer, a Firebase admin claim, or a scheduler OIDC token).
For longer sessions, the persist / load endpoints map to the
checkpoint & resume flow.