Errors

Error shapes, status codes, retries, rate limits and on-chain reverts.

The API uses standard HTTP status codes. Treat every non-2xx response as non-executable: never submit a transaction from a failed or expired quote.

Error shape

Most failures return a flat JSON object with one error string:

{ "error": "amount must be positive" }

The error message is diagnostic text and can change. Branch on the HTTP status and, when present, on the machine-readable code. Log the message on your backend and show your own copy in the UI. Not every error includes a code; clients must still handle the HTTP status when it is absent.

{ "code": "quote_capacity_exhausted", "error": "quote capacity exhausted; retry shortly" }

Error codes

codeStatusMeaningClient action
amount_not_raw_integer400amount is not a raw base-unit integer stringConvert with the input token's decimals and send digits only, without a sign, decimal point, exponent or hex prefix
outside_notional_range400The requested size is outside the executable range for this pairRead Markets and limits and resize; the message gives the range when known
recipient_funding_insufficient400The recipient lacks the input token balance or SettlementRouter allowanceFund and approve the input, then request a new firm quote
provider_request_rejected400This exact request was rejected; the message gives a public-safe reasonCorrect the request; do not retry unchanged
trial_order_too_large400The requested order exceeds your trial access size allowanceReduce the size within your agreed trial allowance; do not retry unchanged
trial_access_paused403Trial quoting is paused for your accessContact Rave before retrying
trial_pair_not_allowed403The requested pair or direction is not included in your trial accessUse an agreed trial pair and direction, or contact Rave
trial_recipient_not_allowed403The recipient is not included in your trial accessUse an agreed recipient; do not substitute a different wallet automatically
route_requires_solver_assignment403The request requires an authenticated solver order assignment that was not providedUse the assigned-order integration agreed with Rave; do not retry unchanged
route_not_found404The API path does not existCheck the path and API version; authentication may be checked first
method_not_allowed405The path does not accept this HTTP methodUse the documented method
quote_capacity_exhausted409The requested market capacity is temporarily exhaustedHonor Retry-After when present, then request a fresh quote; re-read levels and limits before resizing
exact_input_sizing_rejected409A firm quote could not fit within the input amount requestedRequest a fresh quote without increasing the user's budget automatically
caller_rate_limited429An identical firm operation was repeated too oftenHonor Retry-After, then back off with jitter
trial_daily_limit_reached429Your trial access has reached its usage allowanceHonor Retry-After, then request a fresh quote; avoid repeated immediate retries
source_capacity_limited503Quote capacity is currently limited for this request source; no executable quote is returnedBack off with jitter and request a fresh quote; contact Rave if it persists. Do not change source attribution to bypass the refusal
trial_guardrail_unavailable503Trial access eligibility could not be verified; no executable quote is returnedBack off with jitter and request a fresh quote; contact Rave if it persists
external_rfq_v2_not_enabled503The requested quoting capability is not enabled for this caller on this chainContact Rave; do not retry the same request until the capability is enabled

A failed quote is never executable, regardless of its code.

One exception: a malformed query string (for example a missing recipient on /v2/executions, or a non-numeric chain_id) returns 400 with a text/plain body such as Failed to deserialize query string: missing field recipient. Check Content-Type before parsing JSON.

Status codes

StatusMeaningClient action
400Invalid field value (for example a non-positive or unparseable amount, a bad recipient, or a missing firm recipient), malformed JSON, or a malformed query stringFix the input; do not retry unchanged
401Missing or invalid API keyCheck backend credential configuration (Authentication)
404Pair not published on that chain, unknown quote ID, or transaction not yet indexedRe-read discovery, or poll transactions with backoff
409Firm quote_attempt_id reused for a different request, already finished, or still in progress; or quote capacity exhaustedUse a new quote_attempt_id, or back off and request a fresh quote
422Valid JSON that does not match the schema (missing required field, wrong type such as a numeric amount, or V1 fields)Fix the body; do not retry unchanged
429Rate limited, when returnedBack off with jitter server-side
500Unexpected service errorRetry later with a fresh quote
503Quoting temporarily unavailable, or the requested size exceeds current depthRe-read levels and limits, reduce size, or retry later

Examples

StatusBody
400{ "error": "recipient required for firm quotes" }
401{ "error": "unauthorized" }
404{ "error": "asset not found for pair 0x.../0x..." }
404{ "error": "transaction not found" }
422{ "error": "invalid quote request" }
503{ "error": "price-stream depth does not cover requested amount for 0x.../0x... on chain 56" }

Treat any 401 as an auth-configuration problem even if an intermediary strips the body. The stream checks the key on the handshake, so a bad key is an HTTP 401 before the upgrade, not a WebSocket close frame.

Temporary quoting-control outages

If a quoting-control read fails, requests can continue using a retained last-known-good control state while that state remains usable. Only when no usable control state remains do quotes, levels and limits return HTTP 503:

{ "error": "current provider controls unavailable; retry shortly" }

This response has no machine-readable code or dedicated Retry-After hint. Handle the HTTP status, back off with jitter, and do not treat the refusal as an executable quote or a healthy empty book. An established stream closes with 1011; discard that connection's cached book and rebuild after reconnecting.

An identical firm-quote retry can also be refused when current eligibility cannot be verified or has changed, even if the original response succeeded. Withholding the replay does not cancel the original transaction packet. If it may have been broadcast, reconcile it before requesting another trade; its own expiry and settlement state still apply.

Retries and backoff

  • Retry 429, 500 and 503 with exponential backoff and jitter (for example base 250 ms, factor 2, cap a few seconds).
  • Do not retry unchanged 400, 401, 422, or a 404 for an unpublished pair. A 404 from /v2/transactions/{id_or_tx_hash} right after a send usually means the settlement is not indexed yet; poll with backoff.
  • Cap retries and fail the user action cleanly instead of looping.
  • Any retry that leads to execution uses a freshly requested quote, and only after an earlier broadcast has been reconciled as failed or dropped. See Transaction safety.

Rate limits

Each API key has separate rolling 60-second request budgets for market-data reads and other operations:

  • GET and HEAD on /api/v2/markets/levels, /api/v2/markets/status, /api/v2/assets, and /api/v2/assets/by-address/{address} use the market-data read budget.
  • Quotes, /api/v2/limits, the stream handshake, and other operations use the other budget. A burst of quote requests does not consume the market-data read budget, and market-data polling does not consume the quote budget. Both budgets can still independently return 429.

Limits are configured for your key; contact Rave if your integration needs a different request rate. The separate identical-firm-operation guard can also return 429 with code: "caller_rate_limited", even when a request budget is not exhausted.

Responses do not carry rate-limit headers (X-RateLimit-*) or a quota counter. When a 429 arrives, back off server-side with jitter. If a Retry-After header is present, honor it. For live data prefer the stream over polling levels.

Request correlation

There is no documented request-ID header. When you contact Rave, send:

  • the firm quote_id (soft-quote IDs are not stored);
  • trade_id and tx_hash from /v2/transactions/{id_or_tx_hash};
  • the endpoint, HTTP method and request time.

On-chain reverts

A firm quote that returned 200 can still fail on chain. A revert is not an API error, so there is no JSON body: you see a failed transaction. If the Rave leg sits inside a larger transaction, the whole transaction fails. The user receives nothing and pays gas.

CauseHow to avoid it
The packet was submitted after expiresSubmit inside valid_for_secs; re-quote instead of resubmitting
Less than the quoted input was available on an exact quoteMake at least amount_in available whenever input_capability is absent or mode is "exact"; settlement consumes no more than that amount
Less than the quoted input was delivered on a variable sideRoute variable sides from levels and let Rave handle a short delivery. Do not put an exact side behind a hop that can land short
token_in allowance to the /v2/limits allowance_target was insufficientComplete the approval before requesting the firm quote

Underfunding surprises integrators most, because the shortfall can be a handful of base units. On an exact side it is not a partial fill: the transaction reverts with FillOutOfSignedWindow(uint256,uint256,uint16,uint16), selector 0x42aa024f. On a variable side Rave handles a short delivery. See Variable Input.

Delivering more than amount_in does not revert. Settlement takes the quoted amount and leaves the surplus with you.

None of these is retryable with the same packet. Once the reverted receipt confirms the failure, request a fresh firm quote.

After a broadcast error

Never re-broadcast or request a new firm quote until the first transaction is known to have failed or been dropped. The full procedure is in Transaction safety.

Transaction safety checklist

The pre-signing checklist and quote-expiry rules moved to Transaction safety.


Did this page help you?