Skip to main content

Installation

# API client only (zero dependencies)
pip install formepdf

# Local rendering with component DSL (adds wasmtime)
pip install formepdf[local]

Hosted API

The API client uses only the Python standard library. Create templates in the dashboard, then render them with data:
from formepdf import Forme

client = Forme("forme_sk_...")

pdf = client.render("invoice", {
    "customer": "Acme Corp",
    "items": [{"name": "Widget", "qty": 5, "price": 49}],
    "total": 245,
})

with open("invoice.pdf", "wb") as f:
    f.write(pdf)

Client options

client = Forme(
    api_key="forme_sk_...",
    base_url="https://custom-api.example.com",  # optional
)

Methods

MethodDescriptionReturns
render(slug, data)Synchronous renderbytes
render(slug, data, s3=opts)Render and upload to S3dict
render_async(slug, data)Start async render jobdict
get_job(job_id)Poll async job statusdict
merge(pdfs)Merge multiple PDFsbytes
certify(pdf, certificate=..., private_key=...)Certify a PDF with X.509 certificatebytes
redact(pdf, patterns=..., presets=...)Redact content from a PDFbytes
extract(pdf_bytes)Extract embedded datadict or None

Certify

certified = client.certify(
    pdf_bytes,
    certificate=open("cert.pem").read(),
    private_key=open("key.pem").read(),
    reason="Approved",
)
Or use a saved certificate on the hosted API:
certified = client.certify(pdf_bytes, certificate_id="cert_abc123")

Redact

# By text pattern
redacted = client.redact(pdf_bytes, patterns=[
    {"pattern": "Jane Doe", "pattern_type": "Literal"},
    {"pattern": r"\d{3}-\d{2}-\d{4}", "pattern_type": "Regex"},
])

# By built-in presets
redacted = client.redact(pdf_bytes, presets=["ssn", "email", "phone"])

# By saved redaction template
redacted = client.redact(pdf_bytes, template="hipaa-patient-record")

Merge

merged = client.merge([pdf1, pdf2, pdf3])

Error handling

from formepdf import Forme, FormeError

try:
    pdf = client.render("invoice", data)
except FormeError as e:
    print(f"Error {e.status}: {e.message}")

Native templates

Build documents in Python code using a component DSL that mirrors the JSX API. Renders locally via the WASM engine — no network calls.
from formepdf import Document, Page, View, Text, Image

doc = Document(
    Page(
        View(
            Text("Invoice #001", font_size=24, font_weight="bold"),
            Text("Acme Corp", font_size=14, color="#666"),
            flex_direction="column", gap=8,
        ),
        View(
            Image("logo.png", width=80),
            Text("Total: $245.00", font_size=18),
            justify_content="space-between",
            align_items="center",
        ),
    ),
    title="Invoice #001",
)

pdf = doc.render()
with open("invoice.pdf", "wb") as f:
    f.write(pdf)

Components

ConstructorDescriptionKey options
Document(*children)Root container, .render() returns PDF bytestitle, author, lang, tagged, pdf_ua, pdfa, flatten_forms
Page(*children)Page containersize (e.g. "A4"), margin
View(*children)Flex/grid containerflex_direction, gap, padding, justify_content, align_items
Text(content)Text elementfont_size, font_weight, color, text_align
Image(src)Image (file path, URL, or data URI)width, height, alt
Table(*rows)Table with auto-repeating headerscolumns
Row(*cells)Table rowheader=True
Cell(*children)Table cellcol_span, row_span
QrCode(data)Vector QR codesize, color
Barcode(data)1D barcodeformat, width, height
BarChart(data)Bar chartwidth, height, title
LineChart(series, labels)Line chartwidth, height, title
PieChart(data)Pie/donut chartwidth, height, donut
TextField(name)Fillable text fieldvalue, placeholder
Checkbox(name)Fillable checkboxchecked
Dropdown(name, options)Fillable dropdownvalue
Watermark(text)Rotated watermarkfont_size, color, angle
PageBreak()Force a page break

Local certify

from formepdf.wasm import certify_pdf
import json

config = json.dumps({
    "certificate_pem": open("cert.pem").read(),
    "private_key_pem": open("key.pem").read(),
    "reason": "Approved",
})

certified = certify_pdf(pdf_bytes, config)

Hosted vs native

Hosted APINative templates
DependenciesZero (stdlib only)wasmtime (~6MB WASM)
TemplatesPre-uploaded via dashboardBuilt in Python code
NetworkRequires API callFully offline
Use caseDynamic data + stored templatesFull control, CI/CD, testing