INTENTS & APPROVALS
Declare. Decide. Confirm.
The intent is APPEN's hook point between "the agent decided to buy" and "money moved." The agent declares what it wants; the engine decides before anything is charged, and the decision comes back explained. Every intent is a persisted row with its full per-rule verdict; that row is the audit trail.
The lifecycle
declare ──► approved ──► confirm ──► completed
│
├──► denied (a rule or envelope said no — with the reason)
│
├──► pending_approval ──► you approve ──► approved (human gates)
│ └──► you deny ──► denied
│
└──► quoted ──► you accept ──► approved (park-a-quote flow)Declare
POST /intents
Authorization: Bearer ak_live_... # or your JWT
{
"merchant": "Grainger Industrial",
"category": "supplies",
"amount_cents": 124000,
"mcc": "5085", # optional — feeds mcc_block rules
"card_id": "<uuid>", # optional — pulls in that card's rules
"reason": "restock: safety gloves" # the agent's own why, kept on the record
}The response is the decision: status, decision_reason, and rule_results — every rule that ran, pass or fail, with its detail string. Agents can read the trace and self-correct inside the lines.
The approval queue — human gates
Two rule kinds park purchases instead of deciding them: approval_threshold (over $X needs you) and new_merchant_review (first purchase from an unseen merchant). A parked intent is pending_approval:
POST /intents/{id}/approve # human JWT only — agent keys get 403
POST /intents/{id}/deny
# approve re-runs the FULL engine with the human gates satisfied.
# if merchant_lock or spend_cap or anything else now trips → still denied.
# approval is not a bypass.Confirm
POST /intents/{id}/confirm
{ "actual_amount_cents": 1250, "external_ref": "order_8812" }
# → status completed; the envelope debits the actual amountRead the log
GET /intents # newest first — every decision with its reasons attachedThis is the same feed the dashboard, the TUI's authorization log, and appen watch render.
WHERE THIS RUNS TODAY
The rule engine decides every declared intent today — live in the API, the MCP server, and the demo. Enforcement on real card swipes begins at our BIN connection with our issuing partner, when the same pre-authorized, user-directed policies execute inside the network authorization step. Card issuance opens by invite once our issuing-partner sandbox is live.