Invoice API
The invoice function is the main entry point of the invoice-pro package. It sets up the page layout, visual theme, localization settings, and the global tax configuration for the entire document.
Every invoice document must start with a #show: invoice.with(..) rule. All other components, such as line-items or payment-goal, must be placed after this show rule.
If you forget the show rule, your components will remain invisible because they rely on the underlying loom state engine to render properly.
invoice
Initializes the document and orchestrates the data calculation passes.
| Key | Type | Description |
|---|---|---|
theme | function | The visual theme to apply to the invoice. See Themes below. |
locale | function | The locale settings for language and number formatting. See Locales below. |
sender | dictionary | Sender details (e.g., name, address, contact info). |
recipient | dictionary | Recipient details (e.g., name, address, customer ID). |
date | datetime | The date of the invoice. Defaults to datetime.today(). |
subject | str | content | auto | The subject line of the invoice. If auto, it is inferred from the locale (e.g., "Rechnung" in German). |
references | none | dictionary | array | Reference information for the document header (e.g., customer number, order date). Accepts a dictionary of key-value pairs or an array of (label, value) tuples. |
invoice-nr | none | str | content | The unique identifier or number of the invoice. |
tax | auto | ratio | dictionary | none | The default tax rate for the document. See Tax below. |
tax-mode | "exclusive" | "inclusive" | Sets the global baseline for tax calculation. "exclusive" treats standard prices as net. "inclusive" treats standard prices as gross. |
tax-exempt-small-biz | bool | If true, applies the small business tax exemption logic based on the selected locale. |
zugferd | none | "minimum" | "basic-wl" | "basic" | "en16931" | (Experimental) Embeds a machine-readable ZUGFeRD / Factur-X XML into the PDF. Requires compiling with --pdf-standard=a-3b. |
body | content | The content of the invoice, containing your containing your line-items and other layout components. |
Key Parameters Explained
While the table above lists all available options, a few parameters dictate the core behavior, layout, and legal compliance of your invoice:
sender & recipient
These parameters define the contact details for the invoicing party (sender) and the customer (recipient). Both parameters accept a standard dictionary.
Standard keys generally include name, address, and city. Additionally, you can use the extra key to provide arbitrary supplementary information (like phone numbers, email addresses, or commercial register numbers) styled according to your theme.
Just like the header references, the extra field accepts either a dictionary of key-value pairs or an array of (label, value) tuples.
Polymorphic Address Support
The address key is polymorphic, accepting strings, content blocks, or arrays of string/content:
strorcontent: A single-line address (e.g."Musterstraße 1"or[Musterstraße 1]).array: Multiple address lines (e.g.("Musterstraße 1", "Hinterhaus 2")).
Layout Formatting:
- In vertical layouts (e.g., envelope address window block), lines are separated by line breaks (
\). - In horizontal layouts (e.g., inline details block), lines are separated by commas (
", ").
Example:
sender: (
name: "Max Mustermann",
address: ("Musterstraße 1", "Hinterhaus 2"),
city: "12345 Musterstadt",
extra: (
"Phone": "+49 123 456789",
"Email": "max@mustermann.de",
"Web": "www.mustermann.de"
)
),
recipient: (
name: "Acme Corporation",
address: "Business Blvd 42",
city: "54321 Metropolis",
extra: (
("Contact Person", "Jane Doe"),
("Department", "Accounting")
)
)
To configure country-specific formatting for the address block (like UK postcodes or US state formats) and specify the ZUGFeRD-compliant country code, use the predefined country configurations from the country module. See the Country API subpage for detailed specifications.
locale
The locale system dictates the language of standard text (like "Invoice" or "Subtotal"), currency formatting, and the default tax rates for your region.
Locales are structured as locale.<lang>-<region>.
- Available Languages (
<lang>):de(German),en(English),fr(French),it(Italian),es(Spanish). - Available Regions (
<region>):de(Germany),at(Austria),ch(Switzerland),fr(France),it(Italy),es(Spain).
Example: locale: locale.en-de (English language formatting, but German regional tax defaults).
See the Locale API Reference for the full list and customization options.
theme
The theme dictates the visual layout and styling of your invoice. You must pass a theme function from the themes module.
The theming engine is currently undergoing expansion. At the moment, there are two primary themes available:
themes.DIN-5008(): A standard German business letter layout.themes.base: A minimal, bare-bones layout.
See the Theme API Reference for more details.
tax & tax-exempt-small-biz
By default (when tax is set to auto), the system fetches the standard VAT/GST rate from your selected locale region. However, you can explicitly override this default at the document root by providing a simple percentage (e.g., 19%) or using a specialized code from the tax module (e.g., tax.vat(21%)).
If you run a small business that is exempt from charging VAT (e.g., the Kleinunternehmerregelung in Germany), you can simply set tax-exempt-small-biz: true.
If you enable the small business exemption, the system automatically applies the correct legal tax code and 0% rate for your region. Therefore, you should leave the tax parameter set to auto. If you manually set a custom tax rate while tax-exempt-small-biz is true, the compiler will throw an error to prevent conflicting configurations.
See the Tax Module API Reference for a detailed breakdown of all available tax codes and margin schemes.
references
The references parameter allows you to add custom metadata to the information block of the invoice (usually positioned in the top-right corner near the date and invoice number). This is the perfect place for Customer IDs, Order Dates, or Delivery Numbers.
You can provide this data in two formats:
- As a Dictionary: The simplest method for key-value pairs.
references: ("Customer No.": "C-9982","Order Date": "2026-04-10")
- As an Array of Tuples: Dictionaries in Typst do not always guarantee a specific order. If the exact visual order of your reference fields is strictly required, use an array of
(label, value)pairs instead.references: (("Customer No.", "C-9982"),("Order Date", "2026-04-10"))
zugferd — ZUGFeRD / Factur-X (Experimental)
ZUGFeRD / Factur-X support is experimental. The generated XML has not yet been validated against all edge cases of the EN 16931 standard. Do not rely on it for legally binding e-invoices without independent validation.
Setting zugferd to a profile string embeds a machine-readable factur-x.xml file inside the PDF according to the ZUGFeRD 2.x / Factur-X 1.0 standard. This allows accounting software to automatically import your invoice data.
Required CLI flag: You must compile with PDF/A-3b support for the attachment to be valid:
typst compile --pdf-standard=a-3b invoice.typ
Available profiles:
| Profile | Description |
|---|---|
"minimum" | Header-only data (seller, buyer, date, total). No line items. |
"basic-wl" | Header + payment details. No line items. |
"basic" | Full line items included. |
"en16931" | Full EN 16931 compliance with complete line-item data (recommended). |
"xrechnung" | Identical to "en16931" but specifies full compliance with the German XRechnung 3.0 standard. |
If zugferd is set to "en16931" and both the sender and recipient are located in Germany (DE), the system automatically promotes the profile internally to "xrechnung" to comply with German national e-invoicing requirements (specification identifier).
Example:
#show: invoice.with(
zugferd: "en16931",
sender: (
name: "Musterfirma GmbH",
address: "Musterstraße 1",
city: "12345 Musterstadt",
vat-id: "DE123456789",
contact: (
name: "Max Mustermann",
phone: "+49 123 456789",
email: "max@musterfirma.de",
),
),
recipient: (
name: "Kunde AG",
address: "Kundenweg 5",
city: "54321 Kundenstadt",
vat-id: "DE987654321",
buyer-reference: "DE123456789-12345-12",
),
invoice-nr: "INV-2026-001",
)
For accurate UN/CEFACT unit codes in the embedded XML, use the dictionary form for unit on your line items — see the Line Items API for details.
Minimal Valid Configuration
While the invoice function offers many ways to customize your document, you only need to provide a few core parameters to generate a legally valid and functional invoice. At a bare minimum, you must define the sender, the recipient, a unique invoice number, and your tax identifier.
Here is an example of the minimal boilerplate needed to get started:
#import "@preview/invoice-pro:0.4.0": *
#show: invoice.with(
sender: (
name: "Max Mustermann",
address: "Musterstraße 1",
city: "12345 Musterstadt",
vat-id: "DE123456789",
),
recipient: (
name: "Acme Corporation",
address: "Business Blvd 42",
city: "54321 Metropolis",
),
invoice-nr: "INV-2026-001",
)
// The document body starts here
#line-items[
#item(
[Consulting Services],
quantity: 10,
unit: "h",
price: 150.00,
)
]
Notice that we didn't provide a date or subject parameter in the minimal example. If you leave these out, the package automatically defaults the date to today (datetime.today()) and infers a standard subject line (like "Invoice" or "Rechnung") based on your active locale.