> For the complete documentation index, see [llms.txt](https://docs.opensoutheners.com/home/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.opensoutheners.com/home/laravel-apiable/request-features/includes.md).

# Includes

Eager-load relationships and include them as compound documents in your JSON:API responses.

Includes let API consumers request related resources alongside the primary data. Included relationships are serialised as [compound documents](https://jsonapi.org/format/#document-compound-documents) in the top-level `included` array of the JSON:API response.

## URL format

```
GET /posts?include=author
GET /posts?include=author,tags
GET /posts?include=author.reviews
GET /posts?include=tags_count
```

Multiple relationships are separated by commas. Nested relationships use dot notation.

## `AllowedInclude::make()`

`AllowedInclude::make()` accepts a single relationship name, an array of names, or a dot-notation nested path:

```php
use OpenSoutheners\LaravelApiable\Http\AllowedInclude;

AllowedInclude::make('author')
AllowedInclude::make('tags')
AllowedInclude::make('author.reviews')          // nested
AllowedInclude::make(['author', 'tags'])        // multiple at once
```

## Allowing includes

{% tabs %}
{% tab title="Using methods" %}
Pass `AllowedInclude` instances to `allowing()`, or call `allowInclude()` directly:

```php
use OpenSoutheners\LaravelApiable\Http\JsonApiResponse;
use OpenSoutheners\LaravelApiable\Http\AllowedInclude;

public function index()
{
    return JsonApiResponse::from(Post::class)
        ->allowing([
            AllowedInclude::make('author'),
            AllowedInclude::make('tags'),
            AllowedInclude::make('author.reviews'),
        ]);
}
```

Using `allowInclude()` directly:

```php
return JsonApiResponse::from(Post::class)
    ->allowInclude('author')
    ->allowInclude('tags')
    ->allowInclude(AllowedInclude::make('author.reviews'));
```

You can also pass an array of relationship names to `allowInclude()`:

```php
return JsonApiResponse::from(Post::class)
    ->allowInclude(['author', 'tags']);
```

{% endtab %}

{% tab title="Using attributes" %}

```php
use OpenSoutheners\LaravelApiable\Attributes\IncludeQueryParam;
use OpenSoutheners\LaravelApiable\Http\JsonApiResponse;

#[IncludeQueryParam('author')]
#[IncludeQueryParam('tags')]
#[IncludeQueryParam('author.reviews')]
public function index(JsonApiResponse $response)
{
    return $response->using(Post::class);
}
```

`IncludeQueryParam` accepts: `relationships` (string or array of strings) and `description`.

You can also pass multiple relationships in a single attribute:

```php
#[IncludeQueryParam(['author', 'tags'])]
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Passing multiple `AllowedInclude` instances — whether through several `allowInclude()` calls or all together in one `allowing()` array — accumulates every one of them. None are dropped or overwritten by later calls.
{% endhint %}

## Nested includes

To allow consumers to request a relationship of a relationship, use dot notation:

```php
AllowedInclude::make('author.reviews')
```

This both allows the nested path and eager-loads `author.reviews` via a single `with('author.reviews')` call.

{% hint style="info" %}
The package enforces a `max_include_depth` limit (default: `3`, dot-separated segments count as depth — `tags_count` is depth `1`, `author.reviews` is depth `2`) to prevent exponential relationship tree fan-out. You can adjust this in `config/apiable.php` under `responses.max_include_depth`. An include path beyond the limit is silently dropped by default, or rejected with a `400 Bad Request` when `requests.validate_params` is enabled — see [Validation](/home/laravel-apiable/request-features/validation.md).
{% endhint %}

## Count includes

Append `_count` to any relationship name to request a relationship count instead of the full related resources. The package calls `withCount()` on the query instead of `with()`:

```
GET /posts?include=tags_count
```

This adds a `tags_count` attribute to the resource's attributes without loading the actual `tags` records.

```php
AllowedInclude::make('tags_count')
```

No special configuration is required — the `_count` suffix is detected automatically by the package.

## Response shape

When the consumer requests `?include=author`, the response contains a top-level `included` array:

```json
{
  "data": [
    {
      "id": "1",
      "type": "post",
      "attributes": { "title": "Hello World" },
      "relationships": {
        "author": {
          "data": { "id": "5", "type": "user" }
        }
      }
    }
  ],
  "included": [
    {
      "id": "5",
      "type": "user",
      "attributes": { "name": "Taylor Otwell" }
    }
  ]
}
```

Duplicate resources across multiple includes are deduplicated automatically — each unique resource appears only once in the `included` array.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.opensoutheners.com/home/laravel-apiable/request-features/includes.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
