Skip to content

API reference

A REST API for applications that need to print labels and documents. Bearer tokens, JSON in and out, and idempotency keys so a retry never costs you a second label.

Quick start

Three requests: find a printer, print to it, check it worked.

1. What can I print to?
curl -H "Authorization: Bearer $TOKEN" \
     https://api.getprintr.co.uk/v1/printers
2. Print something
curl -X POST https://api.getprintr.co.uk/v1/printjobs \
     -H "Authorization: Bearer $TOKEN" \
     -H "Content-Type: application/json" \
     -H "Idempotency-Key: order-1041-label" \
     -d '{
       "printer_id": 7,
       "template": "shipping-label",
       "data": { "order": "SO-1041", "customer": "Acme Ltd" }
     }'
3. Did it work?
curl -H "Authorization: Bearer $TOKEN" \
     https://api.getprintr.co.uk/v1/printjobs/8814

Authentication

Every request carries a bearer token. Create one in the dashboard under Settings → API tokens; it is shown once at creation and cannot be recovered afterwards, so store it where your application reads its secrets.

Every request
Authorization: Bearer 1|abc123…

A token is scoped to the account that created it. A resource belonging to another account answers 404, never 403, because telling you it exists would leak that someone else has it.

Endpoints

Base URL https://api.getprintr.co.uk/v1. The same reference is available as plain Markdown, for AI assistants and coding tools.

Printers

GET /printers Everything you can print to, with live status.
GET /printers/{id} One printer.
GET /printers/languages Which languages this installation can print.

Print jobs

POST /printjobs Print something.
GET /printjobs Job history, filtered and paginated.
GET /printjobs/{id} One job, with its full event trail.
POST /printjobs/{id}/cancel Cancel a job that has not printed yet.

Computers

GET /computers The computers running the agent, and whether they are checking in.
GET /computers/{id} One computer, with its printers embedded.

Templates

GET /templates Available label templates.
GET /templates/{slug} One template, with every published version.
POST /templates/{slug}/render Render without printing, to preview in your own UI.

Printing a label or a document

Address a printer by printer_id, or by device_id plus printer_key. The second survives a computer being re-enrolled, which renumbers its printers. Then send exactly one of: a template with data, raw markup of your own, or a pdf. Sending more than one is refused rather than guessed at.

Field Type Notes
printer_id integer Required unless you address by device and key.
device_id + printer_key integer + string Address a printer by its stable key on a computer. Survives re-enrollment.
template string Template slug. One of template, raw or pdf.
data object Values for the template's variables.
raw string Label commands (ZPL or TSPL2), up to 2 MB. One of template, raw or pdf.
language string Language of a raw payload: zpl or tspl2. Defaults to the printer's own.
pdf string A base64-encoded PDF, up to about 6 MB. One of template, raw or pdf.
copies integer 1 to 100. Defaults to 1.
ttl_seconds integer Expire if unprinted after this long. Defaults to 900; 0 means never.
title string Your own reference, shown in the dashboard.
202 Accepted
{
  "data": {
    "id": 8814,
    "state": "queued",
    "printer_id": 7
  }
}

A PDF needs a printer set up on the computer. The document is rendered by that printer's own driver, on Windows or macOS, which is what lets one API print to a label printer, an office laser and a Dymo alike. A printer addressed directly over the network has no driver behind it, so a PDF sent to it is refused with 409 rather than emerging as pages of nonsense.

Job states

A job is in exactly one state. The four terminal ones never change again, so you can stop polling the moment you see one.

State Meaning Terminal
queued Accepted and waiting for the computer to collect it. –
dispatched The agent has it. –
printing Being written to the printer. –
printed The bytes reached the printer. Yes
failed Something stopped it. Carries an error code. Yes
cancelled Cancelled before it printed. Yes
expired Not printed before its TTL elapsed. Yes

Errors

A failed job carries one of these, each with a retryable flag so you do not have to guess which failures are worth sending again.

Code Meaning Retryable
printer_unreachable Nothing answered at the printer. Yes
printer_error The printer reported a fault. Yes
write_timeout The connection stalled mid-write. Yes
internal Our fault. Yes
unsupported_language The agent cannot print that language. No
payload_invalid The label markup was malformed. No
job_expired Its TTL elapsed first. No
cancelled Someone cancelled it. No
Retry with a new idempotency key. Reusing the original returns the original failed job rather than submitting anything, which looks a lot like a retry that silently did nothing. A key identifies one attempt, not one label.

Templates

Keep label layout on the server and send data instead of markup. Versions are immutable, so a job records exactly what it rendered and a bad edit is one rollback rather than an incident.

Syntax Meaning
{{ order }} Insert a value, sanitised.
{{ order.customer.name }} Dotted paths read into nested data.
{{ block|raw }} Insert verbatim. Only for markup you generate yourself.
Values are stripped of characters a printer would read as commands: ^ and ~ for ZPL, " and \ for TSPL2. That is what stops a customer's name from rewriting the label.

Idempotency

Send Idempotency-Key on a POST /printjobs and a repeated request returns the original job with 200 instead of printing again, including when two retries race each other. Keys are scoped to your account.

Reusing a key with a different body still returns the first job. The key wins, not the payload.

Conventions

  • Successful responses wrap their payload in data. Errors do not.
  • Printr's own errors carry error and message. Validation failures instead carry message and an errors object keyed by field, so handle both.
  • Timestamps are ISO 8601 with an offset.
  • Only GET /printjobs paginates, and it alone returns meta. The other lists return a complete array.
  • 600 requests a minute per token. A 429 carries Retry-After.
  • Job outcomes are polled rather than pushed. Poll until you see a terminal state.

Try it against your own printers

A free account comes with the same reference filled in with your printer ids, so the examples run as written.

Start free