Rundunrundun

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.