Skip to main content

Errors

The Merchant API uses conventional HTTP status codes and returns a consistent JSON error envelope for every error.

Error envelope

{
"code": "validation_failed",
"message": "Validation failed",
"request_id": "req_2c1f8a7b9e3d4051",
"errors": [
{"field": "currency", "message": "must be a valid ISO 4217 currency code"},
{"field": "amount", "message": "must not be null"}
]
}
FieldTypeDescription
codestringA stable, machine-readable error code (snake_case). Branch on this, not on message.
messagestringA human-readable description. May change without notice; do not parse it.
request_idstringCorrelation ID for this request. Include it when contacting support.
errorsarrayPresent for validation failures. Each entry has a field and a message. May be omitted otherwise.
Always log request_id

Every response is traceable by its request_id. Logging it on your side makes support investigations dramatically faster.

HTTP status codes

StatusMeaning
200 OKRequest succeeded.
201 CreatedResource created (e.g. a checkout session).
400 Bad RequestMalformed JSON, invalid request, or validation failure.
401 UnauthorizedMissing/invalid API key, or signature verification failed.
403 ForbiddenAuthenticated, but not permitted to perform this action.
404 Not FoundThe referenced resource does not exist for your account.
405 Method Not AllowedThe HTTP method is not supported on this path.
409 ConflictThe request conflicts with current state (e.g. duplicate reference, invalid state transition, or a differing card-storage consent re-asserted for the same payment).
415 Unsupported Media TypeThe request Content-Type is not application/json.
422 Unprocessable EntityThe request was well-formed but could not be reconciled — e.g. a provider callback whose amount or currency disagrees with the transaction.
500 Internal Server ErrorAn unexpected error on Orchestr's side. Safe to retry idempotently.
502 Bad GatewayA provider or downstream service was unreachable. Retry with backoff.
503 Service UnavailableA dependency is temporarily unavailable. Retry with backoff.
Creates are not all 201

POST /v1/checkout/sessions, /v1/refunds, /v1/payouts and /v1/transfers return 201, but POST /v1/payments and the card verbs (/v1/payments/capture, /v1/payments/void, /v1/payments/{id}/3ds/complete, /v1/transfers/{orderId}/execute) return 200. Branch on the response body, not on the status code.

Transport & authentication error codes

These come from the API layer common to all endpoints.

codeHTTPWhen it happens
malformed_request400The request body is not valid JSON.
invalid_request400The request is structurally invalid.
validation_failed400One or more fields failed validation; see errors[].
unauthenticated401Missing or invalid API key.
invalid_signature401The X-Signature did not verify, or its timestamp was outside the replay window.
malformed_signature_header401The X-Signature header is missing or not in the t=…, v1=… form.
forbidden403The account is not permitted to perform the action.
conflict409The request conflicts with the resource's current state.
method_not_allowed405The HTTP method is not supported on this path.
unsupported_media_type415The Content-Type is not application/json.
missing_request_parameter400A required query parameter is missing.
missing_request_header400A required header is missing.
invalid_parameter400A path parameter is malformed.
internal_error500Unexpected server-side error.
general_error500Unexpected server-side error raised below the API layer.
downstream_error502A downstream service failed. The message relays its report.

Domain error codes

Returned by specific resources. The code is the snake_case form of the values below.

Payments, orders & checkout sessions

codeHTTPMeaning
order_not_found404No order matches the identifier/reference.
invalid_order_status_transition409The order cannot move to the requested state.
merchant_reference_required400A merchant_reference is required.
duplicate_merchant_reference_id409That merchant_reference already exists for your account.
transaction_not_found404No transaction matches the identifier.
invalid_transaction_status400The transaction is not in a valid status for this operation.
checkout_session_not_found404No checkout session matches the identifier/reference.
invalid_session_state409The checkout session cannot transition from its current state (e.g. cancelling a completed session).
country_required400A country is required for this operation.
unknown_payment_method400The supplied payment method is not recognised.
payment_method_not_found404The referenced payment method does not exist.
payment_method_not_supported_by_provider409The selected route's provider does not support this method.
payment_unroutable404No route is available to process the payment.
ambiguous_original_transaction_target400Supply exactly one of order_id, transaction_id, or merchant_reference when creating a refund.
original_transaction_not_found404No original transaction matches the supplied refund target.
original_transaction_not_eligible409The original transaction is not eligible for refund.
refund_amount_invalid400The refund amount must be positive.
refund_amount_exceeds_refundable400The refund amount exceeds the remaining refundable balance.
refund_already_fully_refunded409The original transaction has already been fully refunded.
refund_in_progress409A refund is already in progress for that transaction.
refund_requires_transaction_target400The payment was captured in parts, so order_id is ambiguous — name the specific capture by transaction_id.
merchant_reference_ambiguous409The merchant_reference matches more than one transaction.
transaction_provider_mismatch400The transaction does not belong to the specified provider.
customer_not_found404No customer matches the identifier.
payment_method_not_supported_as_destination400This payment method cannot be used as a destination instrument.
consent_conflict409A different card-storage consent was asserted for a payment that already has one. Re-sending an identical consent is safe.

Card payments

codeHTTPMeaning
card_payment_invalid_order_state409The order is not awaiting a card payment.
card_payment_in_progress409A payment for this order is already in progress.
payment_unexpected_state409The payment is not in a state that allows this operation — capturing an already-captured payment, voiding after a final capture, and so on. The message names the verb, the current status, and the expected one.
capture_amount_exceeds_authorized400The capture amount is more than was authorized, or is not positive.
capture_amount_exceeds_remaining400The capture amount is more than the uncaptured remainder, counting captures still in flight.
card_api_unavailable502The card authorization service is unreachable. Reaches you as code: provider_unavailable — see below.
Declines are not errors

A card refused by the issuer or the provider returns 200 OK with status: "failed", not a 4xx. That applies to authorizations, captures, and voids alike. The codes above are pre-flight rejections — the request never reached a provider. To learn why an attempt failed, read decline_code on the transaction.

Payouts

codeHTTPMeaning
payout_not_found404No payout matches the identifier.
payout_in_progress409A payout is already in progress for that transaction.

Transfers

codeHTTPMeaning
transfer_not_found404No transfer matches the identifier.
transfer_not_supported_by_provider409The routed provider channel does not support transfers.
transfer_destination_invalid400The destination is invalid or incomplete — for a card transfer, most often a missing consent.
transfer_destination_not_registered409The destination is not registered with the provider.
transfer_unroutable400No provider channel could be routed. Supply channel_id.
transfer_card_token_required400A card_token is required when the destination is a card.
transfer_invalid_order_state409POST /v1/transfers/{orderId}/execute was called on a transfer not awaiting card collection.
transfer_in_progress409This transfer is already being executed.
recipient_pending_verification409The provider recipient is still pending verification.
note

Additional provider-configuration error codes exist for account setup performed in the Dashboard. They are not part of the merchant request/response flow documented here.

Decline codes in the error envelope

Error codes and decline codes are normally separate vocabularies: an error code says the request was rejected, a decline_code says a payment attempt failed.

There is one deliberate overlap. When an error carries an associated decline code, that decline code is what appears in the envelope's code. The case you are most likely to meet is card_api_unavailable, which reaches you as:

{
"code": "provider_unavailable",
"message": "Card authorization service is unavailable",
"request_id": "req_2c1f8a7b9e3d4051"
}

So a small number of values from the decline vocabulary can legitimately appear as an error code with a 5xx status. Branch on code as usual — just don't assume a code you don't recognise is absent from the decline-code reference.

Webhooks

codeHTTPMeaning
webhook_not_found404The referenced webhook endpoint does not exist.
webhook_limit_exceeded400The maximum number of webhook endpoints has been reached.
webhook_delivery_not_found404The referenced webhook delivery does not exist.
webhook_delivery_not_retryable400The delivery is not in a state that can be retried.

Handling errors

  • Branch on code, never on message.
  • For validation_failed, surface the per-field errors[] to the caller or your logs.
  • Treat 401 invalid_signature / malformed_signature_header as a signing bug — re-check the signed string and clock before retrying.
  • 409 duplicate_merchant_reference_id means the operation was already accepted under that reference — fetch the existing resource by reference rather than retrying with a new reference.
  • 500 and network errors are safe to retry, provided you reuse the same merchant_reference so the operation stays idempotent.