Skip to main content

quirepdf (Python)

Send JSON, get back a polished PDF. Python 3.9+, standard library only, synchronous.

Install

pip install quirepdf

Quickstart

Any JSON object renders. Quire picks the best-matching template, or a clean generic layout:

from quirepdf import Quire

client = Quire()  # reads QUIRE_API_KEY (and QUIRE_API_URL)

order = {
    "order_id": "ORD-88213",
    "customer": {"name": "Lena Fischer", "email": "lena@example.de"},
    "lines": [{"sku": "TS-BLK-M", "name": "Organic tee", "qty": 2, "price": 29.0}],
    "currency": "€",
}
result = client.render(order)
result.save("order.pdf")
print(result.template, result.template_source, result.pages)  # document fallback 1
if result.hint:
    print("almost matched:", result.hint)  # e.g. "invoice (seller is required)"

Name a template and use the generated types so your editor checks the fields:

from quirepdf.types import InvoiceData

invoice: InvoiceData = {
    "number": "INV-2026-0142",
    "issued": "1 Oct 2026",
    "due": "15 Oct 2026",
    "seller": {"name": "Northwind Studio", "address": ["221 Market Street", "San Francisco, CA 94105"]},
    "customer": {"name": "Ravi Kumar", "address": ["14 Residency Road", "Bengaluru 560025"]},
    "items": [{"description": "Pro plan", "qty": 1, "unit_price": 49}],
    "status": "due",  # Literal["draft", "due", "paid", "overdue", "void"]
}

pdf = client.render(invoice, template="invoice")
png = client.render(invoice, template="invoice", format="png", page=1)  # preview one page
print(pdf.content[:5], len(png.content), pdf.render_ms, pdf.quota)    # Quota(limit=100, remaining=97)

RenderResult fields: content (the file as bytes), content_type, pages, template, template_source (explicit | detected | fallback), hint, render_ms, quota, and save(path).

Other calls:

check = client.validate(invoice, template="invoice")   # free, nothing rendered
check.valid, check.errors                               # False, [{"path": "...", "message": "..."}]

client.templates.list()            # [{"name": "invoice", "title": "Invoice", ...}, ...]
client.templates.get("invoice")    # {"template": {...}, "schema": {...}, "sample": {...}}
client.usage()                     # {"plan": "free", "used": 3, "limit": 100, "remaining": 97, ...}

new = client.keys.create(name="ci")   # new["api_key"] is shown only once
client.keys.list()                    # [{"id", "prefix", "name", "current": bool, ...}]
client.keys.revoke(new["key"]["id"])

Errors

Every failure raises QuireError with status, type, message and fields:

from quirepdf import QuireError

try:
    client.render({"number": "INV-1"}, template="invoice")
except QuireError as err:
    print(err.status, err.type)  # 422 invalid_data
    print(err)                   # data has 5 problems
                                 #   - issued is required
                                 #   - due is required ...
    for f in err.fields:
        print(f["path"], f["message"])

Common types: invalid_data, unknown_template, unauthorized, quota_exceeded, bad_request, payload_too_large, timeout. Client-side failures have status == 0: type == "network" (can't connect) or type == "timeout" (no reply within timeout seconds). The SDK never retries.

Configuration

Argument Environment Default
api_key QUIRE_API_KEY none (no Authorization header is sent)
base_url QUIRE_API_URL https://api.quirepdf.dev
timeout 30.0 seconds
client = Quire(api_key="qk_...", base_url="http://127.0.0.1:8787", timeout=10)

A local engine in open mode (make serve) needs no key.

Development

python3 scripts/gen_types.py          # regenerate src/quirepdf/types.py after a schema change
python3 scripts/gen_types.py --check  # fail if it is stale
PYTHONPATH=src python3 -m unittest discover -s tests -v   # runs against engine/target/release/quire-engine (make build)

Metadata

Release files for quirepdf 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for quirepdf 0.1.0
File Size Uploaded
quirepdf-0.1.0.tar.gz 12.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for quirepdf 0.1.0
File Interpreter ABI Platform
quirepdf-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 26.3 kB

Release files / quirepdf-0.1.0.tar.gz

Download URL quirepdf-0.1.0.tar.gz
Size 12.3 kB
Tags Source
SHA-256 checksum
How to use checksums
fab20a68b5ccf23769fa14597d80c88f88f7c8510b7130970b8be380564acbc5
BLAKE2b-256 checksum
How to use checksums
93123c9cd99de7c0b9289c223a4f9bc75614b6c858f09d1c16e4a700cf3f77d1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release files / quirepdf-0.1.0-py3-none-any.whl

Download URL quirepdf-0.1.0-py3-none-any.whl
Size 14.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7cd3a8b844c8104d9971feeafdee159d5581c89015594b0bda512777725c67b1
BLAKE2b-256 checksum
How to use checksums
ed9912ccab46a94e79b1eff974310d7bbdd9012125fd6a25f36d5c2d85a3e005
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release history Release notifications | RSS feed

0.2.0

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page