Skip to content
cronpad
API reference / Runs API

Runs API

Runs record each occurrence of a job and every attempt to deliver it. Use these endpoints to build dashboards, export history, or debug failures.

The run object

{
  "id": "run_01J9ZM1A…",
  "job_id": "job_01J9ZK3Q…",
  "scheduled_at": "2026-11-10T03:30:00Z",
  "trigger": "schedule",
  "status": "succeeded",
  "attempts": 2,
  "claimed_at": "2026-11-10T03:30:00.004Z",
  "started_at": "2026-11-10T03:30:00.006Z",
  "finished_at": "2026-11-10T03:30:21.410Z",
  "next_attempt_at": null,
  "start_lag_ms": 6,
  "e2e_ms": 21410,
  "sla_breached": false,
  "last_error": null
}
FieldValues
triggerschedule, manual, retry_manual
statusrunning, deferred, succeeded, failed, skipped, cancelled

See Jobs, runs and attempts for what each state and timestamp means.

List runs of a job

GET /api/v1/jobs/{id}/runs?status=failed&from=2026-11-01T00:00:00Z&to=2026-11-10T00:00:00Z&limit=50

Newest first, with run ID breaking ties at the same scheduled time. Pass next_cursor as cursor to continue a page (default 50, maximum 200). Filter by status, trigger, sla_breached=true, and a from/to range on scheduled_at.

List runs across the workspace

GET /api/v1/runs with the same filters plus job_id and tag.

Get a run

GET /api/v1/runs/{id} returns the run plus its attempts:

{
  "id": "run_01J9ZM1A…",
  "status": "succeeded",
  "attempts": [
    {
      "n": 0,
      "started_at": "2026-11-10T03:30:00.006Z",
      "finished_at": "2026-11-10T03:30:01.010Z",
      "duration_ms": 1004,
      "outcome": "retryable",
      "status_code": 503,
      "error": "HTTP 503",
      "request_summary": "POST https://api.example.com/reports (231 bytes)",
      "response_body": "upstream unavailable"
    },
    {
      "n": 1,
      "started_at": "2026-11-10T03:30:11.300Z",
      "finished_at": "2026-11-10T03:30:21.410Z",
      "duration_ms": 110,
      "outcome": "success",
      "status_code": 200,
      "error": null,
      "request_summary": "POST https://api.example.com/reports (231 bytes)",
      "response_body": null
    }
  ]
}

response_body is null when it wasn’t stored (successful attempts by default) or has aged out. See Data retention.

Retry a failed run

POST /api/v1/runs/{id}/retry → 202 with the new run. Only runs with status failed can be retried; the new run has trigger = retry_manual, the same scheduled_at, and a fresh set of attempts. Repeated requests for the same occurrence coalesce into one manual retry; an exhausted manual retry returns 409 conflict.