Skip to main content

Errors and limits

Error format​

Every error has the same shape, with a machine-readable code and a human-readable message:

{
"error": {
"code": "SIMULATION_FAILED",
"message": "The output at the latest block is below minAmountOut: request a new quote or allow more slippage",
"reason": "Slippage"
},
"requestId": "req_5f2c9a0b1d3e4f67"
}

The same requestId is in the X-Request-Id header of every response, successful or not. Log it, and include it when you contact support.

Branch on code, not on message: messages may be reworded.

Error codes​

HTTPcodeMeaningWhat to do
400INVALID_REQUESTA field is missing or invalid, or the body isn't JSON. The message names the field.Fix the request. Don't retry unchanged.
401UNAUTHORIZEDMissing, wrong or revoked API key.Check the header. Ask for a new key if it was revoked.
404NOT_FOUNDUnknown path.Use POST /quote or POST /swap.
404API_DISABLEDThe API is temporarily switched off.Retry later.
405METHOD_NOT_ALLOWEDNot a POST.Use POST with a JSON body.
409SIMULATION_FAILEDThe transaction would revert. See reason below.Build a fresh /swap, or tell the user.
413INVALID_REQUESTBody larger than 16 KB.Send a smaller body.
422NO_ROUTENo route for this pair and amount.Try a smaller amount, or another pair. Tokens with transfer taxes or restrictions are never routable.
429RATE_LIMITEDOver your key's per-minute limit, or too many requests with a bad key from your IP.Wait for Retry-After seconds.
429CONCURRENCY_LIMITEDToo many requests in flight on your key at once.Wait for one to finish, then retry.
502INTERNALThe route couldn't be prepared.Retry once or twice with backoff.
503OVERLOADEDThe API is busy.Wait for Retry-After seconds.
503UNAVAILABLERouting is briefly unavailable.Retry with backoff.
504TIMEOUTRouting took too long.Retry with backoff.

Simulation failures​

A 409 SIMULATION_FAILED comes with a reason from the executor when there is one:

reasonMeaningFix
SlippageThe output would fall below minAmountOut.Request a fresh /swap. If it keeps happening, the pair is volatile: allow more slippage.
ExpiredThe deadline has passed.Use a later deadline, or leave it out for the 20-minute default.
PausedThe executor is paused.Retry later.
StaleFeeConfigAchSwap's fee changed since the quote.Request a fresh /swap.
InvalidRoute, InvalidConfigThe route is no longer valid, for example a pool changed.Request a fresh /swap.
InvalidValueThe transaction value doesn't match the input.Send tx.value exactly as returned.
UnsupportedTokenA token in the route can't be settled exactly.Choose another token.
NativeTransferFailedThe recipient or fee recipient can't receive native USDC.Use an address that can, or take the ERC-20 (0x3600…) as output.
Error or noneAnother revert, often an allowance or balance the sender doesn't have.Check the sender's balance.

When to retry​

Retry with exponential backoff (for example 0.5 s, 1 s, 2 s) and give up after a few attempts. When Retry-After is present, wait at least that long.

Rate limits​

LimitValue
Requests per keySet per key, 60 a minute unless agreed otherwise.
Requests in flight per key2 at a time.
Request body16 KB.

Responses to an authenticated request tell you where you stand:

HeaderMeaning
X-RateLimit-LimitYour key's requests per minute.
X-RateLimit-RemainingRequests left in the current window.
Retry-AfterOn 429 and 503: seconds to wait.

To stay within limits:

  • Quote when the user pauses typing, not on every keystroke.
  • Share one quote between users looking at the same pair and amount, for a few seconds.
  • Call /swap only when a user confirms.

Need more? Email support@achswap.app with your expected volume.

Troubleshooting​

For problems your users may report from the app itself (failed swaps, approvals, gasless), see the user troubleshooting guide.

SymptomLikely cause
Every request returns 401The key is in the wrong header, or has spaces or a line break around it.
amountOut looks a million times too small or too largeThe amount's decimals are wrong. USDC is 6 as the ERC-20 and 18 as native.
The transaction reverts on chain with an allowance errorThe approval wasn't confirmed before the swap was sent. Wait for the approval's receipt.
The swap reverts with Slippage on chainToo long passed between /swap and sending. Build the transaction right before signing.
A user can't swap their whole USDC balanceThe balance also pays gas. Leave a little for the fee.
Your fee isn't arrivingfeeBps is 0, or feeRecipient is missing. Check fees.partnerAmount in the response.