Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

printsocket/printsocket

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.

Install

composer require printsocket/printsocket

Quickstart

An 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_...  queued

Responses are associative arrays with the exact snake_case fields the API reference documents, so the docs read straight across to the code.

Configuration

$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
]);

Errors

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.

Retries and idempotency

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']);

Pagination

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";
}

Documents

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.

Webhooks

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.

Enrolling devices

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.

Scales

$scale = $ps->scales->retrieve('scl_...');
if ($scale['reading']['stable'] ?? false) {
    echo $scale['reading']['weight_grams'], ' g at ', $scale['reading']['captured_at'];
}

Development

php tests/run.php

The test suite is dependency-free on purpose; it runs anywhere PHP does, with no install step.

License

MIT