> For the complete documentation index, see [llms.txt](https://developer.paddle.com/llms.txt).

# Get started with Paddle in PHP

Install the Paddle PHP SDK, initialize a client, make your first request, and verify webhook signatures.

---

{% version-badge sdk="paddle-php" /%}

This quickstart walks through installing the Paddle PHP SDK, initializing a client, making your first read-only API call, and verifying webhook signatures.

{% callout type="note" title="Using Laravel?" %}
Use [Laravel Cashier Paddle](https://developer.paddle.com/sdks/community/laravel-cashier.md) instead. It's maintained by the Laravel team and comes with framework-native conventions for payments, billing, and subscriptions.
{% /callout %}

## Before you begin

You'll need:

- A [Paddle sandbox account](https://developer.paddle.com/sdks/sandbox.md).
- A [sandbox API key](https://developer.paddle.com/api-reference/about/authentication.md) with permission to read and write products.
- PHP 8.1 or later, with [Composer](https://getcomposer.org/) installed.

## Install the SDK {% step=true %}

Install `paddlehq/paddle-php-sdk` with Composer:

```sh
composer require paddlehq/paddle-php-sdk
```

[View the PHP SDK on GitHub](https://github.com/PaddleHQ/paddle-php-sdk)

## Initialize the client {% step=true %}

Create a `Client` with your API key. Use the `SANDBOX` environment while you're building.

```php
use Paddle\SDK\Client;
use Paddle\SDK\Environment;
use Paddle\SDK\Options;

$paddle = new Client(
    apiKey: getenv('PADDLE_API_KEY'),
    options: new Options(Environment::SANDBOX),
);
```

For production, drop the `options` argument:

```php
$paddle = new Client(getenv('PADDLE_API_KEY'));
```

{% callout type="note" %}
Sandbox API keys contain `_sdbx`. Sandbox and live keys are separate — using one against the other API returns a `forbidden` error.
{% /callout %}

## Make your first request {% step=true %}

List products to confirm the client is wired up. The SDK returns an iterable that paginates automatically.

```php
use Paddle\SDK\Client;
use Paddle\SDK\Environment;
use Paddle\SDK\Options;
use Paddle\SDK\Exceptions\ApiError;

$paddle = new Client(
    apiKey: getenv('PADDLE_API_KEY'),
    options: new Options(Environment::SANDBOX),
);

try {
    $products = $paddle->products->list();
    foreach ($products as $product) {
        echo $product->id . '  ' . $product->name . PHP_EOL;
    }
} catch (ApiError $error) {
    echo 'Paddle API error: ' . $error->getMessage();
}
```

If your sandbox account is empty, the loop runs zero times. Create a product in the dashboard or via `$paddle->products->create()` to see results.

## 4. Verify webhooks {% step=true %}

You can use [webhooks](https://developer.paddle.com/webhooks.md) to keep your app in sync with Paddle. For example, you can [provision access](https://developer.paddle.com/build/subscriptions/provision-access-webhooks.md) when a subscription is created, or revoke access when a subscription is cancelled.

The SDK's `Verifier` accepts any [PSR-7](https://www.php-fig.org/psr/psr-7/) `RequestInterface`, like Guzzle, Symfony, Laravel (`Illuminate\Http\Request::toPsrRequest()`), and most modern PHP HTTP frameworks all support this. Always verify the signature before acting on the payload.

```php
use GuzzleHttp\Psr7\ServerRequest;
use Paddle\SDK\Entities\Event;
use Paddle\SDK\Notifications\Secret;
use Paddle\SDK\Notifications\Verifier;

$request = ServerRequest::fromGlobals();
$secret = new Secret(getenv('PADDLE_WEBHOOK_SECRET'));

if (!(new Verifier())->verify($request, $secret)) {
    http_response_code(400);
    exit('invalid signature');
}

$event = Event::fromRequest($request);

switch ($event->eventType) {
    case 'transaction.completed':
        // Provision access, send a receipt, etc.
        break;
    case 'subscription.updated':
        // Sync the subscription to your database.
        break;
}

http_response_code(200);
echo 'ok';
```

For the full webhook setup flow, including creating notification destinations, picking events, and retry behavior, see [Verify webhook signatures](https://developer.paddle.com/webhooks/about/signature-verification.md).

## Next steps

- Explore [Laravel Cashier Paddle](https://developer.paddle.com/sdks/community/laravel-cashier.md) for a Laravel-native way to build with Paddle.
- Use the [webhook simulator](https://developer.paddle.com/webhooks/simulator.md) to test webhook events.
- Browse the [API reference](https://developer.paddle.com/api-reference.md) to see every endpoint Paddle exposes.
- View the [PHP SDK reference](https://developer.paddle.com/sdks/libraries/php.md) for the full SDK reference.