Skip to content

PHP SDK

clearance-rest/sdk wraps the Numbers, Emails and Captchas APIs with one client and three services. Every call sends your API key, sets a hard deadline, and turns failures into typed exceptions.

composer require clearance-rest/sdk
use ClearanceRest\Client;
$client = new Client(apiKey: 'cr_live_...');
// Or with no arguments, reading the environment:
$client = new Client();

With no arguments the client reads these environment variables, the same names the Node.js SDK uses:

Variable Purpose
CLEARANCE_REST_API_KEY Your project’s API key.
CLEARANCE_REST_URL Override the API base URL.
CLEARANCE_REST_NUMBERS_URL Override the Numbers base URL. Default https://api.clearance.rest/numbers.
CLEARANCE_REST_EMAILS_URL Override the Emails base URL. Default https://api.clearance.rest/emails.
CLEARANCE_REST_CAPTCHAS_URL Override the Captchas base URL. Default https://api.clearance.rest/captchas.

Without a key, none is sent and the API answers 401.

Pass timeout (milliseconds) to any call. The SDK sends it as X-Service-Timeout and also sets the HTTP client’s own timeout slightly above it, so a dead network can never hang a call forever. The SDK does not retry.

Methods take named arguments, so write them in camelCase.

use ClearanceRest\Services\Captchas;
$solution = $client->captchas->resolve(
task: ['type' => 'ImageToTextTask', 'body' => '<base64 image>'],
provider: 'capsolver',
timeout: 30_000,
);
echo Captchas::solutionValue($solution); // the token or text, whichever solver answered

Guide: Solving captchas.

$email = $client->emails->wait(
emailAccount: 'user@domain.com',
matchRegex: 'Verification',
codeRegex: '\d{6}',
timeout: 45_000,
);
echo $email['code'];

Connecting a Gmail or Outlook mailbox:

$authorizeUrl = $client->emails->oauthStart('gmail', 'https://app.example.com/settings/mailboxes', 'user-42')['authorize_url'];
$result = $client->emails->oauthResult('gmail', $token);
$accounts = $client->emails->accounts('gmail')['accounts'];
try {
$client->emails->disconnect('gmail', 'a@b.com');
} catch (\ClearanceRest\Exceptions\ChallengeRequestException $e) {
if ($e->getStatus() !== 404) throw $e; // 404: it was not connected
}

Guides: Waiting for an email and Connecting a mailbox.

$number = $client->numbers->rent(service: 'tg', country: 6)['number'];
$sms = $client->numbers->wait(number: $number['phoneNumber'], codeRegex: '\d{4,6}', timeout: 120_000);
$client->numbers->release(sid: $number['sid']);
$numbers = $client->numbers->list(sync: true)['numbers'];

rent defaults to Hero SMS. Twilio:

$client->numbers->availables(country: 'US', sms: true);
$client->numbers->rent(provider: 'twilio', phoneNumbers: ['+14155550100']);

Hero SMS reference data, and a one-call “check price then rent”:

$countries = $client->numbers->countries()['countries'];
$services = $client->numbers->services(country: 6)['services'];
$prices = $client->numbers->prices(country: 6, service: 'tg')['prices'];
$operators = $client->numbers->operators(country: 6)['operators'];
$cheapest = $client->numbers->rentCheapest(service: 'tg', country: 6);
$client->numbers->resend(sid: $number['sid']); // ask Hero SMS to resend the SMS

Mobile numbers:

$claim = $client->numbers->claimToken(label: 'agency-1'); // token, expires_at, qr_payload
// Makes an HTTP call to get a single-use ticket, and returns a ws URL that is
// safe to hand to a browser: it carries the ticket, not your API key.
$socketUrl = $client->numbers->claimSocketUrl(label: 'agency-1');
$apkUrl = $client->numbers->downloadApkUrl(); // no request, no key

Guides: Hero SMS numbers, Twilio numbers and Mobile numbers.

The tests of an app that uses the SDK should not call the real API. The client takes any Guzzle ClientInterface, so give it one with a MockHandler:

use ClearanceRest\Client;
use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
$mock = new MockHandler([
new Response(200, [], json_encode(['success' => true, 'number' => ['sid' => 'x', 'phoneNumber' => '+6281234567890']])),
]);
$client = new Client(
apiKey: 'test-key',
httpClient: new GuzzleClient(['handler' => HandlerStack::create($mock)]),
);

Laravel’s Http::fake() does not intercept this client, because it only sees requests made through Http::get() and friends. MockHandler returns its responses in the order you queued them and does not match URLs, so queue them in the order your test will make the calls.

AbortSignal cancellation is specific to the Node.js SDK; PHP has no equivalent.