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.10; tested through 3.14

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-2.0.0.tar.gz (18.8 kB view details)

Uploaded Source

Built Distribution

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

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

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for zpljet-2.0.0.tar.gz
Algorithm Hash digest
SHA256 9b4621441a7c4f7a8138dd8734601ae10f996ba262bf0a4c2235879565feed9c
MD5 d1458edf5e52d73ba2b812f8323d1bf8
BLAKE2b-256 ed3cbad2b557882265c696b79cf9c62564a127c9ecc7e138000305a419b4302d

See more details on using hashes here.

Provenance

The following attestation bundles were made for zpljet-2.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-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: zpljet-2.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-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0f52155cae1235feb42ef2d4081cf9ac74ae00b5f107cbd015f73cc2a3328ad7
MD5 e909d222dc82d2293b922d2718133a45
BLAKE2b-256 d6514dc073c24c3cfc342d28ec863a955f5a722ee061fb8738027fe343e696c8

See more details on using hashes here.

Provenance

The following attestation bundles were made for zpljet-2.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