$npx -y skills add selmakcby/claude-agents-skills --skill api-designBackend API design specialist. Use when building REST/GraphQL APIs, designing endpoints, data models, or backend architecture. Covers RESTful principles, HTTP semantics, error handling, versioning, and OWASP-aligned security.
| 1 | <!-- |
| 2 | Source: wshobson/agents (backend-development plugin) |
| 3 | File: https://github.com/wshobson/agents/tree/main/plugins/backend-development/skills/api-design-principles |
| 4 | Used by: builder agent (backend) |
| 5 | --> |
| 6 | |
| 7 | # API Design Principles |
| 8 | |
| 9 | ## When to trigger |
| 10 | - Designing a new API endpoint |
| 11 | - Adding routes to existing API |
| 12 | - Database schema work that affects API contract |
| 13 | - Keywords: "endpoint", "API", "route", "backend", "server", "REST", "GraphQL" |
| 14 | |
| 15 | ## Core RESTful principles |
| 16 | |
| 17 | ### Resource-oriented URLs |
| 18 | - Nouns, not verbs: `/users/123`, not `/getUser?id=123` |
| 19 | - Pluralize resources: `/orders`, not `/order` |
| 20 | - Nest only when expressing parent/child: `/users/:id/orders` |
| 21 | - Max 2 levels deep — beyond that, use query params |
| 22 | |
| 23 | ### HTTP methods (correct semantics) |
| 24 | | Method | Use for | Idempotent | Safe | |
| 25 | |--------|---------|------------|------| |
| 26 | | GET | Read | Yes | Yes | |
| 27 | | POST | Create | No | No | |
| 28 | | PUT | Replace (full update) | Yes | No | |
| 29 | | PATCH | Partial update | No* | No | |
| 30 | | DELETE | Remove | Yes | No | |
| 31 | |
| 32 | \* PATCH can be idempotent depending on semantics. |
| 33 | |
| 34 | ### Status codes (correct use) |
| 35 | - **200** OK — successful GET/PUT/PATCH with body |
| 36 | - **201** Created — successful POST creating resource |
| 37 | - **204** No Content — successful DELETE or action with no body |
| 38 | - **400** Bad Request — validation failure |
| 39 | - **401** Unauthorized — missing/invalid auth |
| 40 | - **403** Forbidden — authenticated but not authorized |
| 41 | - **404** Not Found — resource doesn't exist |
| 42 | - **409** Conflict — version mismatch, duplicate resource |
| 43 | - **422** Unprocessable Entity — semantic validation failure |
| 44 | - **429** Too Many Requests — rate limited |
| 45 | - **500** Internal Server Error — unhandled server fault |
| 46 | |
| 47 | ### Response envelope |
| 48 | Consistent shape for all responses: |
| 49 | ```typescript |
| 50 | { |
| 51 | success: boolean |
| 52 | data: T | null |
| 53 | error: string | null |
| 54 | metadata?: { total, page, limit } |
| 55 | } |
| 56 | ``` |
| 57 | |
| 58 | ## Endpoint design patterns |
| 59 | |
| 60 | ### Pagination |
| 61 | - Cursor-based for large/changing sets: `?cursor=abc&limit=20` |
| 62 | - Offset-based for small stable sets: `?page=1&limit=20` |
| 63 | - Always cap `limit` server-side (max 100) |
| 64 | |
| 65 | ### Filtering |
| 66 | - Query params: `?status=active&created_after=2024-01-01` |
| 67 | - Sort: `?sort=-created_at` (minus prefix = descending) |
| 68 | |
| 69 | ### Versioning |
| 70 | - URL path: `/v1/users`, `/v2/users` (easiest to deprecate) |
| 71 | - Never introduce breaking changes to existing version |
| 72 | |
| 73 | ## Security (mandatory) |
| 74 | |
| 75 | - **Authentication** — every non-public endpoint checks auth first |
| 76 | - **Authorization** — row-level checks, not just auth-exists |
| 77 | - **Input validation** — Zod schema on every request body + query |
| 78 | - **Rate limiting** — public routes + AI/LLM routes especially |
| 79 | - **CORS** — whitelist, not `*` |
| 80 | - **Output filtering** — never leak internal IDs or PII in error messages |
| 81 | - **Webhook signatures** — verify signature before trusting payload |
| 82 | |
| 83 | ## Error handling |
| 84 | |
| 85 | - Never expose stack traces to the client |
| 86 | - Log server-side with request ID |
| 87 | - Return structured error: `{ code: "INVALID_INPUT", message: "...", field: "email" }` |
| 88 | - HTTP status code must match error type |
| 89 | |
| 90 | ## Output format |
| 91 | |
| 92 | ```markdown |
| 93 | ## API Design Summary |
| 94 | |
| 95 | ### Endpoint |
| 96 | `<METHOD> /path/to/resource` |
| 97 | |
| 98 | ### Purpose |
| 99 | <what it does, who uses it> |
| 100 | |
| 101 | ### Request |
| 102 | - **Auth:** <required | optional> |
| 103 | - **Body schema:** Zod |
| 104 | - **Query params:** ... |
| 105 | |
| 106 | ### Response |
| 107 | - **200:** <shape> |
| 108 | - **Error cases:** 400, 401, 403, 404, 422, 429, 500 |
| 109 | |
| 110 | ### Security checks |
| 111 | - [ ] Auth verified |
| 112 | - [ ] Authorization verified (row-level) |
| 113 | - [ ] Input validated (Zod) |
| 114 | - [ ] Rate limit applied |
| 115 | - [ ] PII not leaked in errors |
| 116 | |
| 117 | ### Dependencies |
| 118 | - Database tables: <list> |
| 119 | - External services: <list> |
| 120 | ``` |
| 121 | |
| 122 | ## Rules |
| 123 | |
| 124 | - **RESTful first.** Only use GraphQL / RPC if there's a concrete reason. |
| 125 | - **No breaking changes** to existing API versions. Ever. |
| 126 | - **Every endpoint validates input** — no "we'll add validation later". |
| 127 | - **Every endpoint has a test** (unit for business logic, integration for HTTP layer). |
| 128 | - **Document before coding.** OpenAPI spec or at least a Markdown contract. |
| 129 | - **Rate limit on day 1** — retrofitting is painful. |