Rate Limiting
The API allows 60 requests per minute per API key. Limits are enforced with a sliding window.
Response Headers
Responses that pass API key validation and permission checks include rate-limit headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests per window (60) |
X-RateLimit-Remaining | Requests remaining in the current window |
X-RateLimit-Reset | Unix timestamp (seconds) when the window resets |
curl -i https://shipwave.app/api/v1/orders \
-H "Authorization: Bearer sw_live_abc123..."
# Response headers:
# X-RateLimit-Limit: 60
# X-RateLimit-Remaining: 58
# X-RateLimit-Reset: 1708372800
Exceeding the Limit
When you exceed the limit, the API returns 429 Too Many Requests:
{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded. Try again later."
}
}
The response still includes the X-RateLimit-Reset header so you know when to retry.
Best Practices
-
Check headers proactively. Use
X-RateLimit-Remainingto slow down before hitting the limit. -
Implement exponential backoff. On a 429, wait and retry with increasing delays:
async function fetchWithRetry(url: string, options: RequestInit, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const res = await fetch(url, options);
if (res.status !== 429) return res;
const resetAt = Number(res.headers.get("X-RateLimit-Reset"));
const waitMs = Math.max((resetAt * 1000) - Date.now(), 1000);
await new Promise((r) => setTimeout(r, waitMs));
}
throw new Error("Rate limit exceeded after retries");
}
- Batch where possible. Use filters and pagination to reduce the number of requests instead of fetching resources one at a time.