> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apivalk.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Pagination

> Apivalk provides built-in support for different pagination types: Page, Offset, and Cursor. Pagination is defined at the route level and metadata is automatically injected into the request and response.

<Tip>For a strategy-picker and controller recipes, see the [Add pagination](/how-to/pagination) how-to.</Tip>

## Route Configuration

To enable pagination for a specific route, you use the `pagination()` method on the `Route` object. This automatically handles the documentation and request parameter resolution (like `page`, `limit`, `offset`, or `cursor`).

```php theme={null}
use apivalk\apivalk\Router\Route\Pagination\Pagination;
use apivalk\apivalk\Router\Route\Route;

public static function getRoute(): Route
{
    return Route::get('/pets')
        ->pagination(Pagination::page()->setMaxLimit(50));
}
```

### Supported Types

* `Pagination::page()`: Standard page-based pagination (uses `page` and `limit`).
* `Pagination::offset()`: Offset-based pagination (uses `offset` and `limit`).
* `Pagination::cursor()`: Cursor-based pagination (uses `cursor` and `limit`).

***

## Usage in Controller

When a route has pagination enabled, the `AbstractApivalkRequest` automatically creates the appropriate paginator object. You can access it via the `paginator()` method.

### 1. Fetching Data

Use the `PaginatorFactory` to resolve the paginator from the request and apply it to your repository or data source.

```php theme={null}
use apivalk\apivalk\Http\Request\Pagination\PaginatorFactory;

public function __invoke(ApivalkRequestInterface $request): AbstractApivalkResponse
{
    // The paginator is automatically resolved based on the Route configuration
    $paginator = $request->paginator();
    
    // Example for PagePaginator
    $pets = $this->petRepository->findAll(
        ($paginator->getPage() - 1) * $paginator->getLimit(),
        $paginator->getLimit()
    );
    
    // ...
}
```

### 2. Attaching Metadata to Response

After fetching your data, you must create a `PaginationResponse` object and attach it to your response. This ensures the pagination metadata (like `total_pages` or `has_more`) is included in the JSON output.

```php theme={null}
use apivalk\apivalk\Http\Response\Pagination\PagePaginationResponse;

// Inside Controller:
$totalEntries = $this->petRepository->count();
$totalPages = (int)ceil($totalEntries / $paginator->getLimit());
$hasMore = $paginator->getPage() < $totalPages;

$response = new GetPetsResponse($pets);
$response->setPaginationResponse(
    new PagePaginationResponse(
        $paginator->getPage(),
        $paginator->getLimit(),
        $hasMore,
        $totalPages
    )
);

return $response;
```

***

## JSON Output Example

When a response has a pagination object attached, the `JsonRenderer` automatically includes a `pagination` key in the response body. The structure depends on the pagination type used.

### Page Pagination

```json theme={null}
{
    "data": [...],
    "pagination": {
        "page": 1,
        "page_size": 20,
        "has_more": true,
        "total_pages": 5
    }
}
```

### Offset Pagination

```json theme={null}
{
    "data": [...],
    "pagination": {
        "limit": 20,
        "offset": 40,
        "has_more": true,
        "total": 100
    }
}
```

### Cursor Pagination

```json theme={null}
{
    "data": [...],
    "pagination": {
        "limit": 20,
        "current_cursor": "eyJpZCI6NDB9",
        "next_cursor": "eyJpZCI6NjB9",
        "has_more": true
    }
}
```
