Skip to content

API Design First

Claude CodeSKILL.mdCoding

Write and review the endpoint contract — resources, errors, pagination, versioning — before any handler code exists.

Use when: Use when adding or changing API endpoints, so the contract is designed and reviewed before implementation locks in accidental decisions.

@library0 upvotes0 remixes0 comments

Get this skill

Add the skill file with the CLI, by hand, or over MCP.

Save this to your project or home directory so Claude Code can load it.

npx goodprompts add api-design-first
Saves to~/.claude/skills/api-design-first/SKILL.md
npx goodprompts add api-design-first
Saves to ~/.claude/skills/api-design-first/SKILL.md

Skill file

SKILL.md3,680 characters
# API Design First
Implementation details leak into contracts when the contract is written last. Design the interface as an artifact (OpenAPI spec, tRPC router signatures, or a markdown contract doc), get it reviewed, then implement against it.
## Step 1 — Write the contract document
For every endpoint, specify before writing handler code:
- Method + path, request shape, response shape with field types and nullability, status codes, auth requirement, and rate-limit class.
- At least one concrete example request/response pair per endpoint. Examples expose bad designs faster than schemas do.
- Walk a consumer scenario end to end ("client creates X, lists X, updates X") using only the contract. If the walkthrough needs information the API doesn't return, the design is incomplete.
## Naming and shape rules
- Resources are plural nouns: `/invoices`, `/invoices/{id}/line-items`. Verbs only for true actions that aren't CRUD: `/invoices/{id}/send`.
- Pick one casing for JSON fields (camelCase or snake_case) and never mix. Match the codebase's existing choice.
- No booleans that will grow a third state — use an enum (`status: "draft" | "sent" | "void"` instead of `isSent`).
- Timestamps are ISO 8601 UTC strings, money is integer minor units plus a currency code, IDs are opaque strings (never expose auto-increment integers in new APIs).
- Don't return different shapes from the same endpoint based on input. Variants belong in a discriminated union with an explicit `type` field.
## Errors
- Define the error envelope once and use it everywhere: `{ "error": { "code": "invoice_already_sent", "message": "...", "details": {...} } }`. Machine-readable `code` is the contract; `message` is for humans and may change.
- Map deliberately: 400 malformed input, 401 unauthenticated, 403 unauthorized, 404 missing (also for resources the caller can't know exist), 409 state conflict, 422 semantically invalid, 429 throttled. Reserve 500 for actual bugs — never return 500 for predictable conditions.
- Validation errors list *all* failures in `details`, not just the first. Clients hate fix-one-resubmit loops.
- Write the error cases into the contract with the same rigor as success cases. Every 4xx an endpoint can return is part of its signature.
## Pagination, filtering, ordering
- Every collection endpoint paginates from day one — retrofitting breaks clients. Default and max page sizes are stated in the contract.
- Prefer cursor pagination (`?cursor=...&limit=50`, response carries `nextCursor: string | null`) for anything that grows; offset pagination drifts under concurrent writes.
- Filters are explicit query params with documented semantics. Reject unknown params with a 400 rather than ignoring them — silent ignoring hides client typos forever.
## Versioning and evolution
- Additive changes (new optional field, new endpoint) need no version bump. Breaking changes (removing/renaming a field, changing a type, tightening validation) need a new version or a deprecation cycle — never a silent change.
- State the deprecation policy in the contract: how breakage is announced, the sunset window, and how callers detect it (e.g. a `Deprecation` header).
- Plan for unknown fields: clients must ignore fields they don't recognize; document this so future additions stay non-breaking.
## Before implementing
- [ ] Contract reviewed by at least one consumer of the API (or by walking their use case yourself).
- [ ] Every endpoint has examples, error cases, auth requirement, and pagination defined.
- [ ] Names checked against existing endpoints for consistency.
- [ ] Implementation tests assert against the contract's examples, so drift fails CI.
Comments

Comments

Sign in to commentSign in

Remixes

Loading remixes…