Skip to main content

Sub-Resource (Nested Resource)

GET /users/123/ordersPOST /posts/abc/commentsGET /orders/ord_1/line-items

Sub-resources represent entities that only exist in the context of a parent resource. /users/123/orders, /posts/abc/comments. The nesting reflects a strong ownership relationship. Keep nesting to one or two levels maximum – deeper nesting creates brittle URLs and coupling.

Details

Nested resources model the case where one resource logically belongs to another. The nested URL expresses that relationship.

When to nest: - The child resource cannot exist without the parent (/orders/123/line-items) - You always filter by the parent when accessing the child (/posts/abc/comments means only comments for post abc) - Access control is inherited from the parent

When NOT to nest: - The child resource can exist independently (/users/123/tags – tags exist independently) - You need to access the child without knowing the parent (/comments/xyz – you know the comment ID) - The nesting would exceed 2 levels

Maximum depth rule: /level1/{id}/level2/{id} is the deepest commonly recommended. /level1/{id}/level2/{id}/level3/{id} creates brittle client code and makes link sharing unwieldy.

Dual endpoints: for child resources that need both nested and standalone access, provide both: POST /posts/abc/comments – create a comment on post abc GET /comments/xyz – access any comment by its ID directly

URL Examples

PatternDescription
GET /users/123/ordersAll orders for user 123
POST /posts/abc/commentsCreate comment on post
GET /orders/ord_1/line-itemsLine items for an order
DELETE /users/123/addresses/addr_5Delete a specific address

Do

  • +Use nesting when the child genuinely cannot exist without the parent
  • +Limit nesting to 2 levels maximum: /parent/{id}/child/{id}
  • +Provide both nested creation (POST /posts/{id}/comments) and direct access (GET /comments/{id})
  • +Validate parent ownership in handlers – ensure /users/123/orders only returns user 123's orders

Don't

  • !Never nest beyond 2 levels: /a/{id}/b/{id}/c/{id}/d/{id} – break into flatter endpoints
  • !Never use nesting when the child exists independently (tags, categories, labels)
  • !Never allow accessing /users/123/orders to return orders from other users

Examples

Nested create + standalone read
# Create: POST to nested URL
POST /api/v1/posts/post_abc/comments
{ "text": "Great article!" }
→ 201 Created, Location: /api/v1/comments/cmt_xyz

# Read: GET directly (no need to know parent)
GET /api/v1/comments/cmt_xyz
→ 200 OK { "id": "cmt_xyz", "postId": "post_abc", "text": "..." }

See Also