| Old workaround | Why it is no longer needed |
|---|---|
| Reading a save response and hoping it landed | Every write returns the stored object; a readback is one call |
| Manual re-read before an edit to dodge a race | Sending If-Match refuses a stale write instead of overwriting it |
| Guessing whether a workflow is deployed | status is in every read. A write to a deployed workflow is allowed and applies immediately, so read the status before you change a live one |
| Exporting to see whether a credential leaked into a file | The export redacts credentials and lists where |
| Rebuilding a copied workflow by hand | POST /{workflowId}/duplicate copies steps, trigger and references |
| Comparing screenshots to see what changed | Two reads compared by revision answer whether anything changed |
revision, status, the step ids and the options of the step you mean to change. Note which credentials appear in redactedPaths: those are the values you must echo back rather than retype.PATCH on a step replaces options wholesale but leaves fields you omit alone, so send only what changes. The response is the stored step and the new revision.409 VERSION_CONFLICT means someone else changed the workflow, usually a person in the canvas. meta.currentRevision is the live revision.GET /{workflowId}.If-Match.status in step 1, and use the copy routine below when the change deserves a review.POST /{workflowId}/duplicate to get a draft copy with new ids.PATCH and POST /{workflowId}/nodes on the copy until it is what you want.POST /{workflowId}/validate and POST /{workflowId}/test on the copy.POST /{workflowId}/deploy on the copy, then POST /{workflowId}/undeploy on the original.webhook again, which mints a new one, and reconfigure the copy's sender.secretsToFill.defaultValue in selector and value slots. An exported default can be a real customer identifier or a reward amount.GET /catalog and compare its platformActionFields with the keys in the export before importing.secretsToFill. Supply each one with PATCH /{workflowId}/nodes/{nodeId}. The list is kept on the server and survives a PATCH, including a rename, and each path drops out as soon as it holds a real value, so filling one credential does not clear the reminder for the rest. A later read does not show the marker itself, and an export writes the still-empty paths as ["__REDACTED__"], which is how you see what is left.POST /{workflowId}/validate reports MISSING_SECRET for any that are still empty. That is a warning, not a refusal: the deploy goes ahead with the credential empty, so fill them first.PUT /{workflowId}/trigger to give the copy its own trigger. A webhook trigger created there mints its own key; a copy that kept the source's webhook trigger keeps the source's key until you set another type and back.mode: "dry-run" test.{{stepId.path}} templates. The pairing is by step identity rather than position, so an insert after the trigger or a step inside a router branch still binds to the step it meant, and a template that points at the source's trigger or steps lands on the imported ones. Validate the copy anyway, because a reference to something outside the document has nowhere to point. The two communities' workflows can still share an external destination: an HTTP step's URL survives the import, so check every outside call before deploying the copy.| What you see | What it means | What to do |
|---|---|---|
409 VERSION_CONFLICT | Another writer got there first | Re-read, rebuild the change, resend. |
| A change landed on a live workflow that you meant to stage | The API does not gate edits to a deployed workflow | Use the copy routine, and read status before every write. |
400 REDACTED_VALUE_WITHOUT_STORED_SECRET | A marker arrived where nothing is stored | Send the real value. |
| An HTTP step now calls the wrong host, still carrying a stored credential | The marker is restored by path, so the credential follows the URL | Repoint the step and replace the credential rather than echoing the marker. |
MISSING_SECRET after an import | A credential the import blanked is still empty | Patch that step with a real value. |
| The copy behaves differently from the source | A field, role or identifier the target community does not have | Compare the steps and the target's field keys. |
| The canvas editor shows unsaved changes on an API-built step | The editor fills a default the API did not store | Save deliberately in the canvas, then re-read and compare. |
If-Match.