Error Codes

HTTP status codes, error response format, and common error codes for the Axon API.

Error Codes

All Axon API error responses follow a consistent format and use standard HTTP status codes.

Error Response Format

{
  "error": "Human-readable error message",
  "code": "MACHINE_READABLE_CODE",
  "details": "Optional additional context"
}
FieldTypeDescription
errorstringA human-readable description of the error.
codestringA machine-readable error code. Use this for programmatic error handling.
detailsstring?Optional additional context, such as which field failed validation or the expected format.

HTTP Status Codes

400 Bad Request

The request is malformed or missing required fields.

CodeDescription
INVALID_REQUESTRequest body is not valid JSON or is missing required fields. Check the details field for which field is invalid.
INVALID_SIGNATUREThe EIP-712 signature does not match the provided intent data. The recovered signer address does not match the bot field.
INVALID_ADDRESSAn address field is not a valid Ethereum address (not checksummed or wrong length).
INVALID_AMOUNTThe amount field is not a valid non-negative integer string.
INVALID_REFThe ref field is not a valid bytes32 hex string (must be 0x-prefixed, 66 characters).
DEADLINE_EXPIREDThe intent's deadline timestamp has already passed. Generate a new intent with a future deadline.
INVALID_CHAIN_IDThe chainId is not a supported chain.
INVALID_IDEMPOTENCY_KEYThe idempotencyKey is not a valid UUID.
MEMO_TOO_LONGThe memo field exceeds 1000 characters.
METADATA_TOO_LARGEThe metadata object exceeds 10 keys or a value exceeds 500 characters.

403 Forbidden

The request is well-formed but authorization checks failed.

CodeDescription
BOT_NOT_ACTIVEThe bot address is not whitelisted on the specified vault. Register the bot via the dashboard or contract before submitting payments.
EXCEEDS_PER_TX_LIMITThe payment amount exceeds the bot's maxPerTxAmount configured on the vault.
EXCEEDS_DAILY_LIMITThe payment would cause the bot to exceed its rolling daily spending limit.
EXCEEDS_VELOCITY_LIMITThe payment would exceed a rolling spend window limit (e.g. more than $300 in 60 minutes).
DESTINATION_NOT_ALLOWEDThe recipient address is not on the vault's or bot's destination whitelist, and a whitelist is configured.
VAULT_PAUSEDThe vault is currently paused by the owner. No payments can be processed.

404 Not Found

CodeDescription
NOT_FOUNDThe requested resource does not exist. For GET /v1/payments/:requestId, the request ID is not recognized.
VAULT_NOT_FOUNDNo vault exists at the specified vaultAddress on the given chain.

409 Conflict

CodeDescription
IDEMPOTENCY_CONFLICTA payment with this idempotencyKey was already submitted with different intent data. Each unique payment must use a unique idempotency key. The original cached response is not returned in this case because the intent data does not match.
DUPLICATE_INTENTThe exact intent hash has already been executed on-chain. The contract tracks all executed intent hashes and rejects duplicates.

A 409 IDEMPOTENCY_CONFLICT means the same key was used with different data. If you re-submit the exact same request with the same idempotency key, you will receive a 200 with the original cached response -- that is the intended deduplication behavior.

422 Unprocessable Entity

The request is valid but cannot be executed.

CodeDescription
INSUFFICIENT_BALANCEThe vault does not hold enough of the requested token to cover the payment amount.
SIMULATION_FAILEDThe transaction simulation (eth_call) reverted. The details field contains the revert reason. No gas was spent.
SWAP_SLIPPAGE_EXCEEDEDFor swap-and-pay transactions, the available swap route would result in slippage exceeding the vault's configured tolerance.
NO_SWAP_ROUTEFor swap-and-pay transactions, no viable swap route was found for the requested token pair.

429 Too Many Requests

CodeDescription
RATE_LIMITEDThe bot or vault has exceeded the rate limit. The response includes a Retry-After header with the number of seconds to wait before retrying.

500 Internal Server Error

CodeDescription
INTERNAL_ERRORAn unexpected error occurred in the relayer. The payment was not executed. Retry with the same idempotencyKey is safe.
RPC_ERRORThe relayer was unable to communicate with the blockchain RPC node. Retry after a brief delay.
AI_VERIFICATION_TIMEOUTThe AI verification agents did not respond within the expected window. The payment was not executed. You may retry.

Handling Errors

Retryable Errors

The following errors are safe to retry with the same idempotencyKey:

  • 429 RATE_LIMITED -- wait for the duration specified in Retry-After
  • 500 INTERNAL_ERROR -- retry after a brief backoff
  • 500 RPC_ERROR -- retry after a brief backoff
  • 500 AI_VERIFICATION_TIMEOUT -- retry after 30-60 seconds

Non-Retryable Errors

These errors require changes to the request before retrying:

  • 400 errors -- fix the request body
  • 403 errors -- check vault configuration (bot whitelist, limits, pause state)
  • 409 IDEMPOTENCY_CONFLICT -- use a new idempotency key for the new intent
  • 422 INSUFFICIENT_BALANCE -- deposit funds to the vault

Example Error Handling

const response = await fetch('https://relay.axonfi.xyz/v1/payments', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(payload),
});
 
if (!response.ok) {
  const error = await response.json();
 
  switch (error.code) {
    case 'RATE_LIMITED':
      const retryAfter = response.headers.get('Retry-After');
      await sleep(Number(retryAfter) * 1000);
      // Retry with same idempotencyKey
      break;
    case 'INSUFFICIENT_BALANCE':
      console.error('Vault needs more funds:', error.details);
      break;
    case 'BOT_NOT_ACTIVE':
      console.error('Bot not registered on vault');
      break;
    default:
      console.error(`${error.code}: ${error.error}`);
  }
}