zpl.tools
Compatibility LayersLabelary Compatibility

Error Reference

API error codes and responses

Render errors are returned as plain text with a Content-Type: text/plain header, matching Labelary behavior. All plain-text error messages are prefixed with ERROR: .

Authentication and authorization errors (401, 403, 429) are returned as JSON — see Authentication & authorization errors below.

HTTP Status Codes

400 Bad Request

Invalid request parameters or malformed ZPL code.

Examples:

  • Invalid DPMM value (with or without the dpmm suffix — both are validated the same way): ERROR: Unknown print density 10; valid values: 6, 8, 12, 24
  • Label too large: ERROR: Label width is larger than 15.0 inches
  • Label too small: ERROR: Label width is less than 0.001 inches
  • Invalid rotation: ERROR: Label rotation must be 0, 90, 180 or 270 degrees
  • Invalid page size: ERROR: Invalid page size: A3
  • Invalid page orientation: ERROR: Invalid page orientation: Diagonal
  • Invalid page layout: ERROR: Invalid page layout: 0x3
  • Invalid page alignment: ERROR: Invalid alignment: Middle
  • Invalid page vertical alignment: ERROR: Invalid vertical alignment: Middle
  • Invalid label border: ERROR: Invalid label border: Dotted
  • Page too small to fit the label: ERROR: Not enough room to fit 1 label vertically; please adjust page layout, page size, page orientation, label size, or label rotation.

The X-Page-* / X-Label-Border headers above are validated but not yet composed into the actual PDF layout — see Behavioral notes. An unrecognized X-Quality value is not an error — it's silently treated as the Grayscale default.

404 Not Found

Missing or invalid data.

Examples:

  • No ZPL content, all-labels endpoint (no index requested): ERROR: no labels generated
  • No ZPL content, specific index requested: ERROR: Requested 1st label but ZPL generated no labels
  • Index out of bounds: ERROR: Requested 2nd label but ZPL only generated 1 label
  • PNG requested on the all-labels endpoint (PNG requires an index): ERROR: HTTP 404 Not Found

406 Not Acceptable

Unsupported Accept header value.

Example:

ERROR: HTTP 406 Not Acceptable

Supported formats: image/png, application/pdf

Authentication & authorization errors

Auth-layer errors use a JSON envelope with a stable machine-readable error code and a human-readable message:

{ "error": "invalid_key", "message": "Invalid API key" }

401 Unauthorized

error codeMeaning
invalid_keyThe X-API-Key header is missing, or the key is unknown/revoked
key_expiredThe key exists but is past its expiration date

403 Forbidden

error codeMeaning
scope_deniedThe key's scope does not allow the requested output format

A scope_denied response includes the format the request asked for and the key's configured scope:

{
    "error": "scope_denied",
    "message": "API key scope 'png' does not allow pdf output",
    "required": "pdf",
    "actual": "png"
}

The requested output format is derived from the Accept header (application/pdf selects PDF; anything else selects PNG). Keys are scoped on the API Keys page: PDF only, PNG only, or all formats.

429 Too Many Requests

Returned when a rate limit is exceeded. limit_scope is key for your own soft limits and organization for the platform abuse limit.

{
    "error": "rate_limited",
    "message": "Rate limit exceeded: 10 requests/sec per key",
    "limit_type": "requests_per_sec",
    "limit_scope": "key",
    "limit": 10,
    "retry_after_seconds": 1
}

Every 429 carries reset headers:

headermeaning
Retry-AfterSeconds to wait before retrying
X-RateLimit-LimitThe limit that was exceeded
X-RateLimit-RemainingAlways 0 on a 429
X-RateLimit-ResetUnix timestamp (seconds) when the limit resets

limit_type is requests_per_sec (resets within seconds) or pages_per_day (resets at midnight UTC).

Troubleshooting

Check your ZPL syntax

Ensure all ZPL commands are properly formatted:

  • Labels must be wrapped in ^XA (start) and ^XZ (end)
  • Commands must be properly closed
  • Check the ZPL Documentation for command reference

Verify endpoint path

Ensure you're using the correct endpoint structure:

  • Single label: POST /v1/printers/{dpmm}/labels/{width}x{height}/{index}
  • All labels: POST /v1/printers/{dpmm}/labels/{width}x{height}

Validate path parameters

  • dpmm: must be 6, 8, 12, or 24 — the dpmm suffix (8dpmm) is optional
  • width/height: must be numeric values between 0.001 and 15 inches
  • index: must be 0 or greater, and less than the total number of labels in the ZPL

Check Accept header

Only these formats are supported — anything else, including formats Labelary itself supports (application/json, application/epl, etc.), returns 406:

  • image/png (default)
  • application/pdf