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 idempotent DeFi order reuse 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
Unable to fetch actionable same-chain DeFi fixed-rate quote for the provided deposit_amount. Please retry.GET /rate/ (actionable)Transient RFQ failureRetryable with backoff (respect the ~15s refetch cooldown)
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)An indicative quote was used where an actionable one is requiredFix the flow: request an actionable quote
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

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 fieldsAddress failed the per-currency format validation
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 (RFQ) quoting has additional, tighter limits, returned as 429 with:

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

These responses may arrive without a Retry-After header — apply your own backoff. Additionally, identical same-chain actionable quote requests are internally cooled down for ~15 seconds; don't re-request an actionable quote for the same pair/amount more often than that.

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).
  • Actionable RFQ quotes can take several seconds to produce — set request timeouts of 15 s or more for GET /rate/?actionable_quote=true and POST /orders/ on DeFi fixed-rate flows, and treat client-side timeout + retry via the idempotency/refresh patterns above.

Next steps