Skip to main content

Validate and normalize Stripe, Shopify, and custom billing data for Factur-X/ZUGFeRD

Project description

TrustRender

Validate and normalize billing data before Factur-X/ZUGFeRD embedding.

Quick start

pip install trustrender

Stripe and Shopify billing exports don't include the seller fields required for compliant invoices. TrustRender catches this:

$ trustrender validate examples/demo_stripe.json --source stripe

Invoice:   INV-2026-0187
From:
To:        Rheingold Maschinenbau GmbH
Items:     3
Total:     $2,685.37

BLOCKED — 1 problem(s)

  Missing vendor/sender name
    Add a sender.name field to your invoice data.

This invoice cannot be processed until the problems above are fixed.
$ trustrender validate examples/demo_shopify.json --source shopify

Invoice:   1047
From:
To:        Klaus Berger
Items:     3
Total:     $1,309.00

BLOCKED — 1 problem(s)

  Missing vendor/sender name
    Add a sender.name field to your invoice data.

This invoice cannot be processed until the problems above are fixed.

Add your seller identity to the source payload and it passes:

$ trustrender validate examples/demo_stripe_ready.json --source stripe

Invoice:   INV-2026-0187
From:      NovaTech Solutions GmbH
To:        Rheingold Maschinenbau GmbH
Items:     3
Total:     $2,685.37

PASS — invoice data is valid

Safe to embed in Factur-X/ZUGFeRD PDF.
$ trustrender validate examples/demo_shopify_ready.json --source shopify

Invoice:   1047
From:      Werkzeug-Kontor GmbH
To:        Klaus Berger
Items:     3
Total:     $1,309.00

PASS — invoice data is valid

Safe to embed in Factur-X/ZUGFeRD PDF.

The only difference between the blocked and passing files is one added field:

"sender": { "name": "NovaTech Solutions GmbH" }

Why this exists

Stripe and Shopify billing exports are missing seller fields, use platform-specific formats (cents, Unix timestamps, decimal strings), and have no concept of tax compliance. factur-x and drafthorse generate compliant Factur-X/ZUGFeRD XML, but they assume clean input. TrustRender validates and normalizes source billing data before handoff — it catches arithmetic mismatches, missing required fields, and structural problems so they don't silently produce non-compliant documents.

Install

pip install trustrender

Core install requires only drafthorse. No Typst, no browser, no heavy deps.

Optional extras:

pip install "trustrender[zugferd]"    # XSD/Schematron validation
pip install "trustrender[render]"     # PDF rendering via Typst
pip install "trustrender[all]"        # everything

Requires Python 3.11+.

Python API

from trustrender import validate_invoice
from trustrender.adapters import from_stripe

# Raw Stripe API response → validated canonical invoice
result = validate_invoice(from_stripe(raw_stripe_response), zugferd=True)

if result["render_ready"] and result.get("zugferd_ready"):
    canonical = result["canonical"]
    # safe to hand off to factur-x / drafthorse
else:
    for error in result["errors"]:
        print(f"BLOCKED: {error['message']}")

validate_invoice() returns:

  • status: "ready" | "ready_with_warnings" | "blocked"
  • render_ready: bool
  • canonical: normalized invoice dict (all fields in canonical names)
  • errors: list of blocking issues with rule_id, path, expected/actual
  • warnings: advisory issues
  • normalizations: field-level provenance (what was renamed, coerced, computed)
  • zugferd_ready: bool (if zugferd=True)

Also works with messy data from any source:

result = validate_invoice({
    "invoiceNo": "INV-001",
    "vendor": {"companyName": "Acme Corp"},
    "customer": {"Name": "Client Inc"},
    "LineItems": [{"desc": "Widget", "qty": 2, "unitPrice": 50, "amount": 100}],
    "SubTotal": 100,
    "tax": 8.50,
    "TotalAmt": 108.50,
}, zugferd=True)

Stripe adapter

Raw Stripe Invoice API responses use cents, Unix timestamps, and nested structures. The adapter handles all of it:

trustrender validate stripe_invoice.json --source stripe --zugferd
from trustrender.adapters import from_stripe
result = validate_invoice(from_stripe(raw_stripe_response), zugferd=True)

Converts cents to dollars, timestamps to dates, extracts line items from lines.data[], maps customer fields to recipient. If you enrich the source payload with sender, vendor, or seller, the adapter passes it through.

Shopify adapter

Shopify orders use decimal strings, split customer names, and a different structure from invoices:

trustrender validate shopify_order.json --source shopify
from trustrender.adapters import from_shopify
result = validate_invoice(from_shopify(raw_shopify_order))

Parses string amounts to floats, combines first_name + last_name, maps order fields to invoice structure, preserves structured address fields. Shopify orders have no seller info or due date — TrustRender flags the missing seller and handles the absent due date correctly.

What it normalizes

90+ vendor field aliases across QuickBooks, Xero, Stripe, and generic CSV/ERP formats:

Source field Canonical field
DocNumber, invoiceNo, inv_no, ref invoice_number
CompanyName, account_name, bill_from_name sender.name
customer, billTo, Contact recipient
Line, LineItems, entries, products items
UnitPrice, cost, rate, unitCost unit_price
Amount, LineAmount, line_total line_total
SubTotal, net_total, sub_total subtotal
TotalAmt, grand_total, amount_due total

Plus: type coercion ("$1,234.56"1234.56), date parsing ("April 10, 2026"2026-04-10), computed defaults (missing line_total = qty × price), near-match typo detection (invioce_number → suggests invoice_number).

What it checks

7 deterministic semantic checks, all arithmetic:

Check What it catches
identity.invoice_number Missing or empty invoice number
identity.sender_name Missing vendor/sender name
identity.recipient_name Missing recipient/buyer name
items.non_empty No line items
arithmetic.line_total line_total ≠ qty × unit_price
arithmetic.subtotal subtotal ≠ sum of line_totals
arithmetic.total total ≠ subtotal + tax_amount

No AI. No heuristics. Every check is deterministic and objectively verifiable.

CLI

trustrender validate <data.json> [--zugferd] [--format text|json]
trustrender ingest <data.json> [-o canonical.json]
trustrender render <template> <data.json> -o <output.pdf> [--zugferd en16931]
trustrender preflight <template> <data.json> [--zugferd en16931]
trustrender serve --templates <dir> [--port 8190]
trustrender doctor [--smoke]

Integration with factur-x / drafthorse

TrustRender validates and normalizes. You generate and embed with the library of your choice.

from trustrender import validate_invoice

# Step 1: Validate with TrustRender
result = validate_invoice(messy_data, zugferd=True)
if not result["render_ready"] or not result["zugferd_ready"]:
    raise ValueError(f"Invoice blocked: {result['errors']}")

# Step 2: Use the canonical payload with drafthorse or factur-x
canonical = result["canonical"]
# ... your existing ZUGFeRD generation code here

EN 16931 e-invoicing (narrow scope)

Catches many document-level and ZUGFeRD/EN 16931 readiness issues before embedding. Currently supports:

  • Domestic German B2B invoices with standard VAT, EUR, SEPA payment
  • Single or mixed VAT rates (7% + 19%)
  • Invoice type 380 and credit note 381
  • PDF/A-3b with embedded CII XML (requires trustrender[render])

Not supported (fails loudly): reverse charge, cross-border, allowances/charges, non-EUR currencies.

See docs/einvoice-scope.md for the full scope matrix.

Optional: PDF rendering

If you also want TrustRender to generate PDFs (not just validate):

pip install "trustrender[render]"
trustrender render invoice.j2.typ data.json -o invoice.pdf --zugferd en16931

Rendering uses Typst — no browser, no Chromium. Fast and deterministic.

What this is not

  • Not a full AP automation platform
  • Not an e-invoice compliance certification
  • Not an AI-powered data fixer (all corrections are deterministic)
  • Not a replacement for factur-x or drafthorse — it's the validation layer you run before them

Development

pip install -e ".[dev]"
trustrender doctor --smoke
pytest

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

trustrender-0.3.4.tar.gz (1.8 MB view details)

Uploaded Source

Built Distribution

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

trustrender-0.3.4-py3-none-any.whl (1.7 MB view details)

Uploaded Python 3

File details

Details for the file trustrender-0.3.4.tar.gz.

File metadata

  • Download URL: trustrender-0.3.4.tar.gz
  • Upload date:
  • Size: 1.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for trustrender-0.3.4.tar.gz
Algorithm Hash digest
SHA256 877464b05796c7f4f32614f2688ab30bc4ea4437e77e413709077f995de95608
MD5 5112f37d2e2cc147c6cfba7b4212100d
BLAKE2b-256 e15a3d8d6406b488c82050fdd7f9605dc61211ed080afbd5d4147e546426a51e

See more details on using hashes here.

Provenance

The following attestation bundles were made for trustrender-0.3.4.tar.gz:

Publisher: publish.yml on verityengine/trustrender

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file trustrender-0.3.4-py3-none-any.whl.

File metadata

  • Download URL: trustrender-0.3.4-py3-none-any.whl
  • Upload date:
  • Size: 1.7 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for trustrender-0.3.4-py3-none-any.whl
Algorithm Hash digest
SHA256 455141a4e0e4c4bd44edcfadd00950323b8bfbd81616a070d62ddf144dcc1a20
MD5 34abe80a6f0b7e49bf0ecb7797feb428
BLAKE2b-256 02e5a83136effb99a50de7b05af0d96a98461bede2920bdd2dfa444dca416099

See more details on using hashes here.

Provenance

The following attestation bundles were made for trustrender-0.3.4-py3-none-any.whl:

Publisher: publish.yml on verityengine/trustrender

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