Skip to content

Rate Limits

Rate limits protect the API from abuse and ensure fair access for all users.

PlanRequests/DayRequests/MinuteBurst
Free1,0001020
Pro50,000100200
Business200,0005001,000
EnterpriseCustomCustomCustom

Every response includes rate limit information:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 842
X-RateLimit-Reset: 1709856000
HeaderDescription
X-RateLimit-LimitTotal requests allowed per day
X-RateLimit-RemainingRequests remaining today
X-RateLimit-ResetUnix timestamp when limit resets

When you exceed your rate limit, the API returns 429 Too Many Requests:

{
"_tag": "RateLimitExceeded",
"message": "Rate limit exceeded. Retry after 60 seconds.",
"retryAfter": 60
}

The Retry-After header indicates when you can retry.

Cache responses when possible. Card data and set information change infrequently.

// Example: Cache card data for 1 hour
const card = await cache.get(`card:${id}`)
?? await pulls.cards.get(id).then(c => {
cache.set(`card:${id}`, c, { ttl: 3600 })
return c
})

Use bulk endpoints instead of making individual requests:

// Bad: 100 requests
for (const id of cardIds) {
await pulls.cards.get(id)
}
// Good: 1 request
const cards = await pulls.cards.list({ ids: cardIds })
async function fetchWithRetry(fn: () => Promise<T>, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn()
} catch (e) {
if (e.status === 429) {
const delay = Math.pow(2, i) * 1000
await new Promise(r => setTimeout(r, delay))
} else {
throw e
}
}
}
}

Query your current usage via the /v1/usage endpoint:

Terminal window
curl -H "Authorization: Bearer pk_live_..." \
https://api.pulls.app/v1/usage
{
"plan": "pro",
"period": {
"start": "2024-03-01T00:00:00Z",
"end": "2024-03-31T23:59:59Z"
},
"requests": {
"used": 12500,
"limit": 50000,
"remaining": 37500
}
}

Contact us for Enterprise pricing with custom limits, dedicated support, and SLA guarantees.