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
| Status | Meaning | Client action |
|---|---|---|
400 | Invalid request body or unsupported token pair | Fix validation; do not retry unchanged |
401 | Missing or invalid API key | Check backend credential configuration |
404 | Quote, asset, or endpoint not found | Refresh state or request a new quote |
409 | Quote can no longer be used, when returned | Request a fresh quote |
422 | Amount outside accepted limits, when returned | Update UI bounds and ask the user to revise |
429 | Rate limited, when returned | Back off with jitter server-side |
500 | Unexpected service error | Retry later with a fresh quote |
503 | Quoting temporarily unavailable | Disable 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, and503with 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, or422requests — 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_idfrom soft/firm quote responses;trade_idandtx_hashfrom/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
expireshas 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 stillactiveor alreadyexpired.
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.
| Cause | How to avoid it |
|---|---|
The packet was submitted after expires | Submit inside valid_for_secs; re-quote instead of resubmitting |
Less than the quoted input was available on an exact quote | Make 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 side | Route 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 insufficient | Complete 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:
expiresis still in the future.- The connected wallet is on the returned
chain_id. - The transaction target (
to) matches the documented SettlementRouter for that chain (see Smart Contracts); do not substitute other addresses. token_inallowance to the/v2/limitsallowance_targetand the wallet balance are sufficient.- If the side you routed was
exactor the field was missing, at leastamount_inmust be
available. If it wasvariable, Rave handles a short delivery. A missing field always means exact. - Submit
to,data,value, andchain_idunchanged. 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.
Updated 17 days ago