202.
Before you start
Identifiers
1. Set the threshold
approval_threshold_cents is the shorthand. It compiles to an approval_threshold rule and
reports as one:
201 Created
condition rule with
"effect": "require_approval" instead. Passing facts from your own
service holds a payment on how new the buyer is, and reaches the
same 202.
2. Your agent gets a 202
202 Accepted
cosignature, because nothing is authorized yet. The 24000 is already reserved
against the budget, so the next action in the same run cannot quietly spend it while this one
waits.
3. Wait, do not retry
A202 is not a transient failure. Retrying it under a fresh Idempotency-Key creates a second
held intent, reserves the budget twice, and asks a person the same question twice.
In production, subscribe to action.requires_approval and approval.resolved and let the
webhook wake the run back up. In a script, read the intent back:
200 OK
4. What the approver sees
An approver looking at “approve $240?” is rubber-stamping. One call answers what approving would actually do, and it is the same shape for a payment intent:200 OK
session is the budget and runtime is the agent, in the wire names the API has always used.
Two numbers carry most of the decision: returns_on_deny_cents is what denying gives back, and
open_holds counts every other intent competing for the same budget, which is how an approver
notices that three pending approvals total more than the budget can cover.
The console shows the same facts on the Approvals page, where the queue can be narrowed to live
or test agents.
5. Resolve it
200 OK
pending, exactly as if it had come back 201, and approval.resolved
fires. Your agent executes and reports the outcome with complete or fail, and the
reservation is only released when it does.
Denying instead moves the intent to denied and returns the reservation:
200 OK
requires_approval is a 422, so a double click cannot
double execute.
What approvals do not do
Approving is a capability, not a queue with routing. Owners and admins holdapprove; members
hold read only. Say this out loud to whoever runs the process, because the product does not
enforce any of it for you:
- Kordio does not route a hold to a named person, a group, or an on-call rota. Anyone with
approvein the workspace can resolve any hold in it. - There is no quorum. One approval resolves the intent, and
resolved_by_subrecords who. - There is no escalation and no expiry. A hold waits until somebody answers it, and its reservation waits with it.
- An approved intent carries no cosignature. Cosignatures are issued on the authorize call and
only for an
alloweddecision, so an executor that gates on one should read the intent state for this path instead.
Next steps
Roll a policy out safely
Prove the threshold on a test agent before it holds real money.
Webhooks
Wake the run on
approval.resolved instead of polling.Holding spend for a person
The reference for states, capabilities, and the payment path.
Verifying an authorization
Why
approval.resolved is not itself permission.