api-pagination
Implement correct, fast API pagination — cursor vs offset trade-offs, opaque cursor encoding, stable sort keys, page-size limits, total-count costs, and…
Conventions for designing clean, consistent, evolvable REST APIs — resource modeling, HTTP semantics, status codes, pagination, filtering, error envelopes, versioning, idempotency, and security. A deep reference with worked examples and runnable checks.
$ npx -y skills add vanara-agents/skills --skill rest-api-design --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/rest-api-designContext preview
The summary Claude sees to decide when to auto-load this skill.
Conventions for designing clean, consistent, evolvable REST APIs — resource modeling, HTTP semantics, status codes, pagination, filtering, error envelopes, versioning, idempotency, and security. A deep reference with worked examples and runnable checks.
name: rest-api-design description: Conventions for designing clean, consistent, evolvable REST APIs — resource modeling, HTTP semantics, status codes, pagination, filtering, error envelopes, versioning, idempotency, and security. A deep reference with worked examples and runnable checks. type: skill version: 2.0.0 updated: 2026-06-28
A good REST API is **guessable**: once a consumer learns one endpoint, they can predict the rest. This skill is the deep reference for designing one — the principles, the decisions, the trade-offs, and the mistakes to avoid. Heavy detail lives in `references/`; copy-paste material in `examples/`; a runnable contract check in `scripts/`.
Design the API around **resources** (nouns) and use HTTP **verbs** to act on them. The protocol already gives you a rich vocabulary — methods, status codes, headers, caching — so lean on it instead of inventing your own conventions on top.
| Concern | REST answer | |---|---| | What | a resource, named as a plural noun (`/orders`) | | Action | the HTTP method (GET/POST/PUT/PATCH/DELETE) | | Outcome | the status code (200/201/404/409…) | | Shape | a consistent response envelope | | Change | an explicit versioning strategy |
1. Name collections as **plural nouns**: `/users`, `/orders`. Never verbs in the path (`/getUsers` is wrong — the verb is `GET`). 2. Nest to show ownership, but only **one level deep**: `/users/{id}/orders` is fine; `/users/{id}/orders/{id}/items/{id}/...` is a smell — link instead. 3. Model real-world actions that aren't CRUD as sub-resources or controller endpoints: `POST /orders/{id}/refunds` rather than `POST /refundOrder`. 4. Keep identifiers stable and opaque to clients; don't leak DB internals (prefer UUIDs/ULIDs over auto-increment IDs where enumeration is a risk).
| Method | Use | Safe | Idempotent | |---|---|---|---| | GET | read | yes | yes | | POST | create / non-idempotent action | no | no | | PUT | full replace | no | yes | | PATCH | partial update | no | no* | | DELETE | remove | no | yes |
Respect these contracts — clients, proxies, and caches rely on them. A `GET` must never mutate state. See `references/status-codes.md` for the full status-code decision guide.
Return the **accurate** code; never `200 OK` with an error body (it breaks every client's error handling).
201 Created Location: /orders/101 # after a successful POST 204 No Content # successful DELETE, no body 400 Bad Request # malformed/invalid input 401 Unauthorized # not authenticated 403 Forbidden # authenticated, not allowed 404 Not Found 409 Conflict 422 Unprocessable Entity 429 Too Many Requests
Full guidance and edge cases (404 vs 403 to avoid leaking existence, 409 vs 422) live in `references/status-codes.md`.
Standardize one shape across **every** endpoint so clients parse uniformly. See `examples/error-envelope.json` and validate any payload with `scripts/check-envelope.mjs`.
{
"data": [ { "id": 101, "status": "open" } ],
"meta": { "nextCursor": "eyJpZCI6MTIwfQ", "limit": 20 },
"error": null
}On error, the same shape with `data: null` and a populated `error` (see §6).
Every collection endpoint **must** paginate — an unbounded list is a latent outage. Prefer **cursor** pagination for large or frequently-changing data (offset pagination scans and skips rows, getting slower the deeper you go, and double-counts when rows are inserted mid-scan).
GET /v1/orders?status=open&sort=-created_at&limit=20&cursor=eyJpZCI6MTAwfQ
The full comparison, cursor encoding, and pitfalls are in `references/pagination.md`.
One error shape, everywhere. A machine-readable `code`, a human `message`, and optional field-level `details`:
{ "data": null, "error": {
"code": "validation_failed",
"message": "The request was invalid.",
"details": [ { "field": "email", "issue": "must be a valid email" } ]
} }Rules and the full catalogue of codes are in `references/error-handling.md`.
APIs are forever once published. Version explicitly (`/v1/...` in the path is the most operationally clear) and treat additive changes as backward-compatible; breaking changes require a new version. Strategy and a deprecation playbook: `references/versioning.md`.
(the server stores key → result and replays it). Essential for payments.
checking ownership, not just authentication), rate-limit (return `429` + `Retry-After`), and validate all input. Pairs with the `security-auditor` agent and the `owasp-top10` skill.
REST isn't always the right tool. Prefer **GraphQL** when clients need flexible, nested selections and you want to avoid over/under-fetching; prefer **gRPC** for low-latency internal service-to-servic
🐒 Free agents, skills & packs for Claude Code One subscription. An army of Claude Code agents. 30 production-grade agents, skills, and packs for Claude Code — free, Apache-2.0, install with one command.
Repo: vanara-agents/skills
Implement correct, fast API pagination — cursor vs offset trade-offs, opaque cursor encoding, stable sort keys, page-size limits, total-count costs, and…
Deep reference for caching — what to cache, cache-aside vs read/write-through/write-behind, TTLs with jitter, eviction (LRU/LFU/FIFO), invalidation, and…
Write Conventional Commits — the type(scope)!: subject + body + footer spec — so history is readable and changelogs and SemVer bumps can be derived…
How to write safe, reversible, zero-downtime database schema migrations — additive-first changes, the expand/migrate/contract pattern, batched backfills,…
How to handle errors explicitly and consistently across an app — validate at boundaries, classify operational vs programmer errors, add context while…
Run git collaboration that scales — trunk-based vs git-flow decided by deploy cadence, branch protection and required checks, PR sizing and review etiquette,…