totalPrice.centAmount > 5000000 looks correct until Atlas Corporate places an order in New Zealand dollars and the same number means a different amount of money. Approval Rules make governance precise, but a small predicate mistake can make a rule fire on the wrong orders or fail to fire at all.The Approval Rule resource
as-associate endpoint, scoped to the Business Unit, that you have used throughout this path.POST /{projectKey}/as-associate/{associateId}/in-business-unit/key=atlas-apac/approval-rules HTTP/1.1
Content-Type: application/json
{
"name": "APAC orders over 50,000 AUD",
"status": "Active",
"predicate": "totalPrice > \"50000.00 AUD\"",
"requesters": [
{ "associateRole": { "typeId": "associate-role", "key": "apac-buyer" } }
],
"approvers": {
"tiers": [
{ "and": [ { "or": [ { "associateRole": { "typeId": "associate-role", "key": "apac-manager" } } ] } ] }
]
}
}
manage_approval_rules scope; reading them requires view_approval_rules. In practice, only a high-authority role such as Business Administrator should hold manage_approval_rules.Writing the predicate: the currency-precision trap
predicate is an Order Predicate, so it can reference any field on the Order. The most common field is the order total, and it is also where the most common mistake lives.totalPrice.centAmount is a raw integer in the order's currency. Comparing it on its own ignores currency entirely:totalPrice.centAmount > 5000000
This matches 5,000,000 cents whether the Order is in Australian dollars, New Zealand dollars, or British pounds, which is almost never what you want for a multi-currency buyer like Atlas. There are two correct ways to make the comparison currency-safe.
Pair the amount with the currency explicitly:
totalPrice.centAmount > 5000000 and totalPrice.currencyCode = "AUD"
Or use the money form, which carries the currency in the literal:
totalPrice > "50000.00 AUD"
centAmount comparison will misfire across currencies, either demanding approval where it should not or, worse, letting a large order through because the numeric threshold did not match the currency you assumed.Predicates beyond the order total
lineItemExists when the presence of a matching Line Item is enough, and use the Line Item quantity field inside the predicate when the rule depends on units within a matching Line Item.lineItemExists(sku = "ZET-HAZMAT-01") = true
lineItemExists(custom.category = "controlled" and quantity > 10) = true
lineItemCount only when the policy depends on the number of separate matching Line Items, not the units on one Line Item. These patterns mirror real customer rules: approval for orders containing specific products, tiered total thresholds, quantity-sensitive controlled products, and approval when shipping cost exceeds a limit.Predicates on custom business context
custom.<fieldName> path. For example, have your middleware tag an Order with a custom.procurementCategory field, and gate approval on it:custom.procurementCategory = "capital-expenditure"
This is the mechanism for requirements that out-of-the-box fields do not express, such as internal budget categories, contract references, or a risk classification your systems already compute. Keep the Custom Field definition and the predicate in step: a predicate that references a field the Order does not carry never matches.
Choosing requesters
requesters array lists the Associate Roles a rule applies to. It holds at least one RuleRequester, each pointing at an Associate Role by key. An Order needs approval under this rule only if the Associate who placed it holds one of these roles.requesters. If apac-buyer is a requester and apac-manager is an approver, a buyer cannot self-approve, because the rule only applies to buyers and only managers can approve it. Design the two role sets so they do not overlap for any spend you want a second pair of eyes on.Worked example: Atlas APAC spending thresholds
atlas-apac Business Unit.- Single-approver threshold. Orders over AUD 2,000 placed by an
apac-buyerneed a manager. Predicate:totalPrice > "2000.00 AUD"; requesterapac-buyer; a one-tier hierarchy requiringapac-manager. - Dual-approver threshold. Orders over AUD 5,000 additionally need the finance director. This uses the same requester and a higher threshold, but a different approver hierarchy. The next page covers that hierarchy. Predicate:
totalPrice > "5000.00 AUD". - Controlled-product rule. Any order containing a controlled item needs compliance sign-off regardless of value. Predicate:
lineItemExists(sku = "ZET-HAZMAT-01") = true; requesterapac-buyer; approvercompliance-reviewer.
status: "Active", scopes its currency in the predicate, and names the requester role explicitly, so a multi-currency buyer's orders are governed precisely.Key takeaways
- An Approval Rule belongs to one Business Unit and combines a
predicate,requesters, an approver hierarchy, and astatus; onlyActiverules are evaluated. - Constrain currency in any threshold predicate: pair
totalPrice.centAmountwithtotalPrice.currencyCode, or use the money form such astotalPrice > "50000.00 AUD". - Use
lineItemExists(Boolean) andlineItemCount(Number) to trigger approval on order contents, andshippingInfo.price.centAmountto gate on shipping cost. - For business context with no native field, set a Custom Field on the Cart or Order and reference it in the predicate as
custom.<fieldName>. requestersare Associate Roles; keep requester and approver roles non-overlapping to enforce separation of duties.