Pagination & rate limits
Pagination
Most list endpoints return a counting paginator: the items in data,
page URLs in links, and page counts in meta. The shape is:
{
"data": [ ... ],
"links": {
"first": "https://...",
"last": "https://...",
"prev": null,
"next": "https://..."
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 10,
"per_page": 20,
"to": 20,
"total": 200,
"path": "https://..."
}
}
Two endpoints use a different shape:
-
GET /v1/inboxes/{inbox_id}/tagsuses a simple paginator, which does not count the full result set. Itsmetaomitslast_pageandtotal, and addscurrent_page_url. Walk it withlinks.nextuntil that link is null rather than counting pages. -
POST /v1/searchwraps the paginator in{ success, data: { conversations: <paginator> } }.
Query parameters
| Parameter | Default | Notes |
|---|---|---|
page | 1 | 1-indexed page number. |
per-page | 20 | Items per page. Maximum 100. |
sort | newest | Where supported: newest, oldest, priority. |
Rate limits
Every API request first passes a global limiter, and a few sensitive routes add a stricter one on top. All limiters are keyed off the client IP, not the access token, so a high-traffic single host will hit the limit even with a valid token.
| Limiter | Default | Applies to |
|---|---|---|
api.global |
300 req / 1 min | Every API endpoint |
api.register |
10 req / 1 min | /v1/auth/registration/* |
api.email_verification |
5 req / 1 min | /v1/auth/verification/* |
How a throttled request looks
HTTP/1.1 429 Too Many Requests
Retry-After: 47
X-RateLimit-Limit: 5
X-RateLimit-Remaining: 0
Content-Type: application/json
{
"message": "Too Many Attempts."
}
The standard advice applies: back off using the Retry-After header, do
not hammer the endpoint, and consider queueing requests client-side when you would
otherwise approach the limit.
Configuring limits
Each limiter reads its max_attempts and decay_minutes from
environment variables, defaulting to the values above:
API_RATE_LIMIT_GLOBAL=300,1
API_RATE_LIMIT_REGISTER=10,1
API_RATE_LIMIT_EMAIL_VERIFICATION=5,1
Idempotency
The API does not yet honor Idempotency-Key headers. POSTs that you want
to make safe to retry (for example, POST /v1/conversation/{id}/reply)
should be guarded client-side with a deduplication layer keyed off your internal
message ID.