Runs
A run is a single execution of a template dispatched to one person. Dispatch a run to get a link you send to the executor. Retrieve it later to read all answers.
POST /v1/runs
Dispatch a new run. The template is snapshotted at creation time — future edits to the template do not affect this run.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
template_id |
string | yes | ID of the template to execute (t-{uuid}) |
webhook |
object | no | Webhook config for this run (see Webhooks) |
expires_in_hours |
number | no | Hours until the run link expires. Omit for no expiry. |
executor_ref |
string | no | Your own correlation ref stored on the run (e.g. booking ID, customer ID) |
curl -X POST https://api.rundun.app/v1/runs \
-H "Authorization: Bearer rdk_live_..." \
-H "Content-Type: application/json" \
-d '{
"template_id": "t-550e8400-e29b-41d4-a716-446655440000",
"executor_ref": "booking_9f2a3b",
"webhook": {
"url": "https://your-app.com/hooks/rundun",
"secret": "whsec_abc123",
"events": ["step.completed", "run.completed", "run.cancelled"]
},
"expires_in_hours": 24
}'
Response
{
"run_id": "r-550e8400-e29b-41d4-a716-446655440000",
"link": "https://rundun.app/r/r-550e8400-e29b-41d4-a716-446655440000",
"expires_at": "2026-05-22T08:31:00Z",
"assigned_to": null
}
| Field | Description |
|---|---|
run_id |
Stable run identifier. Use this to retrieve the run later. |
link |
Send this to the executor. Opens the app if installed; shows install prompt if not. |
expires_at |
ISO 8601 timestamp when the link expires, or null if no expiry was set. |
assigned_to |
null on creation. Populated with the executor's u-{uuid} when they first open the run. |
Run statuses
| Status | Meaning |
|---|---|
pending |
Dispatched, not yet opened |
in_progress |
Executor has started answering |
completed |
All required steps answered and run submitted |
cancelled |
Executor exited before completion |
expired |
Link expired before completion |
Quota enforcement
POST /v1/runs checks runs_used_this_month against your plan limit before creating the run. If you are over quota, the API returns 402:
{
"error": "quota_exceeded",
"message": "You have used all 30 runs included in your Starter plan this month. Upgrade or purchase a run pack to continue."
}
GET /v1/runs/:run_id
Retrieve a run by ID, including all answers and current status.
curl https://api.rundun.app/v1/runs/r-550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer rdk_live_..."
Response
{
"run_id": "r-550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"template_id": "t-a3f9bc00-e29b-41d4-a716-446655440000",
"template_v": 3,
"executor_ref": "booking_9f2a3b",
"created_at": "2026-05-22T08:31:00Z",
"completed_at": "2026-05-22T08:41:05Z",
"expires_at": "2026-05-23T08:31:00Z",
"assigned_to": "u-abc12300-e29b-41d4-a716-446655440000",
"executor_identity": {
"mode": "member",
"user_id": "u-abc12300-e29b-41d4-a716-446655440000"
},
"progress": { "total": 6, "answered": 5, "skipped": 1 },
"answers": {
"s-od01": {
"value": 42150,
"photos": [],
"geo": null,
"at": "2026-05-22T08:32:00Z",
"by": "u-abc12300-e29b-41d4-a716-446655440000"
},
"s-fu01": {
"value": "o-fu2",
"photos": [],
"geo": null,
"at": "2026-05-22T08:33:00Z",
"by": "u-abc12300-e29b-41d4-a716-446655440000"
},
"s-dm01": {
"value": true,
"photos": [],
"geo": null,
"at": "2026-05-22T08:34:00Z",
"by": "u-abc12300-e29b-41d4-a716-446655440000"
},
"s-dm02": {
"value": ["o-dm1", "o-dm3"],
"photos": [
{ "photo_index": 0, "url": "https://media.rundun.app/runs/r-550e8400-.../s-dm02/photo_0.jpg" }
],
"geo": { "lat": 51.507, "lng": -0.127, "accuracy_m": 5 },
"at": "2026-05-22T08:36:00Z",
"by": "u-abc12300-e29b-41d4-a716-446655440000"
}
}
}
The answers map is keyed by step ID. The value field shape depends on the step type — see Step types for the full mapping.
GET /v1/runs/:run_id/preview
Returns a lightweight preview of a run. Used by the deep link fallback page (rundun.app/r/:run_id) to render run info before the app is installed. Does not require authentication — the run ID is the access credential.
curl https://api.rundun.app/v1/runs/r-550e8400-e29b-41d4-a716-446655440000/preview
Response
{
"run_id": "r-550e8400-e29b-41d4-a716-446655440000",
"status": "pending",
"template_name": "Vehicle rental — outgoing check",
"step_count": 6,
"created_by_name": "Alex",
"expires_at": "2026-05-23T08:31:00Z"
}
This endpoint returns 410 Gone if the run has expired.
Executor identity modes
The executor's identity on a run is determined by the template's execution.identity_required setting. The possible modes returned in executor_identity:
{ "mode": "anonymous" }
{ "mode": "external", "name": "Jane Smith", "email": "jane@example.com" }
{ "mode": "member", "user_id": "u-abc12300-e29b-41d4-a716-446655440000" }
The assigned_to field is always a u-{uuid} when the executor is an org member, and null for external or anonymous executors.