> ## 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.

# Request

> Requests in Apivalk are strongly typed and self-validating. By defining a request class, you define the "shape" of the data your endpoint expects.

## Creating a Request

Every request class must extend `AbstractApivalkRequest` and implement the `getDocumentation()` method.

### Example

```php theme={null}
namespace App\Http\Request\Pet;

use apivalk\apivalk\Http\Request\AbstractApivalkRequest;
use apivalk\apivalk\Documentation\ApivalkRequestDocumentation;
use apivalk\apivalk\Documentation\Property\StringProperty;
use apivalk\apivalk\Documentation\Property\IntegerProperty;

class CreatePetRequest extends AbstractApivalkRequest
{
    public static function getDocumentation(): ApivalkRequestDocumentation
    {
        $doc = new ApivalkRequestDocumentation();

        // Body parameters — addBodyProperty (body), addQueryProperty (query),
        // addPathProperty (path). `setIsRequired(true)` is the default; call
        // `setIsRequired(false)` to mark a property as optional.
        $doc->addBodyProperty(new StringProperty('name', 'Pet name'));
        $doc->addBodyProperty(
            (new StringProperty('type', 'Species of the pet'))->setIsRequired(false)
        );

        // Path parameters (matched from route like /pet/{id})
        $doc->addPathProperty(
            new IntegerProperty('id', 'Internal ID')
        );

        return $doc;
    }
}
```

## Accessing Data

Data is organized into "Bags". The framework automatically populates these bags and casts the values to the types defined in your documentation.

```php theme={null}
public function __invoke(ApivalkRequestInterface $request): AbstractApivalkResponse
{
    // Access body parameters (returns the value directly via magic getter)
    $name = $request->body()->name;
    
    // Access query parameters
    $page = $request->query()->page ?? 1;
    
    // Access path parameters (/user/{id})
    $userId = $request->path()->id;
    
    // Access headers
    $token = $request->header()->Authorization;
    
    // Access uploaded files (returns File object)
    $image = $request->file()->get('avatar');

    // Access populated sorting (as defined in Route). SortBag is iterable —
    // iterate directly. The bag is always populated: if the user does not
    // provide an order_by parameter, it contains the default sorting defined
    // on the route. User-requested sorts iterate first, route defaults last.
    // Each Sort knows its origin via $sort->isRequested().
    foreach ($request->sorting() as $field => $sort) {
        $isAsc = $sort->isAsc();
    }
}
```

### Magic Getters

`ParameterBag` supports magic getters for cleaner code:

```php theme={null}
$name = $request->body()->name;
$userId = $request->path()->id;
```

## Base vs. Runtime Documentation

Every request class exposes **two** documentation views:

* **Static** — `RequestClass::getDocumentation()`. Returns the base `ApivalkRequestDocumentation` as declared by the developer. Stable and independent of the route.
* **Instance** — `$request->getRuntimeDocumentation()`. Returns the base documentation merged with route-derived metadata (pagination query params, filter fields, `order_by`, available sort fields). This is what the `RequestValidationMiddleware` validates against and what the population strategies consume.

You normally only define the base via `getDocumentation()`. The framework builds the runtime view for you in `RequestDocumentationFactory::buildRuntimeDocumentation()`.

## Automatic Request Documentation

When a route has [sorting defined](/routing/route#sorting) or [pagination enabled](/http/pagination), the framework automatically documents the corresponding query parameters (`order_by`, `page`, `limit`, `offset`, or `cursor`) in your OpenAPI specification.

This includes:

* **Validation**: Ensuring that only allowed values and correct formats are used.
* **Example generation**: Showcasing correct usage for sorting and pagination.
* **Default values**: Reflecting the configuration defined on the route (e.g., `setMaxLimit`).

Additionally:

* The `sorting()` bag is automatically populated with default values if the user does not provide an `order_by` parameter.
* The `paginator()` object is automatically created and accessible if pagination is enabled.

## Validation

Validation happens automatically if you use the `RequestValidationMiddleware`. If the incoming data does not match your `getDocumentation()` definition, the framework will immediately return a `422 Unprocessable Entity` response with detailed error messages.

## Resource Requests

For endpoints backed by a resource CRUD controller you typically don't author a request class at all — the framework uses a single shared `ResourceRequest`, and the runtime documentation is derived from your `AbstractResource` definition. See [Resources](/resources/index).

## Authentication Identity

You can attach an authentication identity to the request:

```php theme={null}
$user = $this->authService->authenticate($request);
$request->setAuthIdentity($user);

// Later in controller or middleware
$currentUser = $request->getAuthIdentity();
```
