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.
- 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 async —
ZplJetfor scripts and servers,AsyncZplJetfor 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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e294b0705d704c2f6df44b5a936a78e972972d4b996e29146103c0edb02b5021
|
|
| MD5 |
c00741eb6d2f631d35cafc0d103c94c2
|
|
| BLAKE2b-256 |
a43df708ba761c2201b019304a20950eaabff865265b0c25234ad8a077f364dd
|
Provenance
The following attestation bundles were made for zpljet-1.0.0.tar.gz:
Publisher:
release.yml on zpljet/zpljet-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zpljet-1.0.0.tar.gz -
Subject digest:
e294b0705d704c2f6df44b5a936a78e972972d4b996e29146103c0edb02b5021 - Sigstore transparency entry: 2187867384
- Sigstore integration time:
-
Permalink:
zpljet/zpljet-python@3a57973def6b3d8cd06d043a589761b4ab75f7cf -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/zpljet
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3a57973def6b3d8cd06d043a589761b4ab75f7cf -
Trigger Event:
release
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
34b7ab47057b520103d6e2ad02b1646dc989b38e7dc5aaa6b9f8170f2f525346
|
|
| MD5 |
4e0e740e8d1bca54b00e37fa18c5ddc4
|
|
| BLAKE2b-256 |
c02058a55710a7e4af23cf994e50865d89615932c0c5cb3bb24cad1be5bf5382
|
Provenance
The following attestation bundles were made for zpljet-1.0.0-py3-none-any.whl:
Publisher:
release.yml on zpljet/zpljet-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zpljet-1.0.0-py3-none-any.whl -
Subject digest:
34b7ab47057b520103d6e2ad02b1646dc989b38e7dc5aaa6b9f8170f2f525346 - Sigstore transparency entry: 2187867405
- Sigstore integration time:
-
Permalink:
zpljet/zpljet-python@3a57973def6b3d8cd06d043a589761b4ab75f7cf -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/zpljet
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3a57973def6b3d8cd06d043a589761b4ab75f7cf -
Trigger Event:
release
-
Statement type: