GoRunner docs
Search or askSearch⌘K

Get a workflow

GET/api/workflows/{id}

Returns one workflow, with its draft definition.

Needs an API token with the Read permission for workflows (workflow:read).

Parameters

Path

idRequired · UUID

The workflow’s ID.

Draft and live

definition is the draft, the version being edited. Production runs the published version, latestVersionId. hasUnpublishedChanges says the draft has moved on since.

The definition comes back with what GoRunner fills in on a save: a branch’s or loop’s pieceId, a branch’s config.executionMode and config.branches, and every valid. The stored draft isn’t changed, and saving it back as it came changes nothing.

status is draft (never published), active (live) or paused (was live, now off). updatedAt changes with edits only: publishing, pausing, tagging and filing leave it.

Keep definitionRev, and send it back as expectedRev when you update the draft, so you never overwrite someone else’s save.

webhookToken is the secret part of the webhook address. Only a token with the Run permission for workflows gets it. A field that holds a secret, such as a password, always reads [hidden secret: kept as set].

sourceTemplate names the template it was made from, while you can still see that template.

Responses

  • 200OK

    The workflow.

  • id isn’t a UUID.

  • The token lacks the Read permission for workflows.

  • No workflow with this ID in the token’s workspace. A workflow in another workspace is a 404 too.

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 workflows
WORKFLOW_ID="your-workflow-id"

curl "$GORUNNER/api/workflows/$WORKFLOW_ID" \
  -H "Authorization: Bearer $GORUNNER_TOKEN"

Response · 200 OK, shortened

json
{
  "data": {
    "id": "3b1e5c2a-7d4f-4e8b-a1c6-5f2d9b0e7a31",
    "name": "Order intake",
    "definition": { … },
    "status": "active",
    "definitionRev": 7,
    "webhookToken": "2f4c8e1a-6b3d-4f7e-9a05-c1d2e3f4a5b6",
    "latestVersionId": "f20f671a-2c8e-4b9d-a7f1-6e3b0d5c9a12",
    "hasUnpublishedChanges": false,
    "updatedAt": "2026-10-24T16:40:00Z",
    "sourceTemplate": null
  }
}
Every field

It takes no body.

Response · 200 OK

dataobject
idUUID
namestring
descriptionstring
definitionobject

The workflow definition, and the single most important shape in this API.

A workflow definition: its fields are in Workflow definition.

statusstring

draft = never published. active = live, triggers registered and the webhook URL reachable. paused = was live, now switched off. Server-owned: it moves only through publish/unpublish, never through a create or update body.

One of draft, active, paused.

triggerTypestring

Mirrors definition.trigger.type for dispatch. Derived server-side from the definition by every update and publish, so treat it as read-only in practice. A create that sends its own value keeps it until then, unchecked.

One of manual, cron, webhook, callable, event, error, run_finished, poll.

cronExpressionstring or null

Nothing derives or reads this: the schedule runs from the trigger’s own config, and nextRunAt projects from it too. Null unless a caller wrote one with PUT /api/workflows/{id}.

webhookTokenstring or null

The secret segment of the public webhook URL. Made by the first update of a webhook workflow, or at publish; absent until then (so absent in the answers of create, duplicate and import). Returned ONLY to a caller holding workflow:run: by GET /api/workflows/{id} and in the answers of update, publish, unpublish and restore (rotate answers it to its caller). It is never present on a list row, an export or a version snapshot. It is a bearer capability against an unauthenticated endpoint — possessing it is the ability to fire this workflow in production. Rotate it with POST /api/workflows/{id}/webhook/rotate.

latestVersionIdUUID or null

The published snapshot production executes. Absent means nothing has ever been published.

definitionRevinteger

Optimistic-lock revision, bumped by every definition save. Populated by GET /api/workflows/{id}, by the update response and by the answers of create, duplicate and import; absent (0) on list rows. Send it back as expectedRev on an update to refuse a clobbering write.

hasUnpublishedChangesboolean

The draft has moved ahead of the published version. Computed on the single-workflow read and on every list row; always false for a workflow never published.

folderIdUUID or null

Absent/null = uncategorized. Changed only through PUT /api/workflows/{id}/folder.

tagsarray of strings

Changed only through PUT /api/workflows/{id}/tags or the bulk addTags operation — never through the workflow update body.

testPayloadsobject or null

The saved test-fixture library, stored outside the definition so publish and version restore never reset it.

pinnedDataobject or null

The pin library ({"pins": {"<stepName>": {"data": …, "pinnedAt": …, "configHash": …, "staleAt": …, "pieceId": …}}}). A pinned step emits its fixture instead of executing, and only on test runs. configHash, staleAt and pieceId are the server’s: a step whose config changed keeps its pin marked stale, and a stale pin is not replayed (the step runs); a step whose app was replaced loses it.

workspaceIdUUID

Stamped from the credential’s scope; never accepted from a request body.

orgIdUUID
createdByUUID or null
createdByNamestring

List rows only: the creator’s name, else their email address. Absent when the creator is unknown or not a member of the organization (staff who built it on a support visit, someone since removed), and on every row for an embedded person whose installation switched presence off (an embedded person is never told an address).

createdAttime
updatedAttime

When the workflow itself was last edited. Publishing, pausing, tagging and filing it are not edits and leave it alone.

failingboolean

List rows only: the workflow is live (status: active) and its latest FINISHED production run (one that worked or failed) failed. A later run that is waiting, running, held or was cancelled changes nothing, and test runs never count. A paused or draft workflow is never failing.

failingSincetime

Only on a failing row: when the first production run failed after the last one that worked (runs cancelled, held or running in between neither break nor begin the streak). Left out for a caller without run:read.

failingRunobject

Only on a failing row: the run that decided it, its latest finished production run, with why it failed. It is lastRun unless a later run is waiting, running, held or was cancelled. Without run:read it carries status and startedAt alone.

idUUID
statusstring

One of failed.

startedAttime
finishedAttime or null
errorobject

Why it failed, as lastRun.error says it.

stepstring or null
stepKeystring or null
messagestring
summaryobject

List rows only: what a list draws instead of the definition.

triggerobject or null

The chosen trigger; null while none is chosen.

pieceIdstring
actionIdstring
displayNamestring
piecesarray of objects

The apps the workflow uses, each once, in walk order (the trigger first), with their display names.

idstring
namestring
stepCountinteger

Steps after the trigger, across branch arms, loop bodies and error paths.

needsSetupinteger

Steps (and a chosen trigger) the editor marks to configure: valid: false, or no app and action chosen.

runs7darray of integers

List rows without view=summary only: counted runs per UTC day over the last seven days, oldest first (production runs that are not a sub-flow’s, cancelled runs left out).

nextRunAttime

Next fire time of an active schedule workflow, projected from its cron in the trigger’s own timezone. Populated by the list endpoint.

lastRunobject or null

The most recent PRODUCTION run’s outcome (test runs never count). Populated on list rows only. Without run:read it carries status and startedAt alone.

idUUID
finishedAttime or null
errorobject

Only when status is failed: why.

stepstring or null

The display name of the step it failed at; null when the reason names no step.

stepKeystring or null
messagestring

The reason’s first clause, at most 160 characters.

statusstring

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

startedAttime
sourceTemplateobject or null

The template this workflow was made from, while it exists and the caller may see it (the gallery’s own rule: this organization’s, this customer workspace’s, or an installation template still offered); null otherwise. Only this read carries it.

idUUID
namestring
triggerSubscriptionobject

The trigger’s registration with its provider, for a vendor webhook trigger that registers itself on publish (absent otherwise): registering, active, or failed with the provider’s refusal in lastError and the next try in nextAttemptAt. A subscription that expires (expiresAt) is renewed by the workers before it does. Only this read carries it.

statestring

One of registering, active, failed.

piecestring
lastErrorstring
lastErrorAttime
nextAttemptAttime
expiresAttime
registeredAttime
detailsobject

What the registration listens to, by the provider’s own ids — only safe facts, per app: GitHub owner/repository, GitLab project, Asana resource/workspace, ClickUp team, Jira site, Linear teamId, Trello idModel, Mailchimp list, Pipedrive object/action, Shopify topic, Calendly scope/organization/user, Typeform formId/tag, Tally and Jotform formId, Twilio phoneNumber, WhatsApp phoneNumberId/businessAccountId. Absent when there is none. Never a secret or an address that carries one.

{key}string

Each key’s value.

requestUrlstring

For a trigger whose app sends every event to one address (Slack with your own Slack app): the Request URL to paste into the app’s Event Subscriptions once. Not a secret: every delivery is verified with the app’s Signing Secret.