Workflows
PaidBuild an automation on a canvas: one trigger, conditions, and steps that act, with every firing recorded step by step in run history.
A reacts to a Carbon event by evaluating conditions and running actions. Examples include notifying an account manager after a sales-order assignment, creating an issue when a job is put on hold, or calling an external service after shipment posting. Build the workflow under Automate → Workflows by connecting one trigger to condition and action cards, then select "Publish". A trigger can fan out into multiple branches. Carbon records each execution in runs and history.
What starts a workflow
Every workflow has exactly one Trigger step, and it works one of two ways. The "Trigger type" toggle picks between "Event" and "Schedule"; choosing one clears the other.
Events. An event is a specific change to a specific record:
| Shape | Example | What you get |
|---|---|---|
| Created | job.created | The new record |
| Deleted | purchaseOrder.deleted | The record as it was |
| A column changed | customer.assignee.changed | The record, plus its before and after values |
There is no generic “updated” event
You pick the exact field you care about. Ten record types can be watched — purchase orders, sales orders, jobs, items, receipts, shipments, quotes, suppliers, customers, and issues — each with its own short list of watched fields. A change to a field nobody watches starts nothing at all.
Business moments. Below the per-record events, the picker has one group headed "Business moments": the nine points in Carbon's own flows where something meaningful finished: a job released or put on hold, a job operation completed, a quote sent or accepted, a receipt or shipment posted, a sales or purchase invoice posted. A hands your workflow the identity of each record, not a copy of its fields; add a Find step when you need to read something the moment didn't name.
Schedules. In "Schedule" mode you pick a "Frequency" of Daily, Weekly, or Monthly, the days it applies to, a "Time of day", and a "Timezone"; the builder shows a live "Next fires at:" line as you change it.
Schedules never catch up
Carbon stores the wall-clock time and time zone separately, so 09:00 remains 09:00 across daylight-saving changes. A monthly schedule on day 31 skips months without that date. After an outage, Carbon resumes at the next due time and records runs more than one hour late as skipped. A fixed offset of up to five minutes spreads load, so a 09:00 schedule runs between 09:00 and 09:05.
"Triggered by". Event triggers also choose who caused the change: "People", "Workflows", or "Both". A new trigger starts at "People", which is the safe answer: it stops a workflow from reacting to edits made by workflows, including its own. Switch it to "Both" deliberately, when you want one automation to feed another.
The steps you can add
Seven kinds, in palette order:
| Step | What it does |
|---|---|
| Trigger | Starts the workflow. One per workflow, and nothing can connect into it. |
| Condition | Sends the run down one path. Each path is a set of clauses, with an optional "Otherwise". |
| Action | Does the work — notifies, creates, updates, or calls out. Has separate Success and Failure handles. |
| Integration | Runs a step in a connected app — Google Calendar, Gmail, or Slack — acting as an account you connected. |
| Compute | Works out a number from a record, such as an order total or a scrap percentage. Read-only. |
| Find | Looks a record up so later steps can use it. |
| Filter | Keeps only the items in a list that match your rules. |
Actions come in three families. Four create records (a job, an issue, a purchase order, or a sales order), each through the same service Carbon's own screens use, so sequences, defaults, and required fields behave identically. Ten update an existing record, one per watched record type. The last two are "Notify someone" and "Call an outside URL".
Updates are deliberately narrow
An update step can only set the fields Carbon lists for that record: an assignee, a due date, a reference, a priority. Statuses are not writable from a workflow, and there is no delete action of any kind. What a workflow can watch and what it can write are two different lists.
Filling in a step
Most fields take either a value you type or a value from an earlier step. Type { in a text field and a menu opens listing the steps above this one, their outputs, and up to two levels of properties. Only steps guaranteed to have run before this one are offered — a value from the other side of a condition is not on the menu, and referring to one is rejected at publish.
Repeating steps. Connecting a list to a single-value field runs the step once per item, up to 100 items. The form displays this behavior. Connecting two lists to one step causes a publish-time error because the loop source is ambiguous.
Steps in connected apps
An Integration step acts in an outside app. Drop one on the canvas, pick the "App", then the "Step" — "Gmail: Send Email", "Slack: Send Message To A Channel", "Google Calendar: Create Event", and so on. The apps themselves, and the accounts they act as, are set up under Settings → Integrations; see workflow apps.
An app you haven't connected offers no steps. The form says so — "… isn't connected yet. Connect an account before this step can use it." — with a "Connect" button that opens the app's card in a new tab, so the canvas survives the detour.
Which account acts. Every step of an app carries an account choice. With exactly one account connected the field doesn't render, but the account is still stored on the step — so connecting a second account later never silently repoints existing workflows. If a step's stored account was disconnected or needs reconnecting, the form shows a banner with an "Open … accounts" link rather than failing quietly at run time.
Advanced properties. Fields the vendor requires but you rarely change sit in a collapsed "Advanced properties" section, pre-filled with sensible values. A value you set there wins over the default.
Records become links where the app can show them. Drop a record into a Slack message or a Gmail body and the recipient gets a clickable link back to that record in Carbon. Where the destination can't render a link — or a setting has turned it off, such as switching Gmail's body to plain text — the record appears as its plain name, and the builder says so under the field: "Records here appear as plain text …".
The vendor's answer is the step's outcome
An integration step runs as the connected account, not as the workflow's owner, on the vendor's side. If the vendor refuses, the step fails with the vendor's own message in run history; if the account is missing a permission, the message instead points you to the fix — reconnect the account under the app's "Accounts" tab.
Everything else works like an action: variables and the Success and Failure handles. The one exception is repeating — an integration step doesn't yet run once per item when a list is wired into a single-value field, so the builder flags that wiring instead of guessing.
Calling an outside URL
The "Call an outside URL" action sends an HTTP request, a , so another system can react to something in Carbon.
https address to call. Variables are allowed, so the address can include a record's id.GET, POST, PUT, PATCH, or DELETE. A new step starts at GET.POST, PUT, and PATCH.What the webhook step refuses to do
Plain http is rejected, and so is any address resolving to a private or link-local network, localhost and cloud metadata endpoints included. Redirects are not followed, the call gives up after ten seconds, and any answer that isn't a success status fails the step. Eight headers are set by Carbon and cannot be overridden. Carbon does not sign the request — if the receiving system needs to verify the caller, give it a shared secret in a header.
Saving, publishing, and versions
There is no Save button: the builder saves as you work and reports "Saving…", "Saved", or "Could not save" next to the title. A half-finished draft saves happily; nothing is checked until you publish.
"Publish" is all-or-nothing. Carbon validates the whole workflow — a trigger exists, no step loops back, every required field is filled, every variable resolves and comes from upstream — and if anything is wrong, nothing is written; the problems appear in a panel and clicking one pans the canvas to the offending step. Publishing is also the only on/off switch: whichever version you publish is the one that runs, and "Unpublish" stops the workflow entirely. Nothing is deleted, so publishing again starts it back up. A workflow with nothing published reads as Draft.
Publishing freezes that version. To keep working, use the version menu to create a new version, which copies the published one and numbers it one higher. A run already in flight keeps using the version it started with even if you publish another mid-run. The trigger card also has a "Test run" button (owner only): it executes for real, and the run is saved to run history with a "Test" badge.
Who can do what
Workflows have their own permission module: View opens the list, builder, and run history; Create adds workflows and versions; Update edits, publishes, and test-runs; Delete removes a workflow with its versions and history. Every route also requires an employee account.
A workflow runs as its owner, not as whoever triggered it
Every step reads and writes with the owner's permissions, re-checked at each step. If the owner's access is revoked the run stops with a plain message naming the area. Nothing a workflow does can reach outside the company it belongs to — and run history is read-only in the database itself, so no user, however privileged, can edit or forge a run log.
Runs and history
Every firing is recorded as a : one row for the run and one per step, with the values in, the values out, and why it ended the way it did. Open Automate → Runs for the list: status, workflow, trigger, the record it started from (shown by its name or number, and linked so you can open it), duration, owner, and a Chain cell reading "Hop 2" when the run was caused by another run. Rows update live while anything is queued or running.
Clicking a row opens the "Run Details" drawer with a one-line plain-English outcome ("Failed at 'notify the buyer': The address answered 500."). Below it the steps appear in workflow order rather than execution order, so a step that never ran still holds its place, greyed and marked "Not reached" or skipped with its reason. Expand a step for its Input, Output, and — on conditions — a clause-by-clause Why with the path taken marked. A repeating step records each item plus a summary that counts what actually ran ("Ran 100 of 150; 50 were not used" means the 100-item cap, not an error).
A run can succeed having done nothing
If a condition matches none of its paths and has no "Otherwise", that step succeeded — it correctly decided not to continue. The run ends successful with most steps never reached, which is why the outcome sentence spells out what happened instead of leaving you to read a green badge. Missing data is likewise a skip, not a failure, and a condition whose values cannot be read does not fall through to its "Otherwise": an unknown is not a no.
A failed step stops its branch, not the run: other branches keep going, and a wired Failure handle is followed, though the run is marked failed at the end regardless. The one exception is a permission failure, which stops the branch outright even when a failure path exists.
Chains. When one workflow's writes trigger another, Carbon links the runs and displays the complete chain. A repeated workflow or a chain deeper than ten hops records a Blocked run. Use "Triggered by" to limit which changes can start a workflow.
There is no retry button
A finished run cannot be re-run from the Runs page. Fix the outside cause and let the next trigger fire, or use the builder's "Test run". A run that crashes mid-flight is retried automatically by the queue, and because each step is claimed before it acts, the retry cannot repeat work that already completed.
Retention. A nightly job tidies history in four passes, ignoring runs still in flight: after 24 hours a run still queued or running is closed as failed; after 7 days recorded values are summarised in place; after 30 days step rows are deleted (the run survives); after 90 days the run is deleted entirely. Values whose names look like credentials are stored as [REDACTED] and every webhook header value is masked, while ordinary fields that merely sound sensitive (an item key, who authorised something) are left alone: a debugging tool that hides too much is as broken as one that hides too little.