Skip to content

PHP SDK

Reference
For:
Developers

The HostRepute PHP SDK, hostrepute/sdk version 0.1.0, is a client for the REST API v1 that sends its requests through any PSR-18 HTTP client. It needs PHP 8.2 or later with ext-json, plus a PSR-18 client and PSR-17 factories such as Guzzle’s. Version 0.1.0 manages domains and IPs, check profiles, alert channels and delivery hours well, but can’t read check results or metrics yet: read known problems in 0.1.0 before you build on it.

Install (when it's published)
composer require hostrepute/sdk guzzlehttp/guzzle

Leave out guzzlehttp/guzzle if your project already has a PSR-18 client: the SDK finds it with php-http/discovery.

Client::builder() collects the settings and build() returns the client; new Client($token) uses the defaults. Create the token in Settings, then API tokens with the abilities your code needs; Authentication and API tokens explains them. The SDK doesn’t read environment variables itself: the examples on this page read the token from HOSTREPUTE_API_TOKEN.

index.php
<?php
require __DIR__ . '/vendor/autoload.php';
use GuzzleHttp\Client as Guzzle;
use Hostrepute\Client;
$client = Client::builder()
->withToken(getenv('HOSTREPUTE_API_TOKEN') ?: throw new RuntimeException('Set HOSTREPUTE_API_TOKEN'))
->withUserAgent('deploy-checks/1.4')
->withHttpClient(new Guzzle(['timeout' => 45, 'connect_timeout' => 10]))
->build();
foreach ($client->hosts()->iterate(perPage: 100) as $host) {
echo $host->host, ' ', $host->isBlocklisted() ? 'listed' : 'not listed', PHP_EOL;
}

The example passes its own Guzzle client because that’s where request timeouts are set: withTimeout() has no effect in 0.1.0. build() throws an InvalidArgumentException for an empty token, an invalid base URL or an invalid retry setting, and a LogicException when no token was set.

Builder method Default What it does
withToken($token) required The team API token, sent as Authorization: Bearer <token>.
withBaseUrl($url) https://app.hostrepute.com The API’s address. Give the origin only: the SDK adds /api/v1/… to every path.
withHttpClient($client) found by php-http/discovery The PSR-18 client that sends the requests. Set timeouts, proxies and TLS options on it.
withRequestFactory($factory), withStreamFactory($factory) found by php-http/discovery The PSR-17 factories that build the requests.
withUserAgent($userAgent) hostrepute-php/0.1.0 php/<version> The User-Agent header.
withRetry(maxAttempts: 3, baseDelayMs: 200, maxDelayMs: 5000) 3 attempts, 200 ms, 5,000 ms The retry policy. See retries.
withDefaultHeader($name, $value) none An extra header on every request. It is applied after Accept, Authorization and User-Agent, so it can replace them.
withTimeout($seconds) 30 Stored, but not passed to the HTTP client in 0.1.0.

The client has one method per API resource. The names follow the API, not the portal:

In HostRepute Method Methods API
Domains and IPs $client->hosts() list, iterate, get, create, update, delete /api/v1/hosts
Blocklists $client->dataSources() list, iterate, get /api/v1/data-sources
Check profiles $client->monitoringProfiles() list, iterate, get, create, update, delete /api/v1/data-source-groups
Alert channels $client->alerts() list, iterate, get, create, update, delete /api/v1/alerts
Delivery hours $client->contactGroups() list, iterate, get, create, update, delete /api/v1/alert-groups
Blocklist checks $client->blacklist() check, status, checkAndWait, waitFor /api/v1/blacklist
Certificate checks $client->certificates() check, status, checkAndWait, waitFor /api/v1/certificates
Email authentication checks $client->deliverability() check, status, checkAndWait, waitFor /api/v1/deliverability
Prometheus metrics $client->metrics() get /api/v1/metrics
  • list(page: …, perPage: …) returns a Paginated with data, meta and links, and currentPage(), lastPage(), perPage(), total() and hasNextPage(). perPage is 1–100; the API sends 15 when you leave it out. iterate() is a generator over every page, 50 items per request unless you set perPage. Read Pagination.
  • get, update and delete take the uuid, except dataSources()->get(), which takes the blocklist’s numeric id.
  • update sends PUT with the arguments you pass, and throws an InvalidArgumentException when you pass none.
  • The SDK has no method for sending a test alert. Call POST /api/v1/alerts/{alert}/test directly.

Every domain or IP needs a check profile. The SDK calls it monitoringProfileUuid and sends it as data_source_group_uuid:

Add a domain with the default check profile
$profiles = $client->monitoringProfiles()->list();
$default = array_values(array_filter($profiles->data, fn ($profile) => $profile->isDefault))[0];
$host = $client->hosts()->create(
name: 'Mail',
host: 'mail.example.com',
monitoringProfileUuid: $default->uuid,
);

Delivery hours are contactGroups() in the SDK. schedule is an array that the SDK sends unchanged, so give it the shape the API expects:

  • Keys mon, tue, wed, thu, fri, sat and sun, each with enabled, start and end. Times are HH:MM, and an enabled day must end after it starts.
  • A day you leave out gets no alerts. Leave schedule out entirely for delivery hours that are open at any time.
  • update leaves out null arguments, so it can’t turn existing delivery hours back to any time. Send "schedule": null with the REST API instead.
  • The SDK’s README shows a days and hours shape: the API rejects it with 422.
Weekdays 08:00 to 18:00 in New York
$weekday = ['enabled' => true, 'start' => '08:00', 'end' => '18:00'];
$weekend = ['enabled' => false, 'start' => '08:00', 'end' => '18:00'];
$hours = $client->contactGroups()->create(
name: 'Business hours',
timezone: 'America/New_York',
schedule: [
'mon' => $weekday, 'tue' => $weekday, 'wed' => $weekday, 'thu' => $weekday, 'fri' => $weekday,
'sat' => $weekend, 'sun' => $weekend,
],
);

An alert channel is alerts(). settings holds the field the channel type needs (email here; Set up alert channels lists them all), and contactGroupUuids the delivery hours it follows:

An email alert channel that follows the delivery hours
use Hostrepute\Enums\AlertFrequency;
use Hostrepute\Enums\AlertType;
$channel = $client->alerts()->create(
type: AlertType::Email,
frequency: AlertFrequency::OnceOnListedDelisted,
settings: ['email' => 'ops@example.com'],
contactGroupUuids: [$hours->uuid],
);

For frequency, use AlertFrequency::OnceOnListedDelisted (Listed and removed in the portal) or AlertFrequency::OncePerCheckWhileListed (Only when listed). The SDK also defines AlertFrequency::Daily, which the API rejects with 422, and AlertFrequency::EveryCheck, a retired value that the API stores as once_on_listed_delisted.

Each check uses 1 credit (credit costs). check() starts a blocklist or certificate check and returns it with status pending; its uuid identifies the check:

Start a blocklist check
$scan = $client->blacklist()->check(host: 'mail.example.com');
echo $scan->uuid, ' ', $scan->status->value, PHP_EOL;

certificates()->check() also takes protocol, port and sni, and both take callbackUrl to be told when the check ends. A callback’s signature can’t be verified yet, so treat the callback as a notification and read the result from the status endpoint, as Receive webhooks explains. The SDK’s own webhook helpers don’t match what HostRepute sends, so don’t use them.

The SDK also has status($uuid), waitFor($uuid, timeout: …, pollInterval: …) and checkAndWait(host: …, timeout: …, pollInterval: …). The wait helpers poll status until the check is completed or failed, for up to timeout seconds (60 by default) every pollInterval seconds (2), and then throw a TimeoutException whose message names the check. In 0.1.0 they don’t work against the API (see below), so poll GET /api/v1/blacklist/status/{uuid} or GET /api/v1/certificates/status/{uuid} yourself, or use a callback, as Run checks and wait for results shows.

  • Status and wait helpers fail while a check runs. status(), waitFor() and checkAndWait() on blacklist() and certificates() throw a ValueError ("processing" is not a valid backing value) as soon as the API reports the check as running. It’s PHP’s own ValueError, so catch (HostreputeException $e) doesn’t catch it.
  • Results are missing. The blocklist and certificate check objects have no result and no counts (such as how many blocklists list the host), so even a completed check doesn’t tell you what it found.
  • Email authentication checks always throw. Every deliverability() method throws a ValueError (or an UnexpectedValueException for failed) on the API’s status, after the API has run the check and used the credit.
  • metrics()->get() throws a DecodingException, because it reads the Prometheus text as JSON.
  • withTimeout() has no effect. Set timeouts on the HTTP client you pass to withHttpClient().
  • 402 has no typed exception. Read getBody()['required_credits'] and getBody()['available_credits'] on the ApiException.

The SDK retries a failed request up to 3 attempts in total:

  • 429 is retried for every method. A 429 means the API refused the request before running it, so a retried check isn’t charged twice.
  • 5xx and network errors are retried only for GET, HEAD, OPTIONS, PUT and DELETE. A POST that creates something or starts a check isn’t retried, so the SDK never starts a check twice.
  • Waits. When the response has Retry-After (seconds or an HTTP date), the SDK waits that long. Otherwise it waits a random delay between zero and 200 ms × 2attempt − 1, capped at 5 seconds. The waits block the PHP process.
  • When the attempts run out, you get the exception for the last response, for example a RateLimitException.
Five attempts with longer waits
$tuned = Client::builder()
->withToken(getenv('HOSTREPUTE_API_TOKEN') ?: throw new RuntimeException('Set HOSTREPUTE_API_TOKEN'))
->withRetry(maxAttempts: 5, baseDelayMs: 500, maxDelayMs: 10_000)
->build();

withRetry(maxAttempts: 1) turns retries off. Rate limits lists the limits behind 429.

The SDK’s exceptions live in Hostrepute\Exceptions and extend HostreputeException. API errors extend ApiException, with getStatusCode(), getMessage(), getErrors() (field names to messages), getBody() (the parsed response) and getResponse().

Status or cause Exception Extra methods
401 AuthenticationException
403 AuthorizationException
404 NotFoundException
422 ValidationException getErrors()
429 RateLimitException getRetryAfter(), in seconds
5xx ServerException
Any other status, including 402 ApiException
No response, or an HTTP timeout NetworkException getPrevious(), the PSR-18 exception
A wait helper’s timeout TimeoutException
A response the SDK can’t read DecodingException
Handle the errors a check can return
use Hostrepute\Exceptions\ApiException;
use Hostrepute\Exceptions\RateLimitException;
use Hostrepute\Exceptions\ValidationException;
try {
$client->blacklist()->check(host: 'mail.example.com');
} catch (ValidationException $e) {
print_r($e->getErrors());
} catch (RateLimitException $e) {
echo "Rate limited, retry in {$e->getRetryAfter()} s", PHP_EOL;
} catch (ApiException $e) {
if ($e->getStatusCode() !== 402) {
throw $e;
}
$body = $e->getBody();
echo "Needs {$body['required_credits']} credits, {$body['available_credits']} left", PHP_EOL;
}

Errors shows the response body behind each status.