Rate Limits
Understand rate limiting tiers, response headers, and how to handle throttling.
Overview
The LendWorks API uses a sliding window rate limiter scoped per API key. Each key is assigned a tier that determines its request-per-minute allowance.
Tiers
| Tier | Requests / minute | Best For |
|---|---|---|
basic | 100 | Development, testing, low-volume integrations |
standard | 1,000 | Production integrations |
premium | 10,000 | High-volume production, bulk operations |
Your key's tier is set when the key is created in Admin > API Keys.
Response Headers
Every authenticated response includes rate limit headers:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 987
X-RateLimit-Reset: 1709510400
X-RateLimit-Window: 60| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed in the window |
X-RateLimit-Remaining | Requests remaining in the current window |
X-RateLimit-Reset | Unix timestamp when the window resets |
X-RateLimit-Window | Window duration in seconds (always 60) |
When You're Throttled
When you exceed the rate limit, you'll receive a 429 Too Many Requests response:
{
"errors": [
{
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Try again in 45 seconds.",
"detail": {
"retryAfter": 45,
"limit": 1000,
"remaining": 0,
"resetAt": "2025-01-15T10:30:00Z"
}
}
]
}The Retry-After header is also set with the number of seconds to wait.
Monthly Quotas
In addition to per-minute rate limits, some plans enforce monthly API quotas. When exceeded:
HTTP/1.1 429 Too Many Requests
Retry-After: 86400{
"errors": [
{
"code": "MONTHLY_QUOTA_EXCEEDED",
"message": "Monthly API quota exceeded. Upgrade your plan for higher limits.",
"detail": {
"currentPlan": "basic",
"resetAt": "2025-02-01T00:00:00Z"
}
}
]
}Handling Rate Limits
With the SDK
The SDK handles rate limit retries automatically with configurable behavior:
import { LendWorksClient } from '@lendworks/sdk-node'
const client = new LendWorksClient({
apiKey: process.env.LENDWORKS_API_KEY,
// SDK automatically retries on 429 with exponential backoff
})Manual Handling
async function apiCall(url: string, options: RequestInit) {
const response = await fetch(url, options)
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get('Retry-After') || '60', 10)
console.log(`Rate limited. Retrying in ${retryAfter}s...`)
await new Promise(r => setTimeout(r, retryAfter * 1000))
return apiCall(url, options) // Retry
}
return response
}Best Practices
- Monitor headers — Track
X-RateLimit-Remainingto proactively slow down before hitting limits - Batch operations — Use bulk endpoints where available instead of individual requests
- Cache responses — Cache read responses client-side to reduce API calls
- Use webhooks — Subscribe to webhooks instead of polling for changes
- Spread requests — Distribute requests evenly across the minute window rather than bursting