Skip to content

API Reference — Rate limits ​

The API is public and needs no key. Two things are metered so that one script cannot starve everyone else: how many requests an IP sends, and — more tightly — how many signed quotes it asks for.

Limits ​

ScopeLimitKey
Every /api/* route600 requests / minuteclient IP
POST /api/quote10 quotes / minuteclient IP
POST /api/quote30 quotes / minutesender address (canonical form)

Limits are token buckets: the allowance refills continuously (600/min ≈ one request every 100 ms, with the full 600 available as a burst from idle). CORS preflight (OPTIONS) and the long-lived GET /api/orders/stream connection are not counted.

There is also a coarser per-IP cap at the edge (nginx), meant for floods: about 30 requests/s on /api/* with a burst of 20, and 2 requests/s on POST /api/quote with a burst of 5. It answers 429 with a non-JSON body and no Retry-After — pause for a second or two and retry.

What a rejection looks like ​

Every metered response carries the allowance of the last bucket checked: the per-IP bucket on most routes; on POST /api/quote with a sender in the body, the per-sender bucket (30) — the 10/min per-IP bucket only shows up in its own 429.

txt
X-RateLimit-Scope: anonymous
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 29

When you are over the limit you get 429 Too Many Requests:

txt
HTTP/1.1 429 Too Many Requests
Retry-After: 6
Content-Type: application/json

{ "error": "RATE_LIMITED", "retryAfterSec": 6 }

Retry-After (seconds, whole) is the earliest moment the next request will pass. Sleep for it, then retry — do not tight-loop; every rejected attempt is itself a request.

Quote once, pay once

A quote is valid for 180 s — you do not need to re-quote while a quote is still live, and you should not request a quote before you are ready to send the transaction. Batches (multisend) are one quote regardless of the recipient count, so 10 quotes/min is 10 swaps, not 10 recipients.

Running at volume?

If the anonymous allowance is too small for what you are building, reach out on Telegram or Discord.

Not rate limits ​

Two other 5xx answers look similar but mean something else:

StatusBodyMeaning
503{ "error": "WARMING_UP", "retryAfterSec": 5, "waitingFor": [...] }The backend just restarted and is loading prices / balances (/api/quotes, /api/prices, POST /api/quote). Retry after Retry-After.
503{ "error": "Quoting is disabled", "code": "SIGNING_DISABLED" }Quoting is paused by the operator — see POST /api/quote.

Summary of error shapes ​

StatusBodyMeaning
429{ "error": "RATE_LIMITED", "retryAfterSec": n }per-minute allowance exhausted (IP or sender)
429(empty)edge flood protection — back off harder
503{ "error": "WARMING_UP", "retryAfterSec": n, "waitingFor": [...] }backend warming up — retry