Runs
Operations of the Workflow Engine API. Paths are relative to your deployment's API host.
GET /api/workflow-engine-api/runs
List runs across every pipeline for the caller org.
Newest first. Narrow with projectId, workflowSlug, and status. When projectId is provided, the caller's access is verified against project-registry-api before any row is returned.
Authentication: bearer token (Authorization: Bearer <token>)
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
limit | query | number | no | |
offset | query | number | no | |
projectId | query | string | no | Filter by project id. |
status | query | WorkflowRunStatus | no | Filter by status. |
workflowSlug | query | string | no | Narrow to a single pipeline slug. |
| Status | Description | Body |
|---|---|---|
| 200 | application/json RunResponseDtoDataArrayEnvelope |
GET /api/workflow-engine-api/runs/{id}
Fetch a single run by id (slug-free).
Returns the run row for the caller org. 404 if the run does not exist or belongs to a different org. Used by service-to-service callers (notification self-heal) that hold a runId without slug context.
Authentication: bearer token (Authorization: Bearer <token>)
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | Workflow run id (UUID). |
| Status | Description | Body |
|---|---|---|
| 200 | application/json RunResponseDtoDataEnvelope |
GET /api/workflow-engine-api/workflows/{slug}/runs
List runs for a workflow
Lists runs belonging to the caller's org, newest first. Filter by projectId + status; paginate with limit + offset.
Authentication: bearer token (Authorization: Bearer <token>)
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
slug | path | string | yes | |
limit | query | number | no | |
offset | query | number | no | |
projectId | query | string | no | Filter by project id. |
status | query | array of WorkflowRunStatus | no | Filter by status. Repeat the parameter to match any of several statuses. |
| Status | Description | Body |
|---|---|---|
| 200 | application/json RunResponseDtoDataArrayEnvelope |
POST /api/workflow-engine-api/workflows/{slug}/runs
Start a workflow run (workflow_dispatch)
Compiles the workflow against the caller's trigger inputs, persists a CompiledRun snapshot, creates the WorkflowRun row, and starts the root workflow on Temporal. The caller's access to the supplied projectId is verified before any work is done — cross-org dispatch is blocked with 403. Dispatch is also capacity-fenced: an org that already holds its maximum number of concurrent non-terminal runs is refused with 429 WORKFLOW_ORG_CONCURRENCY_LIMIT_EXCEEDED (the request is rejected, never queued — retry once one of the org's runs reaches a terminal status).
Authentication: bearer token (Authorization: Bearer <token>)
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
slug | path | string | yes |
Request body: application/json StartRunRequestDto
| Status | Description | Body |
|---|---|---|
| 201 | application/json RunResponseDtoDataEnvelope | |
| 429 | The caller's organization is at its concurrent-workflow-run limit. The RFC 9457 problem document carries code: WORKFLOW_ORG_CONCURRENCY_LIMIT_EXCEEDED as a canonical member, with limit and inUse as extension members beside it. | application/problem+json ProblemDetailsDto |
POST /api/workflow-engine-api/workflows/{slug}/runs/reconcile-stalled
Reconcile stale non-terminal runs against Temporal state.
Scans pending/running/waiting/paused rows for this workflow and repairs rows whose Temporal execution has already closed. Emits workflow.run.status_changed plus workflow.run.completed/failed when applicable so realtime subscribers converge immediately.
Authentication: bearer token (Authorization: Bearer <token>)
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
slug | path | string | yes | |
limit | query | number | no | Maximum non-terminal rows to inspect for this workflow. |
projectId | query | string | no | Optional project scope. |
| Status | Description | Body |
|---|---|---|
| 200 | application/json ReconcileStalledRunsResponseDtoDataEnvelope |
GET /api/workflow-engine-api/workflows/{slug}/runs/{id}
Get a run by id (live or pruned)
Discriminated response — exactly one of run (state=live) or archive (state=pruned) is populated. A 404 with code=RUN_NOT_FOUND is returned when the run never existed (or belongs to a different org — the same shape is returned in both cases to avoid cross-org probing). The frontend switches on state to render either the full run detail page or a "this run was pruned per retention policy" banner with the archive metadata.
Authentication: bearer token (Authorization: Bearer <token>)
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
slug | path | string | yes |
| Status | Description | Body |
|---|---|---|
| 200 | application/json RunDetailResponseDtoDataEnvelope |
POST /api/workflow-engine-api/workflows/{slug}/runs/{id}/cancel
Cancel a run (graceful — in-flight children still finish).
Forwards a cancelRun Temporal signal + stamps the DB row with status=cancelled. The workflow exits after the currently in-flight job completes; no new jobs are dispatched. Hard cancellation (abort in-flight activities) is a separate follow-up.
Authentication: bearer token (Authorization: Bearer <token>)
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
slug | path | string | yes |
Request body: application/json RunControlBodyDto
| Status | Description | Body |
|---|---|---|
| 200 | application/json RunResponseDtoDataEnvelope |
GET /api/workflow-engine-api/workflows/{slug}/runs/{id}/describe
Pending activities + execution-level metadata.
Mirrors Temporal's DescribeWorkflowExecution. Surfaces pending-activity records (attempt counter, last-heartbeat, last-failure) so the FE can render a retry-storm view. 2s server cache.
Authentication: bearer token (Authorization: Bearer <token>)
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
slug | path | string | yes |
| Status | Description | Body |
|---|---|---|
| 200 | application/json RunDescribeResponseDtoDataEnvelope |
GET /api/workflow-engine-api/workflows/{slug}/runs/{id}/history
Paginated Temporal history with FE-ready grouping.
Server-side pagination + grouping. Activity / child-workflow lifecycles fold to one row per logical operation; everything else surfaces as a standalone event row. Set waitNew=true to long-poll for new events (server cap 25s, comfortably below typical 30s ingress idle-timeouts).
Authentication: bearer token (Authorization: Bearer <token>)
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
slug | path | string | yes | |
direction | query | one of "forward", "reverse" | no | Reserved for future reverse-paginate support; currently always forward. |
limit | query | number | no | |
nextPageToken | query | string | no | Continuation token from a previous call. Base64-encoded Temporal nextPageToken. |
waitNew | query | boolean | no | Set true to long-poll for new history events (server cap 25s). |
| Status | Description | Body |
|---|---|---|
| 200 | application/json RunHistoryResponseDtoDataEnvelope |
GET /api/workflow-engine-api/workflows/{slug}/runs/{id}/jobs
List job runs for a workflow run
Returns every JobRun row belonging to the run, newest-ordered by (jobKey, matrixIndex). Each row carries the action-defined outputs payload (post-completion) so the UI can render review verdicts, artifact references, and action-specific fields without a per-job round-trip.
Authentication: bearer token (Authorization: Bearer <token>)
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
slug | path | string | yes |
| Status | Description | Body |
|---|---|---|
| 200 | application/json JobRunResponseDtoDataArrayEnvelope |
GET /api/workflow-engine-api/workflows/{slug}/runs/{id}/metadata
Defined query / signal names on the workflow.
Reads Temporal's built-in __temporal_workflow_metadata query. Used by the FE Query tab to populate the dropdown without us hard-coding query names per workflow type. 60s cache.
Authentication: bearer token (Authorization: Bearer <token>)
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
slug | path | string | yes |
| Status | Description | Body |
|---|---|---|
| 200 | application/json RunMetadataResponseDtoDataEnvelope |
POST /api/workflow-engine-api/workflows/{slug}/runs/{id}/pause
Pause a run (stalls the job loop before the next dispatch).
Forwards a pauseRun Temporal signal to the running workflow. Pending activities/children finish as scheduled; the root workflow waits for a matching resumeRun or cancelRun before starting the next job. Idempotent.
Authentication: bearer token (Authorization: Bearer <token>)
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
slug | path | string | yes |
Request body: application/json RunControlBodyDto
| Status | Description | Body |
|---|---|---|
| 200 | application/json RunResponseDtoDataEnvelope |
POST /api/workflow-engine-api/workflows/{slug}/runs/{id}/query
Execute a named workflow Query.
Runs handle.query(name, ...args) against the live workflow. Result is decoded via the engine's payload codec and redacted before serialization. 404 when the run is no longer queryable (terminal + retention closed).
Authentication: bearer token (Authorization: Bearer <token>)
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
slug | path | string | yes |
Request body: application/json RunQueryRequestDto
| Status | Description | Body |
|---|---|---|
| 200 | application/json RunQueryResponseDtoDataEnvelope |
POST /api/workflow-engine-api/workflows/{slug}/runs/{id}/reset
Reset the workflow to a chosen WorkflowTaskCompleted event.
Temporal's ResetWorkflowExecution. Re-dispatches everything after the chosen event id; for activities like xema/agent whose resume short-circuit honors deliverables-on-disk, the retry is cheap. The chosen eventId MUST be a WorkflowTaskCompleted event — other event types are rejected with 400.
Authentication: bearer token (Authorization: Bearer <token>)
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
slug | path | string | yes |
Request body: application/json RunResetRequestDto
| Status | Description | Body |
|---|---|---|
| 200 | application/json RunResetResponseDtoDataEnvelope |
POST /api/workflow-engine-api/workflows/{slug}/runs/{id}/resume
Resume a paused run.
Forwards a resumeRun Temporal signal. The paused workflow's await condition(...) returns and the job loop picks back up at the next job. Idempotent.
Authentication: bearer token (Authorization: Bearer <token>)
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
slug | path | string | yes |
| Status | Description | Body |
|---|---|---|
| 200 | application/json RunResponseDtoDataEnvelope |
POST /api/workflow-engine-api/workflows/{slug}/runs/{id}/signal
Forward a custom signal to the workflow.
Generic signal forwarder. Reserved lifecycle names (pauseRun / resumeRun / cancelRun) are rejected — use the dedicated /pause /resume /cancel endpoints instead so DB bookkeeping stays consistent. Signal args must be JSON-serializable.
Authentication: bearer token (Authorization: Bearer <token>)
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
slug | path | string | yes |
Request body: application/json RunSignalRequestDto
| Status | Description | Body |
|---|---|---|
| 200 | application/json EmptyResponseDtoDataEnvelope |
GET /api/workflow-engine-api/workflows/{slug}/runs/{id}/stream
Stream run events (SSE).
Temporal-native: polls getRunStatus Query on the root workflow at 2s cadence and emits snapshot-delta status events + 20s heartbeats. Closes on terminal DB status or client disconnect.
Authentication: bearer token (Authorization: Bearer <token>)
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
slug | path | string | yes |
| Status | Description | Body |
|---|---|---|
| 200 | A server-sent event stream of run status and heartbeat frames. | text/event-stream string |
GET /api/workflow-engine-api/workflows/{slug}/runs/{id}/summary
Live workflow summary (status + per-job outputs).
Folds the workflow getRunStatus + getJobOutputs queries into one Temporal round-trip. The FE polls this every ~10s; results are cached server-side for 1s so concurrent tabs collapse onto a single Temporal call. Returns state: 'expired' when retention has passed.
Authentication: bearer token (Authorization: Bearer <token>)
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
slug | path | string | yes |
| Status | Description | Body |
|---|---|---|
| 200 | application/json RunSummaryResponseDtoDataEnvelope |
GET /api/workflow-engine-api/workflows/{slug}/runs/{id}/timeline
Fetch the run timeline (projection of every workflow.* CloudEvent).
Returns rows ordered ascending by ehGlobalSeq. Pass back the response's nextAfterEhGlobalSeq to keep paginating. Cold-start clients omit the cursor; reconnect after SSE drops to resume from the last received frame.
Authentication: bearer token (Authorization: Bearer <token>)
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | |
slug | path | string | yes | |
afterEhGlobalSeq | query | string | no | Resume cursor: stringified BigInt of the last seen ehGlobalSeq. Returns rows STRICTLY AFTER this value, ordered ascending. Omit on cold start. |
limit | query | number | no | Page size cap. Default 200; max 1000. |
| Status | Description | Body |
|---|---|---|
| 200 | application/json RunTimelinePageDtoDataEnvelope |