Skip to main content
The caretly/caretly package works with any PSR-18 HTTP client, such as Guzzle or Symfony HttpClient, and finds an installed one automatically.

Install

The package needs PHP 8.1 or newer, and a PSR-18 client. If your project doesn’t have one yet, add Guzzle or Symfony HttpClient:

Quickstart

Create a test key in the console and set it in your environment:
Render a label to PDF and save it:
Use single quotes or a nowdoc for ZPL in PHP. In double quotes, PHP reads $ as the start of a variable.

Choose a PSR-18 client

When you don’t pass httpClient, the client creates a Guzzle or Symfony client itself, whichever is installed, and applies timeout to it. If neither is installed, it falls back to php-http/discovery to find another PSR-18 client. To use a client you already configured, pass it with its PSR-17 factories:
PSR-18 has no standard way to set a timeout. When you inject your own client, set its timeout there: the timeout argument only applies to a client that Caretly creates.

Render a page as PNG

A PNG holds one page. Choose it with page, starting at 1:
$caretly->renderPdf($zpl) is the matching shorthand for a PDF. Both shorthands also take dpmm.

Render several files

renderFiles sends the files as multipart/form-data. Pass an array of file name to ZPL. Each file starts from a fresh printer state, and pages follow the order of the array:

Render options

Pass a Caretly\RenderOptions with named arguments: An invalid page, dpmm or idempotencyKey throws \InvalidArgumentException before any request.

Read the result

RenderResult has read-only properties:

Handle errors

Every runtime exception extends Caretly\Exception\CaretlyException. The classes live in the Caretly\Exception namespace: ApiException has status, retryAfter (seconds or null) and the response body as its message.

Retries and idempotency

The client retries 429 and 503 responses and connection errors up to maxRetries times, 2 by default. It waits Retry-After seconds when the server sends it. Otherwise it backs off 0.5 s, 1 s, 2 s, up to 8 s. Other statuses aren’t retried. Timeouts aren’t retried either: the client throws TimeoutException on the first one, because the server may still be rendering. Unless you pass idempotencyKey, the client generates a UUID per call and sends it on every attempt, so a retried render is never billed twice. With maxRetries: 0, it generates no key. Set your own key, such as an order number, to make retries across calls or processes safe too:

Configuration

Health check

health returns false for any other answer and never throws.