Rate Limiting
Per-project request limits, response headers, and 429 handling.
The First Leeward API is shared infrastructure. To keep it reliable for everyone, requests are rate-limited per project on rolling per-second, per-minute, and per-day windows. Limits apply to the project as a whole, not per API key.
Limits
Most endpoints share the default limit. A small set of write endpoints have tighter limits based on the downstream operations they trigger.
Production
| Tier | Per second | Per minute | Per day |
|---|---|---|---|
| Default | 20 | 600 | 500,000 |
| Card issuance | 10 | 100 | 5,000 |
| Card operations | 15 | 250 | 10,000 |
| Identity verification | 5 | 150 | 2,000 |
| Account creation | 3 | 100 | 10,000 |
| Withdrawals | 6 | 60 | 5,000 |
Sandbox
| Tier | Per second | Per minute | Per day |
|---|---|---|---|
| Default | 10 | 150 | 10,000 |
| Card issuance | 5 | 50 | 500 |
| Card operations | 5 | 100 | 1,000 |
| Identity verification | 2 | 30 | 300 |
| Account creation | 2 | 50 | 2,000 |
| Withdrawals | 6 | 30 | 500 |
Card issuance covers:
POST /cardsPOST /card-shipments/:id/submit
Card operations covers:
POST /cards/:id/freezePOST /cards/:id/unfreezePOST /cards/:id/blockPOST /cards/:id/unblockDELETE /cards/:idPOST /cards/:id/revealPOST /cards/:id/reveal-panPUT /cards/:id/pinPOST /cards/:id/activateGET /cards/:id/activation-codePOST /cards/:id/push-provisioningPUT /cards/:id/3ds-challenge-methodPOST /card-shipmentsPOST /disputes
Identity verification covers:
POST /companiesPOST /companies/:id/applicationsPOST /users/:id/applicationPOST /users/:id/application/documents
Account creation covers:
POST /accounts
Provisioning a wallet-backed account creates keys and registers deposit addresses with our chain infrastructure, so it is paced more tightly than plain reads and writes.
Withdrawals covers:
POST /crypto-withdrawalsGET /crypto-withdrawals/:id/payloadPOST /crypto-withdrawals/:id/sign
These limits are lower than the rest because each call reserves scarce chain and custody resources. The per-second allowance leaves room for one withdrawal's three calls back to back. Reading a withdrawal or cancelling one is not affected.
All other endpoints fall under the default limit.
Response headers
Every response includes the following headers so you can track usage without making extra requests.
| Header | Description |
|---|---|
RateLimit-Limit | Maximum requests allowed in the current window |
RateLimit-Remaining | Requests remaining in the current window |
RateLimit-Reset | Unix timestamp (seconds) when the current window resets |
RateLimit-Policy | Identifier for the limit applied to this request |
Legacy X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers are also returned for compatibility with older HTTP clients.
Exceeding the limit
When a request exceeds your limit, the API responds with 429 Too Many Requests:
- The error body uses
code: RATE_LIMIT_EXCEEDED. - A
Retry-Afterheader is set to the number of seconds to wait before retrying.
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. See the Retry-After header for when to retry."
}
}
Wait at least the number of seconds in Retry-After before retrying. Earlier retries will simply receive another 429 until the window resets.
Best practices
- Read the headers. Track
RateLimit-Remainingto back off proactively before the limit hits zero. - Honor
Retry-After. When you receive a429, wait at least the indicated number of seconds before retrying. - Use exponential backoff with jitter. If you must retry beyond the first attempt, increase the wait between retries and add randomness to avoid thundering herds.
- Spread out bulk operations. When onboarding many users or issuing many cards, pace requests against the per-minute and per-day limits rather than firing them as fast as possible.
- Need higher limits? Contact the First Leeward team if your use case genuinely requires more headroom. We tune limits per project where it makes sense.
