Rate Limits & Errors
Learn about API limits and how to handle errors.
Rate Limits
API requests are rate limited to ensure fair usage:
| Limit | Value |
|---|---|
| Requests per minute | 100 |
| Webhook subscriptions per form | 10 |
| API keys per workspace | 10 |
Rate Limit Headers
Rate limit information is included in response headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests per minute |
X-RateLimit-Remaining | Requests remaining in current window |
X-RateLimit-Reset | When the rate limit resets (ISO 8601) |
Retry-After | Seconds to wait (only on 429 responses) |
Handling Rate Limits
async function makeRequest(url, options) {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After');
console.log(`Rate limited. Retry after ${retryAfter} seconds.`);
// Wait and retry
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
return makeRequest(url, options);
}
return response;
}Error Handling
Errors are returned with appropriate HTTP status codes and a consistent JSON structure:
{
"status": "error",
"message": "Human-readable error message",
"code": "machine_readable_code"
}Error Codes
| HTTP Status | Code | Description |
|---|---|---|
| 401 | missing_api_key | No API key provided |
| 401 | invalid_api_key | API key is invalid |
| 401 | api_key_expired | API key has expired |
| 403 | insufficient_scope | API key lacks required permissions |
| 404 | form_not_found | Form does not exist or is inaccessible |
| 429 | rate_limited | Rate limit exceeded |
| 500 | internal_error | Something went wrong on our end |
Error Handling Example
async function verifyApiKey(apiKey) {
const response = await fetch('https://trigglio.com/api/integrations/webhooks/auth/verify', {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
const data = await response.json();
if (data.status === 'error') {
switch (data.code) {
case 'missing_api_key':
throw new Error('Please provide an API key');
case 'invalid_api_key':
throw new Error('Your API key is invalid. Check your dashboard.');
case 'api_key_expired':
throw new Error('Your API key has expired. Generate a new one.');
case 'rate_limited':
throw new Error('Too many requests. Please slow down.');
default:
throw new Error(data.message || 'An unexpected error occurred');
}
}
return data;
}Best Practices
Implement exponential backoff for retries to avoid overwhelming the API during outages.
Do
- Cache responses when appropriate
- Implement retry logic with exponential backoff
- Handle rate limits gracefully
- Log errors for debugging
Don’t
- Retry immediately on failure
- Ignore rate limit headers
- Make unnecessary requests
- Store API keys in client-side code
Webhook Delivery
Retry Policy
If your webhook endpoint returns a non-2xx status code:
- 3 retries with exponential backoff
- Retries at approximately 1 min, 5 min, 30 min
- After 3 failures, the delivery is marked as failed
Timeouts
- Webhook requests timeout after 30 seconds
- Make sure your endpoint responds quickly
- Process data asynchronously if needed
Need Help?
If you’re experiencing issues with the API, contact our support team with:
- Your API key prefix (e.g.,
tr_live_abc...) - The endpoint you’re calling
- The full error response
- Timestamps of when errors occurred
Last updated on