PHP SDK
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
Section titled “Install”composer require hostrepute/sdk guzzlehttp/guzzleLeave out guzzlehttp/guzzle if your project already has a PSR-18 client: the SDK finds it with php-http/discovery.
Create a client
Section titled “Create a client”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.
<?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. |
Resources
Section titled “Resources”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 aPaginatedwithdata,metaandlinks, andcurrentPage(),lastPage(),perPage(),total()andhasNextPage().perPageis 1–100; the API sends 15 when you leave it out.iterate()is a generator over every page, 50 items per request unless you setperPage. Read Pagination.get,updateanddeletetake theuuid, exceptdataSources()->get(), which takes the blocklist’s numericid.updatesendsPUTwith the arguments you pass, and throws anInvalidArgumentExceptionwhen you pass none.- The SDK has no method for sending a test alert. Call
POST /api/v1/alerts/{alert}/testdirectly.
Add a domain or IP
Section titled “Add a domain or IP”Every domain or IP needs a check profile. The SDK calls it
monitoringProfileUuid and sends it as data_source_group_uuid:
$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,);Set delivery hours and an alert channel
Section titled “Set delivery hours and an alert channel”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,satandsun, each withenabled,startandend. Times areHH:MM, and an enabled day must end after it starts. - A day you leave out gets no alerts. Leave
scheduleout entirely for delivery hours that are open at any time. updateleaves outnullarguments, so it can’t turn existing delivery hours back to any time. Send"schedule": nullwith the REST API instead.- The SDK’s README shows a
daysandhoursshape: the API rejects it with422.
$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:
use Hostrepute\Enums\AlertFrequency;use Hostrepute\Enums\AlertType;
$channel = $client->alerts()->create( type: AlertType::Email, frequency: AlertFrequency::OnceOnListedDelisted, 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.
Run checks
Section titled “Run checks”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:
$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.
Known problems in 0.1.0
Section titled “Known problems in 0.1.0”- Status and wait helpers fail while a check runs.
status(),waitFor()andcheckAndWait()onblacklist()andcertificates()throw aValueError("processing" is not a valid backing value) as soon as the API reports the check as running. It’s PHP’s ownValueError, socatch (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
completedcheck doesn’t tell you what it found. - Email authentication checks always throw. Every
deliverability()method throws aValueError(or anUnexpectedValueExceptionforfailed) on the API’s status, after the API has run the check and used the credit. metrics()->get()throws aDecodingException, because it reads the Prometheus text as JSON.withTimeout()has no effect. Set timeouts on the HTTP client you pass towithHttpClient().402has no typed exception. ReadgetBody()['required_credits']andgetBody()['available_credits']on theApiException.
Retries
Section titled “Retries”The SDK retries a failed request up to 3 attempts in total:
429is retried for every method. A429means the API refused the request before running it, so a retried check isn’t charged twice.5xxand network errors are retried only forGET,HEAD,OPTIONS,PUTandDELETE. APOSTthat 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.
$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.
Errors
Section titled “Errors”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 |
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.
Related
Section titled “Related”- Official SDKs compares the five SDKs.
- Make your first API call uses the REST API without an SDK.
- Run checks and wait for results explains polling, callbacks and credits.
- API token abilities lists what each ability allows.
- The API reference documents every operation.

