Skip to main content

Official Python SDK for the ZPLJet API — fast ZPL to PDF/PNG conversion

Project description

zpljet

Official Python SDK for the ZPLJet API — fast ZPL → PDF/PNG conversion.

PyPI version CI license

  • Zero dependencies — a single small client on top of the stdlib
  • Fully typed (py.typed) — parameters, results, and every API error code
  • Reliable by default — automatic retries with exponential backoff (honoring Retry-After), per-request timeouts, typed exceptions
  • Sync and asyncZplJet for scripts and servers, AsyncZplJet for asyncio code
  • Python ≥ 3.9

Installation

Choose one:

pip install zpljet
uv add zpljet
poetry add zpljet

Quickstart

Create an API key in the dashboard (keys look like zpl_…), then:

import os
from pathlib import Path

from zpljet import ZplJet

zpljet = ZplJet(api_key=os.environ["ZPLJET_API_KEY"])

label = zpljet.convert(zpl="^XA^FO50,50^A0N,50,50^FDHello^FS^XZ")

Path("label.pdf").write_bytes(label.data)

Keep your API key server-side. Anyone with the key can spend your quota.

Usage

Convert to PDF or PNG

convert() accepts every parameter of POST /v1/convert:

label = zpljet.convert(
    zpl="^XA^FO50,50^A0N,50,50^FDHello^FS^XZ",
    format="png",     # "pdf" (default) | "png"
    dpmm=12,          # 6 | 8 (default, 203 dpi) | 12 (300 dpi) | 24 (600 dpi)
    width_mm=101.6,   # label width, default 4 in
    height_mm=152.4,  # label height, default 6 in
)

label.data          # bytes — the file
label.content_type  # "application/pdf" | "image/png"
label.id            # conversion id (shows up in your dashboard)

Hosted URLs (paid plans)

Pass output="url" to have ZPLJet host the file and return a public link instead of the bytes. Files are retained for your account's retention window (a dashboard setting, up to your plan's maximum).

hosted = zpljet.convert(zpl="^XA^FO50,50^A0N,50,50^FDHello^FS^XZ", output="url")

hosted.url             # public URL to the PDF (works until the file is deleted)
hosted.pages           # pages rendered (one per ^XA…^XZ block)
hosted.retention_days  # how long the file is kept
hosted.expires_at      # when the file is deleted and the URL stops working (ISO 8601, UTC)

The return type narrows automatically: output="url" gives a HostedLabel, everything else a LabelData.

Async

AsyncZplJet has the identical interface for asyncio code:

from zpljet import AsyncZplJet

zpljet = AsyncZplJet(api_key=os.environ["ZPLJET_API_KEY"])
label = await zpljet.convert(zpl="^XA^FO50,50^A0N,50,50^FDHello^FS^XZ")

The async client runs the dependency-free transport in a worker thread. Bound large batches with a semaphore; see examples/05_async_batch.py.

Error handling

Every API error code maps to a dedicated exception, so you branch with except — no string matching:

from zpljet import (
    ZplJet,
    APIConnectionError,
    BadRequestError,
    ConversionFailedError,
    QuotaExceededError,
    RateLimitError,
)

try:
    label = zpljet.convert(zpl=zpl)
except BadRequestError as err:
    print(f"Invalid request ({err.param}): {err.message}")
except QuotaExceededError as err:
    print(f"Quota used up ({err.used}/{err.quota}), resets {err.resets_at}")
except RateLimitError as err:
    print(f"Rate limited — retry after {err.retry_after}s")
except ConversionFailedError as err:
    print(f"Engine rejected the ZPL (conversion {err.conversion_id})")
except APIConnectionError as err:
    print(f"Network problem: {err}")
Exception Status error.code Extra fields
BadRequestError 400 invalid_request param
AuthenticationError 401 missing_api_key · invalid_api_key
QuotaExceededError 402 quota_exceeded plan, quota, used, resets_at
PermissionDeniedError 403 hosting_not_allowed · no_retention_enforced
PayloadTooLargeError 413 payload_too_large
RateLimitError 429 rate_limit_exceeded retry_after, retry_at
ConversionFailedError 502 conversion_failed conversion_id
ServiceUnavailableError 503 service_unavailable retry_after
APIError any anything else status, code, raw
APITimeoutError (an attempt timed out)
APIConnectionError (request never got a response)

All of these extend ZplJetError, and every HTTP error carries status, code, doc_url, and the raw error payload in raw. Full code reference: zpljet.com/docs/errors.

Retries

Rate limits, transient 5xx responses, timeouts, and network failures retry up to twice by default. Retries use exponential backoff and honor Retry-After. conversion_failed is never retried.

# Client-wide
zpljet = ZplJet(api_key=key, max_retries=5)

# Or per request
zpljet.convert(zpl=zpl, max_retries=0)  # fail fast

Timeouts

Each attempt has a 60-second timeout by default:

zpljet = ZplJet(api_key=key, timeout=10.0)

# Per request:
zpljet.convert(zpl=zpl, timeout=5.0)

A timed-out attempt raises APITimeoutError (after retries).

Configuration

zpljet = ZplJet(
    api_key="zpl_…",                     # required
    base_url="https://api.zpljet.com",   # default
    timeout=60.0,                        # per-attempt timeout, seconds
    max_retries=2,                       # automatic retries
    transport=my_transport,              # custom transport (proxies, tests)
)

The default transport uses stdlib urllib. For connection pooling, inject any callable matching (url, body, headers, timeout) -> TransportResponse.

Examples

Runnable scripts live in examples/:

ZPLJET_API_KEY=zpl_… python examples/01_convert_to_pdf.py

Contributing & development

python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

ruff check .
mypy
pytest

ZPLJET_API_KEY=zpl_… pytest tests/test_e2e.py

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

zpljet-1.0.0.tar.gz (18.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

zpljet-1.0.0-py3-none-any.whl (12.8 kB view details)

Uploaded Python 3

File details

Details for the file zpljet-1.0.0.tar.gz.

File metadata

  • Download URL: zpljet-1.0.0.tar.gz
  • Upload date:
  • Size: 18.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for zpljet-1.0.0.tar.gz
Algorithm Hash digest
SHA256 e294b0705d704c2f6df44b5a936a78e972972d4b996e29146103c0edb02b5021
MD5 c00741eb6d2f631d35cafc0d103c94c2
BLAKE2b-256 a43df708ba761c2201b019304a20950eaabff865265b0c25234ad8a077f364dd

See more details on using hashes here.

Provenance

The following attestation bundles were made for zpljet-1.0.0.tar.gz:

Publisher: release.yml on zpljet/zpljet-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file zpljet-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: zpljet-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 12.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for zpljet-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 34b7ab47057b520103d6e2ad02b1646dc989b38e7dc5aaa6b9f8170f2f525346
MD5 4e0e740e8d1bca54b00e37fa18c5ddc4
BLAKE2b-256 c02058a55710a7e4af23cf994e50865d89615932c0c5cb3bb24cad1be5bf5382

See more details on using hashes here.

Provenance

The following attestation bundles were made for zpljet-1.0.0-py3-none-any.whl:

Publisher: release.yml on zpljet/zpljet-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page