- HTTP 201 can contain
{ "status": false, "error": "..." }for a business error, such as invalid currency precision or an unavailable payment method. - Validation errors use HTTP 400 with
statusCode,errorand amessagearray. - Structured core errors include
status: false,statusCode,errorCode,errorandmessage. - Authentication errors use HTTP 401 with a message. Do not assume every failure has
errorCode.
errorCode values are an open set. The tables below list known codes; new codes can appear
without a version change. Handle an unknown code like other errors of the same HTTP status, and
never parse the human-readable message.
API_KEY_ROTATION_REQUIRED is HTTP 401 with that fixed errorCode and message: the configured
legacy-key sunset has passed. Rotate the key in the merchant cabinet or through your operator,
store the newly issued key securely, and update your server credentials. Retrying the retired
legacy key will not help. This auth rejection does not imply a payment decline.
Do not mark an order declined solely because a request failed or timed out. Keep an unresolved
payment pending in your own system until a verified state update or operational reconciliation
establishes the result. Do not expose internal provider error messages to buyers.
Use transaction ID, order ID, event ID and idempotency key for support correlation. Never attach
API keys, webhook secrets, signature headers, card details or customer information to logs or tickets.
Rate limits
The merchant API applies rate limits per merchant (all of its API keys share one quota) and per client IP address. Repeated failed authentications from one IP temporarily block that IP, including requests with valid keys. Limits are configured per deployment and can change, so read theRateLimit-Policy and RateLimit response headers instead of hard-coding values. A separate
auth-in-flight policy limits concurrent authorization checks per IP and answers with
Retry-After: 1; that response does not mean your API key failed. Reduce concurrency when many
servers share one egress IP.
HTTP 429 returns errorCode: RATE_LIMITED. Wait at least the integer Retry-After seconds, then
retry with the same Idempotency-Key and request body. Do not create a new payment attempt
because of throttling. RateLimit-Policy describes each evaluated policy’s quota and window;
RateLimit gives remaining requests and reset time in seconds. These headers also appear on
successful merchant API responses. Checkout has a separate limit policy.
PSP_OUTCOME_UNKNOWN on an accepted sale appears in
transaction.errorCode alongside status: true and a transaction ID. It is
pending, not declined. No redirect URL is provided. Poll the
transaction status and wait for a verified webhook or
operational reconciliation.
Payment link errors
Payment-link business errors use the structured core error shape. Malformed DTO input instead uses the validation shape (message array) and may have no machine-readable code.
The amount schema uses the common money pattern: 1–20 integer digits, up to 18 fractional digits, no leading zeros, sign or exponent notation. The core also enforces positivity and currency precision. Shape violations are rejected by the gateway before forwarding.
Refund creation uses HTTP errors rather than a sale’s legacy business-error envelope:
409
REFUND_EXCEEDS_AMOUNT includes amounts reserved by unresolved refunds;
409 TRANSACTION_NOT_REFUNDABLE rejects an ineligible parent sale;
422 REFUND_NOT_SUPPORTED rejects an unsupported connector. Foreign IDs and wrong-mode IDs
return 404. An accepted refund is still asynchronous: use the refund ID to read its state,
and reuse the original idempotency key after an uncertain request. See refunds.
For an Adyen hosted session, ADYEN_REFUSED with transaction status PROCESSING
means only that one attempt was refused. Keep the order pending and let the
shopper use the existing session. A later attempt can succeed; session closure
or expiry produces EXPIRED. See transaction status.
Retry rules
Stop retrying a create after the 24-hour idempotency window and reconcile instead.