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>)

ParameterInTypeRequiredDescription
limitquerynumberno
offsetquerynumberno
projectIdquerystringnoFilter by project id.
statusqueryWorkflowRunStatusnoFilter by status.
workflowSlugquerystringnoNarrow to a single pipeline slug.
StatusDescriptionBody
200application/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>)

ParameterInTypeRequiredDescription
idpathstringyesWorkflow run id (UUID).
StatusDescriptionBody
200application/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>)

ParameterInTypeRequiredDescription
slugpathstringyes
limitquerynumberno
offsetquerynumberno
projectIdquerystringnoFilter by project id.
statusqueryarray of WorkflowRunStatusnoFilter by status. Repeat the parameter to match any of several statuses.
StatusDescriptionBody
200application/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>)

ParameterInTypeRequiredDescription
slugpathstringyes

Request body: application/json StartRunRequestDto

StatusDescriptionBody
201application/json RunResponseDtoDataEnvelope
429The 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>)

ParameterInTypeRequiredDescription
slugpathstringyes
limitquerynumbernoMaximum non-terminal rows to inspect for this workflow.
projectIdquerystringnoOptional project scope.
StatusDescriptionBody
200application/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>)

ParameterInTypeRequiredDescription
idpathstringyes
slugpathstringyes
StatusDescriptionBody
200application/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>)

ParameterInTypeRequiredDescription
idpathstringyes
slugpathstringyes

Request body: application/json RunControlBodyDto

StatusDescriptionBody
200application/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>)

ParameterInTypeRequiredDescription
idpathstringyes
slugpathstringyes
StatusDescriptionBody
200application/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>)

ParameterInTypeRequiredDescription
idpathstringyes
slugpathstringyes
directionqueryone of "forward", "reverse"noReserved for future reverse-paginate support; currently always forward.
limitquerynumberno
nextPageTokenquerystringnoContinuation token from a previous call. Base64-encoded Temporal nextPageToken.
waitNewquerybooleannoSet true to long-poll for new history events (server cap 25s).
StatusDescriptionBody
200application/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>)

ParameterInTypeRequiredDescription
idpathstringyes
slugpathstringyes
StatusDescriptionBody
200application/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>)

ParameterInTypeRequiredDescription
idpathstringyes
slugpathstringyes
StatusDescriptionBody
200application/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>)

ParameterInTypeRequiredDescription
idpathstringyes
slugpathstringyes

Request body: application/json RunControlBodyDto

StatusDescriptionBody
200application/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>)

ParameterInTypeRequiredDescription
idpathstringyes
slugpathstringyes

Request body: application/json RunQueryRequestDto

StatusDescriptionBody
200application/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>)

ParameterInTypeRequiredDescription
idpathstringyes
slugpathstringyes

Request body: application/json RunResetRequestDto

StatusDescriptionBody
200application/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>)

ParameterInTypeRequiredDescription
idpathstringyes
slugpathstringyes
StatusDescriptionBody
200application/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>)

ParameterInTypeRequiredDescription
idpathstringyes
slugpathstringyes

Request body: application/json RunSignalRequestDto

StatusDescriptionBody
200application/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>)

ParameterInTypeRequiredDescription
idpathstringyes
slugpathstringyes
StatusDescriptionBody
200A 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>)

ParameterInTypeRequiredDescription
idpathstringyes
slugpathstringyes
StatusDescriptionBody
200application/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>)

ParameterInTypeRequiredDescription
idpathstringyes
slugpathstringyes
afterEhGlobalSeqquerystringnoResume cursor: stringified BigInt of the last seen ehGlobalSeq. Returns rows STRICTLY AFTER this value, ordered ascending. Omit on cold start.
limitquerynumbernoPage size cap. Default 200; max 1000.
StatusDescriptionBody
200application/json RunTimelinePageDtoDataEnvelope