PHP SDK

subdomainto/sdk is a framework-independent typed client for PHP 7.4 and later. It uses PSR-18 HTTP clients and PSR-17 factories.

Installation

BASH
composer require subdomainto/sdk guzzlehttp/guzzle guzzlehttp/psr7

Initialize the client

PHP
use GuzzleHttp\Client as HttpClient;
use GuzzleHttp\Psr7\HttpFactory;
use SubdomainTo\Client;

$factory = new HttpFactory();
$subdomainTo = new Client($_ENV['SUBDOMAINTO_API_KEY'], new HttpClient(), $factory, $factory);

The client defaults to https://api.subdomain.to/v1. Pass a fifth argument to use another base URI.

Create a domain

PHP
$destination = $subdomainTo->destinations()->create('https://app.example.com', 'main-destination');
$domain = $subdomainTo->domains()->create('portal.customer.com', 'customer-42-domain', $destination->id());

Every idempotent creation method requires a stable key. The SDK does not invent one and performs no implicit retry.

Available resources

Method Resource
system() Public health check
destinations() List and create HTTPS destinations
domains() List, create, retrieve, and delete customer domains
webhooks() Create webhook endpoints
widget() Widget sessions and browser hostname creation
usage() Current-plan usage
billing() Stripe Checkout session

Responses become typed models such as Destination, Domain, WidgetSession, and Usage. Lists return CollectionResult with items(), hasMore(), and nextCursor().

Handle errors

PHP
use SubdomainTo\Exception\ApiException;
use SubdomainTo\Exception\ConflictException;

try {
    $domain = $subdomainTo->domains()->create($hostname, $idempotencyKey);
} catch (ConflictException $exception) {
    // The hostname already exists or its state prevents the operation.
} catch (ApiException $exception) {
    error_log(sprintf('subdomain.to: HTTP %d, code %s, request %s', $exception->statusCode(), $exception->apiCode(), $exception->requestId() ?? 'unknown'));
}

Specialized errors cover 400, 401, 403, 404, 409, and 5xx. Transport failures throw TransportException.

Verify a webhook

Always pass the untouched raw body:

PHP
use SubdomainTo\WebhookVerifier;

$event = (new WebhookVerifier())->verify($rawBody, $_SERVER['HTTP_SUBDOMAINTO_SIGNATURE'] ?? '', $_ENV['SUBDOMAINTO_WEBHOOK_SECRET']);

The default time tolerance is 300 seconds. An invalid signature, timestamp, or payload throws InvalidWebhookException.