Errors
Look up the shape of an error response on each surface, what every error code means and what to do about it.
AuthFI reports a failure in the shape that the surface's standard defines. Find the surface you called, then the code.
Response shapes
An OAuth error:
{ "error": "invalid_client", "error_description": "client authentication failed" }An error from another endpoint:
{ "error": "invalid_body" }A successful response from those endpoints puts its result under data:
{ "data": { "decision": "allow" } }OAuth endpoints for applications
These codes come from the endpoints under /oauth/. Each endpoint is described in OAuth and OpenID Connect endpoints.
Presenting a used refresh token revokes every refresh token from the same sign-in and returns invalid_grant. See Refresh tokens.
Guides that use these codes: Add sign-in to an app, Sessions, Application types and Service to service.
Agent token endpoint
These are the only values error takes at /apis/regional/v1/ai/auth/token, so your code can branch on them.
An assertion is accepted once. Sending the same one again returns invalid_client. See Give an AI agent an identity and Accept agents at your own API.
Four more codes apply while an agent polls for a person's answer with the CIBA grant. Each has the status 400. See Ask a named person.
Other endpoints
Endpoints outside OAuth return a code in error with the matching HTTP status.
Some endpoints use these statuses for a specific cause.
Decisions
A decision is a successful response, not an error. The authorize endpoint returns decision and reason under data. See Limit what an agent may do.
{ "data": { "decision": "deny", "reason": "constraint_violated: amount max" } }An approval that nobody answers reaches the status expired. Treat it as denied. See Ask before a sensitive action.
Zero-Code denials
A request denied at the node returns 403 with a reference that identifies the denial in the audit record.
HTTP/1.1 403 Forbidden
WWW-Authenticate: Bearer realm="authfi", error="invalid_token"
X-Authfi-Ref: 7c1f0a2e
Content-Type: application/json
{ "error": "authfi_audience_mismatch", "message": "This credential was issued for a different service.", "ref": "7c1f0a2e" }The checks run in this order on each request to a protected API. See Protect an API.
Other callers are answered differently. See Protect a service with no code and Enforcement in the kernel.
In monitor mode nothing is denied. Each request that would have been denied is recorded with its reason.
MCP gateway
The MCP gateway reports a failure at one of three levels. See The MCP gateway.
HTTP. A request with no token, or one that is expired or revoked, returns 401 with a pointer to the protected resource metadata.
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://acme.authfi.io/.well-known/oauth-protected-resource"JSON-RPC. A request the gateway cannot process returns a JSON-RPC error.
Tool result. A denied call is an ordinary tool result with isError set, so the model reads it and can change course.
{
"jsonrpc": "2.0",
"id": 7,
"result": {
"isError": true,
"content": [{ "type": "text", "text": "Denied by policy: agent:agt_7f3a9c21 is not granted payments.refund" }]
}
}An approval is good for 15 minutes and for that call. A call to a tool with per-person credentials is denied when no person is named, or when the person has not connected their account.