API reference · Runs

Runs

Start work and follow it to the end. Statuses, step telemetry, and bindings are explained on Runs and steps.

POST/v1/runsStart a run.
GET/v1/runsList runs.
GET/v1/runs/{run_id}Read one, with steps and costs.
GET/v1/runs/{run_id}/eventsStream it over SSE.
POST/v1/runs/{run_id}/cancelStop it at the next step boundary.
POST/v1/runs/{run_id}/archiveHide a finished run from lists.
PATCH/v1/runs/{run_id}/projectMove it to another project.
POST/v1/runs/{run_id}/finalizeRecover a stranded run.

POST /v1/runs

Start a run. Returns 201 immediately with status pending; the work happens asynchronously.

requestbash
curl -X POST https://api.esy.com/v1/runs \
  -H "Authorization: Bearer $ESY_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "templateId": "generate-illustration",
    "workspaceId": "9a1b6d4c-…",
    "intake": {
      "prompt": "a lighthouse at dusk, storm rolling in",
      "style": "flat",
      "aspectRatio": "4:3",
      "categories": "landscapes"
    },
    "providers": { "imageGenerator": "openai/gpt-image-2-2026-04-21" }
  }'

Body

FieldTypeRequiredDescription
templateIdstringrequiredThe workflow id, e.g. generate-illustration. Find one in the catalog.
intakeobjectrequiredMust satisfy the workflow’s intakeSchema, or you get a 422 naming each bad field.
workspaceIduuidoptionalWhere the run and its costs land. Defaults to your default workspace.
projectIduuidoptionalOptional project inside that workspace.
providersobjectoptionalRole → model-registry id, for this run only. Validated against GET /v1/models.
Check the field names
The run body uses templateId and providers. Unknown keys are ignored, so a body using workflowId fails with 422 templateId required, and one using providerOverrides silently runs with the default models.

Errors

404 unknown workflow · 400 deprecated workflow or bad provider override · 403 workspace out of reach · 422 invalid intake · 402 a budget refused it. Bodies for each are on Errors.

GET /v1/runs

List runs, newest first.

requestbash
curl -s "https://api.esy.com/v1/runs?workspaceId=$WS&status=failed&limit=20" \
  -H "Authorization: Bearer $ESY_API_KEY"
FieldTypeRequiredDescription
workspaceId / projectIduuidoptionalScope the list.
statusstringoptionalOne of the nine run statuses.
parentOrderIdstringoptionalThe children of one order.
workerIdstringoptionalRuns a worker started.
includeArchivedbooleanoptionalArchived runs are hidden by default.
offset / limitintegeroptionalPagination. limit is capped at 100.

GET /v1/runs/{run_id}

Read a run: status, intake, pinned version, step telemetry, and costs.

The full shape, with real values, is on Runs and steps. Poll this until the status is terminal, or stream run events instead.

POST /v1/runs/{run_id}/cancel

Cancel a run at its next step boundary.

Stops future spend. Provider calls already made stay billed. The run ends as cancelled.

POST /v1/runs/{run_id}/archive

Hide a terminal run from lists.

Archive, never delete: the run keeps its steps, costs, and artifact, and reappears with includeArchived=true. Only terminal runs can be archived.

PATCH /v1/runs/{run_id}/project

Move a run to a different project in the same workspace.

requestbash
curl -X PATCH https://api.esy.com/v1/runs/run-fb0677b2/project \
  -H "Authorization: Bearer $ESY_API_KEY" \
  -H "content-type: application/json" \
  -d '{ "projectId": "b1126320-…" }'

projectId must be present; send null to move the run to the workspace level. Costs follow the run.

POST /v1/runs/{run_id}/finalize

Recover a run whose steps all completed but whose finalization never ran.

A rare recovery tool. If the process running a run dies between the last step and the bookkeeping, the work is done and paid for but the run never reaches a terminal status. This writes the artifact and the terminal status from what was already recorded — no step is re-run.