Docs
One endpoint, a handful of headers, PNG or PDF back.
Quickstart
cURL
curl -X POST --data-binary @label.zpl \
-H "Accept: image/png" \
-H "X-API-Key: $ARKALABEL_KEY" \
https://api.arkalabel.io/v1/printers/8dpmm/labels/4x6/0/ \
-o label.pngNode
const zpl = "^XA^FO50,50^A0N,40,40^FDHello^FS^XZ";
const response = await fetch(
"https://api.arkalabel.io/v1/printers/8dpmm/labels/4x6/0/",
{
method: "POST",
headers: { Accept: "image/png", "X-API-Key": process.env.ARKALABEL_KEY },
body: zpl,
},
);
if (!response.ok) throw new Error((await response.json()).error);
const png = Buffer.from(await response.arrayBuffer());Python
import os, requests
zpl = "^XA^FO50,50^A0N,40,40^FDHello^FS^XZ"
response = requests.post(
"https://api.arkalabel.io/v1/printers/8dpmm/labels/4x6/0/",
data=zpl.encode(),
headers={"Accept": "image/png", "X-API-Key": os.environ["ARKALABEL_KEY"]},
timeout=30,
)
response.raise_for_status()
open("label.png", "wb").write(response.content)Endpoint
POST /v1/printers/{density}dpmm/labels/{width}x{height}/{index}/The body is the raw ZPL. The label index is zero-based; omit it to render every label in the stream. Sides may be up to 15 inches, density 6/8/12/24 dpmm, and the whole raster is capped at 25 million dots.
Request headers
| Accept | image/png (default), application/pdf, image/tiff, image/jpeg, image/gif |
| X-API-Key | Your key. Authorization: Bearer <key> works too. |
| X-Rotation | 0, 90, 180, 270 or 360 |
| X-Quality | Grayscale (default) or Bitonal |
| X-Page-Size | A4, A5, A6, Letter, Legal — PDF only |
| X-Page-Layout | <cols>x<rows>, e.g. 2x2 — tiles labels onto a page |
Response headers
| X-Total-Count | How many labels the submitted ZPL contains |
| X-Warning-Count / X-Warnings | Commands skipped or approximated |
| X-Quota-Limit / -Used / -Remaining | Where your key stands this period |
| X-RateLimit-Remaining / Retry-After | Free-tier pacing |
ZPL support matrix
Supported
| Format | ^XA ^XZ ^FX ^PW ^LL ^LH ^LS ^PO ^FW ^CI |
| Fields | ^FO ^FT ^FS ^FD ^FV ^FH ^FR ^FB |
| Text | ^A (fonts A–H, 0, @), ^CF, orientations N/R/I/B |
| Barcodes | ^BY ^BC (Code 128) ^B3 (Code 39) ^BE (EAN-13) ^BU (UPC-A) ^BQ (QR) |
| Graphics | ^GB boxes and lines, ^GF bitmaps (hex, RLE, :Z64:, :B64:) |
| Stored formats | ^DF download, ^XF recall, ^FN field substitution |
Skipped with a warning
These do not fail the render. The rest of the label is drawn and the command is reported in X-Warnings.
| ^BX | Data Matrix |
| ^B7 | PDF417 |
| ^BD | MaxiCode |
| ^BA ^B1 ^B2 ^B4 ^BK ^BZ | Code 93, Code 11, I2of5, Code 49, Codabar, POSTNET |
| ^SN | Serialised fields |
| ^GD ^GE | Diagonal lines, ellipses |
| ^BC mode D | GS1-128 — renders, but without FNC1 separators |
Error codes
| 400 | Invalid input: media outside the allowed range, no labels in the ZPL, or a label index past the end. The message names the offending value. |
| 401 | Missing or invalid API key. |
| 403 | The API key has been disabled. |
| 429 | Quota exhausted, or the free-tier rate exceeded. Check Retry-After. |
| 503 | The rendering engine was unreachable or too slow. |
Errors are JSON: {"error": "…"}. The message names the specific problem rather than describing the class of problem.