GoRunner docs
Search or askSearch⌘K

List runs

GET/api/runs

Returns runs from every workflow in the workspace, newest first. Production runs only, unless you ask.

Needs an API token with the Read permission for runs (run:read).

Parameters

Query

windowOptional · string

24h, 7d, 30d, 90d or all (the default). Not with from or to.

pageOptional · integer

The page, from 1.

limitOptional · integer

Runs a page, 1 to 100. The default is 20; anything else reads as 20.

environmentOptional · string

production (the default), test or all.

workflowIdOptional · UUID

One workflow’s runs.

qOptional · string

Up to 200 characters. Finds runs whose ID starts with it, or whose workflow name or error has it, ignoring case.

stateOptional · string

One of the Runs page’s words: queued, running, held, worked, failed, cancelled. Not with status, waiting or taken.

What are the rarely used parameters?
statusOptional · string

The run’s own status: waiting, pending, running, completed, failed, cancelled or paused.

triggerTypeOptional · string

How it began: manual, webhook, cron, poll, error, run_finished, event, api, mcp or subflow.

tagOptional · string

Runs with exactly this tag, added by the Tags app.

sortOptional · string

oldest first, or duration, longest first. Left out: newest first.

waitingOptional · string

Held runs by what they wait for: person (an answer) or time (a delay, or an answer being carried out).

takenOptional · boolean

true leaves out runs still waiting in line. With status=pending, lists the runs a worker is running.

fromOptional · time

Runs started at or after this time (RFC 3339).

toOptional · time

Runs started before this time. After from.

cursorOptional · string

Pages by start time instead: empty for the first page, then pagination.nextCursor. No totals.

reasonOptional · string

Up to 200 characters. Runs whose error has it, ignoring case.

groupOptional · string

A failure group’s key, from Group failed runs.

idsOptional · string

Up to 100 run IDs, separated by commas. The other filters still apply.

Where are my test runs?

The list shows production runs unless you send environment=test or all. A run started with Run a workflow without environment=production is often a test run.

queued, running and held ignore the time range: what is open now is listed, however old. The other states follow it.

What a row holds

No steps: Get a run has them. A row adds workflowName, stepTotal, stepFailed, state and, for a failed run, failure: the step and the first part of the reason.

A held run adds what it waits for: waitStep, waitingOn, resumeAt. A run in line adds waitingFor, waitingLimit and linePosition. An answered approval adds decision, decidedBy and decidedAt.

With cursor, pagination is {limit, nextCursor} and rows have no triggerData. sort=duration can’t page by cursor. For totals, count runs by state.

Responses

  • 200OK

    A page of runs, without their steps.

  • A filter has a value it doesn’t take (the message names it), workflowId isn’t a UUID, q is over 200 characters, or filters that don’t go together were sent together.

  • The token lacks the Read permission for runs.

  • The list couldn’t be read. Try again.

Any call can also answer: 401 UNAUTHORIZED · 401 TOKEN_ENDED · 403 TOKEN_SURFACE_OFF · 403 FEATURE_OFF · 403 EMBED_NOT_ALLOWED · 403 EMBED_NOT_AVAILABLE · 403 ACCOUNT_SUSPENDED · 429 RATE_LIMITED · 503 BUSY · 503 PAUSED · 503 SERVICE_UNAVAILABLE. See Errors.

Request

GORUNNER="https://api.gorunner.io"
GORUNNER_TOKEN="grt_…"  # needs Read for runs

curl "$GORUNNER/api/runs?state=failed&window=7d" \
  -H "Authorization: Bearer $GORUNNER_TOKEN"

Response · 200 OK, shortened

json
{
  "data": [
    {
      "id": "8f0c41d2-6b7e-4c1a-9d3f-2a5b7c9e1f04",
      "workflowId": "3b1e5c2a-7d4f-4e8b-a1c6-5f2d9b0e7a31",
      "workflowName": "Order intake",
      "status": "failed",
      "state": "failed",
      "environment": "production",
      "startedAt": "2026-10-25T09:00:00Z",
      "durationMs": 1840,
      "stepTotal": 2,
      "stepFailed": 1,
      "failure": {
        "stepKey": "forward",
        "step": "Forward to fulfilment",
        "reason": "the service answered 503"
      }
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 1,
    "totalPages": 1
  }
}
Every field

It takes no body.

Response · 200 OK

dataarray of objects
idUUID

The run id.

workflowIdUUID

The workflow that ran.

workspaceIdUUID

Tenant workspace, denormalized onto the run.

orgIdUUID

Tenant organization.

statusstring

A run’s lifecycle status. TERMINAL values — stop polling when you see one — are completed, failed and cancelled. NON-TERMINAL values are waiting (accepted and waiting in line for a free slot: its workflow’s or its organization’s runs-at-once limit, or a free worker — waitingFor, waitingLimit and linePosition say which and where; it starts in order, and cancelling it takes it out of the line), pending (a worker has it or is about to: claimedAt says when a worker took it), running (a resumed run executing after its wait) and paused (suspended on a durable wait: an approval/webhook resume, or a scheduled resume time). A paused run can remain paused indefinitely; it resumes only when its wait is satisfied, or ends if you cancel it. waiting is new in v2026.10.4: before it, a run over a limit was refused instead.

One of waiting, pending, running, completed, failed, cancelled, paused.

triggerTypestring

How THIS run began — an open string, not the workflow’s trigger vocabulary. Known values: manual (editor test), webhook, cron, poll, event, error (an error-handler workflow), run_finished, api (started through POST /api/workflows/{id}/run), mcp (the same door, by an AI app’s tool), subflow (started by a parent flow’s Sub-flow step).

triggerDataobject or array or string or number or boolean or null

The payload the trigger delivered — for a webhook run an object with body, headers, query, method. This is what {{trigger...}} expressions resolved against.

startedAttime

When the run was accepted. It may then wait in line for a free slot before a worker starts it (firstStartedAt).

firstStartedAttime or null

When a worker first started the run. durationMs counts from here, so the time from startedAt to this is the time the run waited in line. Null until a worker starts the run, and for a run started on v2026.10.5 or earlier or one that ran inline (a Sub-flow’s, an error handler’s), whose durationMs counts from startedAt.

finishedAttime

When the run settled: the moment its result was decided (not when its record was saved, which can be a moment later). Present as soon as the run is finished, also while its record is still being saved. Absent while non-terminal.

durationMsinteger

How long the run took, in milliseconds: from the first time a worker started the run (firstStartedAt, else startedAt) to its finish. Waits inside the run (a Delay, an Approval) count; the time it waited in the line for a free slot does not. A run cancelled while it waited has none. Rounded to the millisecond. Present as soon as the run is finished, also while its record is still being saved. Absent while non-terminal.

errorMessagestring

Why the run failed (or the cancellation reason). Absent/empty otherwise.

tagsarray of strings or null

Tags attached during execution by the Tags app. Filterable via GET /api/runs?tag=. [] when it has none. null while the run is read from its live cache: in flight until the worker saves it, and for a moment after it is cancelled. A run still waiting in line, read from its record, says [].

environmentstring

Where the run came from. test for anything the editor started; production for real trigger traffic and for POST /api/workflows/{id}/run?environment=production. Deliberately independent of triggerType — a listen-captured run is both a webhook run and a test run. GET /api/runs hides test runs unless asked.

One of production, test.

stepsarray of objects

The executed steps, oldest first. Returned by GET /api/runs/{id} only — never in the list. Step output lives here, keyed by each element’s nodeId.

idUUID

Id of this step-run row. A step that suspended the run gets a new id when the run resumes: address a step by nodeId.

runIdUUID

The run this step belongs to.

nodeIdstring

The definition step NAME (stable identifier, e.g. parse_csv). Use this to find a step, not displayName.

pieceIdstring

The app that ran, e.g. http, code, csv.

actionIdstring

The action within that app, e.g. send_request, convert.

displayNamestring

The human label shown on the canvas. Not an identifier — it can be duplicated and renamed.

statusstring

A single step’s status inside a run. skipped means the step was not executed (a branch arm not taken, or a step after a failure). paused marks the wait step a suspended run is currently sitting on. A step executing when its run is cancelled ends failed ("Cancelled while it ran."), and so does the step a cancelled run was held on. A step can be failed while the run is completed — that happens when the step’s error handling routed to an error path or continued.

One of pending, running, completed, failed, skipped, paused.

inputDataobject or array or string or number or boolean or null

The resolved input the step ran with, after expressions were evaluated. Normally an object of the form {"config": { ...the step's resolved config... }}. Absent when the step never executed, and on a step that suspended the run (a top-level Approval, Delay or Wait for callback) once the run has resumed: its outputData is kept, its input is not.

outputDataobject or array or string or number or boolean or null

THE STEP’S OUTPUT — whatever the app returned, arbitrary JSON. Absent when the step failed before producing output or never executed. Large payloads are offloaded to object storage during the run and rehydrated here transparently, so this is always inline JSON when present; when it cannot be read back, it is absent and dataUnavailable is true.

errorMessagestring

Why the step failed. Absent/empty when it did not.

retryCountinteger

Which attempt this record reflects (0 = first attempt).

startedAttime

When the step began. Absent if it never started.

finishedAttime

When the step settled. Absent while running or if it never finished.

durationMsinteger

How long this record’s attempt took, in milliseconds, rounded (0 = under half a millisecond; the dashboard says "<1 ms"). For a retried step it is the last attempt; for a step that ran more than once (a loop body) its last pass. totalDurationMs has the step’s time in all.

attemptsinteger

How many attempts the step’s last pass took, when it was retried (absent: one attempt; every field of this group is absent on runs recorded before it existed). This record is the last of them.

firstAttemptStartedAttime

When the first of attempts began. Present with attempts.

passesinteger

How many times the step ran in the run, when more than once — a step inside a loop runs once per item. Absent: once. This record is the last pass.

totalDurationMsinteger

The step’s time in all, in milliseconds: each pass from its first attempt’s start to its finish (the waits between retries included), summed over its passes. Present with attempts or passes.

attemptErrorsarray of objects

The earlier attempts of the last pass and why each failed, oldest first: at most the last 20, each error at most 1,000 characters. Present with attempts.

attemptinteger

Which attempt (1 = the first).

errorstring

What it failed with.

attime

When it ended.

recoverystring

In a restarted run (restarts), what the run did with this step: replayed, an earlier attempt finished it, its recorded result was used and it did not run again; rerun, it had started when the worker stopped and ran again (it only reads or computes); unknown, it changes something outside the run and was in flight when the worker stopped, so it was NOT sent again: it failed with "Outcome unknown" and its error handling decided what followed. Absent: an ordinary step.

One of replayed, rerun, unknown.

runAttemptinteger

Which execution of a restarted run produced this record, when it was not the first (2 = the first restart). Absent: the first.

dataUnavailableboolean

Present (true) when the step’s payload was offloaded to object storage and could not be read back: the step did produce inputData/outputData, but it cannot be shown now (they are absent). Tells "produced nothing" apart from "cannot be read". Absent otherwise.

deferredobject

Only on a read with large=defer: the step’s inputData and/or outputData this read left out because each is over 64 KB of JSON (the step a paused run waits on is never left out), each with its size. The value exists; read it with GET /api/runs/{id}?step=<nodeId>. Absent otherwise.

inputobject

A value this read left out because it is large: its size in bytes of JSON, as stored, and for a step’s output its head.

bytesinteger

The value’s size in bytes of JSON.

headobject

A step OUTPUT’s facts, so a client can say what the step did without reading it (an HTTP status, an approval’s answer, a loop’s count): the output’s top-level keys — a scalar (up to 512 bytes) with its value, an object as its own scalar members, every other value null — at most 8 KB, scalars first. Absent for an input, the trigger data and an output that is not a JSON object. Never the output itself.

outputobject

A value this read left out because it is large: its size in bytes of JSON, as stored, and for a step’s output its head.

The same fields as data.steps.deferred.input above.

versionIdUUID

The workflow’s latest published version at the moment the run started. Absent for a workflow that has never been published.

versionNumberinteger

Display number of versionId.

executedVersionIdUUID

The version whose definition ACTUALLY executed. ABSENT means the DRAFT ran (an editor test), so rendering versionId's snapshot would show a graph that never ran. The list and the detail read carry it; GET /api/workflows/{id}/runs does not.

executedVersionNumberinteger

Display number of executedVersionId.

startedFromStepstring

For a partial ("run from here") run, the definition step NAME the run began at. Absent means the run started at its trigger, which is every ordinary run. Everything above that step was seeded, not executed — do not read its steps as having run. Detail read only: a row of GET /api/runs leaves it out.

retryOfRunIdUUID

The run this one is a retry of. Set at creation and immutable.

retriedByRunIdUUID

The most recent run that retried THIS one. The list and the detail read carry it.

parentRunIdUUID

For a run started by another run’s Sub-flow step (triggerType subflow), the run that called it. The list and the detail read carry it; absent for every other run and for sub-flow runs from before 2026-10.

restartsinteger

How many times the run was offered to another worker because the one running it stopped (killed, out of memory, its host lost, or it lost the run’s lease). A restarted run continues from what the stopped attempt finished: a step it finished does not run again (its step record says recovery replayed), and a step that changes something outside the run and was in flight is not sent again (recovery unknown, failed with "Outcome unknown"). Absent: never restarted, and every run from before 2026-11.

answerstring

How the run’s last wait on a person was settled: approved, rejected, or timed_out (nobody answered before the step’s timeout and the run continued without an answer). List read only; absent when the run waited on no one, or its answer was given before 2026-10.

One of approved, rejected, timed_out.

workflowNamestring

The workflow’s name. List read only.

workflowTriggerTypestring

The WORKFLOW’s configured trigger type (as opposed to this run’s triggerType). List read only.

workflowTriggerPiecestring

The PIECE the workflow starts with (form, schedule, gmailtrigger), as opposed to workflowTriggerType, which is how the platform DELIVERS it. Several apps share one type — a hosted form is delivered over a webhook — so the type alone cannot say what a person chose. Absent when the trigger has no app (manual). List read only.

stepTotalinteger

Number of step rows recorded for this run. List read only — use it to avoid fetching the detail just to count steps.

stepFailedinteger

Number of those steps with status failed. List read only.

waitStepstring

Only on a paused run: the definition step NAME that suspended the run.

resumeModestring

Only on a paused run: time = it resumes automatically at resumeAt; webhook = it waits for an external call (an approval) and will not resume on its own. An approval with a timeout is a time wait that is also answerable: read waitingOn for whether a person is waited on.

One of time, webhook.

resumeAttime

Only on a paused run with resumeMode: time: when it will resume.

waitingOnstring

Only on a paused run: person = a resume link is outstanding (an approval, a webhook resume), so someone has to answer it; time = it carries on by itself (a Delay, or a link already answered and resuming). The list’s waiting filter selects by this.

One of person, time.

claimedAttime

Only on an unfinished run a worker has taken: when it took it. A pending run with claimedAt is executing; one without it is about to be taken.

waitingForstring

Only on a waiting run held by a runs-at-once limit: workflow = its workflow is at its limit (settings.concurrencyLimit), organization = its organization is (the limit set on Platform › Organizations or by the embed API). Absent when it only waits for a free worker.

One of workflow, organization.

waitingLimitinteger

Only beside waitingFor: the limit it waits on.

linePositioninteger

Only on a waiting run: its place in its workflow’s line, 1 = next.

statestring

LIST only. The run’s state word: running covers a run in a Delay; a rejected approval is worked (see decision).

One of failed, held, running, queued, worked, cancelled.

retryOfStartedAttime

LIST only. When the run this one retried started. Absent when it is gone.

retryOutcomestring

LIST only. What retrying this run came to, over every retry descending from it: worked if any worked, else an open one’s state, else the newest one’s. Absent when never retried.

One of failed, held, running, queued, worked, cancelled.

retryAttime

LIST only. When the retry retryOutcome is about started.

decisionstring

LIST only. How the run’s last person-wait was settled (the same value as answer).

One of approved, rejected, timed_out.

decidedBystring

LIST only. Who answered from the product, never an address: a member of the workspace by their name (a member when they gave none), a former member for anyone the workspace no longer has, or token {name}. Absent for an answer through the link itself, a timeout, one from before 2026-10-19, and to an embedded person (who reads only decision).

decidedAttime

LIST only. When the last person-wait was settled.

heldSincetime

LIST only. A held run: when its current hold began. A run that held: when its last answered hold began.

heldMsinteger

LIST only. Time held on a person over every answered hold. durationMs includes it, so the run’s own time is durationMs - heldMs.

publishedVersionNumberinteger

LIST only. The workflow’s published version now. Absent for a draft.

publishedAttime

LIST only. When that version was published.

workflowStatusstring

LIST only. The workflow’s status now; absent when it was deleted.

One of active, paused, draft.

failureobject

LIST only, failed runs. The step the error names and the first clause of the reason.

stepKeystring

The step’s key; absent when the message names no step.

stepstring

Its display name in the version that ran (the draft for a test), else the key.

reasonstring

The first clause of the reason, without the step prefix, at most 160 characters.

parentWorkflowNamestring

LIST only. A sub-flow run’s caller: its workflow’s name.

parentStartedAttime

LIST only. When the calling run started.

deferredobject

Only on a read with large=defer: the run’s triggerData, when it was left out because it is over 64 KB of JSON, with its size. Read it with GET /api/runs/{id}?step=trigger. Absent otherwise.

triggerDataobject

A value this read left out because it is large: its size in bytes of JSON, as stored, and for a step’s output its head.

The same fields as data.steps.deferred.input above.

paginationobject

One of: page and limit and total and totalPages, or limit and nextCursor.

pageinteger

The page returned (1-based).

limitinteger

The page size actually applied, after clamping.

totalinteger

Total rows matching the filters, across all pages.

totalPagesinteger

Number of pages at this limit.

nextCursorstring or null

Pass as cursor for the next page; null after the last.