Rate Limits
The PropertyBase API implements rate limiting to ensure fair usage and platform stability.
Rate Limit Tiers​
| Plan | Requests/min | Requests/day | Burst |
|---|---|---|---|
| Starter | 60 | 10,000 | 10 |
| Professional | 120 | 50,000 | 25 |
| Enterprise | 600 | Unlimited | 100 |
Rate Limit Headers​
Every API response includes rate limit information:
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 115
X-RateLimit-Reset: 1706198400
| Header | Description |
|---|---|
X-RateLimit-Limit | Requests allowed per minute |
X-RateLimit-Remaining | Requests remaining in window |
X-RateLimit-Reset | Unix timestamp when limit resets |
Rate Limit Response​
When you exceed the rate limit, you'll receive a 429 Too Many Requests response:
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Please retry after 45 seconds.",
"retry_after": 45
}
}
Retry-After Header​
HTTP/1.1 429 Too Many Requests
Retry-After: 45
Endpoint-Specific Limits​
Some endpoints have additional limits:
| Endpoint | Limit | Notes |
|---|---|---|
POST /leads | 100/min | Lead creation |
POST /leads/bulk | 10/min | Bulk operations |
POST /*/import | 5/min | Data imports |
GET /analytics/* | 30/min | Analytics queries |
Handling Rate Limits​
Exponential Backoff​
Implement exponential backoff for retries:
async function apiRequest(url: string, options: RequestInit, retries = 3) {
for (let i = 0; i < retries; i++) {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
const delay = Math.min(retryAfter * 1000, Math.pow(2, i) * 1000);
console.log(`Rate limited. Retrying in ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
return response;
}
throw new Error('Max retries exceeded');
}
Request Queuing​
Queue requests to stay within limits:
class RateLimiter {
private queue: Array<() => Promise<void>> = [];
private processing = false;
private requestsPerMinute: number;
private requestInterval: number;
constructor(requestsPerMinute: number) {
this.requestsPerMinute = requestsPerMinute;
this.requestInterval = 60000 / requestsPerMinute;
}
async enqueue<T>(fn: () => Promise<T>): Promise<T> {
return new Promise((resolve, reject) => {
this.queue.push(async () => {
try {
const result = await fn();
resolve(result);
} catch (error) {
reject(error);
}
});
this.processQueue();
});
}
private async processQueue() {
if (this.processing) return;
this.processing = true;
while (this.queue.length > 0) {
const fn = this.queue.shift();
if (fn) {
await fn();
await new Promise(r => setTimeout(r, this.requestInterval));
}
}
this.processing = false;
}
}
// Usage
const limiter = new RateLimiter(60); // 60 requests per minute
await limiter.enqueue(() => api.getLeads());
await limiter.enqueue(() => api.getProperties());
Bulk Operations​
For large data operations, use bulk endpoints:
Efficient Approach​
# Single bulk request (10 items)
POST /v1/units/bulk
{
"units": [
{ "name": "Unit 1", ... },
{ "name": "Unit 2", ... },
// ... up to 100 items
]
}
Inefficient Approach​
# 10 separate requests - consumes more rate limit
POST /v1/units { "name": "Unit 1", ... }
POST /v1/units { "name": "Unit 2", ... }
...
Monitoring Usage​
Check Current Usage​
GET /v1/rate-limit
{
"success": true,
"data": {
"plan": "professional",
"minute": {
"limit": 120,
"used": 45,
"remaining": 75,
"reset": "2024-01-25T15:01:00Z"
},
"daily": {
"limit": 50000,
"used": 12500,
"remaining": 37500,
"reset": "2024-01-26T00:00:00Z"
}
}
}
Usage Alerts​
Set up alerts in Settings > API > Usage Alerts:
- 80% daily limit reached
- 90% daily limit reached
- Rate limit exceeded
Best Practices​
- Cache responses - Reduce unnecessary API calls
- Use webhooks - Instead of polling for changes
- Batch requests - Use bulk endpoints when possible
- Implement backoff - Handle rate limits gracefully
- Monitor usage - Track API consumption
- Request only what you need - Use field selection
Requesting Higher Limits​
If you need higher rate limits:
- Contact sales@propertybase.ai
- Describe your use case
- Provide current usage metrics
- Request specific limits needed
Enterprise customers can negotiate custom limits.