Skip to content

POST /print/{target}

Send a print job to a specific printer. Returns a job ID for tracking.

Endpoint:

POST /api/v1/print/{target}
Parameter Type Description
target string The printer’s path value from GET /printers, or a tag alias (e.g. tag_LABELS).

Three options for sending print data:

Send the raw print data (ZPL, PDF, etc.) directly as the request body. Always synchronous — blocks until the job completes.

POST /api/v1/print/tcp_192-168-86-250_9100
Content-Type: application/octet-stream
X-API-Key: ULA9WHXMFCHF
^XA^FO50,50^A0N,50,50^FDHello World^FS^XZ

Send a JSON body with a content field containing a URL to fetch the document from.

POST /api/v1/print/tcp_192-168-86-250_9100
Content-Type: application/json
X-API-Key: ULA9WHXMFCHF
{
"content": "https://example.com/label.zpl",
"contentType": "raw_url"
}

Send a JSON body with base64-encoded content and print options.

POST /api/v1/print/tag_LABELS
Content-Type: application/json
X-API-Key: ULA9WHXMFCHF
{
"content": "XlhBXkZPNTAsNTBeQTBOLDUwLDUwXkZESGVsbG8gV29ybGReRlNeWFo=",
"contentType": "raw_base64",
"title": "Shipping Label #1234",
"source": "my-erp",
"options": {
"copies": 2
}
}
Field Type Required Description
content string Yes The document to print — a URL, base64-encoded data, or a local file path.
contentType string Recommended One of: pdf_url, pdf_base64, raw_url, raw_base64, zpl, zpl_base64. When omitted, inferred from the content and printer type. New integrations should always set this. See content type support by printer family.
title string No Job name. Passed to CUPS. Defaults to "Untitled".
source string No Identifier for the submitting application or user (e.g. "my-erp", "jsmith").
wait boolean No true (default): block until job completes. false: return immediately, poll GET /jobs/{jobId} for status.
options object No Print options (see below). Unsupported options for a given printer are silently ignored.
idempotencyKey string No Unique key to prevent duplicate submissions. If a job with this key already exists (within 1-hour TTL), the existing job is returned with HTTP 200.

Raw content types (raw_url, raw_base64, zpl, zpl_base64, and raw binary bodies) are delivered to the printer byte-for-byte, unmodified — even if the bytes happen to be a PDF. PDF content types (pdf_url, pdf_base64) are rendered on the device to the printer’s native format.

Printer family Raw types PDF types
Zebra ZPL ("content": "zpl") ✅ ZPL passthrough ✅ Rendered to ZPL — see PDF printing
Office / driverless IPP ✅ Passthrough ✅ Rendered by the printer’s driver
Brother label and Dymo ✅ Passthrough ✅ Rendered — the PDF page size must match the loaded media
Epson ESC/POS and other raw devices ✅ Passthrough ❌ Rejected with 400 (see below)

A PDF content type sent to a printer that can’t render returns 400 with the accepted content types — nothing is sent to the printer:

{
"status": "error",
"statusCode": 400,
"result": {
"module": "/print/tcp_192-168-86-250_9100",
"message": "This printer accepts raw data only; supported contentTypes: zpl, zpl_base64, raw, raw_base64, raw_url (or a raw request body)",
"content": {
"jobId": "pj_b7c8d9e0",
"printer": "tcp_192-168-86-250_9100",
"target": "tcp_192-168-86-250_9100",
"state": "failed",
"error": "This printer accepts raw data only; supported contentTypes: zpl, zpl_base64, raw, raw_base64, raw_url (or a raw request body)",
"createdAt": "2026-03-28T14:30:00.000Z",
"completedAt": "2026-03-28T14:30:00.100Z"
}
}
}
Option Type Description
copies number Number of copies. Default 1.
duplex string "one-sided", "long-edge", or "short-edge".
colorMode string "color", "grayscale", or "auto".
paperSize string CUPS media name (e.g. "letter", "a4"). Must be one of the printer’s capabilities.mediaSupported values from GET /printers. Brother P-touch printers ignore this option: USB P-touch uses the loaded tape and PDF dimensions to select the page size.
pageRange string Page range (e.g. "1-5", "1,3,7-9"). PDF only.
bin string Paper tray / input slot name.
fitToPage boolean Scale content to fit the page. PDF only.
orientation string "portrait", "landscape", "reverse-landscape", or "reverse-portrait".
quality string "draft", "normal", or "high".

Returned when wait is true (default) or for raw binary requests.

{
"status": "success",
"statusCode": 200,
"result": {
"module": "/print/tag_LABELS",
"message": "Printed successfully.",
"content": {
"jobId": "pj_a8f3e1b2",
"printer": "tcp_192-168-86-250_9100",
"target": "tag_LABELS",
"title": "Shipping Label #1234",
"source": "my-erp",
"state": "completed",
"error": null,
"createdAt": "2026-03-28T14:30:00.000Z",
"completedAt": "2026-03-28T14:30:08.500Z"
}
}
}

Returned when wait is false. Poll GET /jobs/{jobId} for the final state.

{
"status": "success",
"statusCode": 201,
"result": {
"module": "/print/tag_LABELS",
"message": "Print job accepted.",
"content": {
"jobId": "pj_a8f3e1b2",
"printer": "tcp_192-168-86-250_9100",
"target": "tag_LABELS",
"title": "Shipping Label #1234",
"source": "my-erp",
"state": "queued",
"error": null,
"createdAt": "2026-03-28T14:30:00.000Z",
"completedAt": null
}
}
}

Error: 400 — Label Media Mismatch (Brother label printers)

Section titled “Error: 400 — Label Media Mismatch (Brother label printers)”

The PDF must match the detected tape, within 2pt in either orientation, with a label length of 36–2834pt. Non-PDF data, an unmatched width, or a length outside that range returns 400 before queueing. result.content is { message, loadedTape }; use loadedTape.widthPt to resize the page. See Sizing your labels.

{
"status": "error",
"statusCode": 400,
"result": {
"module": "/print/usb_sn_000F5G234070",
"message": "PDF is sized for 24 mm tape (68 pt wide); the printer has 12 mm tape loaded (34 pt)",
"content": {
"message": "PDF is sized for 24 mm tape (68 pt wide); the printer has 12 mm tape loaded (34 pt)",
"loadedTape": {
"media": "tz-12",
"label": "12 mm tape",
"widthMm": 12,
"widthPt": 34,
"mediaType": 1,
"readAt": "2026-03-28T14:30:00.000Z"
}
}
}
}

If the width matches but the length is 3000pt, the message is PDF length 3000 pt is outside 36–2834 pt. Either page dimension can match the loaded width: a 68 × 51pt page on 18mm tape prints rotated as 51 × 68pt.

QL printers match the PDF against the supported media table. A non-PDF payload or an unmatchable page size returns 400 with validMedia. Each entry includes a human-readable label. The example below shows one entry; the response contains the full family table. Network P-touch printers also use the supported-media table rather than tape detection.

{
"status": "error",
"statusCode": 400,
"result": {
"module": "/print/usb_sn_000F5G234070",
"message": "PDF page size 612x792pt does not match any media this printer supports.",
"content": {
"message": "The PDF page size declares the label media. Size the page to a supported width (continuous tape accepts any length >= 36pt).",
"validMedia": [
{
"name": "62mm",
"label": "62 mm continuous roll",
"width": 176,
"height": 284,
"continuous": true,
"mmLabel": "62mm"
}
]
}
}
}

USB P-touch printers return 409 for no-tape, unsupported-tape, or printer-error. No job is queued. A missing cassette returns:

{
"status": "error",
"statusCode": 409,
"result": {
"module": "/print/usb_sn_000F5G234070",
"message": "No tape cassette is loaded in Brother PT-P900W",
"content": {
"message": "No tape cassette is loaded in Brother PT-P900W",
"loadedTape": {
"reason": "no-tape",
"readAt": "2026-03-28T14:30:00.000Z"
}
}
}
}

A decoded printer error names the condition:

{
"status": "error",
"statusCode": 409,
"result": {
"module": "/print/usb_sn_000F5G234070",
"message": "Brother PT-P900W reports: cover open",
"content": {
"message": "Brother PT-P900W reports: cover open",
"loadedTape": {
"reason": "printer-error",
"readAt": "2026-03-28T14:30:00.000Z"
}
}
}
}

Unsupported media is named in the message, for example Brother PT-P900W: Unsupported tape: heat-shrink tube (2:1), 24 mm.

Returned when the Zebra pre-flight status check detects an issue or the USB P-touch tape cannot be read.

The response contains the failed print job. See Pre-flight Status Check in the Zebra guide for details.

{
"status": "error",
"statusCode": 503,
"result": {
"module": "/print/tcp_192-168-86-250_9100",
"message": "Printer is not ready",
"content": {
"jobId": "pj_c4d5e6f7",
"printer": "tcp_192-168-86-250_9100",
"target": "tcp_192-168-86-250_9100",
"state": "failed",
"error": "Printer not ready: Paper out, Head is open",
"createdAt": "2026-03-28T14:30:00.000Z",
"completedAt": "2026-03-28T14:30:00.500Z"
}
}
}

The tape read has a 3-second bound. An unreadable status returns 503 before queueing. This includes USB load, lookup, open, claim, write, read, and timeout failures. A cleanup failure also makes an otherwise successful reading unreadable:

{
"status": "error",
"statusCode": 503,
"result": {
"module": "/print/usb_sn_000F5G234070",
"message": "Couldn't read the loaded tape from Brother PT-P900W: timeout: timed out",
"content": {
"message": "Couldn't read the loaded tape from Brother PT-P900W: timeout: timed out",
"loadedTape": {
"reason": "unreadable",
"readAt": "2026-03-28T14:30:00.000Z"
}
}
}
}

A busy queue reuses its last reading, including the 20 seconds after its last state change. If no reading exists, loadedTape is null and the message is Couldn't read the loaded tape from Brother PT-P900W: the printer is busy and has not been read yet.

ProxyBox Zero Docs v1.0.29