dskripchenko / printable-sdk
Official PHP SDK for the Printable document-generation service: HMAC-signed integration API client (templates, print-forms, batches, drafts, webhooks).
Requires
- php: ^8.2
- ext-curl: *
- ext-json: *
Requires (Dev)
- pestphp/pest: ^3.0|^4.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-22 20:22:23 UTC
README
Official PHP client for the Printable document-generation service integration API: templates, print-forms, batch rendering, document drafts and webhook verification β with the HMAC request signing (simple and strict canonical modes) built in and byte-compatible with the server implementation.
π English Β· Deutsch Β· Π ΡΡΡΠΊΠΈΠΉ Β· δΈζ
Zero runtime dependencies (ext-curl, ext-json). PHP 8.2+.
Install
composer require dskripchenko/printable-sdk
Quick start
use Dskripchenko\PrintableSdk\PrintableClient; $client = new PrintableClient( baseUrl: 'https://printable.example.com', token: 'erp-main-7f3a', secretKey: getenv('PRINTABLE_SECRET'), salt: getenv('PRINTABLE_SALT'), strict: false, // true if the credential has "verify full payload hash" enabled ); // Render a document $doc = $client->printFormCreate([ 'template' => 'invoice', 'variables' => ['company' => ['name' => 'ACME Ltd']], 'format' => 'link', ]); echo $doc['link']; // Batch with archive + email delivery $batch = $client->printFormBatch([ 'template' => 'certificate', 'items' => [ ['variables' => ['name' => 'Alice']], ['variables' => ['name' => 'Bob']], ], 'archive' => true, 'deliver' => ['email' => 'hr@example.com'], ]); $status = $client->printFormBatchGet($batch['uuid']);
API surface
| Method | Endpoint |
|---|---|
templateList() |
GET template/list |
templateContract($slug, $version?) |
GET template/contract |
templateExport($slug, $version?) |
GET template/export |
templateImport($packageB64, $groupId, $options?) |
POST template/import |
templateImportDocx($docxB64, $groupId, $name?) |
POST template/import-docx |
templateImportXlsx($xlsxB64, $groupIdOrPath, $name?) |
POST template/import-xlsx |
printFormCreate($params) |
POST print-form/create |
printFormGet($uuid, $format?) |
GET print-form/get |
printFormRules($slug, $version?) |
GET print-form/rules |
printFormSignatureRequest($uuid, $certificate, $slot?) |
POST print-form/signature-request |
printFormSignatureComplete($uuid, $cms, $slot?, $format?) |
POST print-form/signature-complete |
printFormSignatureInvite($uuid, $email?, $slot?, $name?) |
POST print-form/signature-invite |
printFormBatch($params) |
POST print-form/batch |
printFormBatchGet($uuid) |
GET print-form/batch-get |
documentDraftCreate($params) |
POST document-draft/create |
documentDraftGet($uuid) |
GET document-draft/get |
call($method, $endpoint, $params) |
anything else |
Every method returns the decoded payload array of the response envelope.
Errors (non-2xx or success: false) raise PrintableException with
status, errorKey and the raw error payload.
Signing and protection
print-form/create and print-form/batch accept optional parameters, passed as-is in the params:
presetβ a print-preset code used instead oftemplate(document-draft/createaccepts it too);signingβ a signature profile per slot, a visible or invisible signature, the reason, andrecipientsβ the counterparties who sign the document themselves;protectionβ PDF protection:{"generate": true}lets the service generate the password, or pass your own one underpassword; the optionalpermissionsisread_print,read_onlyorforms_sign.
The response then carries a protection block (protected, permissions, password, owner_password). Passwords are returned only once β in the response that issues the document; afterwards they come back masked (β’β’β’β’β’β’β’β’), so store them right away. Each signature.slots[] item may carry method (cms, plugin, pdf or sig) and signature_link β the recipient's detached .sig.
$doc = $client->printFormCreate([ 'preset' => 'contract-signed', 'variables' => ['contract' => ['number' => 15]], 'signing' => [ 'slots' => ['company' => ['profile' => 'ceo']], 'invisible' => false, 'reason' => 'Contract 15', 'recipients' => ['buyer' => ['email' => 'buyer@example.com', 'name' => 'Buyer LLC']], ], 'protection' => ['generate' => true, 'permissions' => 'read_print'], ]); // The password comes only in this response β store it now $protection = $doc['protection']; // Hand the link over yourself, or let the service email it $invite = $client->printFormSignatureInvite($doc['uuid'], 'buyer@example.com', 'buyer', 'Buyer LLC'); echo $invite['sign_url'];
printFormSignatureInvite() invites the recipient to sign: it returns sign_url β a personal link to the signing page (CryptoPro browser plug-in, a detached .sig upload, or a PDF signed in its field) β and expires_at. With an email address the service also sends the link (sent).
Webhooks
$valid = $client->verifyWebhook( rawBody: $request->getContent(), signatureHeader: $request->header('X-Printable-Signature'), timestampHeader: $request->header('X-Printable-Timestamp'), );
Testing your integration
Pass a custom transport callable to stub HTTP without touching cURL:
$client = new PrintableClient(..., transport: function ($method, $url, $body) { return [200, '{"success":true,"payload":{"ok":true}}']; });
License
MIT