GoRunner docs
Search or askSearch⌘K

Go back to a version

POST/api/workflows/{id}/versions/{versionId}/restore

Copies a published version into the draft. What runs live doesn’t change until you publish.

Needs an API token with the Write permission for workflows (workflow:write).

Parameters

Path

idRequired · UUID

The workflow’s ID.

versionIdRequired · UUID

The version to bring back.

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 changes

Only the draft. Restore is checked like a save, so an old version that can’t run is refused here, not at the next publish. Then publish to put it live.

Test data and pins are kept apart from the tree, so they survive. Pins whose steps changed are marked stale. triggerType follows the restored tree, and a webhook workflow with no token gets one.

Responses

  • 200OK

    The workflow with the version as its draft. hasUnpublishedChanges says whether that differs from what is live.

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

  • The token lacks the Write permission for workflows.

  • No such workflow in the workspace, or the version isn’t one of its own.

  • 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 version fails the checks a save makes, such as an app this installation can no longer run on a live workflow.

  • The version has a step on an app this workspace may not use, and the draft doesn’t.

  • Nothing was written. Try again.

  • GoRunner couldn’t check which apps this workspace may use. Nothing changed. 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 Write for workflows
WORKFLOW_ID="your-workflow-id"
VERSION_ID="your-version-id"  # from List versions

URL="$GORUNNER/api/workflows/$WORKFLOW_ID/versions/"
URL="${URL}$VERSION_ID/restore"
curl -X POST "$URL" \
  -H "Authorization: Bearer $GORUNNER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "expectedRev": 8
  }'

Response · 200 OK, shortened

json
{
  "data": {
    "id": "3b1e5c2a-7d4f-4e8b-a1c6-5f2d9b0e7a31",
    "name": "Order intake",
    "definition": {
      "schemaVersion": 2,
      "trigger": {
        "name": "trigger",
        "displayName": "Order received",
        "type": "webhook",
        "pieceId": "webhook",
        "pieceVersion": "1.0.0",
        "actionId": "catch_webhook",
        "config": {
          "methods": [
            "POST"
          ]
        },
        "valid": true,
        "nextAction": {
          "name": "forward",
          "displayName": "Forward to fulfilment",
          "type": "PIECE",
          "pieceId": "http",
          "pieceVersion": "1.0.0",
          "actionId": "send_request",
          "config": {
            "method": "POST",
            "url": "https://example.com/fulfilment",
            "body_type": "json",
            "body_json": "{{trigger.body}}"
          },
          "valid": true
        }
      },
      "settings": {}
    },
    "status": "active",
    "latestVersionId": "f20f671a-2c8e-4b9d-a7f1-6e3b0d5c9a12",
    "definitionRev": 9,
    "hasUnpublishedChanges": true
  }
}
Every field

Body

expectedRevOptional · integer

The workflow’s current definitionRev. Makes the restore conditional: a draft that moved underneath you gives 409 and writes nothing. Omit — or send 0 or less, which is ignored — for an unconditional restore.

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