> ## Documentation Index
> Fetch the complete documentation index at: https://docs.atum.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Error codes

> Every error code the Atum APIs return, what each one means, and what to do about it. Branch on the code rather than the message text.

Atum returns 54 public error codes. Every Payment Gateway HTTP error
response carries a `docs_url` pointing at the entry for its code on this page.

This list is generated from the error catalog the services emit from, and is
regenerated whenever that catalog changes, so it cannot fall behind the codes you
actually receive.

<Warning>
  Branch on `code`. It is the stable, machine-readable field. `message` is curated
  text and two responses sharing a code can carry different text.
</Warning>

## Response shape

Payment Gateway HTTP errors return this body. `code` and `message` are always
present. The rest are included when they apply. The example below is a real
catalog entry, not an invented one. The x402 facilitator reports failures in the
[x402 envelope](/api-reference/x402/introduction) instead, using
`isValid`/`invalidReason` or `success`/`errorReason`.

```json theme={null}
{
  "code": "SETTLEMENT_FAILED",
  "message": "We couldn't complete the settlement for this payment. The on-chain outcome is not guaranteed, so reconcile by payment id before retrying.",
  "request_id": "req_123456789",
  "payment_id": "0xc7108e200d11580e7e75185991084b42a535af588ba8267cd0d1e7df089e5c9c",
  "docs_url": "https://docs.atum.xyz/errors#settlement-failed",
  "retry_classification": "RECONCILE_THEN_DECIDE"
}
```

An asynchronous payment failure appears as the `error` object on
[`GET /v1/payments/{payment_id}/status`](/api-reference/payment-gateway/get-payment-status)
instead. It carries the same `code` plus `blockchain_context`, but no `docs_url`,
`request_id` or `retry_classification`.

<ResponseField name="retry_classification" type="string">
  What to do next. Absent means the condition has not been classified, which is not
  the same as safe to retry. Re-sending the same `request_id` is an idempotent replay
  and always safe. This field is about submitting a new one, which starts a new payment.
</ResponseField>

<ResponseField name="domain" type="string">
  The originating service domain, one of ten values. Absent when the error did not
  come from a service that sets it.
</ResponseField>

## Retry after a delay

`RETRY_AFTER_DELAY`: no payment was created and the condition is transient, so re-send the same `request_id` after a delay.

| Code                                                      | HTTP |
| --------------------------------------------------------- | ---- |
| [`AUTHORIZATION_UNAVAILABLE`](#authorization-unavailable) | 503  |
| [`SERVICE_PAUSED`](#service-paused)                       | 503  |
| [`TRANSACTION_NOT_FOUND`](#transaction-not-found)         | 400  |
| [`VERIFICATION_TIMEOUT`](#verification-timeout)           | 400  |

## Reconcile before deciding

`RECONCILE_THEN_DECIDE`: the outcome is not known. Check the payment before issuing a new `request_id`, or you may pay twice. Only meaningful alongside a `payment_id`, since you cannot reconcile a payment you cannot name.

| Code                                                        | HTTP |
| ----------------------------------------------------------- | ---- |
| [`CONFLICT`](#conflict)                                     | 409  |
| [`COUNTERPARTY_TIMEOUT`](#counterparty-timeout)             | 504  |
| [`DUPLICATE_INTENT`](#duplicate-intent)                     | 409  |
| [`PAYMENT_EXPIRED`](#payment-expired)                       | 404  |
| [`SETTLEMENT_FAILED`](#settlement-failed)                   | 502  |
| [`SETTLEMENT_OUTCOME_UNKNOWN`](#settlement-outcome-unknown) | 500  |
| [`WEBHOOK_CONNECTION_ERROR`](#webhook-connection-error)     | 502  |
| [`WEBHOOK_ERROR`](#webhook-error)                           | 502  |

## Retry with a new request id

`RETRY_WITH_NEW_IDENTIFIER`: terminal, and no settlement was ever awarded for it, so a fresh `request_id` is safe to submit.

| Code                                                        | HTTP |
| ----------------------------------------------------------- | ---- |
| [`IDEMPOTENCY_TERMS_MISMATCH`](#idempotency-terms-mismatch) | 409  |
| [`NO_QUOTES_RECEIVED`](#no-quotes-received)                 | 422  |
| [`QUOTES_EXPIRED`](#quotes-expired)                         | 422  |
| [`REQUEST_ID_TAKEN`](#request-id-taken)                     | 409  |

## Poll for completion

`POLL_FOR_COMPLETION`: the operation is still running. Poll its status. Do not submit a new `request_id` until it is terminal, and do not re-send this one expecting a different answer.

| Code                                                        | HTTP |
| ----------------------------------------------------------- | ---- |
| [`EVENT_NOT_FOUND`](#event-not-found)                       | 425  |
| [`INSUFFICIENT_CONFIRMATIONS`](#insufficient-confirmations) | 400  |
| [`PAYMENT_IN_PROGRESS`](#payment-in-progress)               | 409  |

## Fix the request

`NOT_RETRYABLE_FIX_REQUEST`: the request itself is wrong. Fix it and re-send. Whether the same `request_id` may be reused is answered by `request_id_reusable`, not by this value: an unserved corridor is also a fix-the-request condition and it does spend the id.

| Code                                                                  | HTTP |
| --------------------------------------------------------------------- | ---- |
| [`AMOUNT_MISMATCH`](#amount-mismatch)                                 | 400  |
| [`COUNTERPARTY_NOT_FOUND`](#counterparty-not-found)                   | 404  |
| [`FORBIDDEN`](#forbidden)                                             | 403  |
| [`FULFILLMENT_DEADLINE_NOT_FUTURE`](#fulfillment-deadline-not-future) | 400  |
| [`FULFILLMENT_DEADLINE_ORDER`](#fulfillment-deadline-order)           | 400  |
| [`INVALID_DESTINATION_ACCOUNT`](#invalid-destination-account)         | 400  |
| [`INVALID_DESTINATION_ASSET`](#invalid-destination-asset)             | 400  |
| [`INVALID_FULFILLMENT_AMOUNT`](#invalid-fulfillment-amount)           | 400  |
| [`INVALID_REQUEST`](#invalid-request)                                 | 400  |
| [`INVALID_REQUEST_ID`](#invalid-request-id)                           | 400  |
| [`INVALID_SOURCE_ACCOUNT`](#invalid-source-account)                   | 400  |
| [`INVALID_SOURCE_ASSET`](#invalid-source-asset)                       | 400  |
| [`MALFORMED_REQUEST_BODY`](#malformed-request-body)                   | 400  |
| [`METHOD_NOT_ALLOWED`](#method-not-allowed)                           | 405  |
| [`MISSING_DESTINATION`](#missing-destination)                         | 400  |
| [`MISSING_REQUEST_ID_PARAM`](#missing-request-id-param)               | 400  |
| [`MISSING_SENDER_AUTH`](#missing-sender-auth)                         | 400  |
| [`NO_SETTLER_FOR_CORRIDOR`](#no-settler-for-corridor)                 | 422  |
| [`NOT_FOUND`](#not-found)                                             | 404  |
| [`PAYLOAD_TOO_LARGE`](#payload-too-large)                             | 413  |
| [`PAYMENT_ID_DERIVATION_FAILED`](#payment-id-derivation-failed)       | 400  |
| [`QUOTE_DEADLINE_NOT_FUTURE`](#quote-deadline-not-future)             | 400  |
| [`SENDER_AUTH_NOT_ALLOWED`](#sender-auth-not-allowed)                 | 400  |
| [`UNAUTHENTICATED`](#unauthenticated)                                 | 401  |
| [`UNSUPPORTED_DESTINATION_ASSET`](#unsupported-destination-asset)     | 400  |
| [`UNSUPPORTED_DESTINATION_CHAIN`](#unsupported-destination-chain)     | 400  |
| [`UNSUPPORTED_SOURCE_ASSET`](#unsupported-source-asset)               | 400  |
| [`UNSUPPORTED_SOURCE_CHAIN`](#unsupported-source-chain)               | 400  |

## Already done

`ALREADY_DONE`: the operation had already completed. Read its current state rather than submitting anything.

| Code                                  | HTTP |
| ------------------------------------- | ---- |
| [`ALREADY_SETTLED`](#already-settled) | 409  |

## Contact support

`CONTACT_SUPPORT`: not resolvable by the caller. Quote `request_id`.

| Code                                                          | HTTP |
| ------------------------------------------------------------- | ---- |
| [`AUTHORIZATION_DECLINED`](#authorization-declined)           | 403  |
| [`NOT_IMPLEMENTED`](#not-implemented)                         | 501  |
| [`SIGNATURE_GENERATION_FAILED`](#signature-generation-failed) | 500  |
| [`VERIFICATION_FAILED`](#verification-failed)                 | 400  |

## Depends on the condition

Each of these public codes covers several conditions that do not share one
answer, so the value differs per response. Branch on the
`retry_classification` you actually received, not on the code alone.

| Code                                | HTTP |
| ----------------------------------- | ---- |
| [`INTERNAL_ERROR`](#internal-error) | 500  |
| [`SERVICE_BUSY`](#service-busy)     | 503  |

## Reference

<div id="already-settled" />

### ALREADY\_SETTLED

HTTP 409. Retry classification `ALREADY_DONE`.

> This payment has already settled. Read its status rather than submitting it again.

<div id="amount-mismatch" />

### AMOUNT\_MISMATCH

HTTP 400. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> The on-chain amount does not match the expected amount.

<div id="authorization-declined" />

### AUTHORIZATION\_DECLINED

HTTP 403. Retry classification `CONTACT_SUPPORT`.

> This payment was declined during authorization. The reason is not included in this response.

<div id="authorization-unavailable" />

### AUTHORIZATION\_UNAVAILABLE

HTTP 503. Retry classification `RETRY_AFTER_DELAY`.

> This payment could not be authorized because a check could not be completed. It was not declined.

<div id="conflict" />

### CONFLICT

HTTP 409. Retry classification `RECONCILE_THEN_DECIDE`.

> The request conflicts with the current state of the resource.

<div id="counterparty-not-found" />

### COUNTERPARTY\_NOT\_FOUND

HTTP 404. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> No counterparty is registered to authorize this payment.

<div id="counterparty-timeout" />

### COUNTERPARTY\_TIMEOUT

HTTP 504. Retry classification `RECONCILE_THEN_DECIDE`.

> The counterparty did not respond within the timeout window.

<div id="duplicate-intent" />

### DUPLICATE\_INTENT

HTTP 409. Retry classification `RECONCILE_THEN_DECIDE`.

This code covers more than one condition, so `message` differs between
responses. Branch on `code`, never on the text.

> This request duplicates a payment that is already being processed. The outcome of that payment is not guaranteed, so reconcile by payment id before retrying.

> This request duplicates an already-processed payment. The on-chain outcome is not guaranteed, so reconcile by payment id before retrying.

<div id="event-not-found" />

### EVENT\_NOT\_FOUND

HTTP 425. Retry classification `POLL_FOR_COMPLETION`.

> No matching on-chain event has been observed yet.

<div id="forbidden" />

### FORBIDDEN

HTTP 403. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> You do not have permission to perform this action.

<div id="fulfillment-deadline-not-future" />

### FULFILLMENT\_DEADLINE\_NOT\_FUTURE

HTTP 400. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> fulfillment\_deadline must be a timestamp in the future.

<div id="fulfillment-deadline-order" />

### FULFILLMENT\_DEADLINE\_ORDER

HTTP 400. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> fulfillment\_deadline must be after quote\_deadline.

<div id="idempotency-terms-mismatch" />

### IDEMPOTENCY\_TERMS\_MISMATCH

HTTP 409. Retry classification `RETRY_WITH_NEW_IDENTIFIER`.

> This request\_id was already used for a different request (accounts, assets, or amounts differ). Re-submitting a request\_id retries the original, so each new request needs its own request\_id.

<div id="insufficient-confirmations" />

### INSUFFICIENT\_CONFIRMATIONS

HTTP 400. Retry classification `POLL_FOR_COMPLETION`.

> The transaction does not yet have enough confirmations.

<div id="internal-error" />

### INTERNAL\_ERROR

HTTP 500. Retry classification varies by condition: `CONTACT_SUPPORT`, `RETRY_AFTER_DELAY`. Some conditions carry none.

This code covers more than one condition, so `message` differs between
responses. Branch on `code`, never on the text.

> Fulfillment verification is temporarily unavailable for this chain.

> Something went wrong on our side. Quote the request id if you contact support, and check the payment before submitting a new request.

> Something went wrong on our side. Quote the request id if you contact support.

<div id="invalid-destination-account" />

### INVALID\_DESTINATION\_ACCOUNT

HTTP 400. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> A destination account is not a payable address on its destination chain. It must parse for that chain, carry a valid EIP-55 checksum when mixed-case, have no surrounding whitespace, and not be the zero address.

<div id="invalid-destination-asset" />

### INVALID\_DESTINATION\_ASSET

HTTP 400. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> A destination asset identifier is not a valid CAIP-19 asset.

<div id="invalid-fulfillment-amount" />

### INVALID\_FULFILLMENT\_AMOUNT

HTTP 400. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> fulfillment\_amount must be a positive integer in the asset smallest unit.

<div id="invalid-request" />

### INVALID\_REQUEST

HTTP 400. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

This code covers more than one condition, so `message` differs between
responses. Branch on `code`, never on the text.

> An amount in this request is not valid. It must be a positive integer expressed in the chain's smallest unit.

> The request was malformed or missing required fields.

<div id="invalid-request-id" />

### INVALID\_REQUEST\_ID

HTTP 400. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> request\_id may contain only letters, digits, underscore, hyphen, and dot.

<div id="invalid-source-account" />

### INVALID\_SOURCE\_ACCOUNT

HTTP 400. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> source.account is required and must not be empty or padded with whitespace.

<div id="invalid-source-asset" />

### INVALID\_SOURCE\_ASSET

HTTP 400. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> The source asset identifier is not a valid CAIP-19 asset.

<div id="malformed-request-body" />

### MALFORMED\_REQUEST\_BODY

HTTP 400. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> The request body could not be read or did not match the required schema. Check the JSON and required fields.

<div id="method-not-allowed" />

### METHOD\_NOT\_ALLOWED

HTTP 405. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> That HTTP method is not allowed on this path. The path exists, so check the method rather than the URL.

<div id="missing-destination" />

### MISSING\_DESTINATION

HTTP 400. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> At least one destination is required.

<div id="missing-request-id-param" />

### MISSING\_REQUEST\_ID\_PARAM

HTTP 400. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> The request\_id query parameter is required.

<div id="missing-sender-auth" />

### MISSING\_SENDER\_AUTH

HTTP 400. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> sender\_auth is required for this endpoint.

<div id="no-quotes-received" />

### NO\_QUOTES\_RECEIVED

HTTP 422. Retry classification `RETRY_WITH_NEW_IDENTIFIER`.

> No settlement quotes were received within the auction window. This request\_id is spent, so a new attempt needs a new one.

<div id="no-settler-for-corridor" />

### NO\_SETTLER\_FOR\_CORRIDOR

HTTP 422. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> No settlement provider currently serves this source and destination pair. This request\_id is spent, so a new attempt needs a new one, and it will not succeed until a provider covers the pair.

<div id="not-found" />

### NOT\_FOUND

HTTP 404. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

This code covers more than one condition, so `message` differs between
responses. Branch on `code`, never on the text.

> The requested chain is not supported.

> The requested resource was not found.

<div id="not-implemented" />

### NOT\_IMPLEMENTED

HTTP 501. Retry classification `CONTACT_SUPPORT`.

> This operation is not available yet.

<div id="payload-too-large" />

### PAYLOAD\_TOO\_LARGE

HTTP 413. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> The request body is too large.

<div id="payment-expired" />

### PAYMENT\_EXPIRED

HTTP 404. Retry classification `RECONCILE_THEN_DECIDE`.

> This payment has expired and is no longer available.

<div id="payment-id-derivation-failed" />

### PAYMENT\_ID\_DERIVATION\_FAILED

HTTP 400. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> The payment could not be identified from the request. Check sender\_auth and its signed message.

<div id="payment-in-progress" />

### PAYMENT\_IN\_PROGRESS

HTTP 409. Retry classification `POLL_FOR_COMPLETION`.

> This payment is still being processed. Poll its status until it reaches a terminal state rather than submitting again.

<div id="quote-deadline-not-future" />

### QUOTE\_DEADLINE\_NOT\_FUTURE

HTTP 400. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> quote\_deadline must be a timestamp in the future.

<div id="quotes-expired" />

### QUOTES\_EXPIRED

HTTP 422. Retry classification `RETRY_WITH_NEW_IDENTIFIER`.

> No settlement quote could be selected for this payment. Either the quotes received had expired by the award moment, or none was acceptable. This request\_id is spent, so a new attempt needs a new one.

<div id="request-id-taken" />

### REQUEST\_ID\_TAKEN

HTTP 409. Retry classification `RETRY_WITH_NEW_IDENTIFIER`.

> This request\_id is already in use by another account. Submit this payment with a new request\_id.

<div id="sender-auth-not-allowed" />

### SENDER\_AUTH\_NOT\_ALLOWED

HTTP 400. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> sender\_auth must be omitted on a quote request. It is supplied at award time.

<div id="service-busy" />

### SERVICE\_BUSY

HTTP 503. Retry classification varies by condition: `RETRY_AFTER_DELAY`, `RETRY_WITH_NEW_IDENTIFIER`.

This code covers more than one condition, so `message` differs between
responses. Branch on `code`, never on the text.

> No capacity was available to start an auction for this payment. This request\_id is spent, so a new attempt needs a new one.

> The service is temporarily busy.

<div id="service-paused" />

### SERVICE\_PAUSED

HTTP 503. Retry classification `RETRY_AFTER_DELAY`.

> This operation is temporarily paused. Nothing was signed or submitted for this request.

<div id="settlement-failed" />

### SETTLEMENT\_FAILED

HTTP 502. Retry classification `RECONCILE_THEN_DECIDE`.

> We couldn't complete the settlement for this payment. The on-chain outcome is not guaranteed, so reconcile by payment id before retrying.

<div id="settlement-outcome-unknown" />

### SETTLEMENT\_OUTCOME\_UNKNOWN

HTTP 500. Retry classification `RECONCILE_THEN_DECIDE`.

> Something went wrong on our side after settlement had started, so we cannot confirm whether funds moved. Reconcile this payment by payment id before submitting a new request.

<div id="signature-generation-failed" />

### SIGNATURE\_GENERATION\_FAILED

HTTP 500. Retry classification `CONTACT_SUPPORT`.

> Signing failed for this request.

<div id="transaction-not-found" />

### TRANSACTION\_NOT\_FOUND

HTTP 400. Retry classification `RETRY_AFTER_DELAY`.

> The transaction could not be found on-chain.

<div id="unauthenticated" />

### UNAUTHENTICATED

HTTP 401. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> Authentication is required, or the provided credentials are invalid.

<div id="unsupported-destination-asset" />

### UNSUPPORTED\_DESTINATION\_ASSET

HTTP 400. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> A destination asset is not a supported token on its chain, so no settler can be offered this payment.

<div id="unsupported-destination-chain" />

### UNSUPPORTED\_DESTINATION\_CHAIN

HTTP 400. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> A destination chain is not supported.

<div id="unsupported-source-asset" />

### UNSUPPORTED\_SOURCE\_ASSET

HTTP 400. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> The source asset is not a supported token on its chain, so no settler can be offered this payment.

<div id="unsupported-source-chain" />

### UNSUPPORTED\_SOURCE\_CHAIN

HTTP 400. Retry classification `NOT_RETRYABLE_FIX_REQUEST`.

> The source chain is not supported.

<div id="verification-failed" />

### VERIFICATION\_FAILED

HTTP 400. Retry classification `CONTACT_SUPPORT`.

> On-chain verification could not be completed.

<div id="verification-timeout" />

### VERIFICATION\_TIMEOUT

HTTP 400. Retry classification `RETRY_AFTER_DELAY`.

> On-chain verification timed out before a result was available.

<div id="webhook-connection-error" />

### WEBHOOK\_CONNECTION\_ERROR

HTTP 502. Retry classification `RECONCILE_THEN_DECIDE`.

> The counterparty could not be reached.

<div id="webhook-error" />

### WEBHOOK\_ERROR

HTTP 502. Retry classification `RECONCILE_THEN_DECIDE`.

> The counterparty's webhook returned an unexpected status while processing this authorization. That is not a decline, and it does not tell us whether they acted on the request.

<CardGroup cols={2}>
  <Card title="Troubleshooting" icon="wrench" href="/get-started/support/troubleshooting">
    Diagnose a payment that failed or stalled.
  </Card>

  <Card title="Reconciliation" icon="scale-balanced" href="/get-started/support/reconciliation">
    Confirm an outcome before retrying, so you don't pay twice.
  </Card>

  <Card title="Decline reasons" icon="hand" href="/decline-reasons">
    Why one settlement provider did not quote, which is not a payment failure.
  </Card>
</CardGroup>
