Rate Limiting
The Arsel API enforces per-organization rate limits to ensure fair usage and platform stability. The limit is shared across every API key in the organization — adding more keys does not raise the ceiling.
Default Limits
The API allows 1,000 requests per 60-second window per organization (about 16 requests per second on average). It is a fixed window, so the full budget can be spent at any point inside the 60 seconds.
Need more? Contact support@arsel.sa.
This page covers per-second request limits. Your plan also has a monthly send quota for email and SMS. Exhausting the monthly quota returns 429 monthly_quota_exceeded — a separate error that retrying won't resolve. See Common Send Errors.
Rate Limit Headers
Every API response includes standard rate limit headers:
| Header | Description |
|---|---|
ratelimit-limit | Maximum requests allowed in the current window (1000) |
ratelimit-remaining | Requests remaining in the current window |
ratelimit-reset | Seconds remaining until the window resets (a duration, not a Unix timestamp) |
ratelimit-* headers are not returned on a 429 response — only retry-after is. Do not build your backoff around reading ratelimit-remaining from a 429; on a 429, wait for retry-after seconds.
When a rate limit is exceeded, this header is included instead:
| Header | Description |
|---|---|
retry-after | Seconds to wait before retrying |
Rate Limit Exceeded
If you exceed the limit, the API returns HTTP 429:
{
"status_code": 429,
"name": "rate_limit_exceeded",
"message": "Too many requests. Please retry after the period indicated in the retry-after header."
}
Match on status_code and name — the exact message string is not a stable contract and may change.
Handling Rate Limits
Read the headers on successful responses. Check ratelimit-remaining on 2xx responses to pace yourself. On a 429, these headers are absent — use retry-after instead.
Implement exponential backoff. When you receive a 429, wait for the retry-after seconds before retrying. Avoid tight retry loops.
Retry safely with an idempotency key. A retried send or event can be processed twice — double-counting rollups and revenue. Send an Idempotency-Key header so a retry within 24 hours returns the original result instead of repeating the side effect. See Send Event → Idempotency (the same header works on the send-email and send-SMS endpoints).
Batch where a batch endpoint exists. Three endpoints take many items in one request and cost one call against the limit:
| Endpoint | Items per request |
|---|---|
POST /events/send | 50 |
POST /push/devices/bulk | 1,000 |
POST /contacts/bulk-delete | 1,000 |
Everything else is one call per item, so space a bulk push out rather than emptying the 60-second budget at once.