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
composer require subdomainto/sdk guzzlehttp/guzzle guzzlehttp/psr7
Initialize the client
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
$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
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:
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.