Every non-2xx response has one shape:
{"detail": {"code": "MANDATE_LIMIT_EXCEEDED", "category": "PER_TX", "message": "…", "authorization_id": "…"}}Codes are stable strings — match on detail.code, never on the message text.
This page is generated against the live service contracts; codes listed here are the
ones the API actually emits.
Authentication & access
| HTTP | Code | Meaning · next step |
|---|---|---|
| 401 | NO_TOKEN | No credentials — send Authorization: Bearer rgnt_… (an org API key; a rgnt_ctrl_… control key is for control-api and the gateway, see Authentication) |
| 401 | INVALID_TOKEN / INVALID_API_KEY | Expired or wrong credential — issue a new key |
| 403 | NOT_MEMBER | Your key belongs to a different organization than the one in the path |
| 403 | INSUFFICIENT_ROLE | The action needs a higher org role (e.g. revoke needs admin) |
| 403 | EMAIL_NOT_VERIFIED | Confirm your email before registering agents |
| 403 | KYC_NOT_VERIFIED | Complete identity verification before registering agents or issuing mandates |
| 429 | RATE_LIMITED | Honor Retry-After. Current per-IP limits: 30 req/s (burst 20); login/signup 5/min |
Input validation
| HTTP | Code | Meaning · next step |
|---|---|---|
| 422 | AGENT_ID_MALFORMED | agent_id isn’t the canonical agent_… identifier. The message names the common mistake: passing the record UUID from the registration response |
| 404 | AGENT_NOT_FOUND | No such agent in this organization (also returned for agents of other orgs) |
| 404 | MANDATE_NOT_FOUND | No such mandate |
Authorization refusals (HTTP 402)
Every refusal happens before execution — no money has moved. The refusal itself is recorded and auditable.
| Code | Meaning · next step |
|---|---|
MANDATE_LIMIT_EXCEEDED | The amount breaks a per-transaction, daily, monthly, per-entity, or relational limit — category names the window and the message says which. Don’t retry the same amount; surface to the operator |
MANDATE_SUSPENDED | The kill switch: the agent was revoked and its mandates suspended. Stop all activity |
MANDATE_REVOKED / MANDATE_EXPIRED | This mandate is gone — a new one must be issued and approved |
MANDATE_NOT_OWNED | caller_agent_id doesn’t match the mandate’s agent — one agent cannot spend against another’s mandate |
AGENT_NOT_ACTIVE | The agent’s identity record is not active (revoked or pending) |
RISK_SCORE_TOO_HIGH | Guardian’s behavioural score crossed the hard-reject threshold |
IDENTITY_UNREACHABLE | The identity service could not confirm the agent — fail-closed refusal, safe to retry once the service recovers |
JWT_ISSUE_FAILED | Authorization passed but the proof token could not be minted — fail-closed refusal, retry |
Until 2026-10-03 the payment service emitted the bare code LIMIT_EXCEEDED on this endpoint while the
control gate already used MANDATE_LIMIT_EXCEEDED; both surfaces now emit MANDATE_LIMIT_EXCEEDED. Match on the new name.