Skip to main content

typefold-client

Python client for the Typefold API. Needs Python 3.10 or later; its only dependency is httpx. It has a blocking TypefoldClient and an asyncio AsyncTypefoldClient with the same methods.

pip install typefold-client

Create one client per API key and reuse it. The key needs render:create, render:read and template:read, and render:cancel to cancel renders.

from typefold import TypefoldClient

client = TypefoldClient("https://pdf.example.com", api_key)

Close it with client.close() when your application stops, or use it as a context manager.

Render a report

render_report renders a published report or saved template by name or ID and returns the PDF or XLSX bytes:

from typefold import (
    Orientation,
    PageSize,
    PdfMetadata,
    RenderReportRequest,
    ReportFormat,
    ReportPdfOptions,
    TemplateRef,
)

pdf = client.render_report(
    RenderReportRequest(
        template=TemplateRef.by_name("SoldGoodsForWarehouseReportPdf"),
        data={"Data": {"reportRows": report_rows, "summaryRows": summary_rows}},
        pdf=ReportPdfOptions(
            page_size=PageSize.A4,
            orientation=Orientation.LANDSCAPE,
            metadata=PdfMetadata(title="Sold goods, week 39"),
        ),
    )
)

xlsx = client.render_report(
    RenderReportRequest(
        format=ReportFormat.XLSX,
        template=TemplateRef.by_name("SoldGoodsForWarehouseReportXlsx"),
        data=data,
    )
)

data is sent as written: dictionary keys keep their names, and dates, decimals, UUIDs and dataclasses are written as JSON.

Templates imported from jsreport keep their shortids, so stored shortids still work: TemplateRef.by_shortid("rkJTnK2ce"). list_reports returns each template's shortid.

A retry with the same idempotency_key returns the render the key already created. get_report_data_schema returns the JSON Schema of a report's data; list_reports lists templates and the formats each renders.

Render notification text

render_string renders a template string synchronously, without a PDF, for email bodies, subjects, SMS and push messages. The Handlebars engine runs #if, #each and your helpers:

from typefold import RenderStringRequest, StringEngine, StringFormat

body = client.render_string(
    RenderStringRequest(
        template="{{#if (isEqual Status 'paid')}}Paid{{else}}Due{{/if}}: {{Booking.Code}}",
        data=model,
        engine=StringEngine.HANDLEBARS,
        helpers="function isEqual(a, b) { return a === b; }",
        format=StringFormat.HTML,
    )
)

StringFormat.HTML escapes values; StringFormat.TEXT (the default) writes them as they are. Without engine, only {{path}} placeholders are replaced.

Render HTML or a template version

render creates a render, waits for it and downloads the PDF:

from typefold import DirectRenderRequest, HtmlDocument, PageSize, RenderSettings, TemplateVersionRenderRequest

pdf = client.render(
    DirectRenderRequest(
        document=HtmlDocument(html="<h1>Invoice 42</h1>"),
        settings=RenderSettings(page_size=PageSize.A4),
    )
)

ticket = client.render(
    TemplateVersionRenderRequest(template_version_id=version_id, data={"ticket": {"number": "TK-1"}})
)

It gives up after two minutes unless you pass a timeout in seconds. To render in the background, use create_render, then wait_for_render, download or cancel_render, or the API's render webhooks.

Upload to a storage destination

To also upload the PDF to one of the workspace's storage destinations, pass destination with the destination's name. path is the object's key after the destination's prefix; {renderId} is replaced with the render's ID, and it defaults to {renderId}.pdf (or .png, .jpeg, .webp for an image):

from typefold import RenderDestination, TemplateVersionRenderRequest

render = client.create_render(
    TemplateVersionRenderRequest(
        template_version_id=version_id,
        data=invoice,
        destination=RenderDestination(name="invoices-bucket", path="2026/{renderId}.pdf", keep_copy=False),
    )
)
render = client.wait_for_render(render)

key = render.result.destination.key

result.destination.key is the object's full key in the bucket. With keep_copy=False the API keeps no copy: the result has no download_url or expires_at, download raises ValueError, and render raises it before creating the render, so use create_render and read the PDF from the bucket. Batch items take destination too. A failed upload fails the render with the diagnostic code destination_upload_failed.

Render a batch

create_batch creates up to 100 renders in one request; if any item is invalid, none is created. Items are DirectRenderRequest or TemplateVersionRenderRequest; their wait_ms is not sent. wait_for_batch polls until no item is queued or processing (10 minutes unless you pass a timeout), and download_batch returns one PDF of every item in order:

batch = client.create_batch(
    [TemplateVersionRenderRequest(template_version_id=version_id, data=ticket) for ticket in tickets],
    idempotency_key="tickets-2026-10-12",
)
batch = client.wait_for_batch(batch)

if batch.counts.succeeded == batch.total:
    pdf = client.download_batch(batch.id)

A failed item does not stop the others; batch.items gives each render's id and state, to read, download or cancel it as a single render. get_batch reads a batch again.

Embed the content editor

create_embed_token makes a short-lived token that opens the embedded content editor for one content set of a published template, so your own customers can edit their content in your app. Call it on your server each time a customer opens the editor, and send only its url to the page, which frames it with /embed.js:

from typefold import CreateEmbedTokenRequest

embed = client.create_embed_token(
    CreateEmbedTokenRequest(
        template_id=template_id,
        content_set_id=content_set_id,
        expires_in_minutes=30,
        label=customer.id,
    )
)
# Send embed.url to your page; keep embed.id to revoke the token early.
client.revoke_embed_token(embed.id)

The key needs template:read, template:content and render:create. The workspace must list your app's origin under Settings → Embedding first.

Async

AsyncTypefoldClient has the same methods as coroutines:

from typefold import AsyncTypefoldClient

async with AsyncTypefoldClient("https://pdf.example.com", api_key) as client:
    pdf = await client.render_report(request)

Errors

A request the API refuses with 429 RATE_LIMITED, such as a burst of parallel renders, is sent again after its Retry-After up to max_rate_limit_retries times (3 by default; pass 0 to turn this off). Other failures raise TypefoldError. error.code is the API's code, such as NOT_FOUND, RATE_LIMITED or RENDER_TIMEOUT, and error.retryable says whether a retry can help. When a render was created but failed or timed out, error.error.render_id names it.

Versions

Use a client no newer than your server: older clients keep working because /v1 only grows, but a newer client's fields or endpoints answer 400 or 404 on an older server.

httpx client

To share an httpx.Client (or httpx.AsyncClient), pass it as http_client with a timeout above 95 seconds, the longest a report PDF can take. The API key goes on each request, not the client, and never to download URLs. A client you pass in is not closed with the TypefoldClient.

Development

cd clients/python
python -m venv .venv && .venv/bin/pip install -e '.[test]'
.venv/bin/pytest && .venv/bin/mypy src tests && .venv/bin/ruff check . && .venv/bin/ruff format --check .

Metadata

Release files for typefold-client 0.6.1

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

Source distribution (sdist)

Source distribution for typefold-client 0.6.1
File Size Uploaded Provenance
typefold_client-0.6.1.tar.gz 23.9 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for typefold-client 0.6.1
File Interpreter ABI Platform
typefold_client-0.6.1-py3-none-any.whl Python 3 none any Details

Total release size: 43.4 kB

Release files / typefold_client-0.6.1.tar.gz

Download URL typefold_client-0.6.1.tar.gz
Size 23.9 kB
Tags Source
SHA-256 checksum
How to use checksums
53c99cf137990afd8059bc9f62e1997380df44ccd69aff6f633fb2974b4fd70a
BLAKE2b-256 checksum
How to use checksums
80ec74be8c0c86d69bc079a641ed2507e6267bb20dd49d28a58610f05f101ca2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Release files / typefold_client-0.6.1-py3-none-any.whl

Download URL typefold_client-0.6.1-py3-none-any.whl
Size 19.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
417113e7d979f556b1f5bb655d15430f8e850d817f0781ccf0df26054f7b5312
BLAKE2b-256 checksum
How to use checksums
265ee19b967ce2d3c4dfeb0d89704d966b8679afe5d6fe819108c981a6b30efa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Security for typefold-client 0.6.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for typefold_client-0.6.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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