Skip to main content

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.

Rate limit vs. monthly quota

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:

HeaderDescription
ratelimit-limitMaximum requests allowed in the current window (1000)
ratelimit-remainingRequests remaining in the current window
ratelimit-resetSeconds remaining until the window resets (a duration, not a Unix timestamp)
These headers are only on successful responses

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:

HeaderDescription
retry-afterSeconds 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:

EndpointItems per request
POST /events/send50
POST /push/devices/bulk1,000
POST /contacts/bulk-delete1,000

Everything else is one call per item, so space a bulk push out rather than emptying the 60-second budget at once.