Nesting & Relationships
Resources relate to each other, and the URI structure can express some of those relationships. The trick is nesting enough to be intuitive without building brittle, deeply nested paths.
Sub-resources
Section titled “Sub-resources”When one resource clearly belongs to another, nest it one level:
GET /articles/42/comments # comments of article 42POST /articles/42/comments # add a comment to article 42GET /users/7/articles # articles written by user 7flowchart LR A[/articles/42/] --> C[/articles/42/comments/] C --> CI[/articles/42/comments/9/]
How deep to nest
Section titled “How deep to nest”Stop at one, occasionally two, levels. A path like /users/7/articles/42/comments/9/reactions/3 is hard to read and couples resources that should stand alone. Once a sub-resource has its own identity, give it a top-level URI too and link to it instead of nesting further:
GET /comments/9 # the comment as a first-class resourceGET /articles/42/comments # still fine as a scoped collectionLinking
Section titled “Linking”Rather than embedding everything, return references the client can follow:
Common mistakes
Section titled “Common mistakes”Nesting too deep Symptom:
/companies/\{id\}/departments/\{id\}/teams/\{id\}/members/\{id\}/tasks/\{id\}- URIs get very long and are hard to maintain and document
- Cap nesting at two levels, or flatten to
/tasks/\{id\}and filter with query parameters
A many-to-many relationship modeled as nested Symptom:
/users/\{id\}/tags/\{id\}— a user has many tags, a tag has many users- Nesting makes ownership unclear — does deleting remove the tag from the user or delete it entirely?
- Use a junction resource instead:
POST /user-tagswith{ userId, tagId }
💡 Real-world examples
GitHub API:
/repos/\{owner\}/\{repo\}/issues— a clear 2 levels/repos/\{owner\}/\{repo\}/issues/\{number\}/comments— 3 levels maxStripe API:
/customers/\{id\}/payment_methods— nested for an owned resource/payment_methods/\{id\}— accessible directly once you know the IDSources: GitHub REST API — issues, Stripe API — payment methods