How rate limiting works
Gorillaa Mail enforces rate limits per API key and per organization to ensure fair usage and platform stability. When you exceed a limit, the API returns429 Too Many Requests.
All authenticated responses include rate limit headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed in the current window |
X-RateLimit-Remaining | Requests remaining in the current window |
X-RateLimit-Reset | UTC epoch timestamp when the window resets |
Per-endpoint limits
| Endpoint | Limit | Window |
|---|---|---|
POST /v1/emails | 100 requests | 1 hour |
POST /v1/emails/batch | 10 requests | 1 minute |
GET /v1/emails | 1,000 requests | 1 hour |
GET /v1/emails/:id | 1,000 requests | 1 hour |
POST /v1/domains | 10 requests | 1 hour |
GET /v1/domains | 100 requests | 1 hour |
POST /v1/domains/:id/verify | 10 requests | 1 hour |
POST /v1/domains/:id/rotate-dkim | 10 requests | 1 hour |
GET /v1/stats/* | 100 requests | 1 hour |
POST /v1/api-keys | 10 requests | 1 hour |
GET /v1/api-keys | 100 requests | 1 hour |
GET /v1/privacy/export | 3 requests | 24 hours |
POST /v1/privacy/delete | 1 request | 24 hours |
POST /v1/gdpr/export | 3 requests | 24 hours |
POST /v1/gdpr/delete-request | 1 request | 24 hours |
POST /v1/suppressions | 100 requests | 1 hour |
GET /v1/suppressions | 100 requests | 1 hour |
GET /v1/webhooks | 100 requests | 1 hour |
POST /v1/webhooks | 10 requests | 1 hour |
| Default read endpoints | 1,000 requests | 1 hour |
| Default write endpoints | 100 requests | 1 hour |
Organization-wide limit
In addition to per-endpoint limits, there is a global organization-wide cap:| Limit | Window | |
|---|---|---|
| All endpoints combined | 10,000 requests | 1 hour |
Test mode limits
API keys prefixed withgrl_test_ have reduced limits:
| Limit | Value |
|---|---|
| Global rate limit | 500 requests/hour |
| Per-key send limit | 20 emails/hour |
| Daily send limit (per domain) | 100 emails/day |
| Lifetime send limit (per domain) | 300 emails total |
Test mode daily/lifetime limits count each recipient separately. An email to 5 recipients counts as 5 against the limit.
Handling rate limits
When you receive a429 response:
Recommended approach
- Read the
X-RateLimit-Resetheader to know when the window resets - Use exponential backoff with jitter for retries
- Include an
X-Idempotency-Keyfor send requests to prevent duplicates on retry
Monitoring your usage
Check remaining quota before making requests:Tips for staying within limits
Use batch send for multiple emails
Use batch send for multiple emails
Instead of calling
POST /v1/emails 100 times, use POST /v1/emails/batch with up to 100 emails in a single request.Cache email status lookups
Cache email status lookups
If you poll
GET /v1/emails/:id for delivery status, cache results for terminal states (delivered, bounced, failed).Use analytics instead of polling
Use analytics instead of polling
For aggregate delivery metrics, use
GET /v1/stats instead of fetching individual email statuses.Spread requests over time
Spread requests over time
Avoid burst patterns. Distribute API calls evenly throughout the hour window.