--- name: api-design description: Design or review REST/GraphQL APIs when endpoints or contracts change. --- # API Design ## When to Apply - **Classification**: feature, architecture-change, hotfix (if touching API endpoints) - **Phase**: /implement (design & build), /review (compliance check), /test (contract verification) - **Trigger**: Task involves creating, modifying, or deprecating API endpoints ## Conventions > **Customize after /app-init**: Replace these generic conventions with your project's ADR decisions. ### Endpoint Naming - Use nouns for resources, not verbs: `GET /users` not `GET /getUsers` - Plural resource names: `/users`, `/orders`, `/products` - Nested resources for relationships: `/users/:id/orders` - Use kebab-case for multi-word paths: `/order-items` ### HTTP Methods | Action | Method | Success Status | Idempotent | |---|---|---|---| | List | GET | 200 | Yes | | Get one | GET | 200 | Yes | | Create | POST | 201 | No | | Full update | PUT | 200 | Yes | | Partial update | PATCH | 200 | No | | Delete | DELETE | 204 | Yes | ### Error Response Format ```json { "error": { "code": "VALIDATION_ERROR", "message": "Email is required", "details": { "field": "email", "constraint": "required" } } } ``` ### Standard Error Codes | HTTP Status | When | Error Code Pattern | |---|---|---| | 400 | Invalid input | VALIDATION_ERROR, INVALID_FORMAT | | 401 | Not authenticated | UNAUTHORIZED | | 403 | Not permitted | FORBIDDEN | | 404 | Resource not found | NOT_FOUND | | 409 | Conflict (duplicate) | CONFLICT, DUPLICATE | | 422 | Business rule violation | UNPROCESSABLE | | 429 | Rate limited | RATE_LIMITED | | 500 | Server error | INTERNAL_ERROR | ### Pagination ```json { "data": [...], "pagination": { "total": 100, "page": 1, "per_page": 20, "has_next": true } } ``` ### Versioning - URL path versioning: `/api/v1/users` - Breaking changes require new version - Deprecation: add `Sunset` header with date, keep old version for N months ### Input Validation - Validate at the controller/route level BEFORE business logic - Return ALL validation errors at once (batch), not one at a time - Sanitize strings: trim whitespace, escape HTML where applicable - Enforce max lengths on all string fields ## Checklist During /implement: - [ ] Every endpoint has input validation - [ ] Every endpoint returns consistent error format - [ ] Every endpoint has proper auth check (or explicit `public` annotation) - [ ] Pagination for list endpoints - [ ] Rate limiting consideration (at least documented in spec) - [ ] No sensitive data in URL parameters (use body or headers) - [ ] Request/response examples in spec match implementation During /review: - [ ] No N+1 query patterns in list endpoints - [ ] Proper HTTP status codes (not everything is 200) - [ ] Idempotency for PUT/DELETE - [ ] Error messages don't leak internal details (stack traces, SQL, paths) - [ ] CORS configured per ADR policy ## Heading-Scoped Read Note For phase-entry loading, read only: - `When to Apply` - `Checklist` Load `Conventions`, `Anti-Patterns`, and `References` on full read or cache miss only. ## Anti-Patterns - **God endpoint**: One endpoint that does everything based on query params. Split into specific endpoints. - **Verb in URL**: `POST /createUser` → `POST /users` - **Inconsistent naming**: Mixing `/user` and `/products` (singular vs plural) - **Swallowing errors**: Catching exceptions and returning 200 with `{ success: false }` - **Leaking internals**: Returning DB column names directly as API fields without mapping - **Missing 404**: Returning empty 200 instead of 404 when resource doesn't exist - **Unbounded lists**: List endpoints without pagination or default limits ## References - Project ADR: `docs/adr/ADR-002-project-architecture.md` § API Design - Security guardrails: `.agent/rules/security_guardrails.md` (A01: Access Control, A03: Injection) - Spec template: `.agentcortex/templates/spec-app-feature.md` § API Contract