Quickstart
1. Pair a station
A station is the CatzPrint app running on the computer, tablet or Android terminal that your printer is connected to. Install it, then in the console open Locations, pick a location and choose Pair a device. Enter the one-time code (or scan the QR code) in the app. The station reports its printers straight away.
Give each printer a role such as receipt, kitchen or bar. Your code sends to a role, and every location maps that role to its own hardware.
2. Create a test key
In the console, open API keys and create a Test key with the jobs:write scope (add jobs:read to check status too). Test keys start with cz_test_ and live keys with cz_live_. Test jobs print on your real printers but are never billed — up to 200 a day.
Keys belong to one organization. The SDKs find it from the key on first use, so the key is all you configure. The key is shown once, so store it in your secrets manager.
Trying things from the console instead? People with the Developer role can send test jobs from the Playground by switching it to Test — they print, but are marked “Test — not billed”. See Test jobs.
3. Send a job
Install the SDK for your language and put your key in CATZPRINT_API_KEY:
npm install @catzprint/sdk
export CATZPRINT_API_KEY="cz_test_..."Then print a receipt with printReceipt (print_receipt in Python and Rust, PrintReceipt in Go). It takes a list of receipt commands; CatzPrint turns them into ESC/POS for receipt printers, or a PDF for office printers.
import { CatzPrint } from "@catzprint/sdk";
const cz = new CatzPrint(); // reads CATZPRINT_API_KEY
const job = await cz.printReceipt(
[
{ type: "text", text: "Hello CatzPrint", align: "center", size: 2, bold: true },
{ type: "line" },
{ type: "columns", columns: [{ text: "Flat white" }, { text: "4.50", align: "right" }] },
{ type: "qr", data: "https://catzprint.com", align: "center" },
{ type: "feed", lines: 2 },
{ type: "cut" },
],
{ role: "receipt", title: "Hello", reference: "order-1042", idempotencyKey: "order-1042" },
);
console.log(job.id, job.status); // "queued"You get the job back. It's routed to a printer with the role you asked for and queued for its station:
{
"id": "6f1c2a7e-3b0d-4f7e-9a51-2d4c8e0b7a13",
"live": false,
"source": "api",
"kind": "escpos",
"status": "queued",
"status_detail": "",
"title": "Hello",
"reference": "order-1042",
"copies": 1,
"printer_id": "…", "printer_name": "Front counter",
"station_id": "…", "station_name": "Till 1",
"location_id": "…", "location_name": "Main Street",
"billed_as": "test",
"created_at": "2026-10-12T09:14:03Z",
"printed_at": null
}4. Know when it printed
Wait for the job with jobs.waitFor (needs jobs:read), or add a webhook endpoint for job.printed and job.failed and check each delivery with webhooks.verify. It rejects anything not signed with your endpoint's secret.
import { webhooks } from "@catzprint/sdk";
// Wait for it: polls until printed, failed or cancelled (needs jobs:read)
const done = await cz.jobs.waitFor(job.id);
console.log(done.status); // "printed"
// Or let CatzPrint tell you: in your webhook handler, verify the raw body
const event = webhooks.verify(rawBody, signatureHeader, process.env.CATZPRINT_WEBHOOK_SECRET);
if (event.type === "job.printed") markOrderPrinted(event.data.job.reference);Next steps
- SDKs — everything the libraries do: PDFs, images, templates, listing jobs, errors.
- Sending jobs — every field, the job kinds (text, PDF, images, documents), routing and job statuses.
- Receipt commands and templates — layouts, barcodes, QR codes and reusable templates with placeholders.
- Sealing content — encrypt documents to CatzPrint before they leave your server.
- Errors and rate limits — what can go wrong and how to retry.
- Retention — job documents are kept 30 days and uploads 7 days by default; job records stay.
- API reference — the HTTP endpoints, if you can't use an SDK.