Rate limits
Per-account, per-endpoint token-bucket limits. 429 responses always include a Retry-After header. Production integrations rarely hit them; they exist to prevent buggy clients from hammering carriers.
Default limits
Limits are token-bucket: each account gets a refill rate + a burst capacity. Quoting and reading is more permissive than buying (carriers themselves rate-limit us on label purchases, so we have to throttle on your behalf).
Reads (GET endpoints)
100 / sec
Burst capacity: 200
Quotes (POST /labels/quote)
20 / sec
Burst capacity: 50
Buys (POST /labels/create)
10 / sec
Burst capacity: 20
Address verify
20 / sec
Burst capacity: 50
Need higher? Email support@shiponline.app with your expected traffic shape and we can lift the buy bucket for high-volume accounts.
429 response
When you exceed a bucket, the next request returns HTTP 429 Too Many Requests with two headers + a structured body:
HTTP/1.1 429 Too Many Requests
Retry-After: 4
X-RateLimit-Reset: 1735233700
Content-Type: application/json
{
"code": "rate_limited",
"error": "You've exceeded the buys-per-second limit. Retry in 4 seconds.",
"requestId": "req_HHH..."
}Retry-Afteris the number of seconds to wait before retrying.X-RateLimit-Resetis the absolute Unix timestamp when the bucket refills. Useful if you're aggregating across multiple clients and want to schedule globally.
Backoff guidance
Don't retry immediately. Use exponential backoff with jitter; the carriers themselves throttle us in waves, so a thundering-herd retry will turn one 429 into a flurry of them.
async function withRetry(fn, { maxAttempts = 5 } = {}) {
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
const res = await fn();
if (res.status !== 429) return res;
const retryAfter = Number(res.headers.get("Retry-After")) || 1;
const jitter = Math.random() * 0.4 + 0.8; // 0.8 - 1.2
const waitMs = retryAfter * 1000 * jitter * 2 ** (attempt - 1);
await new Promise((r) => setTimeout(r, waitMs));
}
throw new Error("Rate-limited after " + maxAttempts + " attempts");
}Idempotency keys + 429 = safe