API usage quotas and limits.
Oquira imposes rate limits on API requests to ensure system stability, fair usage, and protection against abuse. Understanding these limits will help you design robust integrations.
Each API key has dedicated rate limits based on your subscription plan:
| Plan | Requests/minute | Requests/day |
|---|---|---|
| Free | 60 | 1,000 |
| Starter | 300 | 10,000 |
| Business | 1,000 | 100,000 |
| Enterprise | Custom | Custom |
A secondary rate limit applies per IP address to prevent abuse:
Every API response includes rate limit information in the headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum number of requests allowed in the current window |
X-RateLimit-Remaining | Number of requests remaining in the current window |
X-RateLimit-Reset | Unix timestamp when the current window resets |
Retry-After | Seconds to wait before retrying (only on 429 responses) |
HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1710936000When using API keys, additional headers provide key-specific usage information:
| Header | Description |
|---|---|
X-API-RateLimit-Limit | Total requests allowed for this API key per window |
X-API-RateLimit-Remaining | Requests remaining for this API key |
X-API-RateLimit-Reset | When the API key's rate limit resets (UTC epoch) |
When you exceed the rate limit, the API returns a 429 Too Many Requests status:
{
"success": false,
"error": {
"code": "API_RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Please wait before making more requests.",
"details": {
"retryAfter": 30,
"limit": 1000,
"reset": "2024-03-20T10:01:00Z"
},
"timestamp": "2024-03-20T10:00:30.000Z",
"requestId": "req_5f2b8c9d1e"
}
}Check the X-RateLimit-Remaining header in responses to track your approaching limits.
const response = await fetch("https://api.oquira.com/v1/business/queues", {
headers: { Authorization: `Bearer ${apiKey}` },
});
const remaining = response.headers.get("X-RateLimit-Remaining");
if (remaining < 100) {
console.warn(`Low rate limit: ${remaining} requests remaining`);
}When you receive a 429 response, wait before retrying:
async function apiCallWithRetry(url, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = response.headers.get("Retry-After") || 30;
const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
await new Promise((resolve) => setTimeout(resolve, delay));
continue;
}
return response;
}
throw new Error("Max retries exceeded");
}Avoid redundant API calls by caching data that doesn't change frequently:
const cache = new Map();
const CACHE_TTL = 60000; // 1 minute
async function getCachedData(key, fetchFn) {
const cached = cache.get(key);
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
return cached.data;
}
const data = await fetchFn();
cache.set(key, { data, timestamp: Date.now() });
return data;
}Instead of polling endpoints for changes, subscribe to webhooks:
See Webhooks for setup instructions.
Some endpoints support batch operations that reduce the number of API calls:
# Instead of multiple calls:
# curl -X GET "https://api.oquira.com/v1/business/services/srv_1" ...
# curl -X GET "https://api.oquira.com/v1/business/services/srv_2" ...
# curl -X GET "https://api.oquira.com/v1/business/services/srv_3" ...
# Use a single list call with filters:
curl -X GET "https://api.oquira.com/v1/business/services?ids=srv_1,srv_2,srv_3" \
-H "X-API-Key: your_api_key_here"For high-volume applications, queue and throttle outgoing requests:
class RequestQueue {
constructor(maxPerSecond = 10) {
this.queue = [];
this.interval = 1000 / maxPerSecond;
this.processing = false;
}
async add(requestFn) {
return new Promise((resolve, reject) => {
this.queue.push({ requestFn, resolve, reject });
this.process();
});
}
async process() {
if (this.processing || this.queue.length === 0) return;
this.processing = true;
const { requestFn, resolve, reject } = this.queue.shift();
try {
const result = await requestFn();
resolve(result);
} catch (error) {
reject(error);
}
setTimeout(() => {
this.processing = false;
this.process();
}, this.interval);
}
}Beyond rate limits, each plan has monthly quotas:
| Plan | Monthly Tickets | Monthly API Calls | Webhooks |
|---|---|---|---|
| Free | 500 | 10,000 | 1 |
| Starter | 5,000 | 100,000 | 5 |
| Business | 50,000 | 1,000,000 | 25 |
| Enterprise | Unlimited | Unlimited | Unlimited |
If you exceed your monthly quota, the API returns a 403 Forbidden:
{
"success": false,
"error": {
"code": "QUOTA_EXCEEDED",
"message": "Monthly API call quota exceeded",
"details": {
"limit": 10000,
"used": 10000,
"resetsAt": "2024-04-01T00:00:00Z"
}
}
}To increase your limits:
For enterprise needs, contact support@oquira.com.