Billing profiles
Two distinct objects hold the billing-side identity of every invoice:
tenant_billing_profiles— the buyer. One row per tenant. Carries company name, address, EU VAT number, contact email, preferred language, and the names of the templates this tenant gets.partner_configuration— the seller. One row per partner. Carries legal name, address, VAT, bank details (IBAN/BIC), and the default templates the partner's tenants inherit.
At invoice finalisation time, both rows are snapshotted into the invoice itself (buyer_snapshot and seller_snapshot JSON columns) so the invoice stays immutable even if either profile is edited later.
Tenant billing profile#
The full schema:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
A tenant can perform any commerce action (subscribe, get an invoice) only if this profile exists. Triggering its first creation emits the tenant.billing_linked.v1 event; subsequent edits emit tenant.billing_updated.v1 with changed_fields[].
Endpoints:
- Self-service (the tenant edits its own):
GET/PUT /billing/billing-profile— see Billing (tenant). - Admin:
PUT /admin/tenants/{tenant_id}/billing-profile— see Admin — tenants.
Partner configuration (seller side)#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
A partner is considered billable once legal_name AND seller_country_code are both set. The first time those fields cross from null → set, partner.billing_linked.v1 fires. Subsequent changes to any seller field emit partner.billing_updated.v1 with changed_fields[].
Endpoint: PATCH /admin/partners/{partner_id} — see Admin — partners.
Snapshots at finalisation#
When an invoice is finalised:
- The tenant's billing profile is copied into
invoices.buyer_snapshot(JSON). - The partner's relevant seller fields are copied into
invoices.seller_snapshot. - The VAT determination is recomputed and frozen into
invoices.vat_details.
After that point, edits to the tenant profile do NOT propagate. Generating a credit note from the same invoice will reuse the snapshots, ensuring downstream documents reference the original buyer/seller exactly as they were at the time.
If the tenant moves countries, gets a new VAT number, etc., the next invoice picks up the new state, but the existing ones stay correct for audit purposes.
Template assignment#
Both invoice templates and email templates resolve through a two-step chain at render time:
- Try the tenant's assigned template (
tenant_billing_profiles.invoice_template_name/.email_template_name). - Fall back to the partner's assigned template (
partner_configuration.invoice_template_name/.email_template_name). - Fall back to the built-in filesystem default.
Each step also tries the tenant's preferred_language first, falling back to the any-language template variant. See Templates.
E-invoicing identifiers#
Several optional fields on the buyer side cover European e-invoicing requirements:
- Peppol — used in the Netherlands, Nordics, Belgium.
peppol_id+peppol_schemetogether identify the receiver in the Peppol network. - Leitweg-ID — required for German XRechnung-format invoices to public-sector buyers.
preferred_einvoice_format—ubl,xrechnung,cii,zugferd,facturx, or null for PDF-only. Drives the format of the XML attachment shipped alongside the PDF.
The seller side mirrors these so the operator (or reseller) can act as an e-invoicing sender.
Editing a billing profile mid-stream#
Profile edits are non-blocking — any in-flight subscription continues, and the next invoice picks up the new buyer info. The only special case is country_code, which changes VAT treatment (domestic ↔ intra-EU ↔ export). The next finalisation will recompute. If you need to correct a previously-issued invoice for a buyer-side error, issue a credit note and a fresh invoice — never edit a finalised one.