English
Draft, published version and history
Every workflow has two sides: the draft, which you edit in the editor, and the published version, which is what triggers actually run. Editing never changes what runs; only publishing does. This page explains how the draft is saved, what publishing checks and does, how to read and restore earlier versions, and which version a run uses.
The graph itself and the publish check are described in Workflows.
Draft and published version
A workflow points to at most two versions:
| Draft | Published version | |
|---|---|---|
| What it is | the graph you are editing | the graph that triggers run |
| Changes | every time you edit | never: a published version is frozen |
| Runs | only in test runs | every live run |
| How many | one | at most one at a time |
A version is a numbered copy of the graph (Version 1, Version 2…). A new workflow starts with an empty draft, version 1. As long as the draft has never been published, saving overwrites it and its number stays the same. Publishing freezes the draft as it is: the version keeps its number and can no longer be changed. The next change you make after publishing opens a new draft with the next number.
Version numbers therefore count drafts, not publications: "Version 4" is not necessarily the fourth publication, and the current draft has its own number in the list.
Some settings belong to the workflow rather than to a version, and change without republishing: the pause, the rank used by your trigger policy, the webhook URL and the error workflow.
Automatic saving
There is no Save button. The editor saves the draft on its own about a second and a half after your last change. The save state is shown next to the workflow name: "Changes pending…", "Saving…", "Saved at {time}", or "Saving failed".
- Saving never blocks. A draft with errors is saved anyway: a workflow under construction is rarely complete. Errors only block a test run and publishing.
- Leaving the page triggers a last save. If it fails, a dialog "Leave without saving?" offers "Try saving again", "Stay on the page" or "Leave without saving".
- Two editors on the same draft. If the draft was changed elsewhere (another tab or another member) since you opened it, nothing is overwritten: the state shows "Changed elsewhere", automatic saving stops, and you choose between "Reload their version" and "Keep my version" (which overwrites the other change).
Through the API, the draft is read with GET /api/v1/workflows/:id/draft and saved with PUT /api/v1/workflows/:id/draft and a body { "graph": { … } }. Add "expectedDraft": { "id": …, "updatedAt": … } (the values returned by the previous read) to have the save refused with 409 workflow.draft_conflict if someone else wrote in the meantime.
Publishing
Click Publish in the editor. The "Publish the workflow" dialog shows, in order:
- the blocking errors, if any: the Publish button stays disabled until they are fixed;
- What changes: the differences from the live version, or "First publication: the whole workflow goes live.";
- What happens once published: one sentence per trigger, for example "“Email received” will start on every new email that matches its conditions." or "a webhook URL will be generated. It is shown only once, in the trigger's panel.";
- the warnings, which do not block.
The button reads "Publish" for a first publication, "Publish changes ({count})" when the draft differs from the live version, and "Published" (disabled) when there is nothing to publish.
What the server checks, in this order:
| Check | Refusal |
|---|---|
| The workflow is archived | 409 workflow.archived |
| The draft has blocking errors (warnings never block) | 422 workflow.not_publishable, with the list of errors |
| The organisation's node policy forbids a node of the graph | workflow.forbidden_node (see Governance) |
workflow.call nodes would form a loop of calls | 422 workflow.call_cycle |
The errors and warnings themselves are listed in Workflows.
What publishing does, in one go: it freezes the draft as the published version, then arms the triggers — email triggers on every mailbox you own that is not disconnected, schedules, polling triggers, and the webhook URL. The webhook URL is generated at the first publication only: republishing keeps the same URL. A paused workflow stays paused after publishing ("it stays paused after publishing. Resume it for it to trigger.").
Through the API: POST /api/v1/workflows/:id/publish. The response carries ok, validation, publishedVersion, armedMailboxes and, for a webhook workflow published for the first time, the webhook URL and its token.
What changed since publishing
When the draft differs from the live version, the editor shows an Unpublished changes badge. Click it ("See what changed") to list the differences:
| Difference | Shown as |
|---|---|
| A node was added | Node added: {name}. |
| A node was removed | Node removed: {name}. |
| A node was renamed | Node renamed: {name}. |
| A node's settings changed | Settings changed: {name}. |
| Links between nodes changed | The links between nodes changed. |
Moving a node on the canvas does not count as a change. The same comparison appears in the Publish dialog under "What changes".
The workflow list also shows "Unpublished changes" next to a workflow whose draft has been saved since the last publication. That badge is based on saving, not on the comparison above: it can appear after you only moved a node, while the editor shows no difference.
The Versions panel
Open Versions from the editor's "⋯" menu. The panel lists the versions of the workflow, newest first — at most the last 50 — with:
- the number ("Version {number}");
- a date: "Published on {date}" for a published version, "Draft edited on {date}" for the draft;
- a badge: Live for the version that triggers run, Current draft for the draft you are editing.
Expand a version to compare it with the current draft: "Same as the current draft.", or "Restoring this version would change {count} items:" followed by the differences, in the same terms as above. Versions can only be compared with the current draft, not with each other.
A version records no author and no comment.
Through the API: GET /api/v1/workflows/:id/versions lists the versions (id, number, publishedAt — null for the draft —, createdAt, updatedAt), and GET /api/v1/workflows/:id/versions/:versionId/graph returns the frozen graph of one version.
Restoring an earlier version
Restore as draft copies an earlier version into the draft. It never publishes anything: the live version keeps running until you publish again.
- Open Versions from the "⋯" menu.
- Expand the version you want, and check what would change.
- Click Restore as draft, then confirm. The dialog warns: "The current draft is replaced by this version, and its unpublished changes are lost. The live version does not change until you publish."
- Check the restored draft, run a test if needed, then Publish.
The button is disabled when the version is identical to the draft, and on an archived workflow. In the editor, restoring also clears the undo history.
Rolling back a live workflow is therefore two steps: restore the earlier version as the draft, then publish it. It goes live under a new version number; the history keeps every version.
Through the API: POST /api/v1/workflows/:id/versions/:versionId/restore. It replaces the draft without any concurrency check, and returns the new draft and its validation. On an archived workflow it answers 409 workflow.archived.
Which version a run uses
Every run is tied to the version it started on, and keeps it until the end:
- Republishing changes nothing for runs in progress. A run that started on version 3 finishes on version 3, even if version 5 is published in the meantime. This includes runs that resume later: after a wait or an approval, the following steps still use the graph of version 3.
- New runs use the version published at the moment they start. An email that arrives after the publication runs the new version.
- One run per email and per version. The same email never starts the same published version twice. A different version is a different version: republishing can process again an email that the previous version had already seen, if it is delivered again.
- Manual runs from the webmail ("Run a workflow") always use the current published version.
- Sub-workflows called with Call a workflow run the version of the called workflow that is published at the moment of the call.
- Replaying a failed run (see Error handling and replay) is only possible while the version it ran on is still the published one. After a republish or an unpublish, the replay is refused with
execution.version_unavailable.
Pausing, unpublishing, archiving
| Action | Where | Triggers | Published version | Runs in progress |
|---|---|---|---|---|
| Pause / Resume | editor | no new run starts from emails, schedules or polling triggers; nothing is disarmed | unchanged | finish |
| Unpublish | editor, "⋯" menu | all disarmed: no email, webhook call or schedule starts it | withdrawn; the workflow shows as Draft | finish |
| Archive / Unarchive | workflow list | all disarmed; unarchiving re-arms nothing | withdrawn | finish |
| Delete | workflow list | — | — | — |
- Unpublish opens a dialog that offers "Pause instead": a pause can be undone with one click on Resume, while an unpublished workflow must be published again. Either way, "runs already in progress finish."
- Archived workflows cannot be published or restored. Unarchive one from the workflow list, then publish it again.
- Delete is only possible for a workflow that has never been published and has never run. Otherwise the server refuses with
workflow.delete_forbidden: archive it instead. - None of these actions cancels a run that is already running. To hold back emails that are about to be sent, an administrator can stop sending for the whole organisation (see Governance).
The status shown in the workflow list is, by priority: Archived, Paused, Published, Draft. Old versions are never purged: they are deleted only with the workflow itself.
Duplicating, importing and exporting
- Duplicate (workflow list, or the editor's "⋯" menu) creates a new workflow, "Copy of {name}", from the draft of the source — not from its live version. The copy is a draft that has never been published. It takes neither the runs, nor the test emails, nor the webhook URL of the source. Through the API:
POST /api/v1/workflows/:id/duplicatewith{ "name": … }. - There is no file import or export in the editor. Through the API, read a graph with
GET /api/v1/workflows/:id/draft(or the graph of a version), and create a workflow from a graph withPOST /api/v1/workflows, whose body accepts an optionalgraph. The graph is attached to the new workflow and its first version. See the API reference.