PHP client for the PrintSocket cloud print API.
A lightweight agent runs on a machine, connects outbound to PrintSocket, and exposes that machine's printers (and scales) to a REST API. This library wraps API v1: devices, printers, scales, documents, print jobs, webhooks, and API keys, plus webhook signature verification for your receiver.
Zero dependencies beyond ext-curl and ext-json. Requires PHP 8.1 or newer.
Full API documentation lives at
www.printsocket.com/docs.
composer require printsocket/printsocketAn sk_test_ key comes with a virtual device and printer that runs the full
job lifecycle, so this works before any hardware is enrolled:
use PrintSocket\PrintSocketClient;
$ps = new PrintSocketClient(['api_key' => getenv('PRINTSOCKET_API_KEY')]);
$printers = $ps->printers->all(['state' => 'online']);
$job = $ps->jobs->create([
'printer_id' => $printers['data'][0]['id'],
'title' => 'Order #12345 label',
'content' => ['format' => 'pdf', 'url' => 'https://example.com/label.pdf'],
'metadata' => ['order_id' => '12345'],
]);
echo $job['id'], ' ', $job['status']; // job_... queuedResponses are associative arrays with the exact snake_case fields the API reference documents, so the docs read straight across to the code.
$ps = new PrintSocketClient([
'api_key' => 'sk_live_...', // required
'base_url' => 'https://api.printsocket.com/v1', // default
'timeout' => 30.0, // seconds per attempt
'max_retries' => 2, // connection failures, 429s, and 5xx
]);Every API error throws a typed subclass of ApiErrorException carrying
$status, $type, $errorCode, $param, and $requestId (quote the
request id in support requests):
use PrintSocket\Exception\ConflictException;
try {
$ps->jobs->cancel($jobId);
} catch (ConflictException $e) {
if ($e->errorCode === 'job_not_cancelable') {
// already printing or finished
} else {
throw $e;
}
}The classes are InvalidRequestException, AuthenticationException,
PermissionException, NotFoundException, ConflictException,
RateLimitException, BillingException, and ServerException, one per
error.type the API returns. Requests that never got a response throw
ApiConnectionException.
Connection failures, 429s, and 5xx responses are retried automatically
(max_retries, default 2), honoring Retry-After. Every POST carries an
Idempotency-Key header, generated when you do not pass one, and the key is
identical across the client's own retry attempts, so a retried create cannot
produce a duplicate job. To extend the guarantee across your own retries,
pass a key derived from your record:
$ps->jobs->create($params, ['idempotencyKey' => 'order-12345-label']);all() returns one page (data, has_more, next_cursor). Each list
resource also has iterate(), which follows cursors for you:
foreach ($ps->jobs->iterate(['status' => 'failed', 'limit' => 100]) as $job) {
echo $job['id'], ' ', $job['error']['message'] ?? '', "\n";
}Upload once, print many times:
$doc = $ps->documents->upload([
'content' => file_get_contents('packing-slip.pdf'),
'content_type' => 'application/pdf',
'expire_after_seconds' => 3600,
]);
$ps->jobs->create([
'printer_id' => 'prn_...',
'content' => ['format' => 'pdf', 'document_id' => $doc['id']],
]);$ps->documents->createFromUrl(['source_url' => ...]) has the API fetch the
file server-side instead.
Subscribe with the client, verify deliveries with PrintSocket\Webhook.
Verification needs the raw request body; a decoded and re-encoded body will
not match the signature.
use PrintSocket\Webhook;
use PrintSocket\Exception\WebhookVerificationException;
$endpoint = $ps->webhooks->create([
'url' => 'https://example.com/printsocket/webhook',
'events' => ['job.*', 'printer.state_changed'],
]);
// $endpoint['secret'] is shown only this once; store it.
// In your receiver:
try {
$event = Webhook::constructEvent(
file_get_contents('php://input'),
$_SERVER['HTTP_PRINTSOCKET_SIGNATURE'] ?? '',
getenv('PRINTSOCKET_WEBHOOK_SECRET'),
);
} catch (WebhookVerificationException $e) {
http_response_code(400);
exit;
}
// Delivery is at-least-once: dedupe on $event['id'] before acting.Generate a short-lived, single-use token server-side and hand it to the agent installer, so your API keys never touch a customer machine:
$token = $ps->enrollmentTokens->create(['name' => 'Front desk PC']);
// $token['token'] is the secret; it expires in about an hour.$scale = $ps->scales->retrieve('scl_...');
if ($scale['reading']['stable'] ?? false) {
echo $scale['reading']['weight_grams'], ' g at ', $scale['reading']['captured_at'];
}php tests/run.phpThe test suite is dependency-free on purpose; it runs anywhere PHP does, with no install step.
MIT