GoRunner docs
Search or askSearch⌘K

Unpublish a workflow

POST/api/workflows/{id}/unpublish

Takes a workflow offline: its triggers stop, and its draft and versions stay.

Needs an API token with the Publish permission for workflows (workflow:publish).

Parameters

Path

idRequired · UUID

The workflow’s ID.

Body

Optional.

expectedRevOptional · integer

The definitionRev you read. If the draft changed since, nothing happens and you get 409. Left out, 0 or less: no check.

What stops, and what stays

Schedules skip it, and its webhook address answers 404. Runs already going are not cancelled.

The webhook address stays the same, so publishing again brings it back. A self-registering trigger is signed off from its service. A trigger that checks a service for new items starts from now when you publish again, not from where it stopped.

Its runs waiting in line stay. Cancel them if you don’t want them.

Responses

  • 200OK

    Paused. A paused workflow answers 200 as it is, and a draft stays a draft.

  • id isn’t a UUID, or expectedRev isn’t a whole number.

  • The token lacks the Publish permission for workflows.

  • Only Keel’s own publish card sends this: a write no person clicked. An API call never gets it.

  • No workflow with this ID in the token’s workspace.

  • expectedRev is out of date: someone saved since. Nothing changed. Read the workflow again.

  • Another write to this workflow took too long. Try again.

  • The workflow is still live. 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 · 413 PAYLOAD_TOO_LARGE · 415 INVALID_CONTENT_TYPE · 429 RATE_LIMITED · 503 BUSY · 503 PAUSED · 503 SERVICE_UNAVAILABLE. See Errors.

Request

GORUNNER="https://api.gorunner.io"
GORUNNER_TOKEN="grt_…"  # needs Publish for workflows
WORKFLOW_ID="your-workflow-id"

URL="$GORUNNER/api/workflows/$WORKFLOW_ID/unpublish"
curl -X POST "$URL" \
  -H "Authorization: Bearer $GORUNNER_TOKEN"

Response · 200 OK, shortened

json
{
  "data": {
    "id": "3b1e5c2a-7d4f-4e8b-a1c6-5f2d9b0e7a31",
    "name": "Order intake",
    "status": "paused",
    "triggerType": "webhook",
    "latestVersionId": "f20f671a-2c8e-4b9d-a7f1-6e3b0d5c9a12",
    "definitionRev": 7,
    "updatedAt": "2026-10-24T16:40:00Z"
  }
}
Every field

Body

expectedRevOptional · integer

The definitionRev of the draft the caller holds. Makes the write conditional: a draft that moved since gives 409 and nothing is written. Omit — or send 0 or less, which is ignored — for an unconditional write.

Response · 200 OK

dataobject

A workflow. definition is the DRAFT — what the editor saves into. Production executes the snapshot named by latestVersionId instead, which is why hasUnpublishedChanges matters.

idUUID
namestring
descriptionstring
definitionobject

The workflow definition. It is a TREE, not a list of steps: the trigger holds nextAction, each action holds the next one, and branches/loops/error paths nest their own sub-chains. A flat actions array is not a definition and would execute nothing.

A workflow definition: its fields are in Workflow definition.

statusstring

draft = never published. active = live, triggers registered, public webhook reachable. paused = was live, toggled off.

One of draft, active, paused.

triggerTypestring

Derived from the definition’s trigger on every write. Only webhook workflows have a webhookToken.

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

cronExpressionstring or null
webhookTokenstring or null

The workflow’s public production door. POST /api/webhooks/{webhookToken} is UNAUTHENTICATED — the unguessable URL is the credential. Minted by publish for a webhook workflow, revoked and replaced by POST /api/workflows/{id}/webhook/rotate. Present here only for a credential holding workflow:run; redacted below that, and never present in the workflow LIST.

latestVersionIdUUID or null

The published snapshot production runs. Null until first publish.

definitionRevinteger

Optimistic-lock revision, bumped on every save. Pass it back as expectedRev to make a write conditional. Present on the single-workflow read and on write responses; absent (0) in lists.

hasUnpublishedChangesboolean

True when the draft has moved ahead of what is live. Computed in SQL, so it is exact — undoing an edit back to the published bytes reads false again.

folderIdUUID or null
tagsarray of strings
testPayloadsobject or null

Saved test fixtures. Stored outside the definition, so publish/restore never resets them.

pinnedDataobject or null

Frozen step outputs replayed instead of executing, TEST runs only. Stored outside the definition.

workspaceIdUUID
orgIdUUID
createdByUUID or null
createdAttime
updatedAttime