Python client for the Pulp Engine document generation API
Project description
Pulp Engine Python SDK
Typed Python client for the PulpEngine document generation API.
Mirrors the TypeScript SDK 1:1 with snake_case method names and Pythonic conventions (context manager, type hints, Pydantic response models).
Installation
Not yet published to PyPI. This SDK currently ships in-repo only; registry publication is pending trusted-publisher setup. Until then, install from the workspace path (
pip install -e packages/sdk-python). The command below will work once the package is live on PyPI.
pip install pulp-engine
Requires Python 3.11+.
Quickstart
from pulp_engine import PulpEngineClient
with PulpEngineClient(
base_url="https://pulp-engine.example.com",
api_key="dk_admin_...",
) as client:
# List templates
templates = client.templates.list()
for t in templates.items:
print(t.key, t.current_version)
# Render a PDF
result = client.render.pdf("invoice", {"amount": 100, "customer": "Acme"})
result.save("invoice.pdf")
# Render to HTML (returns string)
html = client.render.html("invoice", {"amount": 100, "customer": "Acme"})
print(html)
Preview routes in production
The Pulp Engine OpenAPI spec this SDK is generated from includes /render/preview/html and /render/preview/pdf routes. In production (NODE_ENV=production), those routes return 404 unless the API operator has explicitly enabled them with PREVIEW_ROUTES_ENABLED=true. They are intended for the live editor, not for production rendering pipelines.
Before calling a preview method against an unknown deployment, query GET /capabilities at runtime and check the advertised preview capability. Use the production render endpoints (POST /render/pdf — POST /render is a deprecated alias — and the per-format routes POST /render/html|csv|xlsx|docx|pptx, plus POST /render/batch for bulk jobs) for all production document generation — they are always registered and are not affected by this flag.
Authentication
Pass either an API key (X-Api-Key header) or an editor session token (X-Editor-Token header):
# API key
client = PulpEngineClient(base_url="...", api_key="dk_admin_...")
# Editor session token
client = PulpEngineClient(base_url="...", editor_token="...")
# Switch at runtime
client.set_api_key("new-key")
client.set_editor_token("new-token")
Available resources
| Resource | Methods |
|---|---|
client.templates |
list, get, create, update, delete, schema, sample, validate, versions, get_version, restore |
client.render |
pdf, html, csv, xlsx, docx, pptx, dry_run, validate |
client.batch |
pdf, docx, submit_async, submit_async_docx, poll_job, wait_for_job |
client.pdf_transform |
merge, watermark, insert |
client.assets |
list, upload, delete |
client.audit_events |
list, purge |
client.admin |
list_users, create_user, update_user, delete_user, reload_users |
client.auth |
status, editor_token |
client.health |
liveness, readiness |
client.schedules |
list, get, create, update, patch, delete, trigger, list_executions, get_execution |
Error handling
All methods raise PulpEngineError on non-2xx responses:
from pulp_engine import PulpEngineClient, PulpEngineError
try:
client.render.pdf("missing-template", {})
except PulpEngineError as e:
print(e.status) # 404
print(e.error) # "NotFound"
print(e.code) # None (or e.g. "template_expression_error" for render errors)
print(e.issues) # None (or list[ValidationIssue] for 400/422)
print(str(e)) # Human-readable message
Dry-run mode (CI/CD pre-flight checks)
client.render.dry_run() validates input data and exercises all template
expressions via a trial HTML render, then returns a structured result without
producing any binary output. Skips Chromium / DOCX / PPTX entirely — typical
latency is 5–50 ms vs 1–10 s for a full PDF render. Useful for CI/CD
pre-flight checks and integration tests.
Unlike the normal render methods, dry_run() does not raise on template
author errors (validation failures, undefined variables, etc.) — those are
surfaced in the result so callers can display them to users. The only way it
raises is if the request itself is malformed (network error, 4xx auth, etc.).
result = client.render.dry_run("invoice", {"amount": 100})
if result.valid:
print(f"Template OK ({result.field_mappings_applied} field mappings applied)")
else:
# Validation errors (schema mismatches)
for err in result.validation.errors:
print(f"Validation: {err.path}: {err.message}")
# Expression errors (Handlebars failures, undefined variables)
for err in result.expressions.errors:
location = err.location.node_path if err.location else "(no location)"
print(f"Expression at {location}: {err.message}")
if err.suggestion:
print(f" Did you mean: {', '.join(err.suggestion.suggestions)}?")
The format parameter selects which per-format route to hit (defaults to
"pdf"). The result shape is identical regardless of format — the selector
only matters when different formats have different rate limits or feature
gates server-side:
client.render.dry_run("invoice", data, format="html")
client.render.dry_run("invoice", data, format="docx")
Binary results
PDF, CSV, XLSX, DOCX, and PPTX renders return a BinaryResult (or PptxResult) with:
.data— raw bytes.content_type— response Content-Type header.content_disposition— response Content-Disposition header.save(path)— convenience method to write bytes to a file (creates parent dirs)
result = client.render.pdf("invoice", {"amount": 100})
result.save("output/invoice.pdf") # creates output/ if needed
PptxResult adds:
.warning_count— number of structured warnings parsed from theX-Render-Warningsheader
Pagination
List endpoints return a PaginatedResult[T] envelope:
page = client.templates.list(limit=20, offset=0)
print(page.total) # total count across all pages
print(len(page.items)) # items on this page
# Auto-paginate with the helper
from pulp_engine import paginate
for template in paginate(lambda offset, limit: client.templates.list(limit=limit, offset=offset)):
print(template.key)
Development
cd packages/sdk-python
pip install -e ".[dev]"
pytest
Releasing
See RELEASING.md for the publish runbook. Releases are
automated via the publish-sdk-python.yml
GitHub Actions workflow using PyPI Trusted Publishing (no API tokens).
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 pulp_engine-0.85.0.tar.gz.
File metadata
- Download URL: pulp_engine-0.85.0.tar.gz
- Upload date:
- Size: 28.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
be89bef647452c96d06409a686be21fc5ac8465335304812ab853474be86fe00
|
|
| MD5 |
85ec030811e1b980016b1a8d1d5c942b
|
|
| BLAKE2b-256 |
c867170d882b5f84263219f4376760ba3be54f790da58e2a641f240a9ccbb4d6
|
Provenance
The following attestation bundles were made for pulp_engine-0.85.0.tar.gz:
Publisher:
publish-sdk-python.yml on TroyCoderBoy/pulpengine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pulp_engine-0.85.0.tar.gz -
Subject digest:
be89bef647452c96d06409a686be21fc5ac8465335304812ab853474be86fe00 - Sigstore transparency entry: 1822283939
- Sigstore integration time:
-
Permalink:
TroyCoderBoy/pulpengine@00f1fe1aa84eba3105aa1e3c3e144ac1ada30dc7 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/TroyCoderBoy
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-sdk-python.yml@00f1fe1aa84eba3105aa1e3c3e144ac1ada30dc7 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file pulp_engine-0.85.0-py3-none-any.whl.
File metadata
- Download URL: pulp_engine-0.85.0-py3-none-any.whl
- Upload date:
- Size: 27.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
42c290bccae6fb5c89245a7d7d8bc9e14ccb84f8afe5ed2263e2c6ed82932976
|
|
| MD5 |
127a0cc0c47437be46e098d519a0a759
|
|
| BLAKE2b-256 |
9d57f4c2ba9979b0182660f7c78ffcb259a82938696fe8110257e81fdf711c93
|
Provenance
The following attestation bundles were made for pulp_engine-0.85.0-py3-none-any.whl:
Publisher:
publish-sdk-python.yml on TroyCoderBoy/pulpengine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pulp_engine-0.85.0-py3-none-any.whl -
Subject digest:
42c290bccae6fb5c89245a7d7d8bc9e14ccb84f8afe5ed2263e2c6ed82932976 - Sigstore transparency entry: 1822283944
- Sigstore integration time:
-
Permalink:
TroyCoderBoy/pulpengine@00f1fe1aa84eba3105aa1e3c3e144ac1ada30dc7 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/TroyCoderBoy
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-sdk-python.yml@00f1fe1aa84eba3105aa1e3c3e144ac1ada30dc7 -
Trigger Event:
workflow_dispatch
-
Statement type: