Rails
Reference

Error codes

Every real error code AbaPay's rails can return, pulled straight from the route handlers — not a curated happy-path subset. If something failed, it's one of these.

HTTP status codes

StatusMeaningWhere
200Settled, or a JSON-RPC-framed result (MCP/A2A always return 200 at the transport level, even for a tool-level error — see the JSON-RPC table below).REST, MCP, A2A
402Payment Required — a genuine x402 challenge, or a signed authorization that failed verification (see x402 error codes below).x402 / REST
401No credential at all (missing api_key and no OAuth token) — carries a WWW-Authenticate header pointing at the OAuth flow.MCP
409This exact payment is already locked/being processed — don't retry, it's not a fresh failure.x402 / REST
429Rate limited — 60/min per-IP on the whole MCP/A2A surface, and separately per-credential on money-moving calls (pay_bill 10/min, schedule_bill 5/min, pay_bill_batch 5/min). Carries a Retry-After header.MCP, A2A
500Server-side failure unrelated to the caller's request (token not configured, vault misconfigured, or an unhandled exception).x402 / REST

x402 challenge / settlement errors

Carried in the 402 response body as errorCode, alongside a human-readable error string and a retryable flag — check retryable before deciding whether to sign a fresh authorization and try again.

CodeRetryableMeaning
MALFORMED_AUTHORIZATIONNoThe signed authorization was incomplete or its numbers unreadable — a client-side bug in how it was built, not a transient issue.
WRONG_RECIPIENTNoThe authorization named a different payTo than this specific payment's challenge — stale or reused authorization.
NOT_YET_VALIDNovalidAfter is in the future relative to the server's clock — usually the caller's device clock is off. Fix the clock, then retry.
AUTHORIZATION_EXPIREDYesvalidBefore already passed. Sign a fresh authorization against a fresh challenge and retry.
AMOUNT_MISMATCHNoThe signed value doesn't match this bill's required amount — the challenge and the signature disagree on price.
Malformed X-PAYMENT headerNoThe X-PAYMENT header wasn't valid base64-encoded JSON in the expected shape.
Facilitator error (<http status>)YesCelo's x402 facilitator itself returned a non-success status while settling. Not AbaPay's failure — safe to retry.
Facilitator temporarily unavailableYesThe facilitator couldn't be reached at all. Retry with backoff.

Settlement status (200 response body)

The status field on a settled x402/REST response — a 200 HTTP status doesn't always mean the money-to-bill leg finished cleanly.

StatusMeaning
SUCCESSBill vended, or reliably queued for background delivery.
FAILED_VENDINGPayment settled on-chain, but the underlying bill purchase (VTpass) failed — enters the automatic on-chain refund flow. See the Custody chapter in the handbook.
TIMEOUTThis exact payment was already being processed when the request landed — a duplicate submission, not a fresh failure. Don't resubmit.
SYSTEM_CRASHAn unhandled exception during settlement. Treat as pending, not failed — check transaction_history / the receipt before assuming nothing happened.

MCP / A2A JSON-RPC error codes

Standard JSON-RPC 2.0 codes (spec §8) plus AbaPay-specific ones. A tool-level error (e.g. a wrong PIN) comes back as normal result text, not one of these — these are transport/protocol-level failures.

CodeMeaning
-32700Parse error — the request body wasn't valid JSON.
-32600Invalid Request — missing/malformed jsonrpc, method, or id.
-32601Method not found.
-32602Invalid params — a required field was missing or the wrong type. Check the tool's parameter table on the MCP or A2A page.
-32603Internal error, unrelated to the request itself.
-32001Unauthorized — no valid credential. Carries a WWW-Authenticate pointer to start OAuth.
-32004Unsupported operation (A2A spec §8).

Invalid or revoked API keys return the same plain-text message regardless of which tool was called: "Invalid or revoked API key. Create a new one in the AbaPay app under Agent Hub → MCP."