Skip to main content

design-api

Design RESTful and GraphQL APIs following current best practices for naming, versioning, error shapes, and auth patterns. Use when the user says "design an API", "create endpoints", "structure my API responses", "plan API architecture", "REST vs GraphQL", or "API contract".

Source facts

Repository
kensaurus/cursor-kenji
Last source activity
September 12, 2026 at 14:20
Detected SKILL.md language
English
Stars
9
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
design-api
description
Design RESTful and GraphQL APIs following current best practices for naming, versioning, error shapes, and auth patterns. Use when the user says "design an API", "create endpoints", "structure my API responses", "plan API architecture", "REST vs GraphQL", or "API contract".
license
MIT
# API Design Skill **Degree of freedom: MIXED.** Resource model, error shape, and REST vs GraphQL `[HIGH freedom]`; pre-design docs/schema/grep `[LOW freedom — run exactly]`. Design clean, consistent, and developer-friendly APIs. ## How to reason 1. **Survey** — existing docs, schema, and similar endpoints 2. **Model** — resources, relations, REST vs GraphQL 3. **Contract** — paths, statuses, error shape, auth, pagination 4. **Check** — naming matches this repo; no duplicate endpoint ## Worked example > **Survey:** `orders` has `user_id`; no `GET /users/:id/orders`; clients use `useQuery`. > **Model:** order is a nested user resource, not a `/getUserOrders` RPC. > **Contract:** `GET /users/:id/orders` → `{ data, meta }`; shared `{ error: { code, message, details } }`. > **Check:** plural kebab-case; list paginated; 401/404/422 only from the status table. ## Self-critique before reporting - **Pre-design stated** — docs, schema, and similar endpoints were checked out loud - **One error shape** — every failure uses `{ error: { code, message, details } }` - **Lists paginate** — no unbounded `GET /resources` - **Right owner** — live 4xx/5xx repro → `debug-fe-be-integration`; product scope still fuzzy → `design-prd` ## Pre-design checks [LOW freedom — run exactly] **Before designing any API:** ### 1. Check Existing API Documentation ``` http://localhost:8080/api-docs (if backend running) http://localhost:8080/naming-conventions (naming standards) src/api/_api-README.md (frontend API layer docs) ``` ### 2. Verify Database Schema Use Supabase MCP to understand existing data structure: ```sql -- Check table schema SELECT column_name, data_type, is_nullable FROM information_schema.columns WHERE table_name = 'your_table'; -- Check enum values SELECT enum_range(NULL::your_enum_name); -- Check foreign keys SELECT tc.constraint_name, kcu.column_name, ccu.table_name AS foreign_table FROM information_schema.table_constraints tc JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name JOIN information_schema.constraint_column_usage ccu ON tc.constraint_name = ccu.constraint_name WHERE tc.table_name = 'your_table' AND tc.constraint_type = 'FOREIGN KEY'; ``` ### 3. Check for Existing Endpoints Use `Grep` to search for similar endpoints already implemented: ``` Grep: "router.get|router.post" to find existing route patterns Grep: "useQuery|useMutation" to find existing frontend integrations ``` ### 4. Verification Statement (REQUIRED) Before designing, state: ``` "Pre-design check: - Existing API docs reviewed: [YES/NO] - Database schema verified: [tables/enums checked] - Similar endpoints found: [list or none] - Naming conventions confirmed: [YES/NO]" ``` --- ## REST API Design [HIGH freedom] ### URL Structure ``` GET /resources # List GET /resources/:id # Get one POST /resources # Create PUT /resources/:id # Replace PATCH /resources/:id # Update DELETE /resources/:id # Delete ``` ### Naming Conventions | Do | Don't | |----|-------| | `/users` | `/getUsers`, `/user-list` | | `/users/:id` | `/user/:id`, `/users/get/:id` | | `/users/:id/orders` | `/getUserOrders` | | Plural nouns | Verbs, singular | | kebab-case | camelCase, snake_case | ### Examples ``` GET /users # List users GET /users/123 # Get user 123 GET /users/123/orders # User's orders GET /users/123/orders/456 # Specific order POST /users/123/orders # Create order for user ``` --- ## Request/Response Format [LOW freedom — run this shape] ### Request Body ```json { "name": "John Doe", "email": "john@example.com", "role": "admin" } ``` ### Successful Response ```json { "data": { "id": "123", "name": "John Doe", "email": "john@example.com", "createdAt": "2024-01-15T10:30:00Z" } } ``` ### List Response (with pagination) ```json { "data": [ { "id": "1", "name": "John" }, { "id": "2", "name": "Jane" } ], "meta": { "total": 100, "page": 1, "perPage": 20, "totalPages": 5 } } ``` ### Error Response ```json { "error": { "code": "VALIDATION_ERROR", "message": "Invalid input data", "details": [ { "field": "email", "message": "Invalid email format" }, { "field": "name", "message": "Name is required" } ] } } ``` --- ## HTTP Status Codes [LOW freedom — use this table] ### Success (2xx) | Code | When to Use | |------|-------------| | `200 OK` | GET, PUT, PATCH success | | `201 Created` | POST created new resource | | `204 No Content` | DELETE success, no body | ### Client Errors (4xx) | Code | When to Use | |------|-------------| | `400 Bad Request` | Invalid request body | | `401 Unauthorized` | Not authenticated | | `403 Forbidden` | Authenticated but not allowed | | `404 Not Found` | Resource doesn't exist | | `409 Conflict` | Resource conflict (duplicate) | | `422 Unprocessable` | Validation failed | | `429 Too Many` | Rate limited | ### Server Errors (5xx) | Code | When to Use | |------|-------------| | `500 Internal Error` | Unexpected server error | | `502 Bad Gateway` | Upstream service failed | | `503 Unavailable` | Service temporarily down | --- ## Query Parameters ### Filtering ``` GET /users?role=admin GET /users?role=admin&status=active GET /orders?createdAfter=2024-01-01 ``` ### Sorting ``` GET /users?sort=name # Ascending GET /users?sort=-createdAt # Descending (prefix with -) GET /users?sort=role,-name # Multiple fields ``` ### Pagination ``` GET /users?page=2&perPage=20 GET /users?offset=40&limit=20 GET /users?cursor=abc123 # Cursor-based ``` ### Field Selection ``` GET /users?fields=id,name,email GET /users?include=orders,profile ``` --- ## Versioning ### URL Path (Recommended) ``` GET /v1/users GET /v2/users ``` ### Header ``` GET /users Accept: application/vnd.api+json;version=2 ``` --- ## Authentication ### Bearer Token ``` Authorization: Bearer eyJhbGciOiJIUzI1NiIs... ``` ### API Key ``` X-API-Key: your-api-key # or ?apiKey=your-api-key ``` --- ## Common Patterns ### Bulk Operations ``` POST /users/bulk { "create": [{ "name": "John" }, { "name": "Jane" }], "update": [{ "id": "1", "name": "Updated" }], "delete": ["2", "3"] } ``` ### Search ``` POST /users/search { "query": "john", "filters": { "role": "admin" }, "sort": { "field": "name", "order": "asc" } } ``` ### Actions (non-CRUD) ``` POST /orders/123/cancel POST /users/123/verify-email POST /payments/123/refund ``` --- ## API Design Checklist [LOW freedom — do not skip] ### Consistency - [ ] Consistent naming conventions - [ ] Consistent response format - [ ] Consistent error format - [ ] Consistent pagination ### Usability - [ ] Intuitive URLs - [ ] Clear documentation - [ ] Meaningful error messages - [ ] Sensible defaults ### Security - [ ] Authentication required - [ ] Authorization checked - [ ] Input validation - [ ] Rate limiting ### Performance - [ ] Pagination for lists - [ ] Field selection available - [ ] Efficient queries - [ ] Caching headers --- ## Documentation Template ```markdown ## Create User Create a new user account. **Endpoint:** `POST /users` **Authentication:** Required (Bearer token) **Request Body:** | Field | Type | Required | Description | |-------|------|----------|-------------| | name | string | Yes | User's full name | | email | string | Yes | Valid email address | | role | string | No | User role (default: "user") | **Response:** `201 Created` \`\`\`json { "data": { "id": "123", "name": "John Doe", "email": "john@example.com", "role": "user", "createdAt": "2024-01-15T10:30:00Z" } } \`\`\` **Errors:** - `400` - Invalid request body - `409` - Email already exists - `422` - Validation failed ```
View on GitHub