Api design
REST and GraphQL API design conventions — resource modeling, pagination, error envelopes, versioning, idempotency. Use when adding, changing, or reviewing endpoints.From its SKILL.md
npx -y skills add atuljha23/holocron --skill api-designAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 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.
SKILL.md
2.9 KB, 695 tokens by cl100k_base, as published. Nobody here has run it
API design
REST
Resource, not action
URLs name nouns. Actions are verbs.
Good: POST /users/:id/password-reset
Bad: POST /resetUserPassword?id=123
Status codes mean things
200success with body201created (includeLocation)204success, no body400client sent something invalid (bad syntax, bad shape)401not authenticated403authenticated but not authorized404resource doesn't exist (or the caller isn't allowed to know it does)409conflict (version conflict, duplicate, precondition failed)422semantic validation failed (body parses but rules reject)429rate limited5xxserver fault — internal detail logged, opaque to caller
Error envelope
Pick one. Use it everywhere.
{
"error": {
"code": "resource_not_found",
"message": "User [email protected] not found.",
"requestId": "abc123"
}
}
codeis machine-readable, stable, lowercase_snake.messageis human-readable. Safe to surface.requestIdlets the caller tell you what went wrong without you reading prod logs.
Pagination
Cursor-based for anything you'll scale. Offset paging breaks under concurrent writes.
GET /messages?cursor=abc&limit=50
→ { items: [...], nextCursor: "xyz" }
Idempotency
Any POST that has side-effects and will be retried needs an idempotency key:
POST /payments
Idempotency-Key: <uuid-v4>
Server stores the (key → response) for a reasonable TTL. Retries return the cached response, not a second charge.
Versioning
Prefer additive changes. Add fields; don't remove or rename. When you must break, version:
- URL (
/v2/...) — simple, explicit, slightly ugly - Accept header (
Accept: application/vnd.foo.v2+json) — prettier URLs, slightly opaque
Pick one per service. Never mix.
GraphQL
Nullability is a contract
String! says "this WILL be present". If you're not sure, it's String (nullable). A lie here cascades.
Relay-style pagination
Connections, edges, pageInfo, cursors. Don't invent your own.
One mutation per intent
updateUser(input: { name, email, password }) is three different operations glued together. Split them.
Errors as types
Return { user: User | UserNotFoundError | ValidationError } unions where it matters. Generic errors[] at the top is for transport-level fault, not business rules.
Across both
- Typed shapes. Schemas (OpenAPI / GraphQL / proto). Generate clients from them.
- Rate limit expensive or abuse-prone endpoints.
- Observability. Every request has a
requestId. Log it. Return it on errors. Tie logs, metrics, and traces together with it. - Auth at the edge — check in the handler or middleware the handler trusts. Never rely on the gateway alone.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.
Gives 3 of the 12 instructions most api design skills give in 695 tokens
Counted across 224 of the 224 authors here whose files we hold, read 2026-09-06
- Use plural nouns for resource nameshere, and in 50 of 224, across 49 files
- Implement pagination for all list endpointsin 42 of 224, across 32 files
- Use cursor-based pagination for large datasetshere, and in 42 of 224, across 40 files
- Return appropriate HTTP status codes for all responsesin 31 of 224, across 21 files
- Use URL path versioning for API changesin 29 of 224, across 19 files
- Use HTTP methods semantically for CRUD operationsin 22 of 224, across 13 files
- Use HTTP methods for resource actionsin 20 of 224, across 18 files
- Use plural nouns in kebab-case for resource URLsin 18 of 224, across 9 files
- Enforce authentication and authorization on all resourcesin 17 of 224, across 7 files
- Use standard HTTP status codeshere, and in 17 of 224
- Validate all incoming request data against a schemain 16 of 224, across 7 files
- Limit URL nesting to two levelsin 16 of 224
Said here and by no other author read
- Define nullability strictly in GraphQL schemas
- Split mutations into single-intent operations
- Use union types for business logic errors
- Generate client code from API schemas
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.