# Pagination, filtering and idempotency
URL: https://skedcast.com/developers/guides/api-pagination-guide

List endpoints in the SkedCast API use keyset (cursor) pagination instead of page numbers (a few short lists, such as campaigns and best times, return everything at once), and every write needs an Idempotency-Key. Both exist for the same reason: correctness under concurrent writes, not just convenience.

## Why keyset, not offset
Offset pagination (?page=3) breaks under concurrent writes: if a row is inserted or deleted while you're paging, you can see a row twice or skip one, and it gets slower the deeper you page. Keyset pagination follows a cursor derived from the last row you saw, so it stays correct and fast at any depth.

## Example
```bash
curl "https://api.skedcast.com/v1/posts?limit=50&cursor=eyJ…" \
  -H "Authorization: Bearer sked_live_YOUR_KEY"
```

## The list envelope. Iterate until hasMore is false.
```json
{
  "data": [ { "object": "post", "id": "…" } ],
  "page": { "cursor": null, "nextCursor": "eyJ…", "hasMore": true },
  "meta": { "correlationId": "c-…" }
}
```

## Filtering
Most list endpoints accept status, client and platform filters as ordinary query parameters next to `limit` and `cursor`. See the resource's table in the API reference for the filters it supports.

## Idempotency on writes
Every POST, PATCH and DELETE needs an Idempotency-Key header (except `POST /v1/posts/preview`). Any unique string works. A UUID is simplest. Replaying the same key returns the original result instead of creating a duplicate, so a network retry after a timeout is safe. A different body under the same key is refused with `422 idempotency_key_reuse`, never silently accepted.

## FAQ
**Q: Can I jump to a specific page number?**
A: No. Keyset pagination has no page numbers, only "the next batch after this cursor". If you need a specific slice, filter more narrowly (by date range or status) instead of skipping ahead.

**Q: What happens if I reuse an Idempotency-Key with a different request body?**
A: You get 422 idempotency_key_reuse and the request isn't run. Generate a fresh key for each distinct request.
