PHP SDK
Package: wisecp/whost-php-sdk 0.1.1 — a download from this site
Download: whost-php-sdk.zip
· SHA-256: whost-php-sdk.zip.sha256
Requires: PHP 7.4 or newer with the curl and json extensions
The SDK is a PHP client for the WHost admin API. It is not tied to one billing system: WISECP, WHMCS, Blesta and your own code use the same package. It signs every request, offers an idempotency key on every write call, retries on request, maps error answers to typed exceptions and verifies incoming webhooks.
The package is not published on Packagist or GitHub; the archive on this site is the way to get it.
Download and install
curl -O https://whost.wisecp.com/developer/downloads/whost-php-sdk.zip
curl -O https://whost.wisecp.com/developer/downloads/whost-php-sdk.zip.sha256
sha256sum -c whost-php-sdk.zip.sha256
unzip whost-php-sdk.zip
The archive holds one folder, whost-php-sdk/: the SDK (src/), four
examples, a README, the CHANGELOG, the LICENSE and a vendor/ folder with
the SDK's dependencies (Guzzle 7 and the PSR HTTP interfaces, chosen to run
on PHP 7.4 and newer).
Licence. The LICENSE lets you use, copy and modify the SDK, its examples included, and distribute it as part of your own integration that connects to WHost (for example a billing-system module) — not on its own. Keep the LICENSE file and the copyright notices in every copy; anything else needs written permission from WISECP LLC.
Without Composer — load the bundled autoloader:
require __DIR__ . '/whost-php-sdk/vendor/autoload.php';
With Composer — if your project already has its own vendor/, delete
the bundled whost-php-sdk/vendor/ folder, point a path repository at the
extracted folder and require the package; Composer then installs the
dependencies itself:
{
"repositories": [
{ "type": "path", "url": "./whost-php-sdk", "options": { "symlink": false } }
],
"require": {
"wisecp/whost-php-sdk": "^0.1"
}
}
Run composer update wisecp/whost-php-sdk afterwards. Without the path
repository composer require wisecp/whost-php-sdk does not find the
package.
API key
Create a key in the WHost admin panel under Settings → API Access and limit it to the addresses your integration calls from. The secret is shown once, when the key is created; keep it outside your code (an environment variable or a secrets store).
A key created there is a server-wide key and reaches the admin API the SDK
calls. A key that a reseller or customer creates in the client panel is
bound to that account and reaches only the client API
(/api/v1/client/...); the SDK's resources answer 403 SCOPE_DENIED for
it.
Quickstart
<?php
require __DIR__ . '/whost-php-sdk/vendor/autoload.php';
use WHost\WHostClient;
use WHost\Exceptions\WHostException;
$whost = new WHostClient(
(string) getenv('WHOST_API_KEY'),
(string) getenv('WHOST_API_SECRET'),
'https://panel.example.com', // the address you open the WHost panel on
['timeout' => 30.0]
);
try {
$page = $whost->accounts->list(['limit' => 25]);
foreach ($page['accounts'] as $account) {
echo $account['username'], "\t", $account['domain'], PHP_EOL;
}
$account = $whost->accounts->create([
'username' => 'demo01',
'domain' => 'demo01.example.com',
'email' => '[email protected]',
'password' => $password, // plain text over TLS; the agent hashes it itself
'plan_id' => $planId, // the "id" of a plan from $whost->plans->list()
], 'order-12345'); // idempotency key, see below
echo 'Created: ', $account['username'], PHP_EOL;
} catch (WHostException $e) {
fwrite(STDERR, sprintf(
"[%d %s] %s\n",
$e->getHttpStatus(),
$e->getErrorCode(),
$e->getMessage()
));
exit(1);
}
- Base URL: the panel's address; the client appends
/api/v1itself. The WHost agent listens only on the server's loopback interface, so requests reach it through the panel's web server. - TLS: certificate verification is on by default (
verify_ssl); turn it off only for a test server with a self-signed certificate. - Answers: each method returns the
datafield of the agent's answer as an array.
What the SDK covers
One accessor per area of the admin API, 38 in all: accounts, domains, DNS,
SSL, e-mail, databases, FTP, files, cron, backups, PHP, plans, Python and
Node.js applications, firewall, Fail2Ban, WAF, spam filter, mail queue and
sent mail, logs, metrics, system and services, updates, licence, migration,
plugins, reseller permissions and white label. The method list of each
accessor is in src/Resources/ of the archive; an IDE completes it from
there.
Only a signed-in panel session reaches these, not an API key: API key
management (apiKeys), the administrator's own profile (profile), the
administrator's notification centre (notifications), the panel sign-in
calls (auth) and the white-label settings. Over an API key they answer
401 AUTH_FAILED. Changing an account's password
(accounts->changePassword()) or the server's root password is refused for
API keys too (403 HMAC_FORBIDDEN_FOR_CREDENTIAL_MUTATION); the account
owner changes the password in the panel.
No helper method yet: webhook endpoint management
(/api/v1/system/webhooks/...), the client API (/api/v1/client/...) and
some newer admin endpoints. Call them through the low-level client with the
path after /api/v1:
$events = $whost->http()->request('GET', '/system/webhooks/events');
// request(string $method, string $path, ?array $body = null,
// array $query = [], ?string $idempotencyKey = null)
Every endpoint is listed in the endpoint catalogue.
Idempotency
Write methods take an optional idempotency key as their last argument: the
second for create($data, $key), the third where the method also takes a
data array, as in suspend($username, $data, $key). A key is 8–64
characters of letters, digits, - and _; use one key per business event,
for example order-12345 for provisioning order 12345.
The agent keeps the answer under that key for 24 hours:
X-Idempotent-Replay: true; the action does not run again. A secret shown once (API key or webhook secret, 2FA material, one-time sign-in link, OAuth token) comes back as "***"409 IDEMPOTENCY_KEY_REUSED400 IDEMPOTENCY_KEY_INVALIDRetries
$whost = $whost->withRetry(3);
retries a request up to three more times on 429, on 5xx and on
connection errors, waiting 1 s, 2 s and 5 s. Send an idempotency key with
every write call you retry.
Errors
AuthExceptionHTTP 401 or 403, or an error_code that starts with AUTH_NotFoundExceptionHTTP 404RateLimitExceptionHTTP 429 or RATE_LIMIT_EXCEEDED; getRetryAfter() gives the wait in seconds when the agent sends oneValidationExceptionHTTP 400 or 422, or VALIDATION_ERROR; getFieldErrors() lists the fieldsWHostExceptionAnything else: other 4xx and 5xx answers, and connection errors (TRANSPORT_ERROR)All of them are WHost\Exceptions\WHostException subclasses and carry
getHttpStatus(), getErrorCode(), getDetails() and getRawBody(). The
meaning of each error code is in the error code
catalogue.
Request signing
The SDK signs every request with HMAC-SHA256 and sends X-WHost-Key,
X-WHost-Timestamp, X-WHost-Nonce and X-WHost-Signature. The signed
text is
METHOD\nPATH\nTIMESTAMP\nNONCE\nBODY
where PATH is the full request path including /api/v1 and the query
string. The agent rejects a timestamp more than 300 seconds away from its
own clock, so keep the calling server's clock synchronised (NTP).
Webhook verification
use WHost\Http\WebhookVerifier;
use WHost\Exceptions\WHostException;
try {
$event = WebhookVerifier::parse(
file_get_contents('php://input'),
$_SERVER['HTTP_X_WHOST_WEBHOOK_SIGNATURE'] ?? '',
$_SERVER['HTTP_X_WHOST_WEBHOOK_TIMESTAMP'] ?? '',
$endpointSecret
);
} catch (WHostException $e) {
http_response_code(401); // WEBHOOK_SIGNATURE_INVALID, WEBHOOK_TIMESTAMP_OUT_OF_RANGE, ...
exit;
}
switch ($event['event']) {
case 'account.created': /* ... */ break;
case 'account.suspended': /* ... */ break;
case 'ssl.failed': /* ... */ break;
}
The verifier checks X-WHost-Webhook-Signature (sha256=<hex> over
"{timestamp}.{raw body}") against the raw request body and rejects a
delivery older than 300 seconds. The agent makes up to five delivery
attempts and retries any answer other than 2xx, so drop duplicates by
X-WHost-Webhook-Event-Id. Events and payloads: Webhooks.
Examples in the archive
examples/01-quickstart.phpList accounts, create one, read it backexamples/02-account-lifecycle.phpCreate → suspend → unsuspend → deleteexamples/03-billing-integration-pattern.phpThe order hooks of a billing system: activate, suspend, resume, terminate, change planexamples/04-webhook-receiver.phpA webhook endpoint with signature check and duplicate filterRun them from the extracted folder with WHOST_API_KEY,
WHOST_API_SECRET and WHOST_BASE_URL set. They create accounts on the
server they point at; use a test server.
Why is there no WHMCS, Blesta or WISECP module?
The SDK is deliberately billing-agnostic: the glue to a billing system
lives on the billing side. examples/03-billing-integration-pattern.php
shows the hooks such a module needs. If you maintain a module that uses
this SDK, tell us at [email protected].
Versions and status
The SDK has its own version number, independent of the WHost version.
While it is 0.x, a minor release may change behaviour; the CHANGELOG.md
in the archive says what changed. The SDK is part of the WHost beta; report
problems with a support ticket from your wisecp.com client area (or
[email protected] when you cannot open one).
Our support team is here around the clock for anything you can't find above.