> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hookstream.io/llms.txt
> Use this file to discover all available pages before exploring further.

# 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-*`](https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit-headers/) 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:

```http
RateLimit-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](/api/websockets) instead of polling list endpoints.