Approvals
Multi-step approval processes on any record — entry criteria, approvers by user, profile or manager, record locking while pending, and status write-back.
An approval process routes a record through one or more approval steps.
Processes run on leads, contacts, accounts, deals (opportunities), cases, tasks
and custom objects, as well as the deal-desk entities (quotes, discounts,
orders, contracts). Manage them under Settings → Sales process → Approval
workflows; people decide in Approvals (/dashboard/approvals) or on the
record page. Approvals are part of the Enterprise plan.
A process
| Setting | Meaning |
|---|---|
entity (+ customObjectName) | What it runs on: LEAD, CONTACT, ACCOUNT, OPPORTUNITY, CASE, TASK, CUSTOM_OBJECT, QUOTE, DISCOUNT, ORDER, CONTRACT. |
conditions | Entry criteria: [{ field, operator, value }], all must match. Operators EQUALS, NOT_EQUALS, GREATER_THAN(_OR_EQUALS), LESS_THAN(_OR_EQUALS), CONTAINS, IN. Fields are the record's own (API names; custom object fields by name). |
priority | When several processes apply, the highest priority whose criteria match is used. |
| steps | In order. Each step's approver is a USER, anyone with a profile (ROLE), the requester's MANAGER or SKIP_LEVEL_MANAGER; a step can require a comment and allow delegation. |
lockRecord | While a request is pending, only the current step's approvers and admins can edit the record. Default on for records; never for the deal-desk entities. |
allowRecall | Whether the requester can recall (cancel) a pending request. |
statusField, statusValues | A field that mirrors the request: written PENDING, APPROVED, REJECTED or RECALLED (or your own values per outcome). |
fieldUpdates | { onSubmit, onApprove, onReject, onRecall: [{ field, value }] }. Values are literals or $Now, $Today, $Approver, $Submitter. |
Status and field updates are written as the process's author through the
entity services, so validation rules, before-save hooks, field-level security,
workflows, webhooks and the audit trail apply; they pass the process's own
lock. Writable fields are the record's editable fields and, on leads, contacts,
accounts and deals, custom fields as customFields.<name> — anything else is
400 INVALID_APPROVAL_FIELD. A write that is refused is logged on the request
(entityDetails.writeBackError) and does not undo the decision.
Quotes keep their deal-desk behaviour: submitting sets the quote to
PENDING_APPROVAL, approval makes it APPROVED, rejection returns it to
DRAFT with the reason, and editing its pricing resets it to draft and cancels
the open request.
Record locking
A locked record answers 423 RECORD_LOCKED to edits and deletes by anyone
else, wherever they come from: the REST API and inline edits, GraphQL
mutations, the Bulk API, bulk edits, imports, workflows, flows and custom field
values. The body names the request:
Org owners and admins (and system admins), and whoever can decide the current step, can still edit. System jobs without a user are not locked out. The lock ends when the request is approved, rejected or recalled.
Submitting and deciding
The submitter must be able to see the record. A record has at most one pending
request (409 APPROVAL_ALREADY_PENDING); a record that matches no process's
entry criteria is 400 ENTRY_CRITERIA_NOT_MET. For custom objects pass
entityType: "CUSTOM_OBJECT" and the record id. Flows submit with the
Submit for approval element.
Events
approval.approved and approval.rejected are in the
event catalog: data.record is the request,
data.relatedTo the record ({ object, id }), plus workflowName and the
approver's comment.
Metadata
Processes move as APPROVAL_PROCESS components
(approval-processes/<ENTITY>.<name>.approval.json). Approvers travel as the
user's email and the profile's name; a process with pending requests can't
have its steps replaced by a deploy. New processes arrive inactive unless the
deploy activates them.
Flows
Guided screen flows and autolaunched processes built without code — run from records, lists, pages, a link, workflows or events, and through the API.
Apps
Package custom fields, objects, actions, hooks, webhooks and UI extensions in one versioned manifest that any SalesOS organization can install, upgrade and cleanly uninstall.