Skip to content

Actions and receipts

Authorise an action

POST/v1/actions/authorize

Ask whether this agent may take a consequential action. The answer is a decision: allow with a signed receipt, approval_required with an approval to wait on, or deny with reasons. A refusal is a 200, not an error.

Send idempotencyKey in the body (or the idempotency-key header) and a retry gets the same decision; the same key with a different body is 409 idempotency_conflict. Limited per agent per minute (IMMISCIBLE_AGENT_RPM, default 60). Tool calls from the Claude Code hook (type: tool.call with session.client: claude-code) count in a separate bucket, 300 a minute per agent by default (IMMISCIBLE_HOOK_RPM), because the hook asks before every Bash, Edit and WebFetch call and refuses when it is limited.

#Authentication

Agent key

An agent-scoped key (ask_...) bound to exactly one agent, or an OAuth access token (aat_...) issued to an MCP client for that agent, sent as Authorization: Bearer. An agent key may ask, poll and settle. It can never approve, widen a mandate or lift a freeze.

#Body

FieldTypeRequiredDescription
typestringyespayment, data.release, email.send, calendar.write, account.change, tool.call or your own dotted type; an undotted word that is not built in is refused with a suggestion
summarystringyesone sentence a person can read: what and why (at most 500 characters)
paymentobjectfor paymentsamount (whole minor units), currency (ISO 4217), merchant (name, domain, category, mcc)
dataobjectfor data releasesfields, recipient (a domain), purpose
targetobjectnodomain or recipient the action reaches
provenancearrayno{ source, detail } with source one of user, agent, web, email, document, tool. Missing means untrusted
volumeobjectno{ records } for actions that move data
sessionobjectno{ client, id }: the inference session, for observed provenance
idempotencyKeystringrecommended1 to 128 characters

A field that is plainly a mistake is refused before anything is decided or recorded: a 400 invalid_request names it in param and errors, with didYouMean (summry gives summary; a top-level marchant gives payment.merchant). Any other field not in this table is ignored, never silently: the decision carries warnings, one { type: "unknown_field", field, message } per field.

This is the finance agent from the proof page: the payee is on its allow list and the amount inside its monthly limit, but an email shaped the request, so a person decides. An allowed payment returns allow with a signed receipt in the same shape.