Skip to content

Runs

Base URL: https://api.syntheticusers.io

Every endpoint on this page needs an API key: Authorization: Bearer sk_live_.... See API keys for how to create one.

POST /runs

Start a run. The response comes back right away with a run_id; the synthetic users do their work in the background. Poll the run (below) to watch progress.

Request body

FieldTypeRequiredNotes
target_urlstring (https)yesThe page to test. Must be HTTPS, and its host must be on your allowlist. Private/internal IPs are rejected.
persona_idsstring[]yes1–10 personas. Library or custom. Each persona runs as its own session.
taskstringnoA plain-language goal, e.g. "Sign up for a trial". Leave it out to let the persona explore freely.
flowsstring[]noNamed steps you want attempted in order.
credential_idsstring[]noLogins to use when the target needs authentication. See Authenticated targets.
duration_budget"short" | "medium"noHow long each session may run. "short" (default) ≈ 15 turns / ~3 min; "medium" ≈ 120 turns / ~20 min.
guided_exploration"off" | "standard" | "deep"noDefault "off". "standard" and "deep" attach a questioner that pushes the persona to probe more before finishing.
modelstringnoThe public API runs on claude-opus-4-8 (Claude Opus 4.8, Anthropic direct), which is also the default. You can omit it.

Response (202 Accepted)

{
"run_id": "run_01H...",
"status": "queued",
"sessions": [
{ "id": "sess_1", "persona_id": "pers_a" },
{ "id": "sess_2", "persona_id": "pers_b" }
],
"guided_exploration": "standard"
}
Terminal window
curl -s -X POST "$API_URL/runs" \
-H "Authorization: Bearer $SYNTHUSERS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"target_url": "https://staging.example.com",
"persona_ids": ["pers_..."],
"task": "Sign up for a trial",
"guided_exploration": "standard"
}'

GET /runs

List your runs, newest first. Uses cursor pagination.

Query paramNotes
limit1–100. Default 50.
statusFilter by queued, running, completed, failed, partial, cancelled.
cursorPass next_cursor from the previous page.
Terminal window
curl -s "$API_URL/runs?limit=20" \
-H "Authorization: Bearer $SYNTHUSERS_API_KEY"
{
"items": [
{
"id": "run_01H...",
"target_url": "https://staging.example.com",
"status": "completed",
"guided_exploration": "standard",
"created_at": "2026-05-15T18:24:00Z",
"session_count": 3
}
],
"next_cursor": "1747334640000|run_01H..."
}

GET /runs/:id

Fetch one run and its sessions. Poll this to track progress.

{
"run_id": "run_01H...",
"target_url": "https://staging.example.com",
"status": "running",
"guided_exploration": "standard",
"aggregate_status": "pending",
"sessions": [
{ "id": "sess_1", "persona_id": "pers_a", "status": "completed" },
{ "id": "sess_2", "persona_id": "pers_b", "status": "running" },
{ "id": "sess_3", "persona_id": "pers_c", "status": "queued" }
]
}

A run’s status is one of queued, running, completed, failed, partial (some sessions failed), or cancelled. Each session’s status is one of queued, running, completed, or failed.

Reports

Reports are ready once a session’s status is completed. Each format is a separate endpoint.

Per-session report

  • GET /runs/:id/sessions/:sid/report.json — structured findings. The shape is stable and carries a schema_version.
  • GET /runs/:id/sessions/:sid/report.md — the same report as Markdown.
  • GET /runs/:id/sessions/:sid/report.html — a rendered HTML report.

Aggregate report (multi-persona)

When a run has more than one persona, an aggregate report compares them.

  • GET /runs/:id/aggregate-report.json
  • GET /runs/:id/aggregate-report.md
  • GET /runs/:id/aggregate-report.html

The aggregate is ready once its sessions have finished — check aggregate_status (pending, ready, failed, or not_applicable) on the run. For a friendlier view, the dashboard renders both reports at https://app.syntheticusers.io/r/<run_id>.

Other per-session endpoints

  • GET /runs/:id/sessions/:sid/screenshots/:filename — a PNG captured during the walk. Filenames are zero-padded, e.g. 001-landing.png.
  • GET /runs/:id/sessions/:sid/transcript — the full, replay-ready transcript.
  • GET /runs/:id/sessions/:sid/events — a polling feed of session events (since a millisecond timestamp).
  • GET /runs/:id/sessions/:sid/stream — the same events as a live Server-Sent Events stream.
  • GET /runs/:id/map — a node-and-edge map of the screens the sessions reached (the journey map).

Cancelling a run

POST /runs/:id/cancel asks the platform to stop a run. Cancellation is best-effort: a session already writing its final report finishes normally. You can also cancel from the dashboard.