Rate Limits & Error Handling

Understand API rate limits and build resilient integrations with proper error handling.

Rate Limits

The tersOS API enforces rate limits to ensure fair usage and platform stability. Standard rate limits apply to all API tokens, with exact limits depending on your plan.

PlanRequests / MinuteDaily Limit
Standard6010,000
Pro12050,000
EnterpriseCustomCustom

Rate Limit Headers

Every API response includes headers that indicate your current rate limit status:

Response Headers
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 54
Retry-After: 30
  • X-RateLimit-Limit — Maximum requests allowed per minute
  • X-RateLimit-Remaining — Requests remaining in the current window
  • Retry-After — Seconds to wait before retrying (only present on 429 responses)

Error Response Format

When an error occurs, the API returns a consistent JSON structure with success: false and an error message:

{
"success": false,
"data": "The given data was invalid."
}

For validation errors (422), the response includes field-level details:

{
"success": false,
"data": "The given data was invalid.",
"errors": {
"email": ["The email field is required."],
"date": ["The date must be a future date."]
}
}

Common Error Codes

CodeMeaningWhat to Do
400Bad RequestThe request was malformed or missing required parameters.
401UnauthorizedAuthentication failed. Token is missing, invalid, or revoked.
403ForbiddenThe token does not have permission for this action.
404Not FoundThe requested resource does not exist.
422Validation ErrorThe request body failed validation. Check the error details.
429Too Many RequestsRate limit exceeded. Wait and retry using exponential backoff.
500Server ErrorAn internal error occurred. Contact support if it persists.

Best Practices

Exponential Backoff

When you receive a 429 or 5xx response, wait before retrying. Double the wait time with each attempt (1s, 2s, 4s, 8s...) to avoid overwhelming the server.

Cache Responses

Cache responses for data that does not change frequently (e.g., room lists, user profiles). This reduces API calls and improves your application's performance.

Use Pagination

List endpoints return paginated results. Use the page parameter to iterate through results rather than fetching everything at once.

Respect Retry-After

When the Retry-After header is present, always honor it. This tells you exactly how long to wait before sending another request.


Retry Example

Here is a complete example of an API client with exponential backoff and retry logic:

async function apiRequestWithRetry(url, token, maxRetries = 3) {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
},
});
if (response.status === 429) {
// Rate limited — use exponential backoff
const retryAfter = response.headers.get('Retry-After');
const delay = retryAfter
? parseInt(retryAfter, 10) * 1000
: Math.pow(2, attempt) * 1000;
console.warn(`Rate limited. Retrying in ${delay}ms...`);
await new Promise((resolve) => setTimeout(resolve, delay));
continue;
}
if (response.status >= 500 && attempt < maxRetries) {
// Server error — retry with backoff
const delay = Math.pow(2, attempt) * 1000;
await new Promise((resolve) => setTimeout(resolve, delay));
continue;
}
return response.json();
}
throw new Error('Max retries exceeded');
}

Always set a maximum number of retries to prevent infinite loops. Three retries with exponential backoff is a reasonable default for most use cases.


Next Steps