Skip to main content
Version: 0.4.0

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.

info

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.

KeyTypeDescription
themefunctionThe visual theme to apply to the invoice. See Themes below.
localefunctionThe locale settings for language and number formatting. See Locales below.
senderdictionarySender details (e.g., name, address, contact info).
recipientdictionaryRecipient details (e.g., name, address, customer ID).
datedatetimeThe date of the invoice. Defaults to datetime.today().
subjectstr | content | autoThe subject line of the invoice. If auto, it is inferred from the locale (e.g., "Rechnung" in German).
referencesnone | dictionary | arrayReference 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-nrnone | str | contentThe unique identifier or number of the invoice.
taxauto | ratio | dictionary | noneThe 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-bizboolIf true, applies the small business tax exemption logic based on the selected locale.
zugferdnone | "minimum" | "basic-wl" | "basic" | "en16931"(Experimental) Embeds a machine-readable ZUGFeRD / Factur-X XML into the PDF. Requires compiling with --pdf-standard=a-3b.
bodycontentThe 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:

  • str or content: 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")
)
)
tip

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.

note

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.

note

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)

warning

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:

ProfileDescription
"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.
info

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,
)
]
tip

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.