Pagination & Rate Limits
Cursor-based pagination and rate limiting across all API endpoints.
hookstream uses cursor-based pagination for all list endpoints and applies rate limiting to protect the platform. Understanding these patterns helps you build robust integrations that handle large datasets and respect rate limits.
Cursor-based pagination
All list endpoints return paginated results. Each endpoint uses a named wrapper key matching the resource type (e.g., sources, destinations, events, connections). To fetch the next page, pass the cursor value as a query parameter.
Cursors are opaque strings — do not parse or construct them. They remain stable across pages even when new records are inserted.
Example
bash# First page GET /v1/sources?limit=20
json{ "sources": [...], "cursor": "eyJpZCI6...", "has_more": true }
bash# Next page GET /v1/sources?limit=20&cursor=eyJpZCI6...
json{ "sources": [...], "cursor": null, "has_more": false }
Query Parameters
Opaque cursor from a previous response. Omit for the first page.
Number of results per page. Maximum 100.
Results are ordered by creation time (newest first) unless otherwise specified on the endpoint.
Always check has_more before fetching the next page — do not assume fixed page sizes. Some endpoints (events, delivery-attempts) use different defaults and wrapper shapes; always read the actual response.
Rate limiting
Authenticated endpoints are rate-limited per organization. Unauthenticated endpoints (ingest, test sessions, tools) are rate-limited per IP address. When you exceed the rate limit, the API returns 429 Too Many Requests.
Rate limit headers
Every response includes IETF standard RateLimit-* response headers:
| Header | Meaning |
|---|---|
RateLimit-Limit | Maximum requests allowed in the current window. |
RateLimit-Remaining | Requests remaining in the current window. |
RateLimit-Reset | Seconds until the window resets. |
Example:
httpRateLimit-Limit: 1000 RateLimit-Remaining: 742 RateLimit-Reset: 37
When RateLimit-Remaining reaches 0, wait until RateLimit-Reset seconds have elapsed before making additional requests.
Best practices
Check has_more, not cursor presence
Always check has_more to decide whether to fetch another page — some endpoints return cursor: null on the last page, others don't.
Back off on 429
Implement exponential backoff when receiving 429 responses. Read RateLimit-Reset for the minimum wait.
Tune limit to your workload
Use the limit parameter to control page size based on your processing capacity. Larger pages = fewer round trips but more latency per request.
Prefer WebSocket streaming for live data
For high-volume integrations, use WebSocket streaming instead of polling list endpoints.