paulund

7. Including Related Data

7. Including Related Data

Fetching a resource and then issuing a second request for every related object it references leads to chatty APIs and slow client-side loading. Providing a mechanism to include related data in a single response solves this without permanently bloating every payload.

The Principle: Keep the Base Payload Lean

By default, return only the fields that belong directly to the requested resource. Do not eagerly embed related objects. This keeps responses small, predictable, and fast.

Opt-In Expansion with include

Let clients request related resources by passing an include query parameter listing the relationships they want:

GET /posts/100?include=author
GET /posts/100?include=author,category
GET /posts/100?include=author,comments

The server embeds the requested relations into the response:

{
    "data": {
        "id": 100,
        "title": "Designing Better APIs",
        "author": {
            "id": 7,
            "name": "Jane Smith"
        },
        "category": {
            "id": 3,
            "name": "Engineering"
        }
    }
}

Nested Expansion

Some APIs support dot-notation to expand relations one level deeper:

GET /orders/42?include=items,items.product

This returns each order item together with its associated product, all in one request. Be cautious with deep nesting — it can lead to large payloads and expensive database queries. Document any depth limits clearly.

Guidelines

  • Whitelist the allowed relationships. Do not let clients expand arbitrary paths; only support the relations you have explicitly designed and tested.
  • Document every supported relation in your API specification so clients know what is available.
  • Set a limit on the number of relations that can be requested in a single call to prevent abuse or accidental over-fetching.
  • Cache-friendly by default. The base resource URL without include parameters remains cacheable; expansions can be treated as separate cache keys.