Actions and receipts
Authorise an action
/v1/actions/authorizeAsk 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
| Field | Type | Required | Description |
|---|---|---|---|
type | string | yes | payment, 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 |
summary | string | yes | one sentence a person can read: what and why (at most 500 characters) |
payment | object | for payments | amount (whole minor units), currency (ISO 4217), merchant (name, domain, category, mcc) |
data | object | for data releases | fields, recipient (a domain), purpose |
target | object | no | domain or recipient the action reaches |
provenance | array | no | { source, detail } with source one of user, agent, web, email, document, tool. Missing means untrusted |
volume | object | no | { records } for actions that move data |
session | object | no | { client, id }: the inference session, for observed provenance |
idempotencyKey | string | recommended | 1 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.