Go back to a version
POST/
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 · UUIDThe workflow’s ID.
versionIdRequired · UUIDThe version to bring back.
Body
Optional.
expectedRevOptional · integerThe
definitionRevyou 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.
hasUnpublishedChangessays whether that differs from what is live. idorversionIdisn’t a UUID, orexpectedRevisn’t a whole number.- 403
FORBIDDENThe token lacks the Write permission for workflows.
- 404
NOT_FOUNDNo such workflow in the workspace, or the version isn’t one of its own.
- 409
CONFLICTexpectedRevis out of date: someone saved since. Nothing changed. Read the workflow again. - 409
CONFLICTAnother 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
}'const GORUNNER = "https://api.gorunner.io";
const TOKEN = process.env.GORUNNER_TOKEN;
const WORKFLOW_ID = process.env.WORKFLOW_ID;
const VERSION_ID = process.env.VERSION_ID; // from List versions
const res = await fetch(
`${GORUNNER}/api/workflows/${WORKFLOW_ID}/` +
`versions/${VERSION_ID}/restore`,
{
method: "POST",
headers: {
Authorization: `Bearer ${TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ expectedRev: 8 }),
},
);
const { data } = await res.json();import os, requests
GORUNNER = "https://api.gorunner.io"
TOKEN = os.environ["GORUNNER_TOKEN"]
WORKFLOW_ID = os.environ["WORKFLOW_ID"]
VERSION_ID = os.environ["VERSION_ID"] # from List versions
res = requests.post(
f"{GORUNNER}/api/workflows/{WORKFLOW_ID}/"
f"versions/{VERSION_ID}/restore",
headers={"Authorization": f"Bearer {TOKEN}"},
json={"expectedRev": 8},
)
data = res.json()["data"]Response · 200 OK, shortened
{
"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 · integerThe 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
dataobjectA workflow.
definitionis the DRAFT — what the editor saves into. Production executes the snapshot named bylatestVersionIdinstead, which is whyhasUnpublishedChangesmatters.idUUIDnamestringdescriptionstringdefinitionobjectThe 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 flatactionsarray is not a definition and would execute nothing.A workflow definition: its fields are in Workflow definition.
statusstringdraft= never published.active= live, triggers registered, public webhook reachable.paused= was live, toggled off.One of
draft,active,paused.triggerTypestringDerived from the definition’s trigger on every write. Only
webhookworkflows have awebhookToken.One of
manual,cron,webhook,error,run_finished,poll.cronExpressionstring or nullwebhookTokenstring or nullThe 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 byPOST /api/workflows/{id}/webhook/rotate. Present here only for a credential holdingworkflow:run; redacted below that, and never present in the workflow LIST.latestVersionIdUUID or nullThe published snapshot production runs. Null until first publish.
definitionRevintegerOptimistic-lock revision, bumped on every save. Pass it back as
expectedRevto make a write conditional. Present on the single-workflow read and on write responses; absent (0) in lists.hasUnpublishedChangesbooleanTrue 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 nulltagsarray of stringstestPayloadsobject or nullSaved test fixtures. Stored outside the definition, so publish/restore never resets them.
pinnedDataobject or nullFrozen step outputs replayed instead of executing, TEST runs only. Stored outside the definition.
workspaceIdUUIDorgIdUUIDcreatedByUUID or nullcreatedAttimeupdatedAttime