# REST — Derived Rules > Derives from `domains/api/first-principles.md`. Applies P1–P10 to REST specifically. ## Resource Naming (P2 Clarity, P3 Predictability) - Nouns, not verbs: `/users`, `/orders`, not `/getUsers`. - Plural: `/users` (collection), `/users/{id}` (item). - Lowercase, hyphenated: `/order-items`, not `/OrderItems` or `/order_items`. - Nesting max 2 levels: `/users/{id}/orders`, not `/users/{id}/orders/{oid}/items/{iid}`. ## HTTP Methods (P1 Contract Fidelity, P6 Idempotency) | Method | Semantics | Idempotent | Safe | |--------|-----------|------------|------| | GET | Read | Yes | Yes | | POST | Create | No | No | | PUT | Replace (full) | Yes | No | | PATCH | Update (partial) | No | No | | DELETE | Remove | Yes | No | - PUT requires the full resource. PATCH requires only the delta. Never accept a partial PUT. - POST creates; never use POST for read operations. POST is not cacheable. ## Status Codes (P9 Error Transparency, P1 Contract Fidelity) | Code | Meaning | When | |------|---------|------| | 200 | OK | Successful GET, PUT, PATCH | | 201 | Created | Successful POST that created a resource | | 204 | No Content | Successful DELETE, or empty response | | 400 | Bad Request | Malformed request (client error) | | 401 | Unauthorized | Authentication required or failed | | 403 | Forbidden | Authenticated but not permitted | | 404 | Not Found | Resource does not exist | | 409 | Conflict | State conflict (e.g., duplicate) | | 422 | Unprocessable | Well-formed but semantically invalid | | 429 | Too Many Requests | Rate limited | | 500 | Internal Error | Server bug — never leak stack trace | - Never return 200 on an error. Never return 500 with a stack trace. - 401 vs 403: 401 = "who are you?", 403 = "I know who you are, but you can't." ## Idempotency (P6 Idempotency) - POST: not idempotent. Use an idempotency key (`Idempotency-Key` header) for safe retry. - PUT: idempotent by definition — same PUT twice = same state. - DELETE: idempotent — deleting a non-existent resource is success (204). - PATCH: not idempotent by default; can be made idempotent with explicit versioning. ## Pagination (P7 Performance, see `pagination.md`) - Default to cursor pagination for collections > 100 items. - Never return unbounded collections. - `Link` header or `cursor` field in response body. ## Versioning (P5 Versioning, P10 Stability, see `versioning.md`) - Version in the URL (`/v1/users`) or in the header (`Accept: application/vnd.atelier.v1+json`). - Pick one. Be consistent across all endpoints. - Never make a breaking change without a new version and a deprecation cycle. ## Security (P8 Security, see `domains/security/`) - HTTPS only. Redirect HTTP to HTTPS. - Authentication on every non-public endpoint. No opt-in auth. - Rate limiting on write endpoints (POST, PUT, PATCH, DELETE). - Validate every input against a schema. Never pass raw request body to the database.