Approvals
An approval rule says that certain changes to a table must not be applied until a named person accepts them. “Discounting a deal below 20% margin needs a manager’s sign-off.” “Moving a project to Cancelled needs the owner’s OK.”
When a rule matches, the update is rejected, not queued: the record is untouched, and the person editing is offered a request instead. That request — a pending change — carries the proposed values until an approver approves or declines it.
This guide is written for workspace admins (who create rules) and members (who request and decide).
If you only remember one thing:
Approvals gate the change, not the person. A matching rule applies to everyone — including workspace admins and anyone who could have made the change directly. There is no “I have permission, let me through” bypass. That is deliberate: it keeps the audit trail honest and the mental model simple.
Who can do what
Section titled “Who can do what”- Create, edit, delete rules — requires
approvals:manage, granted to workspace admins. A rule shapes who can change data, so it sits at the same trust tier as the role editor. - Request approval — requires
approvals:request, granted to members. Requesting is what you do precisely when a rule stands between you and a change. - Decide — requires
approvals:decide, also granted to members. This action alone grants nothing: the rule’s approver list is the real gate. Holdingapprovals:decidewhile not being named by a rule lets you decide exactly nothing. Members hold it so a workspace can name ordinary people as approvers without promoting them to admin.
These are normal actions in the roles model — a custom role can grant or withhold them like any other.
The permission model (read this before your first rule)
Section titled “The permission model (read this before your first rule)”Three moments, three different answers. They are deliberately not the same.
1. Requesting — capped by your permissions
Section titled “1. Requesting — capped by your permissions”The proposal inherits the requester’s ceiling. To request a change you must:
- hold
records:updateon the table, - be able to update that row under your record visibility, and
- be allowed to write every field you are proposing.
You cannot propose writing a field you could not write yourself. Without this, an approval rule would be a way to get a restricted field written by finding someone willing to say yes.
The proposal is also validated against the table schema at request time, so an invalid change is rejected immediately rather than parked for someone to approve and then watch fail.
2. Deciding — you authorize, you do not author
Section titled “2. Deciding — you authorize, you do not author”To decide, you must:
- hold
approvals:decide, - be eligible for the current step’s approver route — directly named or included through a named group — and
- be able to see the record.
Each rule can route a request through one or more ordered steps. A step can require any one, all, or a quorum of its eligible approvers; only then does the request advance to the next step. A step can also have a deadline that either rejects the request or moves it to the next step. A request is applied only after every step has approved it; one rejection rejects the whole request.
You do not need write access to the fields being changed. An approver is authorizing a change, not making one. Requiring approvers to out-rank requesters on every field would make the most common real rule — a manager approves a change to a field only finance can edit — impossible to express.
Self-approval is blocked unless the active step’s route explicitly makes you eligible. If it does, that was an explicit and auditable choice by whoever wrote the rule.
3. Applying — as the system, on behalf of the requester
Section titled “3. Applying — as the system, on behalf of the requester”An approved change is applied through the same write path as any other update, with full re-validation (schema, constraints, uniqueness). The rule is not re-evaluated — it just matched, and re-running it would loop forever.
Attribution is split three ways, on purpose:
| Who | Where it shows up |
|---|---|
| Requester | The record’s updatedBy, and the ItemUpdated event’s user |
| System | The event’s actor (system, on behalf of the requester) |
| Approver | The ItemUpdated event’s metadata, and first-class on ApprovalDecided |
So the row’s authorship stays with the person who proposed the change, the audit trail shows it wasn’t a direct user write, and the approver is recoverable without becoming a third field on every record event in the system.
Writing a rule
Section titled “Writing a rule”Workspace Settings → Approvals → New rule.
A rule is three answers:
- Which table. One table per rule. A rule’s table can’t be changed later — create a new rule instead.
- When. Conditions are a simple filter
grammar:
amount greater than 10000,stage changed to cancelled,discount is not empty. All conditions must match. With no conditions, every update to the table needs approval. - Who decides. One or more steps, each naming any mix of people and groups. A single step is the simple case: any listed approver decides alone. Add more steps for a chain — see Multi-step routes.
Conditions are evaluated against the record as it would be after the
update — the existing row merged with the proposed change. That is what makes
amount greater than 10000 mean “would end up over 10000” and
stage changed to cancelled mean what it reads as. A change that doesn’t match
any rule is written normally.
Multi-step routes
Section titled “Multi-step routes”Add another step turns a rule into an ordered route: “line manager, then finance”. Each step has its own approvers and its own two settings.
How many must agree
| Setting | Meaning |
|---|---|
| Any one of them | One signature moves it on. The default, and the v1 behaviour. |
| All of them | Everyone the step names must approve. |
| A set number | A quorum — “any two of the three partners”. |
A deadline (optional), in hours from when the step became current. When it passes, the step either declines the request or moves on to the next step — your choice. The last step can only decline: there is nothing to escalate to, and applying a change nobody signed off would defeat the point.
Three things worth knowing:
- Nothing is written until the last step signs off. The record is untouched while the request is walking the route.
- A decline at any step ends the whole request. There is no sending it back a step; the requester re-requests.
- Groups are read live, the route is not. Editing a rule changes only requests made afterwards — one already in flight keeps the route it started with. To change who decides an open request, add or remove people from an approver group; group membership is checked at the moment of each decision.
A quorum never lowers its own bar. If a “two of three” step loses two people, it waits (and eventually hits its deadline or the 90-day expiry) rather than quietly becoming “one of one”.
What this deliberately doesn’t do
Section titled “What this deliberately doesn’t do”- No delegation or out-of-office routing. Name a group and change who’s in it instead.
- No sending a decision back a step. A decline ends the request.
- Updates only. Creates and deletes are not gated.
- No record locking — see Staleness.
Requesting a change
Section titled “Requesting a change”When a rule intercepts your edit you’ll see “This change needs approval” with the rule’s name, and a dialog showing exactly what would change. Add a reason (optional but useful — it’s what the approver reads first) and send it.
Nothing about the record has changed at this point. Your request appears under My Approvals → Requested by me, and the approvers are emailed.
One open request per record. A second proposal against the same row is refused while the first is still waiting — two pending changes racing each other would mean whichever applied second was decided against values nobody reviewed. Withdraw the first, or wait for it.
You can withdraw your own request at any time while it’s open. Approvers decline; they don’t withdraw — erasing the fact that someone chose not to approve would be worse than recording it.
On the API
Section titled “On the API”The write path returns 409 with code: "APPROVAL_REQUIRED" and the rule’s id
and name. Nothing was written. To request it, POST /pending-changes with the
same patch:
{ "tableId": "…", "itemId": "…", "proposedData": { "amount": 50000 }, "requestReason": "Renewal uplift agreed with the customer"}The 409 is deliberate. Silently converting a PUT into a pending change would
lie to an API caller that expects the row to have changed, so requesting is
always an explicit second step.
Deciding
Section titled “Deciding”My Approvals → Waiting on me lists what you can act on — including, for a multi-step rule, only the requests currently sitting on a step you are named on. A request two steps ahead of you isn’t yours yet, and won’t appear until it reaches you.
Opening one shows a field-by-field diff (current value, proposed value, and any conflicts) and, for a route, where it has got to: which step is current, how many approvals that step still wants, and who has already signed.
You may see fewer fields than were proposed
Section titled “You may see fewer fields than were proposed”The diff is masked through your own field permissions, not the requester’s. If a change touches a field you can’t read, you’ll see “1 field in this change is hidden from you” rather than the value. You can still approve or decline — you’re authorizing the change, not reading it.
Approving applies immediately — on the last step
Section titled “Approving applies immediately — on the last step”On a single-step rule, or the final step of a route, the button reads Approve & apply and does exactly that. Anywhere earlier it reads Approve this step, and the dialog says where the request goes next: your signature passes it on, it does not write anything.
Once the last step is satisfied the change is written, the requester is emailed,
and the pending change becomes approved with an applied timestamp. If the apply is rejected (see below), the
status becomes approved — apply failed with the reason. The decision and
its outcome are recorded as separate facts: somebody did say yes, and the change
still didn’t land.
Staleness and conflicts
Section titled “Staleness and conflicts”There is no record locking. Locking the row (or the fields) until someone decides would fight the way people actually work, and a request can sit open for weeks. Instead:
At decision time, if the record has changed at all since the request was made, you get a warning and must explicitly confirm you’ve reviewed the current values before approving. The “Current” column you’re reading is not what the requester was looking at, and pretending otherwise would make the diff a lie.
At apply time, the check is field-level. If someone else changed one of
the proposed fields since the request, the apply fails — status
approved — apply failed, with the conflicting fields named. Their work is not
overwritten, and the requester can re-request against the current values. A
concurrent change to some other field is not a conflict and applies fine.
Expiry
Section titled “Expiry”A pending change nobody decides expires after 90 days (configurable per organization) and leaves the inbox. The row is kept — approvals are audit material and are never pruned.
Notifications, and building on top
Section titled “Notifications, and building on top”Two emails ship built in and need no setup:
- approvers, when a change is requested,
- the requester, when it’s decided (or expires).
Beyond that, the single-action automations that could subscribe to approval events have been replaced by Flows (multi-step automation); documentation for building on approval events arrives with the new builder.
Building staged processes
Section titled “Building staged processes”“Move a project through phases, with rules about who may move what to where” composes out of pieces that already exist:
- The stage itself — an ordinary picklist field.
- Transition guards — an approval rule with a
changed tocondition (“stage changed to Cancelled → the owner approves”). - Side effects on entry — arrive with Flows (multi-step automation), which replaces the earlier single-action automations.
What’s still missing is an allowed-transition map (Draft → Review → Done, no skipping); that’s tracked separately and is independent of approvals.
Troubleshooting
Section titled “Troubleshooting”“No approval rule requires review for this change” — you called
POST /pending-changes for a change nothing is holding back. Make the write
directly.
A rule stopped intercepting. Check it’s enabled. If its stored condition became invalid (for instance a field it referenced was deleted), the rule stops intercepting rather than blocking every write to the table — a rule that suddenly held up all work would be worse than one that stops firing. Open and re-save it to see the validation error.
Nobody can decide a request. The approvers are resolved live, so an approver who has left the workspace or the group no longer counts. If a rule’s approvers have all gone, edit the rule to name someone current. Deleting a rule withdraws the requests it was holding, since nobody could ever decide them.
An approver says they can’t see the record. Deciding requires visibility of the row. Field-level masking is fine — row-level invisibility is not, and the request won’t appear in their inbox at all.