Update a workflow's draft
workflow:writeUpdates the DRAFT. On a published workflow this changes NOTHING in production until you call POST /api/workflows/{id}/publish — the live triggers keep running the published snapshot.
The update is a partial merge: an ABSENT field is left alone. description is the one field where an explicit "" clears it (absent = keep, empty string = clear). Sending definition replaces the WHOLE tree — there is no per-step patch; read the workflow, modify the tree, send it back whole.
A supplied definition is validated in this order: unknown keys anywhere in the tree are refused (400); any webhookToken inside it is stripped (the token lives in its own column and must never be written through a definition); the tree is checked for a named trigger, duplicate/blank step names and legal action types (400); and if the workflow is currently ACTIVE, every piece and action reference must exist on the live worker fleet (422) so a live flow cannot be silently broken. Steps without an explicit pieceVersion are then pinned to the version the fleet serves.
Server-owned fields in the body are ignored: status, webhookToken, latestVersionId, definitionRev, workspaceId, orgId, and also folderId and tags (those have dedicated routes). Writes to one workflow are serialised across the fleet, so a concurrent write may answer 409 — retry it.
Authorization
bearerAuth An API token: Authorization: Bearer grt_…. Mint one in the app under Settings → Workspace → API tokens; the raw value is shown once. Scopes confine the token — see x-permission on each operation.
In: header
Path Parameters
Workflow id. A value that is not a UUID is a 400, not a 404.
uuidRequest Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X PUT "https://example.com/api/workflows/497f6eca-6276-4993-bfeb-53cbbbba6f08" \ -H "Content-Type: application/json" \ -d '{ "name": "Order intake", "expectedRev": 7, "definition": { "schemaVersion": 2, "trigger": { "name": "trigger", "type": "webhook", "pieceId": "webhook", "actionId": "catch_webhook", "config": { "methods": [ "POST" ] }, "valid": true }, "settings": { "timeoutSeconds": 120 } } }'{ "data": { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "name": "string", "description": "string", "definition": { "schemaVersion": 2, "trigger": { "name": "string", "displayName": "string", "type": "manual", "pieceId": "string", "pieceVersion": "string", "actionId": "string", "config": {}, "connectionId": "string", "valid": true, "nextAction": { "name": "string", "displayName": "string", "type": "PIECE", "pieceId": "string", "pieceVersion": "string", "actionId": "string", "config": {}, "connectionId": "string", "valid": true, "skip": true, "nextAction": {}, "branches": [ { "name": "string", "conditions": [ [ { "field": "string", "operator": "text_eq", "value": null } ] ], "firstAction": {} } ], "firstLoopAction": {}, "onErrorAction": {} } }, "settings": { "timeoutSeconds": 0, "errorWorkflowId": "51d8ee47-3646-4ae6-bc48-c85415c9166a", "concurrencyLimit": 0, "maintenanceMode": true, "autoPublishFixes": true }, "annotations": null, "variables": {}, "pinnedData": {} }, "status": "draft", "triggerType": "manual", "cronExpression": "string", "webhookToken": "string", "latestVersionId": "750445c5-7ad9-40bd-a593-bb37d7d846db", "definitionRev": 0, "hasUnpublishedChanges": true, "folderId": "5b6379a4-2a6c-4085-b184-45838a3b8e7e", "tags": [ "string" ], "testPayloads": {}, "pinnedData": {}, "workspaceId": "ef0efa32-d1c1-43d4-a5e2-fe7b4f00403c", "orgId": "25b2c2d5-a7fc-47d0-89e4-8709a1560bfa", "createdBy": "25a02396-1048-48f9-bf93-102d2fb7895e", "createdAt": "2019-08-24T14:15:22Z", "updatedAt": "2019-08-24T14:15:22Z", "lastRun": { "status": "pending", "startedAt": "2019-08-24T14:15:22Z" } }}