ACP Error Codes Reference: Every Code the Module Returns
type, a machine-readable code, and a human-readable message. Nothing else, no stack traces, no nested detail objects, no internal identifiers. This page is the complete reference: each code with its HTTP status, what triggers it, what a platform client should do about it, and how to provoke each one deliberately in tests.
The Error Envelope
The type field classifies the failure into the four buckets the spec defines: invalid_request for anything the caller can fix, processing_error for payment and downstream failures, service_unavailable for temporary conditions, and rate_limit_exceeded for throttling. The code is the field to branch on programmatically, it is stable and specific, while message is for logs and, where appropriate, for what the assistant tells the shopper. A typical decline looks like this on the wire:
{
"type": "processing_error",
"code": "payment_declined",
"message": "Card was declined: insufficient_funds"
}
The Full Code Table
HTTP code when it happens retry?
401 (unauthorized) missing or wrong bearer token, fix credentials
or failed request signature
400 missing_api_version API-Version header absent fix request
415 (unsupported media) POST body not application/json fix request
400 (missing key) POST without an Idempotency-Key fix request
422 idempotency_conflict same key reused with different body new key
409 idempotency_in_flight first request with key still running wait Retry-After
404 not_found unknown route under the prefix fix URL
404 missing session id does not exist fix id
405 not_cancelable cancel called on a completed session do not retry
400 invalid malformed input, frozen session fix request
update, or missing payment token
400 out_of_stock an item is no longer available update the cart
400 payment_declined the charge was declined shopper action
400 requires_3ds issuer requires authentication run 3DS, retry
500 internal_error unexpected server-side failure retry, same key
Request-Level Errors
The 401 family is configuration, not code. Every request needs Authorization: Bearer matching the configured token, and the endpoints are closed by default, no token configured means every request is rejected, opening the API is an explicit act. If HMAC signing is configured, a missing or wrong Signature is also a 401, and the check fails closed, omitting the header does not bypass it. The missing_api_version 400 means the API-Version header was absent entirely, the module requires the header but tolerates adjacent spec snapshots while the protocol is in beta. The 415 fires when a POST body is not application/json. All of these are covered end to end in the endpoints reference and the security model.
Idempotency Errors
Every POST requires an Idempotency-Key, and two codes police its use. A 422 idempotency_conflict means the same key arrived with a different body, which is almost always a client bug about to become a double purchase, the correct response is to generate a fresh key for what is genuinely a new request, never to strip the key. A 409 idempotency_in_flight means the first request under that key is still processing, the response carries a Retry-After hint, and the platform should simply wait and resend the identical request. The happy path of the same machinery is invisible: an exact replay returns the stored response with an Idempotent-Replayed: true header and side effects happen exactly once.
One subtlety rewards attention: server-side 5xx responses are not stored against the key. A transient failure does not poison the key, so the correct retry after a 500 is the same request with the same key, which gets a fresh attempt rather than a replayed error.
Session-State Errors
The missing 404 is a session id that does not exist, distinct from not_found, which is a route that does not exist. The invalid 400 covers malformed input and every illegal state transition: updating a session frozen by a live hosted payment, completing with no payment token, completing an empty session. The 405 not_cancelable fires only when canceling a session that already completed, cancel is otherwise allowed from any state. The out_of_stock code appears in two strengths: as a warning message attached to a session when re-pricing dropped an unavailable item, so the platform can tell the shopper what changed, and as a hard 400 when a request depends on an item that cannot be sold. Session states and the re-pricing rule behind these are described in the endpoints reference.
Payment Errors
Two codes carry the entire payment surface. A payment_declined 400 wraps any decline, with Stripe's decline reason preserved in the message, the session stays ready_for_payment so the shopper can try another method, and nothing was charged. A requires_3ds 400 means the issuer demanded authentication that a server-to-server call cannot perform, the platform runs the challenge with the shopper and retries. Both are documented in depth, including the exact Stripe mechanics behind them, in the Shared Payment Tokens guide and payment modes. Anything unexpected from the provider or the module itself becomes a 500 internal_error whose details are logged server-side and never leaked to the caller.
Retry Guidance in One Paragraph
Branch on the code, not the status. Fix-and-resend errors (missing_api_version, invalid, 415, missing key) need a corrected request. idempotency_in_flight means wait and resend identically. idempotency_conflict means mint a new key. internal_error means retry with the same key, the 5xx was not stored. payment_declined and requires_3ds are shopper-level outcomes, not transport failures, surface them in the conversation. And not_cancelable is final, a completed session stays completed.
tok_decline, tok_3ds) produce the two payment errors, a reused key with an edited body produces the 422, two concurrent sends of the same request produce the 409, and an update after a mock hosted payment starts produces the frozen-session invalid. The quickstart gets a local server running for this in under a minute.
