Skip to main content
Version: v2

Errors & Rate Limits

The error contract for all v2 endpoints: response shapes, an error catalog with retryability, and throttling behavior.

Error response shape​

All endpoints use the standard error envelope:

View-level error
{
"detail": "Authentication credentials were not provided."
}
Field validation error
{
"detail": "Invalid input",
"errors": {
"deposit_currency": ["This field is required."],
"withdraw_currency": ["This field is required."]
}
}

Both keys are optional and can co-occur: detail carries the view-level message, errors maps field names to lists of messages.

One exception: POST /pre_screening/ uses its own {status, message} envelope, including for its 400/401 responses — and compliance rejection there is HTTP 200 with status: "failed".

HTTP status codes​

CodeMeaningNotes
200OK, including an existing DeFi order returned to a legacy integration and pre-screening status: "failed"
201Order created
400Validation errorSee catalog below for retryability
401Missing/invalid credentials; referral code not owned by the key ownerAuthentication
403Access refused (e.g. pre-screening rejected at access level)
404Resource not found — also used for "no quotable pairs" on /rate/ and for /pre_screening/ without a trusted tokenOften temporarily unavailable, not unsupported
417GET /pair/random/ exhausted its attempts
429ThrottledSee Rate limits

Error catalog​

Error identification is currently message-based — there are no machine-readable error codes. Match on the stable substrings below (avoid exact-match: wording can gain IDs/values via interpolation).

Quote & rate errors​

Message (pattern)WhereMeaningAction
rate_id '<id>' is invalid or expired.POST /orders/ (DeFi)The bound quote is goneRetryable: fetch a fresh quote, retry once with the new rate_id (refresh-on-submit)
The quote for this rate_id has expired. Please request a new rate.POST /orders/ (DeFi)Quote TTL elapsedRetryable: same as above
Pair <name> is temporarily unavailable.POST /orders/ (CeFi)Covers CeFi quote-validation failures, including expired rate_idRetryable: fresh quote → retry; if it persists, the pair genuinely lacks liquidity right now
Unable to fetch a cross-chain fixed-rate quote. Please retry.POST /orders/ (DeFi cross-chain)Transient upstream liquidity/quoting failure — despite arriving as a validation errorRetryable with backoff
The market has moved beyond this rate's tolerance. Please request a new rate.POST /orders/ (DeFi fixed)The venue cannot deliver the promised rate within toleranceRetryable: fetch a fresh quote, retry once with the new rate_id
Quote provider is unavailable. Please request a new rate.POST /orders/ (DeFi)Upstream quoting outageRetryable with backoff
The provided fixed-rate rate_id is non-actionable for this route. Request a new actionable rate…POST /orders/ (DeFi fixed)The rate_id was issued for a different routeFix the flow: request a fresh fixed-rate quote for the pair you are ordering
This rate_id was issued for a DeFi quote and cannot be used to create a standard (CeFi) order.POST /orders/Mode mismatch between quote and orderFix the request — quote and order must use the same mode
Promised applied referral rate no longer matches current partner limits; request a new quote (rate_id).POST /orders/Partner fee terms changed between quote and createRetryable: fresh quote
This route cannot be quoted right now. Please request a new rate and retry later, or choose another pair.POST /orders/ (DeFi)The route's liquidity provider declined to quote it. This can be a temporary outage or a pair it does not serve, and the response cannot tell whichRetryable later: fetch a fresh quote after a pause; if it keeps failing, offer the user another pair

Request validation errors (not retryable — fix the request)​

Message (pattern)WhereMeaning
Provide either markup (basis points, preferred) or the legacy referral_rate (decimal fraction), not both./rate/, /orders/Mutually exclusive fee params
Must not exceed <N> basis points (the absolute cap on dynamic referral rates)./rate/, /orders/markup above the absolute cap
referral_rate is not allowed for this referral code/rate/, /orders/Dynamic fee capability not enabled — see Affiliate & Referral
rate_id is not supported for limit orders. Remove rate_id when is_limit_order is true.POST /orders/Limit orders take no quote binding
limit_ttl must be at least 600 seconds (10 minutes).POST /orders/Positive limit_ttl below the minimum; omit it to get the default (currently 24 h)
Deposit amount (amount_quote) is required for cross-chain fixed-rate…POST /orders/Cross-chain fixed-rate needs deposit_amount
<value> has invalid characters for a valid value/orders/ address fields, keyed under the field that failed (withdraw_address or refund_address)Address failed the per-currency format validation. The refund address must be valid for the deposit currency, the withdraw address for the currency received
Only one of deposit_amount or withdraw_amount can be provided/pre_screening/Amount exclusivity

Idempotent-conflict errors (safe to treat as success)​

Message (pattern)WhereMeaning
External deposit notification with tx_id <hash>already exists (sic — no space)PATCH /orders/{ref}/ with deposit_transactionThe hash was already recorded — your earlier submission worked

Address validation scope​

Addresses are validated per currency format (regex + checksum — EVM checksums, base58, bech32, …). A fundamentally wrong format is rejected, but chains sharing an address format are not distinguished: a valid-format EVM address intended for a different EVM chain passes validation. Verify the address/chain pairing client-side before order creation — wrong-chain payouts risk fund loss.

Rate limits​

Global throttle​

All v2 endpoints share a global throttle of 2500 requests/minute per API key (and per IP for unauthenticated access). Exceeding it returns:

HTTP 429
Retry-After: <seconds>
{
"detail": "Request was throttled. Expected available in 58 seconds."
}

Honor the Retry-After header when present.

Quote-specific throttles​

DeFi fixed-rate orders created without a rate_id quote the venue on every request and have a tighter limit, returned as 429 with:

  • Too many fixed-rate quote requests. Please retry shortly.

This response may arrive without a Retry-After header — apply your own backoff. Passing the rate_id from GET /rate/ avoids it.

Client-side guidance​

  • Poll order status at 30–60 s intervals (Order Tracking) — well within limits even for hundreds of concurrent orders.
  • Never fetch the unfiltered rate catalogue in a loop (why).
  • DeFi fixed-rate order creation quotes the venue live and can take several seconds. Set request timeouts of 15 s or more for POST /orders/ on DeFi fixed-rate flows, and after a client-side timeout check whether the order was created before sending the request again (why).

Next steps​