@tank/api-design-mastery
1.1.0Skill
Description
REST, GraphQL, and tRPC API design for backend engineers. Covers endpoint design, HTTP methods, status codes, API versioning, error contracts (RFC 7807/9457), pagination (offset, cursor, keyset, Relay connections), auth (API keys, JWT, OAuth 2.0 PKCE, Client Credentials), RBAC, rate limiting.
Triggered by
REST APIGraphQL schematRPCAPI versioningerror responseRFC 7807
Review Recommended
tank install -g @tank/api-design-masteryScan completed ā 0 findings
0 critical, 0 high, 0 medium ā see security tab for details.
API Design Mastery
Core Philosophy
- Design for the consumer, not the database ā API shape reflects use cases, not schema structure. Consumers should not need to understand your internals.
- Consistency over cleverness ā Uniform patterns across all endpoints reduce cognitive load more than any individual optimization.
- Additive by default ā Plan for backward compatibility from day one. Adding is safe; removing breaks clients.
- Errors are first-class citizens ā Error contracts deserve the same design care as success responses. Use RFC 9457.
- Pick the right tool ā REST for public APIs, GraphQL for multi-client data graphs, tRPC for TypeScript monorepos.
Quick-Start: Common Problems
"Which API style should I use?"
| Signal | Choose |
|---|---|
| Public API, third-party consumers, any client language | REST + OpenAPI |
| Multiple clients needing different data shapes (web + mobile + partner) | GraphQL |
| TypeScript monorepo, internal full-stack app (Next.js/Remix) | tRPC |
| Real-time data streams + existing REST/GraphQL | Add subscriptions (GraphQL / tRPC) |
ā See references/trpc-patterns.md for the REST vs GraphQL vs tRPC comparison table |
"How do I design this endpoint?"
- What is the resource (noun)? ā
/orders, not/createOrder - What HTTP method? ā GET (read) / POST (create) / PUT (replace) / PATCH (partial) / DELETE
- What status code on success? ā 200/201/204
- What is the error contract? ā RFC 7807
application/problem+json - Does it change anything observable? ā If yes, it must be POST/PUT/PATCH/DELETE
ā See
references/rest-endpoint-design.md
"My API returns errors inconsistently"
- Adopt RFC 7807 Problem Details ā
type,title,status,detail,instance - Use
Content-Type: application/problem+json - Add machine-readable
codeextension (SCREAMING_SNAKE_CASE) - Add
errors[]array for field validation failures - Include
requestIdfor server-side correlation ā Seereferences/error-contracts.md
"Clients are breaking when I change the API"
- Was it a breaking change? ā See breaking vs non-breaking table in
references/api-versioning.md - If breaking: add new version; run old version in parallel
- Announce deprecation:
Deprecation: true+Sunset:header (RFC 8594) - Give clients ā„ 6 months; contact high-traffic users directly
ā See
references/api-versioning.md
"Pagination is slow at deep pages"
- Offset/limit past page 100? ā Switch to cursor pagination
- Need GraphQL? ā Use Relay Cursor Connections spec
- REST? ā Keyset pagination with opaque base64 cursor
- Index must cover all ORDER BY columns
ā See
references/pagination-filtering.md
"Auth isn't secure"
- Server-to-server: API key (hashed, Authorization header, never URL param)
- User-delegated: OAuth 2.0 Authorization Code + PKCE
- Service-to-service: OAuth 2.0 Client Credentials
- All JWT access tokens: ⤠15 min expiry; refresh tokens in httpOnly cookie
ā See
references/auth-patterns.md
Decision Trees
HTTP Method Selection
| Operation | Method | Idempotent? | Notes |
|---|---|---|---|
| Fetch resource or list | GET | Yes | Never has side effects |
| Create new resource | POST | No | Returns 201 + Location header |
| Full replace (client provides all fields) | PUT | Yes | Client sends complete representation |
| Partial update (only changed fields) | PATCH | No (unless designed) | Client sends delta only |
| Remove resource | DELETE | Yes | Returns 204 No Content |
| Trigger action (not a CRUD op) | POST | Depends | /orders/42/cancel |
Error Status Code Selection
| Situation | Code |
|---|---|
| Can't parse request body | 400 |
| Valid syntax, fails business validation | 422 |
| No credentials provided | 401 |
| Credentials valid, lacks permission | 403 |
| Resource doesn't exist | 404 |
| Duplicate / state conflict | 409 |
| Permanently removed | 410 |
| Rate limit exceeded | 429 |
GraphQL vs REST Error Handling
| Layer | REST | GraphQL | tRPC |
|---|---|---|---|
| Transport errors | HTTP status + Problem Details | HTTP 200 (partial) or 400 | HTTP status via TRPCError code |
| Field errors | errors[] in Problem Details | errors[] array + extensions.code | Zod error formatter |
Reference Files
| File | Contents |
|---|---|
references/rest-endpoint-design.md | Resource modeling, URL naming, HTTP methods, status codes, idempotency, HATEOAS, request/response design |
references/graphql-schema-design.md | Type system, queries/mutations/subscriptions, N+1 problem, DataLoader, Relay connections spec, complexity limiting, security |
references/trpc-patterns.md | initTRPC setup, procedure types, Zod validation, middleware, context, router composition, error codes, subscriptions, adapters |
references/api-versioning.md | Breaking vs non-breaking changes, URL/header/media-type strategies, deprecation workflow, Sunset header, Stripe versioning model |
references/error-contracts.md | RFC 7807/9457 Problem Details, status code decision trees, field validation errors, error tracing, GraphQL and tRPC error formats |
references/pagination-filtering.md | Offset, cursor, keyset pagination, Relay connections spec, sorting patterns, filtering operators, field selection |
references/auth-patterns.md | API key design, JWT access+refresh pattern, OAuth 2.0 flows (Auth Code+PKCE, Client Credentials), RBAC, rate limiting algorithms |