## TL;DR

Switch the generated client to offset and page parameters for that endpoint, and the 400s stop. The docs still say cursor, but the live API moved to offset and its validator now rejects cursor params.

Probe the endpoint's actual behavior instead of trusting the docs: send offset-style params, confirm 2xx, and page through a few pages to make sure the full result set arrives.

## Verbatim query

```text
docs said pagination was cursor-based  -  the live API silently switched that endpoint to offset and cursors 400 now
```

## Steps

1. Reproduce the 400 with a single call
   Send the cursor params your client currently builds and read the full 400 body.
   Note which parameter the error names - it is usually the cursor itself.
   Expected: You get a clean 400 naming the cursor param, reproducing the client's failure.

2. Probe with offset-style params
   Send offset and limit (or page and per_page) without any cursor param.
   Read the response shape: does it return a total count, and does offset advance the window?
   Expected: Offset-style params return 2xx and the response shows the expected page of records.

3. Page through to confirm completeness
   Fetch pages 1 through 3 and check records do not repeat or skip.
   Compare the total fetched against the total count if the API returns one.
   Expected: Three pages return distinct records and counts add up.

4. Rewrite the client's pagination loop
   Replace the cursor loop with offset iteration in the generated code.
   If the client is regenerated from docs, override just this endpoint's paging strategy.
   Expected: The client builds offset params and never sends a cursor to this endpoint.

5. Add a regression check
   Add a test that asserts this endpoint accepts offset params and returns pages.
   Flag any future regen that reintroduces cursor params for this endpoint.
   Expected: The test passes and would fail if someone regenerates the client from the stale docs.

## Use this when

- Your client sends cursor params and gets 400 on an endpoint the docs say is cursor-based
- Pagination broke with no client change and offset params work when you try them manually
- A provider changelog mentions a paging migration but the docs page was never updated

## Not for this skill when

- The endpoint is still cursor-based and the cursor just expired - that is a cursor-refresh problem
- Every endpoint 400s, not just this one - the API version or auth is wrong
- The 400 names a non-paging field - fix that field first

## Variant phrasings

### endpoint switched from cursor to offset pagination
Providers migrate paging styles during rewrites; the old params 400 while the new ones work.

### cursor param rejected with 400
A 400 naming the cursor param on a docs-cursor endpoint is the signature of a silent paging migration.

### pagination params changed without notice
Same family: any paging param the docs promise but the live validator rejects means the API moved on.

## Why it happens

Pagination migrations usually ship with a backend rewrite: the new service implements offset paging, the old cursor params hit a validator that no longer knows them, and the docs page describes the old service. Nobody announces it because from the provider's view it is an internal change. Your generated client trusts the docs and keeps sending cursors into a 400.

## Edge cases

- Some providers keep cursor working on old API versions but default new keys to offset - check whether an older version header restores cursor behavior
- Offset pagination on shifting datasets can skip rows; if records move during your sync, ask whether the endpoint supports a stable sort
- Watch for a hybrid window: some endpoints accept both styles during migration, then drop cursor - probe again after each provider changelog entry

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_N6COp1xrNLBpMtB1l4VypA
