Errors and Security

Error shapes, retry/backoff, rate limits, quote-expiry recovery, authentication failures, and transaction safety.

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

Error shape

Requests that fail validation or authentication return a flat JSON object:

{
  "error": "amount must be greater than 0"
}

Log the error string on your backend and show user-friendly copy in your UI.

Authentication failures

Missing or invalid authentication returns 401 with the same flat JSON shape:

{ "error": "unauthorized" }

Treat any 401 as an auth-configuration problem even if an intermediary strips the body. WebSocket stream authentication also fails before the protocol upgrade, so rejected handshakes are HTTP 401 responses rather than WebSocket close frames.

if status == 401:
    error = response.json().get("error", "unauthorized") if response.body else "unauthorized"
    handle_auth_error(error)
elif not response.body:
    handle_empty_response()
else:
    error = response.json()["error"]

401 troubleshooting:

  • Confirm the backend is sending Authorization: Bearer *** with a valid, non-expired key.
  • Confirm the request is server-side — keys must never be sent from the browser.
  • Confirm you are calling the direct API host https://api.rave-trading.com/api.

Status handling

StatusMeaningClient action
400Invalid request body or unsupported token pairFix validation; do not retry unchanged
401Missing or invalid API keyCheck backend credential configuration
404Quote, asset, or endpoint not foundRefresh state or request a new quote
409Quote can no longer be used, when returnedRequest a fresh quote
422Amount outside accepted limits, when returnedUpdate UI bounds and ask the user to revise
429Rate limited, when returnedBack off with jitter server-side
500Unexpected service errorRetry later with a fresh quote
503Quoting temporarily unavailableDisable execution UI and retry later

Validation examples

400 — malformed or unsupported request:

{ "error": "unsupported token pair for chain_id 56" }

422 — amount outside the currently quoteable bounds (read /v2/limits and adjust):

{ "error": "amount below minimum input for this side" }

Retry and backoff

  • Retry 429, 500, and 503 with exponential backoff and jitter (for example base 250 ms, factor 2, cap a few seconds, plus random jitter).
  • Do not retry unchanged 400, 401, 404, or 422 requests — fix the input first.
  • Cap retries and fail the user action cleanly rather than looping.
  • Every retry that leads to execution must use a freshly requested quote, never a stored one.

Rate limits

When a 429 is returned, back off server-side with jitter and avoid tight client retry loops. If rate-limit headers (for example Retry-After) are present on a response, honor them; otherwise fall back to your backoff schedule.

Request correlation

The API does not currently return a dedicated request-ID header. Correlate and escalate using the identifiers the API already gives you:

  • quote_id from soft/firm quote responses;
  • trade_id and tx_hash from /v2/transactions/{id_or_tx_hash};
  • the endpoint, HTTP method, and request timestamp.

Quote expiry recovery

Firm quotes are short-lived (typically 15–30 seconds; see valid_for_secs and expires).

  • If expires has passed before submission, discard the quote and request a fresh firm quote.
  • If the wallet signing or broadcast step fails for any reason, request a fresh firm quote before retrying — do not resubmit a stale transaction packet.
  • Use GET /v2/quotes/{quote_id} to check whether a quote is still active or already expired.

On-chain settlement failures

A firm quote that returned 200 can still fail on chain. These failures are reverts of the
settlement transaction, not API errors, so there is no JSON body to read: you see a failed
transaction. Because a Rave leg often sits inside a larger transaction, the revert propagates and the
whole transaction the user signed 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 allowance checklist before requesting the firm quote

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

Delivering more than amount_in is not one of these failures. The settlement takes the quoted
amount and no more, and the surplus is left with you, so overshooting does not revert and needs no
haircut to protect against. Only an exact-side underfund fails.

None of the failures above are retryable with the same packet. Request a fresh firm quote.

Transaction safety checklist

Before signing an execution.transaction:

  1. expires is still in the future.
  2. The connected wallet is on the returned chain_id.
  3. The transaction target (to) matches the documented SettlementRouter for that chain (see Smart Contracts); do not substitute other addresses.
  4. token_in allowance to the /v2/limits allowance_target and the wallet balance are sufficient.
  5. If the side you routed was exact or the field was missing, at least amount_in must be
    available. If it was variable, Rave handles a short delivery. A missing field always means exact.
  6. Submit to, data, value, and chain_id unchanged. Never edit the calldata client-side.

If the user changes token_in, amount, recipient, chain, or slippage, request a fresh firm quote.

API key handling

  • Send API keys only from your backend. Keep them in a secret manager or environment variable and inject them at request time.
  • Never expose keys in browser code, mobile apps, public logs, or support screenshots.
  • Rotate keys if one may have been exposed, and scope requests through your backend.

Public/private boundary

Partner-facing responses intentionally expose only the fields required to price, display, and submit a quote. Private implementation details stay outside the public API. The public transaction packet is enough for wallet submission: to, data, value, and chain_id.


Did this page help you?