REST APIs in Depth · REST Foundations
Modeling Resources and URLs
Design nouns, collections, sub-resources and identifiers that survive change.
Start from client use cases and domain concepts, not database tables. Resources are nouns (/orders, /orders/{id}); collections are plural; sub-resources express ownership (/orders/{id}/items) but keep nesting shallow (max one or two levels). Use stable, opaque identifiers (UUIDs, ULIDs or prefixed IDs like ord_8812) instead of exposing auto-increment keys. Model actions that don't fit CRUD either as state changes (PATCH /orders/7 {"status":"cancelled"}) or as explicit sub-resources/custom methods (POST /orders/7:cancel in Google AIP style, or POST /orders/7/cancellation).
Resource design choices
| Concern | Good | Avoid |
|---|---|---|
| Naming | /customers/{id}/addresses | /getCustomerAddresses?id=7 |
| Nesting | /orders/{id}/items | /customers/1/orders/7/items/3/product |
| Identifiers | ord_01J9ZK… (opaque, prefixed) | Sequential DB ids that leak volume |
| Actions | POST /orders/{id}:cancel or PATCH status | GET /orders/7/cancel |
| Case | kebab-case paths, snake_case or camelCase fields (pick one) | Mixed styles per team |
Common pitfalls
- Mirroring database tables (join tables become resources nobody understands).
- Deep nesting that forces clients to know parents to fetch a child.
- Verbs in URLs and state changes via GET.
Key points
- Nouns, plural collections, shallow nesting
- Opaque, stable identifiers
- Model actions as state changes or explicit custom methods
Further reading: Google AIP-121: Resource-oriented design
Practice questions
How would you expose 'cancel order' in a REST API?
Answer
Either as a state transition (PATCH /orders/{id} with status=cancelled, validated by the server) or as an explicit custom method/sub-resource (POST /orders/{id}:cancel), which makes intent, permissions and side effects (refunds) clearer. Never via GET.
Why use prefixed opaque IDs like cus_123 instead of integers?
Answer
They don't leak business volume, can't be enumerated easily, are globally unique across types (debuggable), and let you change the storage key without breaking clients.
Open in the app to mark lessons complete, take notes and track your progress.