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

# PHP SDK

> Install and use the official BillingServ PHP SDK for the v2 API.

The [BillingServ PHP SDK](https://github.com/BillingServ/PHP-SDK) is the official Composer package for integrating PHP applications with the BillingServ v2 API. It provides resource clients for billing, checkout, domains, reporting, support, VPN, software licensing, and more, while handling authentication, JSON requests, response decoding, and common API errors.

<Note>
  The SDK is for server-side PHP applications. Never expose your merchant API key in browser code or commit it to your repository.
</Note>

## Requirements

* PHP 8.3 or later
* PHP `curl` extension
* PHP `json` extension

## Install

Install the package with Composer:

```bash theme={null}
composer require billingserv/php-sdk
```

The package is released under the MIT license. See the [PHP-SDK repository](https://github.com/BillingServ/PHP-SDK) for the source, tests, and release history.

## Configure the client

Create an API key from the [API Information page](/docs/account/api), then pass the merchant bearer token to the client:

```php theme={null}
<?php

require __DIR__.'/vendor/autoload.php';

use BillingServ\BillingServ;

$billingserv = new BillingServ(
    apiKey: $_ENV['BILLINGSERV_API_KEY'],
    options: [
        'base_uri' => $_ENV['BILLINGSERV_BASE_URI'],
        'timeout' => 15,
    ],
);
```

`base_uri` should point to your BillingServ installation and end in `/api/v2`, for example:

```text theme={null}
https://your-billingserv-domain.com/api/v2
```

If you omit `base_uri`, the SDK uses the public demo API URL. Set it explicitly for production and for self-hosted BillingServ installations. The `timeout` option is in seconds and defaults to 30.

Store configuration in environment variables or another secret store. For example:

```dotenv theme={null}
BILLINGSERV_API_KEY=your-merchant-bearer-token
BILLINGSERV_BASE_URI=https://your-billingserv-domain.com/api/v2
BILLINGSERV_WEBHOOK_SECRET=your-webhook-signing-secret
```

The merchant key must have permission for the resources and operations your application calls. Keep the key on your server; customers authenticate through your application and do not need a merchant API key.

## Make API calls

Resource clients are exposed as properties on the `BillingServ` instance. For example, list customers and create a customer with an idempotency key:

```php theme={null}
$customers = $billingserv->customers->list([
    'search' => 'jane',
    'per_page' => 25,
]);

$reference = bin2hex(random_bytes(16));
$customer = $billingserv->customers->create([
    'name' => 'Jane Doe',
    'username' => 'jane@example.com',
    'password' => 'use-a-secret-password',
    'address_1' => '1 High Street',
    'city' => 'Manchester',
    'county_id' => 1231,
    'country_id' => 81,
    'postal_code' => 'M1 1AA',
], idempotencyKey: 'signup-'.$reference);
```

Idempotency keys are supported for the create and update operations documented in the [API overview](/docs/api-reference/introduction). Use a unique key for each logical write so a retry does not create a duplicate resource.

### Available resources

| Client                                        | Covers                                                 |
| --------------------------------------------- | ------------------------------------------------------ |
| `customers`                                   | Customer records, credits, and customer lookup         |
| `invoices`                                    | Invoices, quotes, unpaid invoices, and payment capture |
| `orders`                                      | Orders, acceptance, and package-change previews        |
| `checkout`                                    | Hosted checkout links                                  |
| `domains`                                     | Domain availability and lookup                         |
| `packages`, `packageGroups`, `packageOptions` | Products and package configuration                     |
| `countries`, `counties`, `currencies`         | Country, county, and currency data                     |
| `marketing`, `reports`, `settings`            | Marketing, reporting, and account settings             |
| `tickets`                                     | Support tickets                                        |
| `usage`, `vpn`, `licenses`, `modules`         | Usage metering, VPN, licensing, and modules            |

Each SDK method maps to a documented v2 API endpoint. Use the [API reference](/docs/api-reference) to check required fields, permissions, and response details.

## Hosted checkout and domains

Create a hosted checkout URL, then redirect the customer to the returned URL:

```php theme={null}
$checkout = $billingserv->checkout->create([
    'package_id' => 12,
    'cycle_id' => 3,
    'callback_url' => 'https://app.example.com/billing/return',
    'customer_id' => 4,
]);

header('Location: '.$checkout['url']);
exit;
```

You can also check domain availability across enabled extensions:

```php theme={null}
$availability = $billingserv->domains->lookup('example');

foreach ($availability['results'] ?? [] as $result) {
    echo $result['domain'];
    echo $result['available'] ? ' is available' : ' is taken';
    echo PHP_EOL;
}
```

For the complete domain-search and callback flow, see the [domain API and hosted checkout guide](/docs/guides/domain-api-checkout).

## Handle errors

Successful responses are returned as plain PHP arrays. API and network failures throw exceptions:

```php theme={null}
use BillingServ\Exception\ApiException;
use BillingServ\Exception\AuthenticationException;
use BillingServ\Exception\NetworkException;
use BillingServ\Exception\RateLimitException;
use BillingServ\Exception\ValidationException;

try {
    $customer = $billingserv->customers->get(999);
} catch (ValidationException $e) {
    $errors = $e->getErrors();
} catch (AuthenticationException $e) {
    // The API key is missing, invalid, or not authorized.
} catch (RateLimitException $e) {
    // Back off for the server-provided duration when available.
    sleep($e->getRetryAfter() ?? 30);
} catch (NetworkException $e) {
    // The HTTP request could not be completed.
} catch (ApiException $e) {
    // Inspect the status, error code, request ID, and response.
}
```

`ApiException` exposes `getStatus()`, `getErrors()`, `getErrorCode()`, `getRequestId()`, and `getResponse()`. Record the request ID with your application logs when reporting an API failure.

## Verify webhooks

When webhook signing is enabled, verify the raw request body before parsing it. The SDK checks the `BillingServ-Signature` header and rejects stale or invalid signatures:

```php theme={null}
use BillingServ\Webhook;

$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_BILLINGSERV_SIGNATURE'] ?? '';
$secret = $_ENV['BILLINGSERV_WEBHOOK_SECRET'];

if (!Webhook::verify($payload, $signature, $secret)) {
    http_response_code(400);
    exit;
}

$event = Webhook::parse($payload);
// Persist or enqueue by $event['id']; deliveries may be retried.
```

Respond to verified deliveries promptly, then process them asynchronously where possible. See the [webhook overview](/docs/api-reference/webhooks/overview) and [webhook event reference](/docs/api-reference/webhooks/events) for event types, retries, and endpoint configuration.

## Further reading

* [PHP-SDK on GitHub](https://github.com/BillingServ/PHP-SDK)
* [API overview](/docs/api-reference/introduction)
* [Complete API reference](/docs/api-reference)
* [Webhook endpoint guide](/docs/api-reference/webhooks/build-an-endpoint)
