Rate Limiting
01 SOFTWARE API rate limit policies and optimization guide
Rate Limiting
The 01 SOFTWARE API enforces two types of limits to ensure fair usage and system stability.
- Rate Limit — Per-minute/per-hour request limits (varies by plan)
- Monthly Quota — Monthly total API call limits (varies by plan)
All limits are applied per tenant. Tenants are identified by the X-Publishable-Key header.
Rate Limit (Per-Minute/Per-Hour)
Burst protection limits vary by plan. Higher plans get higher burst allowances.
| Plan | Per-Minute | Per-Hour |
|---|---|---|
| Free | 600 | 10,000 |
| Starter | 1,200 | 30,000 |
| Basic | 3,000 | 100,000 |
| Pro | 6,000 | 200,000 |
| Enterprise | Unlimited | Unlimited |
Response When Exceeded
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 45
X-RateLimit-Limit: 600
X-RateLimit-Window: minute{
"error": "Rate limit exceeded",
"message": "Too many requests. Per-minute limit (600) exceeded. Please try again later.",
"retryAfter": 45
}| Header | Description |
|---|---|
Retry-After | Wait time until next request (seconds) |
X-RateLimit-Limit | Maximum requests for the window |
X-RateLimit-Window | Applied limit window (minute or hour) |
Monthly Quota
The total monthly API call count varies by plan.
| Plan | Monthly API Calls |
|---|---|
| Free | 500,000 |
| Starter | 500,000 |
| Basic | 2,000,000 |
| Pro | 5,000,000 |
| Enterprise | Unlimited |
Usage Headers
Monthly usage information is included in response headers for successful requests.
HTTP/1.1 200 OK
X-Usage-Limit: 100000
X-Usage-Current: 45230
X-Usage-Remaining: 54770| Header | Description |
|---|---|
X-Usage-Limit | Maximum monthly API calls |
X-Usage-Current | Current month usage |
X-Usage-Remaining | Remaining calls this month |
Response When Exceeded
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
X-Usage-Limit: 10000
X-Usage-Current: 10001
X-Usage-Remaining: 0{
"error": "Usage limit exceeded",
"message": "Monthly API call limit (10,000) exceeded for your plan. Please upgrade your plan or wait until next month.",
"usage": {
"limit": 10000,
"current": 10001,
"remaining": 0
}
}Distinguishing 429 Responses
You can distinguish between the two types of 429 responses by their headers.
| Type | Header | Meaning |
|---|---|---|
| Rate Limit | X-RateLimit-Window present | Per-minute/per-hour limit exceeded - retry after a short wait |
| Monthly Quota | X-Usage-Limit present | Monthly quota exceeded - plan upgrade required |
Retry Strategy
The SDK automatically retries requests with exponential backoff. See Error Handling for retry behavior details.
Error Handling
SDK Error Handling
import { isUsageLimitError } from '@01.software/sdk'
try {
const { docs } = await client.from('posts').find()
} catch (error) {
if (isUsageLimitError(error)) {
// Monthly API quota exceeded
console.log(error.message)
console.log(error.usage) // { used, limit } usage information
console.log(error.suggestion) // Plan upgrade guidance
showNotification('Monthly API call limit exceeded. Please consider upgrading your plan.')
}
}Optimization Strategies
1. Leverage Caching
// Automatic caching with React Query
const { data } = client.query.useQuery(
{
collection: 'posts',
options: { limit: 10 },
},
{
staleTime: 5 * 60 * 1000, // 5 minutes
gcTime: 10 * 60 * 1000 // 10 minutes
}
)2. Batch Requests
// Bad: Multiple requests
for (const id of postIds) {
await client.from('posts').findById(id) // N requests
}
// Good: Single request
const { docs } = await client.from('posts').find({
where: {
id: { in: postIds }
}
})3. Request Only Needed Fields
// Use select option to request only needed fields
const { docs } = await client.from('posts').find({
limit: 10,
select: { title: true, slug: true }
})4. Use Webhooks
Use webhooks instead of polling when you need real-time updates.
// Bad: Polling (inefficient)
setInterval(async () => {
await client.from('posts').find()
}, 5000) // Request every 5 seconds
// Good: Webhook (efficient)
// app/api/webhook/route.ts
export async function POST(request: Request) {
return handleWebhook(request, async (event) => {
if (event.collection === 'posts') {
// Handle post updates
}
})
}5. Pagination Optimization
// Good: Use appropriate limit
const { docs } = await client.from('posts').find({
limit: 20, // Only what you need
page: 1
})
// Bad: Excessive limit
const { docs } = await client.from('posts').find({
limit: 1000 // Unnecessarily large amount of data
})Next Steps
- REST API - How to use the REST API
- Client - SDK client setup
- Error Handling - How to handle errors