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

# Laravel SDK

> The proofage/laravel-client package: configuration, facade, and a ready webhook route.

`proofage/laravel-client` adds Laravel wiring to the [PHP SDK](/integration/server-sdks/php): a service provider with auto-discovery, the `ProofAge` facade, webhook signature middleware, and a command that checks your setup. It supports Laravel 12 and 13 on PHP 8.2 or newer, and sends every request through Laravel's `Http` facade, so `Http::fake()` works in your tests.

## Install

```bash theme={null}
composer require proofage/laravel-client
php artisan vendor:publish --provider="ProofAge\Laravel\ProofAgeServiceProvider" --tag="config"
```

```bash .env theme={null}
PROOFAGE_API_KEY=pk_live_...
PROOFAGE_SECRET_KEY=sk_live_...
```

Check everything, from the keys to the webhook route:

```bash theme={null}
php artisan proofage:verify-setup
```

It checks the configuration, the connection to your workspace, that the workspace has a webhook URL, and that a `POST` route exists for it, protected by the signature middleware.

## Create a verification

```php theme={null}
use ProofAge\Laravel\Facades\ProofAge;

$verification = ProofAge::verifications()->create([
    'external_id' => (string) $user->id,
    'callback_url' => route('verification.done'),
    'external_metadata' => ['plan' => 'pro'],
]);

return redirect()->away($verification['url']);
```

## Read results

```php theme={null}
$verification = ProofAge::verifications()->find($verificationId);
$estimation = ProofAge::verifications($verificationId)->estimation();
```

## Receive webhooks

```php theme={null}
// routes/api.php
Route::post('/webhooks/proofage', [ProofAgeWebhookController::class, 'handle'])
    ->middleware('proofage.verify_webhook');
```

In `routes/web.php` instead, exclude the path from CSRF protection in `bootstrap/app.php`, or every webhook is rejected with `419` before the middleware runs:

```php theme={null}
->withMiddleware(function (Middleware $middleware) {
    $middleware->validateCsrfTokens(except: ['webhooks/proofage']);
})
```

The middleware checks the headers, that `X-Auth-Client` is your public key, that the timestamp is within 300 seconds (`webhook_tolerance`), and the signature. A request that fails is answered `401` with a code such as `INVALID_SIGNATURE`; your controller only sees verified webhooks. Configure the workspace's **active** secret key: webhooks are signed with it.

## Several workspaces

A marketplace verifying buyers and sellers differently runs two workspaces. Add the second set of keys to your config, create a client for it, and name its config prefix on the webhook route:

```php theme={null}
// config/services.php
'proofage_seller' => [
    'api_key' => env('PROOFAGE_SELLER_API_KEY'),
    'secret_key' => env('PROOFAGE_SELLER_SECRET_KEY'),
],
```

```php theme={null}
use ProofAge\Laravel\ProofAgeClientFactory;

$seller = app(ProofAgeClientFactory::class)->make('services.proofage_seller');
$seller->verifications()->create(['external_id' => (string) $user->id]);

Route::post('/webhooks/proofage-seller', [SellerWebhookController::class, 'handle'])
    ->middleware('proofage.verify_webhook:services.proofage_seller');
```

See the [marketplace recipe](/recipes/marketplace-sellers).

## Errors

```php theme={null}
use ProofAge\Laravel\Exceptions\AuthenticationException; // 401
use ProofAge\Laravel\Exceptions\ValidationException;     // 422, getErrors()
use ProofAge\Sdk\Exceptions\TransportException;          // no response
use ProofAge\Sdk\Exceptions\ProofAgeException;           // everything else, and the base of all

try {
    ProofAge::verifications()->create($data);
} catch (ValidationException $e) {
    $e->getErrors();
} catch (ProofAgeException $e) {
    $e->getCode();      // HTTP status
    $e->getErrorCode(); // the API's code
}
```

Retries follow the [PHP SDK](/integration/server-sdks/php#errors-and-retries): a `POST` is never retried after a `5xx` or a timeout.

## Links

* [Packagist: proofage/laravel-client](https://packagist.org/packages/proofage/laravel-client)
* [GitHub: ProofAge/laravel-client](https://github.com/ProofAge/laravel-client)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.