Jobs · 01

Run management.

Nine endpoints to start and operate workflow runs from your own code — start one, list them, fetch one, pause, resume, retry, or cancel, and resolve their pending approvals. All authenticated with the same Access Key as triggers.

Workflow only

These routes are workflow-only. Conversational agents have no runs, so these endpoints return 400 runtime_not_applicable for them.

Endpoints

MethodPathPurpose
POST/api/workflows/{agent_id}/triggerStart a run
GET/api/agents/{agent_id}/runsList runs for an agent
GET/api/agents/{agent_id}/runs/{run_id}Fetch one run with signed output URLs
POST/api/agents/{agent_id}/runs/{run_id}/cancelCancel an in-progress run
POST/api/agents/{agent_id}/runs/{run_id}/pausePause a running run
POST/api/agents/{agent_id}/runs/{run_id}/retryRetry a failed run with the same inputs
POST/api/agents/{agent_id}/runs/{run_id}/resumeResume a paused run
GET/api/agents/{agent_id}/runs/{run_id}/approvalsList a run's pending approvals
POST/api/agents/{agent_id}/runs/{run_id}/approvals/resolveApprove, reject, or modify one approval

Start a run

POST /api/workflows/{agent_id}/trigger

Starts a run of the job's published version. The body is optional: payload is the run's input (reference uploaded files as { "file_id": "fi_..." }), and variables override the job's default variables for this run. Each run is a real, billed run, and counts toward the job's daily run limit.

Start a run · cURLshell
curl -X POST https://webhook.olbrain.com/api/workflows/agt_01HAKZ.../trigger \
  -H "Authorization: Bearer ak_<your-access-key>" \
  -H "Content-Type: application/json" \
  -d '{"payload": {"order_id": "ord_8842"}}'
Response shapeJSON
{ "run_id": "abfcbeef-6d3a-4ab3-aca7-516cbff72d01", "status": "triggered" }

List runs

GET /api/agents/{agent_id}/runs

Returns the job's runs, newest first. Only live runs are listed; Studio test runs are left out.

Query parameters

NameTypeDescription
limitinteger Max runs to return. Defaults to the runtime's own default.
statusstring Filter by run state — one of pending, running, completed, failed, needs_review, cancelled, paused. An unrecognised value returns 400 invalid_status.

Any other query parameters are ignored.

List runs · cURLshell
curl "https://webhook.olbrain.com/api/agents/agt_01HAKZ.../runs?limit=20&status=failed" \
  -H "Authorization: Bearer ak_<your-access-key>"

Fetch one run

GET /api/agents/{agent_id}/runs/{run_id}

Returns the run record — status, progress, timing, a roll-up summary, per-state item_counts, and any output files. Output files come back as output_files[], each with a V4 signed HTTPS URL valid for 15 minutes after the GET. Re-issue the GET to get fresh URLs. The list endpoint above returns the same shape minus output_files (omitted so listing many runs doesn't mint a signed URL per file).

Response shapeJSON
{
  "run_id": "abfcbeef-6d3a-4ab3-aca7-516cbff72d01",
  "agent_id": "agt_01HAKZ...",
  "status": "completed",
  "progress_percent": 100.0,
  "started_at": "2026-05-26T11:42:19Z",
  "completed_at": "2026-05-26T11:43:07Z",
  "duration_seconds": 48.0,
  "trigger_type": "event",
  "error": null,
  "summary": { "total_processed": 100, "successful": 95, "failed": 3, "exceptions": 2, "skipped": 0 },
  "item_counts": { "completed": 95, "failed": 3, "needs_review": 2, "total": 100 },
  "output_files": [
    {
      "filename": "report.pdf",
      "content_type": "application/pdf",
      "size_bytes": 184320,
      "url": "https://storage.googleapis.com/...",
      "url_expires_at": "2026-05-26T12:00:00Z"
    }
  ]
}

Control endpoints

The four control endpoints share the same shape: POST with an empty body, optionally supply ?triggered_by= to attribute the action in audit logs.

POST /api/agents/{agent_id}/runs/{run_id}/cancel
POST /api/agents/{agent_id}/runs/{run_id}/pause
POST /api/agents/{agent_id}/runs/{run_id}/retry
POST /api/agents/{agent_id}/runs/{run_id}/resume

Query parameters

NameTypeDescription
triggered_bystring Optional. Attribution string that appears on the run's audit trail (e.g. shopify-webhook-handler, ops-dashboard).

State transitions

ActionAllowed fromTransitions to
pauserunning, pendingpaused
resumepaused, needs_review, runningrunning
cancelrunning, pending, needs_review, pausedcancelled
retryfailedRe-runs the same run from the failed step

An action against an incompatible state returns 409 invalid_state_transition. Re-fetch the run to see its current state before retrying.

Cancel a runcURL
curl -X POST "https://webhook.olbrain.com/api/agents/agt_01HAKZ.../runs/run_01HZQ7K9.../cancel?triggered_by=ops-dashboard" \
  -H "Authorization: Bearer ak_<your-access-key>"

Approvals

When a step needs a human decision, the run stops in needs_review with one or more pending approvals. List them, resolve each one, and the run resumes on its own once the last blocking approval is resolved.

GET /api/agents/{agent_id}/runs/{run_id}/approvals

Returns the run's unresolved approvals. An empty array means nothing is waiting.

Response shapeJSON
[
  {
    "exception_id": "exc_7f3a...",
    "step_id": "review_invoice",
    "item_id": "item_42",
    "data": { "vendor": "Acme", "amount": 18400 },
    "error": "Amount exceeds the auto-approve limit",
    "requires_human_review": true,
    "blocking": true
  }
]
POST /api/agents/{agent_id}/runs/{run_id}/approvals/resolve

Body

FieldTypeDescription
exception_idstring Required. The approval to resolve, from the list above.
resolutionstring Required. One of approved, rejected, modified.
modified_dataobject Only with modified: the corrected data to continue with.

Anything else returns 400 invalid_resolution. The resolver is recorded as your Access Key; there is no field to name someone else.

Approve · cURLshell
curl -X POST "https://webhook.olbrain.com/api/agents/agt_01HAKZ.../runs/run_01HZQ7K9.../approvals/resolve" \
  -H "Authorization: Bearer ak_<your-access-key>" \
  -H "Content-Type: application/json" \
  -d '{"exception_id": "exc_7f3a...", "resolution": "approved"}'
Response shapeJSON
{
  "exception_id": "exc_7f3a...",
  "resolution": "approved",
  "all_resolved": true,
  "resumed": true
}

all_resolved is true once the run has no approvals left; resumed is true when this call set the run going again. If every approval is resolved but resumed is false, call resume to restart it.

Totals per day

For counts across runs (finished, failed, items processed, cost per day), use GET /api/agents/{agent_id}/stats.

Scope

A run can only be read or controlled via the agent it belongs to. Calling a run-management route with the wrong agent_id in the URL returns 404.