agentsclimarketplace

Api pagination

Skill vanara-agents/skills/skills/api-pagination

29 free, verified agents, skills & packs for Claude Code - install with 'npx vanara install <name>'. Apache-2.0. From the Vanara catalog (206 items).

Install
npx -y skills add vanara-agents/skills --skill api-pagination

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • 22 days oldThe repository was created 22 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
  • 7 stars7 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Implement correct, fast API pagination — cursor vs offset trade-offs, opaque cursor encoding, stable sort keys, page-size limits, total-count costs, and consumer-side iteration that survives inserts, deletes, and retries. With runnable cursor checks.

SKILL.md

3.9 KB, as published. Nobody here has run it

API Pagination

Pagination looks trivial until data changes underneath the reader. Offset pagination silently skips or duplicates rows when inserts land mid-iteration; cursor pagination survives churn but demands a stable sort key and an opaque token contract. This skill covers both sides: designing the API and consuming one correctly. Deep detail lives in references/; copy-paste material in examples/; a runnable cursor round-trip check in scripts/.

Decision: offset vs cursor

SituationUse
Admin tables, small datasets, "jump to page 7" requiredOffset (LIMIT/OFFSET)
Feeds, sync endpoints, anything users scrollCursor (keyset)
Data changes while clients iterateCursor — offset will skip/duplicate
Deep pages (offset > ~10k rows)Cursor — OFFSET n scans and discards n rows

Offset's failure mode is correctness, not just speed: a row inserted before your current position shifts everything, so page 3 re-shows an item from page 2 (duplicate) or swallows one (skip).

Keyset mechanics (the part people get wrong)

The sort key must be unique and immutable. created_at alone is not unique — two rows with the same timestamp make the cursor ambiguous and rows vanish. Always add a tiebreaker:

-- WHERE clause for "next page after (2026-07-01T12:00:00Z, id 4711)" descending
SELECT * FROM items
WHERE (created_at, id) < ('2026-07-01T12:00:00Z', 4711)
ORDER BY created_at DESC, id DESC
LIMIT 51;  -- page_size + 1 to detect has_more without COUNT(*)

Fetch page_size + 1 rows: if you get 51, there is a next page and the 51st row's key becomes the next cursor. This avoids COUNT(*), which on large tables costs more than the page itself (see references/counting-and-totals.md).

Cursor token contract

Cursors are opaque to clients — never let them parse or build one. Encode the keyset values plus the sort direction, base64url it, and (for public APIs) HMAC it so tampering is detectable. Include a version byte so you can change the encoding later. Full recipe: references/cursor-encoding.md; runnable round-trip: scripts/check-cursor.mjs.

Response envelope

{
  "data": [ ... ],
  "page_info": { "has_more": true, "next_cursor": "djEuMj..." }
}

Rules: next_cursor is absent (not empty-string) on the last page; page size is capped server-side (a limit=10000 request gets the cap, documented, not an error); the default page size appears in the docs and never changes silently. Consumer-side iteration rules — retries, cursor expiry, resumption — live in references/consuming-pages.md.

Pitfalls

  • Mutable sort keys (updated_at) — rows teleport across pages as they update. Sort on immutable columns or accept re-delivery and dedupe client-side.
  • Cursor built from row position instead of row values — it is offset with extra steps and inherits every offset bug.
  • COUNT(*) on every page — the count is stale by the time the client renders it; provide totals on a separate, cacheable endpoint if the product truly needs them.
  • Breaking cursor encoding on deploy — clients hold cursors across releases; version the token.
  • Missing composite index — keyset needs an index on exactly (created_at, id) in sort order, or every page is a scan.

Verification

Run node scripts/check-cursor.mjs — encodes, decodes, tampers, and versions a cursor and asserts every property above. For the SQL side, examples/keyset-queries.sql includes an EXPLAIN you can run to confirm the index is used. Pairs with rest-api-design (envelopes, limits) and sql-index-tuning (composite indexes).

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.