POST /v1/generate
Generate a compliant e-invoice from structured invoice data — EN 16931 (UBL/CII) formats, Peppol, hybrid PDF, or Italy FatturaPA FPR12 XML.
Create an e-invoice from JSON data in one API call.
Before Beliq returns the result, it validates your invoice against the rules that apply to the chosen standard. For EN 16931–based formats that means XSD, EN 16931 Schematron, and CIUS/profile Schematron where applicable. For Italy FatturaPA (standard: "fatturapa") validation is authority XSD only (no EN 16931 Schematron layer). If validation fails, you get a 422 INVALID_INVOICE response with details.
Quick copy examples
Generate XML:
curl -X POST https://api.beliq.eu/v1/generate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"standard": "xrechnung",
"profile": "xrechnung",
"output": "xml",
"invoice": {
"number": "INV-2026-001",
"issueDate": "2026-04-13",
"dueDate": "2026-05-13",
"currencyCode": "EUR",
"buyerReference": "04011000-12345-03",
"seller": {
"name": "Acme GmbH",
"vatId": "DE123456789",
"email": "billing@acme.example",
"contactName": "Anna Beispiel",
"phone": "+49 30 1234567",
"address": { "street": "Musterstraße 1", "city": "Berlin", "postalCode": "10115", "countryCode": "DE" }
},
"buyer": {
"name": "Bundesministerium für Beispiele",
"vatId": "DE987654321",
"address": { "street": "Beispielweg 42", "city": "Bonn", "postalCode": "53113", "countryCode": "DE" }
},
"lines": [
{
"description": "IT consulting — April 2026",
"quantity": 20,
"unitCode": "HUR",
"unitPrice": 120.00,
"lineTotal": 2400.00,
"vatRate": 19,
"vatCategoryCode": "S"
}
],
"taxSummary": [
{ "vatCategoryCode": "S", "vatRate": 19, "taxableAmount": 2400.00, "taxAmount": 456.00 }
],
"paymentMeans": {
"typeCode": "58",
"iban": "DE89370400440532013000"
},
"totalNetAmount": 2400.00,
"totalTaxAmount": 456.00,
"totalGrossAmount": 2856.00
}
}'import { Beliq } from '@beliq/sdk';
const beliq = new Beliq({ apiKey: process.env.BELIQ_API_KEY! });
const generated = await beliq.generate({
standard: 'xrechnung',
profile: 'xrechnung',
output: 'xml',
invoice: {
number: 'INV-2026-001',
issueDate: '2026-04-13',
dueDate: '2026-05-13',
currencyCode: 'EUR',
buyerReference: '04011000-12345-03',
seller: {
name: 'Acme GmbH',
vatId: 'DE123456789',
email: 'billing@acme.example',
contactName: 'Anna Beispiel',
phone: '+49 30 1234567',
address: { street: 'Musterstraße 1', city: 'Berlin', postalCode: '10115', countryCode: 'DE' },
},
buyer: {
name: 'Bundesministerium für Beispiele',
vatId: 'DE987654321',
address: { street: 'Beispielweg 42', city: 'Bonn', postalCode: '53113', countryCode: 'DE' },
},
lines: [
{
description: 'IT consulting — April 2026',
quantity: 20,
unitCode: 'HUR',
unitPrice: 120.00,
lineTotal: 2400.00,
vatRate: 19,
vatCategoryCode: 'S',
},
],
taxSummary: [{ vatCategoryCode: 'S', vatRate: 19, taxableAmount: 2400.00, taxAmount: 456.00 }],
paymentMeans: { typeCode: '58', iban: 'DE89370400440532013000' },
totalNetAmount: 2400.00,
totalTaxAmount: 456.00,
totalGrossAmount: 2856.00,
},
});
// `xml` is the same document curl writes to stdout.
console.log(generated.xml);import os
from beliq import Beliq
beliq = Beliq(api_key=os.environ["BELIQ_API_KEY"])
generated = beliq.generate(
standard="xrechnung",
profile="xrechnung",
output="xml",
invoice={
"number": "INV-2026-001",
"issueDate": "2026-04-13",
"dueDate": "2026-05-13",
"currencyCode": "EUR",
"buyerReference": "04011000-12345-03",
"seller": {
"name": "Acme GmbH",
"vatId": "DE123456789",
"email": "billing@acme.example",
"contactName": "Anna Beispiel",
"phone": "+49 30 1234567",
"address": {
"street": "Musterstraße 1",
"city": "Berlin",
"postalCode": "10115",
"countryCode": "DE",
},
},
"buyer": {
"name": "Bundesministerium für Beispiele",
"vatId": "DE987654321",
"address": {
"street": "Beispielweg 42",
"city": "Bonn",
"postalCode": "53113",
"countryCode": "DE",
},
},
"lines": [
{
"description": "IT consulting — April 2026",
"quantity": 20,
"unitCode": "HUR",
"unitPrice": 120.00,
"lineTotal": 2400.00,
"vatRate": 19,
"vatCategoryCode": "S",
},
],
"taxSummary": [{"vatCategoryCode": "S", "vatRate": 19, "taxableAmount": 2400.00, "taxAmount": 456.00}],
"paymentMeans": {"typeCode": "58", "iban": "DE89370400440532013000"},
"totalNetAmount": 2400.00,
"totalTaxAmount": 456.00,
"totalGrossAmount": 2856.00,
},
)
# `xml` is the same document curl writes to stdout.
print(generated.xml)Generate PDF:
curl -X POST https://api.beliq.eu/v1/generate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"standard": "zugferd",
"profile": "en16931",
"output": "pdf",
"invoice": {
"number": "INV-2026-001",
"issueDate": "2026-04-13",
"dueDate": "2026-05-13",
"currencyCode": "EUR",
"seller": {
"name": "Acme GmbH",
"vatId": "DE123456789",
"address": { "street": "Musterstraße 1", "city": "Berlin", "postalCode": "10115", "countryCode": "DE" }
},
"buyer": {
"name": "Bundesministerium für Beispiele",
"vatId": "DE987654321",
"address": { "street": "Beispielweg 42", "city": "Bonn", "postalCode": "53113", "countryCode": "DE" }
},
"lines": [
{
"description": "IT consulting — April 2026",
"quantity": 20,
"unitCode": "HUR",
"unitPrice": 120.00,
"lineTotal": 2400.00,
"vatRate": 19,
"vatCategoryCode": "S"
}
],
"taxSummary": [
{ "vatCategoryCode": "S", "vatRate": 19, "taxableAmount": 2400.00, "taxAmount": 456.00 }
],
"totalNetAmount": 2400.00,
"totalTaxAmount": 456.00,
"totalGrossAmount": 2856.00
}
}' \
--output invoice.pdfimport { writeFile } from 'node:fs/promises';
import { Beliq } from '@beliq/sdk';
const beliq = new Beliq({ apiKey: process.env.BELIQ_API_KEY! });
const generated = await beliq.generate({
standard: 'zugferd',
profile: 'en16931',
output: 'pdf',
invoice: {
number: 'INV-2026-001',
issueDate: '2026-04-13',
dueDate: '2026-05-13',
currencyCode: 'EUR',
seller: {
name: 'Acme GmbH',
vatId: 'DE123456789',
address: { street: 'Musterstraße 1', city: 'Berlin', postalCode: '10115', countryCode: 'DE' },
},
buyer: {
name: 'Bundesministerium für Beispiele',
vatId: 'DE987654321',
address: { street: 'Beispielweg 42', city: 'Bonn', postalCode: '53113', countryCode: 'DE' },
},
lines: [
{
description: 'IT consulting — April 2026',
quantity: 20,
unitCode: 'HUR',
unitPrice: 120.00,
lineTotal: 2400.00,
vatRate: 19,
vatCategoryCode: 'S',
},
],
taxSummary: [{ vatCategoryCode: 'S', vatRate: 19, taxableAmount: 2400.00, taxAmount: 456.00 }],
totalNetAmount: 2400.00,
totalTaxAmount: 456.00,
totalGrossAmount: 2856.00,
},
});
await writeFile('invoice.pdf', generated.bytes);import os
from pathlib import Path
from beliq import Beliq
beliq = Beliq(api_key=os.environ["BELIQ_API_KEY"])
generated = beliq.generate(
standard="zugferd",
profile="en16931",
output="pdf",
invoice={
"number": "INV-2026-001",
"issueDate": "2026-04-13",
"dueDate": "2026-05-13",
"currencyCode": "EUR",
"seller": {
"name": "Acme GmbH",
"vatId": "DE123456789",
"address": {
"street": "Musterstraße 1",
"city": "Berlin",
"postalCode": "10115",
"countryCode": "DE",
},
},
"buyer": {
"name": "Bundesministerium für Beispiele",
"vatId": "DE987654321",
"address": {
"street": "Beispielweg 42",
"city": "Bonn",
"postalCode": "53113",
"countryCode": "DE",
},
},
"lines": [
{
"description": "IT consulting — April 2026",
"quantity": 20,
"unitCode": "HUR",
"unitPrice": 120.00,
"lineTotal": 2400.00,
"vatRate": 19,
"vatCategoryCode": "S",
},
],
"taxSummary": [{"vatCategoryCode": "S", "vatRate": 19, "taxableAmount": 2400.00, "taxAmount": 456.00}],
"totalNetAmount": 2400.00,
"totalTaxAmount": 456.00,
"totalGrossAmount": 2856.00,
},
)
Path("invoice.pdf").write_bytes(generated.content)Request
POST /v1/generate
Content-Type: application/json
Authorization: Bearer <api-key>Request body
| Field | Type | Required | Description |
|---|---|---|---|
standard |
string | required | E-invoice standard. One of: xrechnung, zugferd, facturx, peppol-bis, fatturapa (Italy FatturaPA ordinaria FPR12 XML), facturae (Spain Facturae 3.2.2 XML), eslog (Slovenia e-SLOG 2.0 XML); the three national formats use XSD validation only, not EN 16931 UBL/CII |
profile |
string | optional | Compliance profile. Valid values depend on standard — see Profile compatibility for the full matrix and the per-standard default. A profile that does not belong to the chosen standard is rejected with 422 PROFILE_STANDARD_MISMATCH. |
output |
string | required | Output format. xml for raw XML, or pdf. For ZUGFeRD / Factur-X, pdf is a hybrid PDF/A-3 with embedded XML; for the XML-only standards (xrechnung, peppol-bis, fatturapa, facturae, eslog), pdf is a visualization PDF and requires a template or pdfTemplateId. |
invoice |
object | required | Invoice data (see Invoice object below) |
verify |
boolean | optional | When true (default), the engine validates output before returning it. Set false to skip post-generation validation (not recommended). The response then reports "valid": false alongside "verified": false — nothing looked at the document, so nothing can call it valid. See Reading valid and verified. |
template |
string | optional | Set to "standard" to render the built-in styled invoice layout for pdf output. Required to get a visualization PDF from an XML-only standard; for ZUGFeRD / Factur-X it styles the hybrid’s visible page (omit it for a blank page). See Styling the PDF. |
pdfTemplateId |
string | optional | Render the PDF from one of your stored custom templates, designed in the dashboard. The value is the template’s short ref (a k3d-9mp-style code shown next to it in the dashboard), not a raw UUID. Takes precedence over template. Requires an authenticated request (the template is org-scoped). Honoured for any pdf output. |
Profile compatibility
profile is not a free enum: each standard accepts its own set, and a pair outside this table is rejected with 422 PROFILE_STANDARD_MISMATCH whose details.allowedProfiles repeats the accepted column for the standard you sent. Omit profile to get the default.
| Standard | Accepted profile values |
Default |
|---|---|---|
xrechnung |
xrechnung |
xrechnung |
zugferd |
minimum, basicwl, basic, en16931, extended |
en16931 |
facturx |
minimum, basicwl, basic, en16931, extended, extended-ctc-fr |
en16931 |
peppol-bis |
peppol, romania-ro-cius, netherlands-nlcius |
peppol |
fatturapa |
ordinaria |
ordinaria |
facturae |
ordinaria |
ordinaria |
eslog |
eracun |
eracun |
extended-ctc-fr is the AFNOR XP Z12-012 France CTC overlay and exists on facturx only — ZUGFeRD has no branded counterpart to map it onto. The Peppol CIUS profiles are country overlays on the same UBL document: romania-ro-cius for Romania RO_CIUS, netherlands-nlcius for NLCIUS. See Slovenia e-SLOG for eracun.
Standard and output combinations
PDF output comes in two kinds. ZUGFeRD / Factur-X produce a hybrid PDF/A-3 with the legal XML embedded inside it. The XML-only standards have no hybrid form, so a PDF request returns a visualization PDF — a human-readable rendering of the same validated invoice, with no embedded XML (the legal artifact stays the XML; request it with output: "xml"). A visualization PDF requires a template or pdfTemplateId. The response’s x-pdf-kind header tells you which you received.
| Standard | XML output | PDF output | XML syntax |
|---|---|---|---|
xrechnung |
UBL 2.1 or CII D16B | Visualization PDF (needs template) |
CII (default) or UBL |
zugferd |
CII D22B | Hybrid PDF/A-3 with embedded CII XML | CII (D22B, ZUGFeRD 2.x) |
facturx |
CII D22B | Hybrid PDF/A-3 with embedded CII XML | CII (D22B, Factur-X 1.09.2) |
peppol-bis |
UBL 2.1 | Visualization PDF (needs template) |
UBL |
fatturapa |
FPR12 (Italy FatturaPA ordinaria XML) | Visualization PDF (needs template) |
Authority XSD graph — not EN 16931 UBL/CII |
facturae |
Facturae 3.2.2 (Spain ordinaria XML) | Visualization PDF (needs template) |
Authority XSD graph — not EN 16931 UBL/CII |
eslog |
e-SLOG 2.0 (Slovenia eracun XML) | Visualization PDF (needs template) |
Authority XSD graph, not EN 16931 UBL/CII |
Invoice object
Each field below opens with the EN 16931 business term it
carries, so you can search this page for a term number directly: BT-31, BG-23.
A BT is a single business term and a BG a group of them. Where a term differs
by party, both numbers are given, because the Party and Address objects are
shared between seller and buyer.
A few fields carry no term, and say so rather than being given a number that looks
official: the FatturaPA, Facturae and e-SLOG namespaces are national extensions,
and franceCtc is a Beliq switch. A term that does not appear anywhere on this
page has no field yet.
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
number |
string | required | 1–200 chars | BT-1. Invoice / credit-note number |
issueDate |
string | required | YYYY-MM-DD |
BT-2. Issue date |
dueDate |
string | optional | YYYY-MM-DD |
BT-9. Payment due date |
currencyCode |
string | required | 3 chars (ISO 4217) | BT-5. Currency code, e.g. EUR |
taxCurrencyCode |
string | optional | 3 chars (ISO 4217), not equal to currencyCode |
BT-6. VAT accounting currency, when you account VAT in a currency other than the invoice’s. A Romanian invoice in any currency but RON needs RON here (BR-RO-030). Send it together with taxTotalInAccountingCurrency; either one alone, or a value equal to currencyCode, is a 400. Emitted on UBL and CII outputs except Factur-X MINIMUM, which has no slot for it; fatturapa, facturae and eslog ignore it. |
taxTotalInAccountingCurrency |
number | optional | Required with taxCurrencyCode |
BT-111. Total VAT amount in the taxCurrencyCode currency. Beliq does not convert: send the figure your accounting uses. Emitted as a second cac:TaxTotal on UBL and a second ram:TaxTotalAmount on CII. |
documentType |
string | optional | "invoice" (default) or "creditnote" |
BT-3. Discriminates between an Invoice and a CreditNote. Supported when standard accepts CreditNote payloads: peppol-bis, facturx, xrechnung, zugferd, and eslog (e-SLOG emits document type code 381 in S_BGM). fatturapa and facturae accept invoices only — use documentType: "invoice" or omit the field. See DOCUMENT_TYPE_STANDARD_MISMATCH, the format overview, and Peppol Credit notes. |
precedingInvoiceReference |
object | strongly recommended on every CreditNote — see notes | id: 1–200 chars (the original invoice’s number); issueDate (optional): YYYY-MM-DD |
BG-3, with id as BT-25 and issueDate as BT-26. Reference to the original invoice this credit note corrects. Emitted as UBL cac:BillingReference / cac:InvoiceDocumentReference on UBL outputs (Peppol BIS Billing 3.0, XRechnung-UBL) or CII ram:InvoiceReferencedDocument on CII outputs (XRechnung-CII, ZUGFeRD, Factur-X). The UBL CreditNote builder fails closed without id; the CII CreditNote builder fails closed if the block is supplied without an id. EN 16931 BR-55 requires the link on every credit note, so verify: true (the default) will reject CreditNote output that omits it on every CreditNote-capable standard. |
buyerReference |
string | optional | Max 200 chars | BT-10. Buyer’s reference (required for XRechnung B2G) |
orderReference |
string | optional | Max 200 chars | BT-13. Purchase order reference |
note |
string | optional | Max 5000 chars | BT-22. Free-text note |
seller |
Party | required | BG-4. Seller/supplier details. For standard: "peppol-bis", must include either peppol or a vatId + supported address.countryCode so Beliq can derive the Peppol electronic-address. standard: "xrechnung" takes any of the three: peppol, email, or vatId + country. Both reject a party that resolves to none of them, with 400 INVALID_REQUEST naming the party and the fields. |
|
buyer |
Party | required | BG-7. Buyer/customer details. Same electronic-address requirement as seller. |
|
lines |
InvoiceLine[] | required | Min 1 item | BG-25. Invoice line items |
taxSummary |
TaxSummary[] | optional in the schema, required in practice | One entry per vatCategoryCode / vatRate pair used on the lines |
BG-23. VAT summary per category. The request schema accepts its absence, but EN 16931 does not: BR-CO-18 requires at least one VAT breakdown group, so with verify at its default of true an invoice without it is rejected 422 INVALID_INVOICE on every EN 16931–based standard. Omit it only together with verify: false, which returns an unverified document. |
delivery |
Delivery | optional | BG-13. Delivery information: who received the goods or services, where, and when. delivery.date is the actual delivery date, BT-72. |
|
paymentMeans |
PaymentMeans | optional | BG-16. Payment method details | |
paymentTerms |
string | optional | Max 500 chars | BT-20. Payment terms description |
totalNetAmount |
number | required | BT-106 and BT-109. Total excluding VAT. Beliq writes the same value to both, because it emits no document-level allowances or charges today. | |
totalTaxAmount |
number | required | BT-110. Total VAT amount | |
totalGrossAmount |
number | required | BT-112 and BT-115. Total including VAT. Beliq writes the same value to both, because it emits no prepaid or rounding amount today. | |
franceCtc |
boolean | optional | Opt-in for the French B2B reform CTC overlay on CII (Factur-X). Ignored for fatturapa. |
|
businessProcessId |
string | optional | S8, B8, or M8 |
BT-23. Flux 2 BusinessProcess code; only used when franceCtc is true. |
italy |
object | optional | Italy FatturaPA routing and document defaults when standard is "fatturapa". See Italy (FatturaPA) fields. |
|
spain |
object | optional | Spain Facturae routing and document defaults when standard is "facturae". See Spain (Facturae) fields. |
|
slovenia |
object | optional | Slovenia e-SLOG namespace when standard is "eslog". Intentionally empty today; reserved for future Slovenia-specific fields. |
Italy (FatturaPA) fields
Use the optional invoice.italy object with standard: "fatturapa" and profile: "ordinaria" (or omit profile — it defaults to ordinaria). Fields are forwarded to the engine and should follow the official formato FatturaPA documentation.
| Field | Type | Description |
|---|---|---|
codiceDestinatario |
string | SDI routing code (typically 7 characters; use 0000000 for PEC-based routing per your process). |
regimeFiscale |
string | Seller fiscal regime code (e.g. RF01, RF19). |
progressivoInvio |
string | Transmission progressive id (e.g. 00001). |
idTrasmittente |
object | Optional { "country": "IT", "id": "..." } VAT override; defaults from seller vatId when omitted. |
tipoDocumento |
string | Document type code (e.g. TD01). |
condizioniPagamento |
string | Payment terms code (TP01 / TP02). |
modalitaPagamento |
string | Payment means code (e.g. MP01, MP05). |
esigibilitaIVA |
string | VAT chargeability (e.g. I). |
causale |
string[] | Optional Causale lines on the Italian document. |
For Italian addresses, use seller.address.region / buyer.address.region (or province) for the Provincia code when present in your data (2–3 characters).
Spain (Facturae) fields
Use the optional invoice.spain object with standard: "facturae" and profile: "ordinaria" (or omit profile — it defaults to ordinaria). All fields are optional with MINECO-aligned defaults; fields are forwarded to the engine and should follow the official Facturae format documentation.
| Field | Type | Description |
|---|---|---|
modality |
string | Batch mode: I single invoice (default) or L list. |
invoiceIssuerType |
string | Issuer perspective: EM emitter (default), RE receiver, TE third-party. |
invoiceDocumentType |
string | Document type code, e.g. FC complete (default), FA simplified, AF self-billed. |
invoiceClass |
string | Invoice class code, e.g. OO original (default). |
taxTypeCode |
string | Tax type code, e.g. 01 IVA (default), 02 IPSI, 03 IGIC. |
languageName |
string | ISO 639-1 language code, e.g. es (default), en, ca, eu, gl. |
batchIdentifier |
string | Batch identifier; defaults to BELIQ-{invoice.number}. |
seller / buyer |
object | Optional per-party overrides: { "personTypeCode": "J" | "F", "residenceTypeCode": "R" | "U" | "E" }. Auto-derived from the party VAT and address country when omitted. |
Provide Spanish-resident party vatId as a NIF/CIF (9 characters, optional ES prefix). PersonTypeCode (J legal / F natural) and ResidenceTypeCode (R Spain / U EU·EEA / E third country) are auto-derived; resident parties emit an AddressInSpain block, non-residents an OverseasAddress.
Party object
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
name |
string | required | 1–200 chars | BT-27 on the seller, BT-44 on the buyer. Legal name |
vatId |
string | optional | 2-letter country prefix + 2–18 alphanumeric chars | BT-31 on the seller, BT-48 on the buyer. VAT identification number, e.g. DE123456789 |
taxId |
string | optional | Max 30 chars | BT-32. Tax registration number, seller only. The registration a seller holds with a tax authority that is not a VAT number. Emitted on every standard: ram:SpecifiedTaxRegistration/ram:ID[@schemeID="FC"] on CII, cac:PartyTaxScheme with cac:TaxScheme/cbc:ID of FC on UBL. |
registrationId |
string | optional | Max 50 chars | BT-30 on the seller, BT-47 on the buyer. The company’s entry in an official business register (a German HRB number, a Danish CVR, a Swedish organisationsnummer), not the VAT number, which is vatId. Emitted on every standard: ram:SpecifiedLegalOrganization/ram:ID on CII, cac:PartyLegalEntity/cbc:CompanyID on UBL. Send it whenever vatCategoryCode is O: BR-O-02 forbids every VAT identifier there, and BR-CO-26 still requires the seller to be identifiable. |
email |
string | optional | Max 254 chars, valid email | BT-43 on the seller, BT-58 on the buyer. Email address (required for XRechnung) |
phone |
string | optional | Max 30 chars | BT-42 on the seller, BT-57 on the buyer. Phone number |
address |
Address | required | BG-5 on the seller, BG-8 on the buyer. Postal address | |
contactName |
string | optional | Max 200 chars | BT-41 on the seller, BT-56 on the buyer. Contact person name |
peppol |
PeppolEndpoint | optional | BT-34 on the seller, BT-49 on the buyer. Party electronic-address. Honoured on every standard. Required for standard: "peppol-bis" and "xrechnung" if Beliq cannot derive one from email or vatId + country. |
Peppol endpoint object
For Peppol BIS Billing 3.0, every party needs an electronic-address that uniquely identifies it on the Peppol Network.
XRechnung needs one too (BT-34 and BT-49, enforced by rules KoSIT bundles into the XRechnung Schematron), and it accepts a plain email as well: Beliq emits that as scheme EM. A peppol block is the stronger choice when the invoice will travel over Peppol, because a participant identifier is the form the network can resolve.
The block is read on every standard, not only peppol-bis. Beliq resolves each party’s address in this order, and the standard you pick changes only what happens when none of the rungs resolve:
| Standard | 1. peppol |
2. email (EAS EM) |
3. vatId + country |
Nothing resolves |
|---|---|---|---|---|
peppol-bis |
yes | no — a mailbox is not resolvable on the network | yes | 400 |
xrechnung |
yes | yes | yes | 400 |
zugferd, facturx |
yes | yes | no | element omitted |
A schemeId Beliq does not recognise is rejected on every standard, so a typo cannot ship as an unroutable address. That check fires only on a peppol block you send.
| Field | Type | Required | Description |
|---|---|---|---|
schemeId |
string | required | BT-34-1 on the seller, BT-49-1 on the buyer. Peppol EAS code (e.g. 9930 for German VAT, 9957 for French VAT, 0184 for Danish DK:CVR). See the official EAS code list. |
id |
string | required | BT-34 on the seller, BT-49 on the buyer. The actual identifier under that scheme (often the VAT number, sometimes a national company-registry number). |
Address object
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
street |
string | optional | Max 500 chars | BT-35 on the seller, BT-50 on the buyer. Street and house number |
additionalStreet |
string | optional | Max 500 chars | BT-36 on the seller, BT-51 on the buyer. Additional address line |
city |
string | required | Max 200 chars | BT-37 on the seller, BT-52 on the buyer. City |
postalCode |
string | required | Max 20 chars | BT-38 on the seller, BT-53 on the buyer. Postal/ZIP code |
countryCode |
string | required | 2 chars (ISO 3166-1 alpha-2) | BT-40 on the seller, BT-55 on the buyer. Country code, e.g. DE |
countrySubentity |
string | optional | Max 10 chars | BT-39 on the seller, BT-54 on the buyer. Country subdivision: the state, province or Bundesland the address sits in. This is the field EN 16931 defines for a subdivision, so send it rather than state. Both reach the same element and countrySubentity wins where both are sent. |
state |
string | optional | Max 200 chars | State or province as free text. Emitted as the country subdivision (BT-39 / BT-54 / BT-79) when countrySubentity is absent: cbc:CountrySubentity on UBL, ram:CountrySubDivisionName on CII. Prefer countrySubentity, which is the field EN 16931 defines and the one Romania’s BR-RO-110 / BR-RO-111 check. Factur-X MINIMUM restricts the address to the country code and carries neither. |
region |
string | optional | 2–3 chars | Italian provincia / region code; used for FatturaPA Provincia. |
province |
string | optional | 2–3 chars | Alias for region when mapping Italian addresses. |
Invoice line object
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
description |
string | required | 1–1000 chars | BT-153. Item description |
quantity |
number | required | > 0 | BT-129. Quantity |
unitCode |
string | required | 1–10 chars | BT-130. UN/ECE Recommendation 20 unit code (e.g. HUR for hours, C62 for units) |
unitPrice |
number | required | ≥ 0 | BT-146. Price per unit. EN 16931 calls this the item net price, so it is the price after any discount. To show the discount, send grossPrice and priceDiscount as well. |
lineTotal |
number | required | BT-131. Line total: quantity × unitPrice, or quantity × unitPrice ÷ priceBaseQuantity when you send one (PEPPOL-EN16931-R120). Beliq does not compute it for you. |
|
vatRate |
number | required | 0–100 | BT-152. VAT rate as percentage. Dropped from the output when vatCategoryCode is O: BR-O-05 forbids a rate on a line that is not subject to VAT. Send 0 there; the field stays required. |
vatCategoryCode |
string | required | 1–10 chars | BT-151. VAT category code (e.g. S for standard rate) |
itemId |
string | optional | Max 50 chars | BT-155. Seller’s item identifier: cac:Item/cac:SellersItemIdentification/cbc:ID on UBL, ram:SpecifiedTradeProduct/ram:SellerAssignedID on CII. On Factur-X and ZUGFeRD it needs the en16931 profile or higher: the BASIC profile schema stops at the item name, so the value is dropped below that. |
buyerItemId |
string | optional | Max 50 chars | BT-156. Buyer’s own article number for the line: cac:Item/cac:BuyersItemIdentification/cbc:ID on UBL, ram:SpecifiedTradeProduct/ram:BuyerAssignedID on CII. Same Factur-X profile floor as itemId. |
grossPrice |
number | optional | ≥ 0 | BT-148. Item gross price: the price per unit before the price discount. cac:Price/cac:AllowanceCharge/cbc:BaseAmount on UBL, ram:GrossPriceProductTradePrice/ram:ChargeAmount on CII. unitPrice must equal grossPrice minus priceDiscount to the cent (PEPPOL-EN16931-R046), or the request is a 400. Sent without a discount it must equal unitPrice, and UBL writes a discount of 0.00, because its price allowance has no optional amount. |
priceDiscount |
number | optional | ≥ 0, needs grossPrice |
BT-147. Item price discount: what is taken off grossPrice to reach unitPrice, per unit. cac:Price/cac:AllowanceCharge/cbc:Amount on UBL, ram:AppliedTradeAllowanceCharge/ram:ActualAmount inside the CII gross price. A discount without a grossPrice is a 400, because there is nothing to take it off. For a discount on the whole line rather than on the unit price, EN 16931 has line allowances (BG-27), and Beliq has no field for them today. |
priceBaseQuantity |
number | optional | > 0 | BT-149. The number of units unitPrice and grossPrice are stated for, for example 100 for a price per hundred. cac:Price/cbc:BaseQuantity on UBL; on CII, ram:BasisQuantity on the net price, and on the gross price when you send one. Its unit, BT-150, is not a separate field: Beliq writes the line’s unitCode, because PEPPOL-EN16931-R130 requires the two to be equal. Omitted, the price is per one unit. |
standardItemId |
object | optional | id: required, 1-200 chars; schemeId: required, 1-10 chars |
BT-157, with schemeId as BT-157-1. An identifier for the item under a registered scheme, such as a GTIN with schemeId 0160. cac:Item/cac:StandardItemIdentification/cbc:ID on UBL, ram:SpecifiedTradeProduct/ram:GlobalID on CII. schemeId comes from the ISO 6523 ICD code list (BR-CL-21), which validation checks. |
classifications |
object[] | optional | Max 20. Each: code: required, 1-200 chars; listId: required, 1-10 chars; listVersionId (optional): 1-50 chars |
BT-158, with listId as BT-158-1 and listVersionId as BT-158-2. Item classifications, such as a customs tariff number with listId HS. cac:Item/cac:CommodityClassification/cbc:ItemClassificationCode on UBL, ram:DesignatedProductClassification/ram:ClassCode on CII. listId comes from the UNTDID 7143 code list (BR-CL-13), which validation checks. |
originCountryCode |
string | optional | 2 chars (ISO 3166-1 alpha-2) | BT-159. Country the item comes from. cac:Item/cac:OriginCountry/cbc:IdentificationCode on UBL, ram:OriginTradeCountry/ram:ID on CII. |
attributes |
object[] | optional | Max 50. Each: name: required, 1-200 chars; value: required, 1-1000 chars |
BG-32, with name as BT-160 and value as BT-161. Item attributes, such as a colour or a size. cac:Item/cac:AdditionalItemProperty on UBL, ram:ApplicableProductCharacteristic on CII. |
The seven fields from grossPrice to attributes reach UBL and CII output only; the
FatturaPA, Facturae and e-SLOG builders do not read them. On Factur-X and ZUGFeRD,
grossPrice, priceDiscount, priceBaseQuantity and standardItemId reach every
profile that has lines, from basic up (minimum and basicwl carry no lines).
classifications, originCountryCode and attributes need the en16931 profile or
higher: the basic schema stops at the item’s identifier and name, so they are dropped
below that.
Tax summary object
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
vatCategoryCode |
string | required | 1–10 chars | BT-118. VAT category code |
vatRate |
number | required | 0–100 | BT-119. VAT rate as percentage |
taxableAmount |
number | required | BT-116. Taxable amount for this category | |
taxAmount |
number | required | BT-117. Tax amount for this category | |
exemptionReasonText |
string | optional | Max 1000 chars | BT-120. Why this category carries no VAT, in words, for example Reverse charge. EN 16931 requires a reason on every category other than standard rate: BR-AE-10, BR-E-10, BR-G-10, BR-IC-10 and BR-O-10 each demand this field or exemptionReasonCode, so with verify at its default of true an AE, E, G, K or O breakdown carrying neither is rejected 422 INVALID_INVOICE. |
exemptionReasonCode |
string | optional | Max 100 chars | BT-121. The same reason as a code from the VATEX code list, for example VATEX-EU-AE. Either this or exemptionReasonText satisfies the rules above, and sending both is allowed. |
Delivery object
The deliver-to party, place and date. Only the EN 16931 standards carry it (peppol-bis,
xrechnung, facturx, zugferd); FatturaPA, Facturae and e-SLOG output leave it out. On Factur-X and ZUGFeRD the minimum profile declares no
delivery elements at all, so the whole object is dropped there.
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
name |
string | optional | Max 200 chars | BT-70. Deliver-to party name: cac:DeliveryParty/cac:PartyName/cbc:Name on UBL, ram:ShipToTradeParty/ram:Name on CII. |
locationId |
object | optional | id: required, max 200 chars; schemeId (optional): max 10 chars |
BT-71, with schemeId as BT-71-1. Identifier of the place the goods or services went to, such as a GLN. UBL writes it to cac:DeliveryLocation/cbc:ID with any scheme. On CII a scheme from the ISO 6523 ICD list (four digits starting with 0, e.g. 0088 for GLN) goes to ram:ShipToTradeParty/ram:GlobalID; any other scheme, or none, sends the identifier to the unqualified ram:ID without it, because BR-CL-26 rejects a non-ICD scheme on GlobalID. |
date |
string | optional | YYYY-MM-DD |
BT-72. Actual delivery date: cbc:ActualDeliveryDate on UBL, ram:ActualDeliverySupplyChainEvent on CII. BR-IC-11 requires it on an intra-community supply (vatCategoryCode K). EN 16931 would accept an invoicing period instead, but Beliq has no field for one, so with verify at its default of true a K invoice without date is rejected 422 INVALID_INVOICE. |
address |
DeliveryAddress | optional | BG-15. Deliver-to address, with BT-75 to BT-80 below. BR-IC-12 requires at least its country on an intra-community supply. |
Delivery address object
Its own shape rather than the Address object: only countryCode is
required, because EN 16931 requires only the country in a deliver-to address, while the
seller and buyer addresses must carry a city and postal code. It has no state, region
or province; send a subdivision as countrySubentity.
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
street |
string | optional | Max 500 chars | BT-75. Deliver-to street and house number |
additionalStreet |
string | optional | Max 500 chars | BT-76. Additional deliver-to address line |
city |
string | optional | Max 200 chars | BT-77. Deliver-to city |
postalCode |
string | optional | Max 20 chars | BT-78. Deliver-to postal/ZIP code |
countrySubentity |
string | optional | Max 10 chars | BT-79. Deliver-to country subdivision: the state, province or Bundesland |
countryCode |
string | required | 2 chars (ISO 3166-1 alpha-2) | BT-80. Deliver-to country code, e.g. FR |
Payment means object
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
typeCode |
string | required | 1–10 chars | BT-81. UNTDID 4461 payment means code (e.g. 30 for credit transfer, 58 for SEPA) |
iban |
string | optional | Max 34 chars | BT-84. IBAN |
bic |
string | optional | Max 11 chars | BT-86. BIC/SWIFT code |
bankName |
string | optional | Max 200 chars | Bank name. Accepted but never emitted: EN 16931 declares no bank-name business term, and the nearest UBL slot is discouraged by UBL-CR-429, so emitting it would add a warning to every document. |
paymentReference |
string | optional | Max 200 chars | BT-83. Payment reference / remittance information |
information |
string | optional | Max 200 chars | BT-82. Payment means text, e.g. SEPA credit transfer. UBL has no element for it and writes it as the name attribute on cbc:PaymentMeansCode; CII writes ram:Information. On Factur-X and ZUGFeRD it needs the en16931 profile or higher: the basic and basicwl schemas declare no Information, so the value is dropped below that. |
mandateReference |
string | optional | Max 200 chars | BT-89. SEPA direct debit mandate reference, part of BG-19: cac:PaymentMandate/cbc:ID on UBL, ram:SpecifiedTradePaymentTerms/ram:DirectDebitMandateID on CII. |
creditorId |
string | optional | Max 200 chars | BT-90. SEPA creditor identifier of the seller, part of BG-19. Written on the seller, not inside the payment means: cac:PartyIdentification/cbc:ID with schemeID="SEPA" on the UBL seller party, ram:CreditorReferenceID in the CII header settlement. |
debitedAccountId |
string | optional | Max 34 chars, an IBAN | BT-91. The buyer’s account the direct debit is taken from, part of BG-19: cac:PaymentMandate/cac:PayerFinancialAccount/cbc:ID on UBL, ram:PayerPartyDebtorFinancialAccount/ram:IBANID on CII. Send an IBAN. The request schema checks only the length, but CII has an IBAN slot and nothing else for this term. |
information, mandateReference, creditorId and debitedAccountId reach UBL and CII
output only; the FatturaPA, Facturae and e-SLOG builders do not read them.
Response
Because the body is usually raw bytes, generate reports the validation verdict and the ruleset seal (x-validation, x-ruleset-sha256, x-ruleset-artifacts) in headers. See the Response headers reference.
XML output (output: "xml")
When output is "xml", the response body is XML. Response headers may include x-schematron-version for EN 16931–based formats; FatturaPA responses are validated against the authority XSD graph only (see validation artifacts). The X-Version-Block response header (compact JSON) carries the full set of artifact versions in play — the same fields as the POST /v1/validate body, minus the ruleset-selection fields (rulesetChannel, rulesetFellBack), since generate always uses the current bundled artifacts and does not support Beliq-Ruleset pinning.
<?xml version="1.0" encoding="UTF-8"?>
<rsm:CrossIndustryInvoice xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" ...>
...
</rsm:CrossIndustryInvoice>PDF output (output: "pdf")
When output is "pdf", the response body is a PDF. The x-pdf-kind response header tells you which kind you received:
HTTP/1.1 200 OK
Content-Type: application/pdf
x-pdf-kind: hybrid
x-schematron-version: 1.3.16x-pdf-kind: hybrid(ZUGFeRD / Factur-X) — a PDF/A-3 file with the legal invoice XML embedded inside it for system processing. This is the compliance artifact.x-pdf-kind: visualization(XML-only standards) — a human-readable rendering of the invoice with no embedded XML. It is a convenience view, not a compliance artifact; fetch the legal document separately withoutput: "xml". Returned only when you supply atemplateorpdfTemplateId.
Styling the PDF
By default a hybrid PDF carries a blank visible page (the XML is what matters). To render a styled, human-readable invoice page, opt in with one of:
template: "standard"— Beliq’s built-in invoice layout. This is also what the free generator uses. For XML-only standards it is required to produce a visualization PDF.pdfTemplateId: "k3d-9mp"— one of your own PDF templates, designed visually in the dashboard (logo, colours, fonts, layout). The value is the template’s short ref, shown next to it in the dashboard. Org-scoped, so the request must be authenticated; takes precedence overtemplate. See the PDF template errors for the reference failures.
In every case the invoice data (parties, lines, totals) is bound by Beliq from the invoice you sent — the template only controls presentation, so the visible page can never disagree with the embedded XML.
curl -X POST https://api.beliq.eu/v1/generate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"standard": "facturx",
"output": "pdf",
"template": "standard",
"invoice": {
"number": "FA-2026-0123",
"issueDate": "2026-04-13",
"dueDate": "2026-05-13",
"currencyCode": "EUR",
"seller": {
"name": "Exemple SARL",
"vatId": "FR12345678901",
"address": { "street": "12 Rue de la Paix", "city": "Paris", "postalCode": "75002", "countryCode": "FR" }
},
"buyer": {
"name": "Client SAS",
"vatId": "FR98765432109",
"address": { "street": "8 Avenue des Champs-Élysées", "city": "Paris", "postalCode": "75008", "countryCode": "FR" }
},
"lines": [
{
"description": "Prestation de conseil — Avril 2026",
"quantity": 5,
"unitCode": "DAY",
"unitPrice": 800.00,
"lineTotal": 4000.00,
"vatRate": 20,
"vatCategoryCode": "S"
}
],
"taxSummary": [
{ "vatCategoryCode": "S", "vatRate": 20, "taxableAmount": 4000.00, "taxAmount": 800.00 }
],
"totalNetAmount": 4000.00,
"totalTaxAmount": 800.00,
"totalGrossAmount": 4800.00
}
}' \
--output invoice.pdfimport { writeFile } from 'node:fs/promises';
import { Beliq } from '@beliq/sdk';
const beliq = new Beliq({ apiKey: process.env.BELIQ_API_KEY! });
const generated = await beliq.generate({
standard: 'facturx',
output: 'pdf',
template: 'standard',
invoice: {
number: 'FA-2026-0123',
issueDate: '2026-04-13',
dueDate: '2026-05-13',
currencyCode: 'EUR',
seller: {
name: 'Exemple SARL',
vatId: 'FR12345678901',
address: { street: '12 Rue de la Paix', city: 'Paris', postalCode: '75002', countryCode: 'FR' },
},
buyer: {
name: 'Client SAS',
vatId: 'FR98765432109',
address: {
street: '8 Avenue des Champs-Élysées',
city: 'Paris',
postalCode: '75008',
countryCode: 'FR',
},
},
lines: [
{
description: 'Prestation de conseil — Avril 2026',
quantity: 5,
unitCode: 'DAY',
unitPrice: 800.00,
lineTotal: 4000.00,
vatRate: 20,
vatCategoryCode: 'S',
},
],
taxSummary: [{ vatCategoryCode: 'S', vatRate: 20, taxableAmount: 4000.00, taxAmount: 800.00 }],
totalNetAmount: 4000.00,
totalTaxAmount: 800.00,
totalGrossAmount: 4800.00,
},
});
await writeFile('invoice.pdf', generated.bytes);import os
from pathlib import Path
from beliq import Beliq
beliq = Beliq(api_key=os.environ["BELIQ_API_KEY"])
generated = beliq.generate(
standard="facturx",
output="pdf",
template="standard",
invoice={
"number": "FA-2026-0123",
"issueDate": "2026-04-13",
"dueDate": "2026-05-13",
"currencyCode": "EUR",
"seller": {
"name": "Exemple SARL",
"vatId": "FR12345678901",
"address": {
"street": "12 Rue de la Paix",
"city": "Paris",
"postalCode": "75002",
"countryCode": "FR",
},
},
"buyer": {
"name": "Client SAS",
"vatId": "FR98765432109",
"address": {
"street": "8 Avenue des Champs-Élysées",
"city": "Paris",
"postalCode": "75008",
"countryCode": "FR",
},
},
"lines": [
{
"description": "Prestation de conseil — Avril 2026",
"quantity": 5,
"unitCode": "DAY",
"unitPrice": 800.00,
"lineTotal": 4000.00,
"vatRate": 20,
"vatCategoryCode": "S",
},
],
"taxSummary": [{"vatCategoryCode": "S", "vatRate": 20, "taxableAmount": 4000.00, "taxAmount": 800.00}],
"totalNetAmount": 4000.00,
"totalTaxAmount": 800.00,
"totalGrossAmount": 4800.00,
},
)
Path("invoice.pdf").write_bytes(generated.content)JSON envelope (Accept: application/json)
Ask for the envelope and you get the document and its verdict in one response instead of bytes plus headers. Send Accept: application/json, and Beliq answers with a JSON body carrying the document base64-encoded in data.output alongside the full validationResult — including rulesetSha256 and rulesetArtifacts, the values the hash verification procedure recomputes.
Which representation you get is decided by the Accept header alone: the envelope is returned when application/json ranks above the document’s own media type (application/xml or application/pdf). Send no Accept header, or one that prefers the document type, and the body is the raw document with the same verdict in the response headers.
The data.format field mirrors the invoice syntax: "cii" for CII, "ubl" for Peppol/XRechnung UBL, or "fatturapa" for Italy FPR12.
curl -X POST https://api.beliq.eu/v1/generate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"standard": "xrechnung",
"profile": "xrechnung",
"output": "xml",
"invoice": {
"number": "INV-2026-001",
"issueDate": "2026-04-13",
"dueDate": "2026-05-13",
"currencyCode": "EUR",
"buyerReference": "04011000-12345-03",
"seller": {
"name": "Acme GmbH",
"vatId": "DE123456789",
"email": "billing@acme.example",
"contactName": "Anna Beispiel",
"phone": "+49 30 1234567",
"address": { "street": "Musterstraße 1", "city": "Berlin", "postalCode": "10115", "countryCode": "DE" }
},
"buyer": {
"name": "Bundesministerium für Beispiele",
"vatId": "DE987654321",
"address": { "street": "Beispielweg 42", "city": "Bonn", "postalCode": "53113", "countryCode": "DE" }
},
"lines": [
{
"description": "IT consulting — April 2026",
"quantity": 20,
"unitCode": "HUR",
"unitPrice": 120.00,
"lineTotal": 2400.00,
"vatRate": 19,
"vatCategoryCode": "S"
}
],
"taxSummary": [
{ "vatCategoryCode": "S", "vatRate": 19, "taxableAmount": 2400.00, "taxAmount": 456.00 }
],
"paymentMeans": {
"typeCode": "58",
"iban": "DE89370400440532013000"
},
"totalNetAmount": 2400.00,
"totalTaxAmount": 456.00,
"totalGrossAmount": 2856.00
}
}'import { Beliq } from '@beliq/sdk';
const beliq = new Beliq({ apiKey: process.env.BELIQ_API_KEY! });
// `seal: true` sends Accept: application/json and unpacks the envelope:
// the document bytes, their sha256, and the full validation verdict.
const generated = await beliq.generate({
standard: 'xrechnung',
profile: 'xrechnung',
output: 'xml',
invoice: {
number: 'INV-2026-001',
issueDate: '2026-04-13',
dueDate: '2026-05-13',
currencyCode: 'EUR',
buyerReference: '04011000-12345-03',
seller: {
name: 'Acme GmbH',
vatId: 'DE123456789',
email: 'billing@acme.example',
contactName: 'Anna Beispiel',
phone: '+49 30 1234567',
address: { street: 'Musterstraße 1', city: 'Berlin', postalCode: '10115', countryCode: 'DE' },
},
buyer: {
name: 'Bundesministerium für Beispiele',
vatId: 'DE987654321',
address: { street: 'Beispielweg 42', city: 'Bonn', postalCode: '53113', countryCode: 'DE' },
},
lines: [
{
description: 'IT consulting — April 2026',
quantity: 20,
unitCode: 'HUR',
unitPrice: 120.00,
lineTotal: 2400.00,
vatRate: 19,
vatCategoryCode: 'S',
},
],
taxSummary: [{ vatCategoryCode: 'S', vatRate: 19, taxableAmount: 2400.00, taxAmount: 456.00 }],
paymentMeans: { typeCode: '58', iban: 'DE89370400440532013000' },
totalNetAmount: 2400.00,
totalTaxAmount: 456.00,
totalGrossAmount: 2856.00,
},
seal: true,
});
console.log(generated.sha256, generated.validationResult?.valid);
console.log(generated.meta.rulesetSha256, generated.meta.rulesetArtifacts);import os
from beliq import Beliq
beliq = Beliq(api_key=os.environ["BELIQ_API_KEY"])
# `seal=True` sends Accept: application/json and unpacks the envelope:
# the document bytes, their sha256, and the full validation verdict.
generated = beliq.generate(
standard="xrechnung",
profile="xrechnung",
output="xml",
invoice={
"number": "INV-2026-001",
"issueDate": "2026-04-13",
"dueDate": "2026-05-13",
"currencyCode": "EUR",
"buyerReference": "04011000-12345-03",
"seller": {
"name": "Acme GmbH",
"vatId": "DE123456789",
"email": "billing@acme.example",
"contactName": "Anna Beispiel",
"phone": "+49 30 1234567",
"address": {
"street": "Musterstraße 1",
"city": "Berlin",
"postalCode": "10115",
"countryCode": "DE",
},
},
"buyer": {
"name": "Bundesministerium für Beispiele",
"vatId": "DE987654321",
"address": {
"street": "Beispielweg 42",
"city": "Bonn",
"postalCode": "53113",
"countryCode": "DE",
},
},
"lines": [
{
"description": "IT consulting — April 2026",
"quantity": 20,
"unitCode": "HUR",
"unitPrice": 120.00,
"lineTotal": 2400.00,
"vatRate": 19,
"vatCategoryCode": "S",
},
],
"taxSummary": [{"vatCategoryCode": "S", "vatRate": 19, "taxableAmount": 2400.00, "taxAmount": 456.00}],
"paymentMeans": {"typeCode": "58", "iban": "DE89370400440532013000"},
"totalNetAmount": 2400.00,
"totalTaxAmount": 456.00,
"totalGrossAmount": 2856.00,
},
seal=True,
)
print(generated.sha256, generated.validation_result.valid)
print(generated.meta.ruleset_sha256, generated.meta.ruleset_artifacts){
"success": true,
"data": {
"invoiceId": "",
"format": "cii",
"standard": "xrechnung",
"profile": "xrechnung",
"output": "PD94bWwgdmVyc2lvbj0nMS4wJy4uLg==",
"validationResult": {
"valid": true,
"verified": true,
"format": "cii",
"schematronVersion": "1.3.16",
"ciusVersion": "XRechnung-2.6.0",
"rulesetSha256": "40e47719482fbd95264fc4c06cd644b37f466c254e1f207dadfae1727a82e85c",
"rulesetArtifacts": [
{ "key": "en16931_cii_schematron", "version": "1.3.16", "fileSha256": "0b234dea..." },
{ "key": "xrechnung_schematron", "version": "XRechnung-2.6.0", "fileSha256": "30e64d8b..." }
],
"errors": [],
"warnings": []
}
}
}Reading valid and verified
valid means verified as valid. Read it together with verified:
verified |
valid |
Meaning |
|---|---|---|
true |
true |
A ruleset ran and the document passed. |
true |
false |
A ruleset ran and the document failed. errors says why. |
false |
false |
No ruleset ran, because you sent verify: false. errors and warnings are empty because nothing looked, and there is no rulesetSha256 because no artifact executed. |
verified: false never means the document is bad. It means Beliq has no opinion, because you asked it not to form one.
If you gate a deployment on this response, gate on valid. It is false for both “we checked and it failed” and “we did not check”, so an unverified document stops your pipeline instead of shipping. If you want to treat those two cases differently, branch on verified first.
Error responses
| HTTP Status | Error Code | When |
|---|---|---|
| 400 | VALIDATION_ERROR |
Request body fails JSON schema validation (missing fields, wrong types, constraint violations) |
| 422 | INVALID_INVOICE |
Invoice data is structurally valid but fails validation (EN 16931 / CIUS Schematron for UBL/CII, or authority XSD for fatturapa) |
| 422 | PROFILE_STANDARD_MISMATCH |
The chosen profile is not allowed for the chosen standard (for example profile: "extended" with standard: "peppol-bis"). The error details includes standard, profile, and allowedProfiles. |
| 422 | DOCUMENT_TYPE_STANDARD_MISMATCH |
documentType: "creditnote" with a standard that does not accept CreditNote payloads (for example fatturapa). details: standard, documentType, creditNoteCapableStandards. |
| 400 | PDF_TEMPLATE_AUTH_REQUIRED |
pdfTemplateId was sent on an unauthenticated request (stored templates are org-scoped). Use your API key, or template: "standard". |
| 404 | PDF_TEMPLATE_NOT_FOUND |
The referenced pdfTemplateId does not exist in your organization. |
| 422 | PDF_TEMPLATE_INVALID |
The stored template definition could not be parsed. Re-save it in the dashboard designer. |
| 413 | VALIDATION_ERROR |
Request body is larger than this endpoint’s 1 MB size limit. The cap is enforced before the body is read, so nothing was validated and no quota unit is spent |
| 503 | ENGINE_UNAVAILABLE |
The validation engine is temporarily unavailable |
422 INVALID_INVOICE example
When business rule validation fails, the error includes the full validation result in details:
{
"success": false,
"error": {
"code": "INVALID_INVOICE",
"message": "Invoice validation failed with 2 errors",
"details": {
"validationResult": {
"valid": false,
"format": "cii",
"schematronVersion": "1.3.16",
"errors": [
{
"ruleId": "BR-DE-15",
"severity": "error",
"location": "/rsm:CrossIndustryInvoice/...",
"message": "An XRechnung invoice must contain the buyer reference (BT-10)."
}
],
"warnings": []
}
}
}
}Full example
curl -X POST https://api.beliq.eu/v1/generate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"standard": "xrechnung",
"profile": "xrechnung",
"output": "xml",
"invoice": {
"number": "INV-2026-001",
"issueDate": "2026-04-13",
"dueDate": "2026-05-13",
"currencyCode": "EUR",
"buyerReference": "04011000-12345-03",
"seller": {
"name": "Acme GmbH",
"vatId": "DE123456789",
"email": "billing@acme.example",
"contactName": "Anna Beispiel",
"phone": "+49 30 1234567",
"address": {
"street": "Musterstraße 1",
"city": "Berlin",
"postalCode": "10115",
"countryCode": "DE"
}
},
"buyer": {
"name": "Bundesministerium für Beispiele",
"vatId": "DE987654321",
"email": "rechnung@beispiel.example",
"address": {
"street": "Beispielweg 42",
"city": "Bonn",
"postalCode": "53113",
"countryCode": "DE"
}
},
"lines": [
{
"description": "IT consulting — April 2026",
"quantity": 20,
"unitCode": "HUR",
"unitPrice": 120.00,
"lineTotal": 2400.00,
"vatRate": 19,
"vatCategoryCode": "S"
}
],
"taxSummary": [
{ "vatCategoryCode": "S", "vatRate": 19, "taxableAmount": 2400.00, "taxAmount": 456.00 }
],
"paymentMeans": {
"typeCode": "58",
"iban": "DE89370400440532013000",
"bic": "COBADEFFXXX"
},
"paymentTerms": "Net 30 days",
"totalNetAmount": 2400.00,
"totalTaxAmount": 456.00,
"totalGrossAmount": 2856.00
}
}'import { Beliq } from '@beliq/sdk';
const beliq = new Beliq({ apiKey: process.env.BELIQ_API_KEY! });
const generated = await beliq.generate({
standard: 'xrechnung',
profile: 'xrechnung',
output: 'xml',
invoice: {
number: 'INV-2026-001',
issueDate: '2026-04-13',
dueDate: '2026-05-13',
currencyCode: 'EUR',
buyerReference: '04011000-12345-03',
seller: {
name: 'Acme GmbH',
vatId: 'DE123456789',
email: 'billing@acme.example',
contactName: 'Anna Beispiel',
phone: '+49 30 1234567',
address: { street: 'Musterstraße 1', city: 'Berlin', postalCode: '10115', countryCode: 'DE' },
},
buyer: {
name: 'Bundesministerium für Beispiele',
vatId: 'DE987654321',
email: 'rechnung@beispiel.example',
address: { street: 'Beispielweg 42', city: 'Bonn', postalCode: '53113', countryCode: 'DE' },
},
lines: [
{
description: 'IT consulting — April 2026',
quantity: 20,
unitCode: 'HUR',
unitPrice: 120.00,
lineTotal: 2400.00,
vatRate: 19,
vatCategoryCode: 'S',
},
],
taxSummary: [{ vatCategoryCode: 'S', vatRate: 19, taxableAmount: 2400.00, taxAmount: 456.00 }],
paymentMeans: { typeCode: '58', iban: 'DE89370400440532013000', bic: 'COBADEFFXXX' },
paymentTerms: 'Net 30 days',
totalNetAmount: 2400.00,
totalTaxAmount: 456.00,
totalGrossAmount: 2856.00,
},
});
// `xml` is the same document curl writes to stdout.
console.log(generated.xml);import os
from beliq import Beliq
beliq = Beliq(api_key=os.environ["BELIQ_API_KEY"])
generated = beliq.generate(
standard="xrechnung",
profile="xrechnung",
output="xml",
invoice={
"number": "INV-2026-001",
"issueDate": "2026-04-13",
"dueDate": "2026-05-13",
"currencyCode": "EUR",
"buyerReference": "04011000-12345-03",
"seller": {
"name": "Acme GmbH",
"vatId": "DE123456789",
"email": "billing@acme.example",
"contactName": "Anna Beispiel",
"phone": "+49 30 1234567",
"address": {
"street": "Musterstraße 1",
"city": "Berlin",
"postalCode": "10115",
"countryCode": "DE",
},
},
"buyer": {
"name": "Bundesministerium für Beispiele",
"vatId": "DE987654321",
"email": "rechnung@beispiel.example",
"address": {
"street": "Beispielweg 42",
"city": "Bonn",
"postalCode": "53113",
"countryCode": "DE",
},
},
"lines": [
{
"description": "IT consulting — April 2026",
"quantity": 20,
"unitCode": "HUR",
"unitPrice": 120.00,
"lineTotal": 2400.00,
"vatRate": 19,
"vatCategoryCode": "S",
},
],
"taxSummary": [{"vatCategoryCode": "S", "vatRate": 19, "taxableAmount": 2400.00, "taxAmount": 456.00}],
"paymentMeans": {"typeCode": "58", "iban": "DE89370400440532013000", "bic": "COBADEFFXXX"},
"paymentTerms": "Net 30 days",
"totalNetAmount": 2400.00,
"totalTaxAmount": 456.00,
"totalGrossAmount": 2856.00,
},
)
# `xml` is the same document curl writes to stdout.
print(generated.xml)Italy FatturaPA ordinaria (FPR12) example
Beliq can emit FatturaPA ordinaria XML (standard: "fatturapa", default profile ordinaria). FatturaPA is Schema-checked: validation runs against the Agenzia delle Entrate’s official XSD schema graph, and no machine-readable business rules are published for the format, so XSD structural validation is the highest check any client-side tool can run for it. The FatturaPA format reference covers what backs that verdict, and how verification works defines the tiers. Beliq does not submit to Italy’s SDI interchange: you remain responsible for signing, transmission, and channel operation with your provider.
curl -X POST https://api.beliq.eu/v1/generate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"standard": "fatturapa",
"profile": "ordinaria",
"output": "xml",
"invoice": {
"number": "123",
"issueDate": "2026-04-13",
"dueDate": "2026-05-13",
"currencyCode": "EUR",
"italy": { "codiceDestinatario": "ABC1234", "regimeFiscale": "RF19" },
"seller": {
"name": "Alpha SRL",
"vatId": "IT01234567890",
"address": {
"street": "Via Roma 1",
"city": "Sassari",
"postalCode": "07100",
"countryCode": "IT",
"region": "SS"
}
},
"buyer": {
"name": "Beta SpA",
"taxId": "09876543210",
"address": {
"street": "Via Torino 2",
"city": "Roma",
"postalCode": "00145",
"countryCode": "IT",
"region": "RM"
}
},
"lines": [
{
"description": "Supply",
"quantity": 5,
"unitCode": "C62",
"unitPrice": 1,
"lineTotal": 5,
"vatRate": 22,
"vatCategoryCode": "S"
}
],
"taxSummary": [
{
"vatCategoryCode": "S",
"vatRate": 22,
"taxableAmount": 5,
"taxAmount": 1.1
}
],
"paymentMeans": { "typeCode": "58", "iban": "IT60X0542811101000000123456" },
"totalNetAmount": 5,
"totalTaxAmount": 1.1,
"totalGrossAmount": 6.1
}
}'import { Beliq } from '@beliq/sdk';
const beliq = new Beliq({ apiKey: process.env.BELIQ_API_KEY! });
const generated = await beliq.generate({
standard: 'fatturapa',
profile: 'ordinaria',
output: 'xml',
invoice: {
number: '123',
issueDate: '2026-04-13',
dueDate: '2026-05-13',
currencyCode: 'EUR',
italy: { codiceDestinatario: 'ABC1234', regimeFiscale: 'RF19' },
seller: {
name: 'Alpha SRL',
vatId: 'IT01234567890',
address: {
street: 'Via Roma 1',
city: 'Sassari',
postalCode: '07100',
countryCode: 'IT',
region: 'SS',
},
},
buyer: {
name: 'Beta SpA',
taxId: '09876543210',
address: {
street: 'Via Torino 2',
city: 'Roma',
postalCode: '00145',
countryCode: 'IT',
region: 'RM',
},
},
lines: [
{
description: 'Supply',
quantity: 5,
unitCode: 'C62',
unitPrice: 1,
lineTotal: 5,
vatRate: 22,
vatCategoryCode: 'S',
},
],
taxSummary: [{ vatCategoryCode: 'S', vatRate: 22, taxableAmount: 5, taxAmount: 1.1 }],
paymentMeans: { typeCode: '58', iban: 'IT60X0542811101000000123456' },
totalNetAmount: 5,
totalTaxAmount: 1.1,
totalGrossAmount: 6.1,
},
});
// `xml` is the same document curl writes to stdout.
console.log(generated.xml);import os
from beliq import Beliq
beliq = Beliq(api_key=os.environ["BELIQ_API_KEY"])
generated = beliq.generate(
standard="fatturapa",
profile="ordinaria",
output="xml",
invoice={
"number": "123",
"issueDate": "2026-04-13",
"dueDate": "2026-05-13",
"currencyCode": "EUR",
"italy": {"codiceDestinatario": "ABC1234", "regimeFiscale": "RF19"},
"seller": {
"name": "Alpha SRL",
"vatId": "IT01234567890",
"address": {
"street": "Via Roma 1",
"city": "Sassari",
"postalCode": "07100",
"countryCode": "IT",
"region": "SS",
},
},
"buyer": {
"name": "Beta SpA",
"taxId": "09876543210",
"address": {
"street": "Via Torino 2",
"city": "Roma",
"postalCode": "00145",
"countryCode": "IT",
"region": "RM",
},
},
"lines": [
{
"description": "Supply",
"quantity": 5,
"unitCode": "C62",
"unitPrice": 1,
"lineTotal": 5,
"vatRate": 22,
"vatCategoryCode": "S",
},
],
"taxSummary": [{"vatCategoryCode": "S", "vatRate": 22, "taxableAmount": 5, "taxAmount": 1.1}],
"paymentMeans": {"typeCode": "58", "iban": "IT60X0542811101000000123456"},
"totalNetAmount": 5,
"totalTaxAmount": 1.1,
"totalGrossAmount": 6.1,
},
)
# `xml` is the same document curl writes to stdout.
print(generated.xml)Peppol BIS Billing 3.0 example
For cross-border EU invoicing over the Peppol Network, set standard: "peppol-bis". Both parties need a Peppol electronic-address (or a vatId + country Beliq can map to the standard EAS scheme), and the invoice must carry either a buyerReference or orderReference.
curl -X POST https://api.beliq.eu/v1/generate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"standard": "peppol-bis",
"output": "xml",
"invoice": {
"number": "INV-2026-042",
"issueDate": "2026-04-13",
"currencyCode": "EUR",
"buyerReference": "PO-2026-042",
"seller": {
"name": "Acme SARL",
"vatId": "FR12345678901",
"peppol": { "schemeId": "9957", "id": "FR12345678901" },
"address": {
"street": "12 Rue de Exemple",
"city": "Paris",
"postalCode": "75001",
"countryCode": "FR"
}
},
"buyer": {
"name": "Voorbeeld B.V.",
"vatId": "NL123456789B01",
"peppol": { "schemeId": "9944", "id": "NL123456789B01" },
"address": {
"street": "Voorbeeldlaan 1",
"city": "Amsterdam",
"postalCode": "1011AB",
"countryCode": "NL"
}
},
"lines": [
{
"description": "Cloud subscription — April 2026",
"quantity": 1,
"unitCode": "MON",
"unitPrice": 500.00,
"lineTotal": 500.00,
"vatRate": 21,
"vatCategoryCode": "S"
}
],
"taxSummary": [
{ "vatCategoryCode": "S", "vatRate": 21, "taxableAmount": 500.00, "taxAmount": 105.00 }
],
"totalNetAmount": 500.00,
"totalTaxAmount": 105.00,
"totalGrossAmount": 605.00
}
}'import { Beliq } from '@beliq/sdk';
const beliq = new Beliq({ apiKey: process.env.BELIQ_API_KEY! });
const generated = await beliq.generate({
standard: 'peppol-bis',
output: 'xml',
invoice: {
number: 'INV-2026-042',
issueDate: '2026-04-13',
currencyCode: 'EUR',
buyerReference: 'PO-2026-042',
seller: {
name: 'Acme SARL',
vatId: 'FR12345678901',
peppol: { schemeId: '9957', id: 'FR12345678901' },
address: { street: '12 Rue de Exemple', city: 'Paris', postalCode: '75001', countryCode: 'FR' },
},
buyer: {
name: 'Voorbeeld B.V.',
vatId: 'NL123456789B01',
peppol: { schemeId: '9944', id: 'NL123456789B01' },
address: { street: 'Voorbeeldlaan 1', city: 'Amsterdam', postalCode: '1011AB', countryCode: 'NL' },
},
lines: [
{
description: 'Cloud subscription — April 2026',
quantity: 1,
unitCode: 'MON',
unitPrice: 500.00,
lineTotal: 500.00,
vatRate: 21,
vatCategoryCode: 'S',
},
],
taxSummary: [{ vatCategoryCode: 'S', vatRate: 21, taxableAmount: 500.00, taxAmount: 105.00 }],
totalNetAmount: 500.00,
totalTaxAmount: 105.00,
totalGrossAmount: 605.00,
},
});
// `xml` is the same document curl writes to stdout.
console.log(generated.xml);import os
from beliq import Beliq
beliq = Beliq(api_key=os.environ["BELIQ_API_KEY"])
generated = beliq.generate(
standard="peppol-bis",
output="xml",
invoice={
"number": "INV-2026-042",
"issueDate": "2026-04-13",
"currencyCode": "EUR",
"buyerReference": "PO-2026-042",
"seller": {
"name": "Acme SARL",
"vatId": "FR12345678901",
"peppol": {"schemeId": "9957", "id": "FR12345678901"},
"address": {
"street": "12 Rue de Exemple",
"city": "Paris",
"postalCode": "75001",
"countryCode": "FR",
},
},
"buyer": {
"name": "Voorbeeld B.V.",
"vatId": "NL123456789B01",
"peppol": {"schemeId": "9944", "id": "NL123456789B01"},
"address": {
"street": "Voorbeeldlaan 1",
"city": "Amsterdam",
"postalCode": "1011AB",
"countryCode": "NL",
},
},
"lines": [
{
"description": "Cloud subscription — April 2026",
"quantity": 1,
"unitCode": "MON",
"unitPrice": 500.00,
"lineTotal": 500.00,
"vatRate": 21,
"vatCategoryCode": "S",
},
],
"taxSummary": [{"vatCategoryCode": "S", "vatRate": 21, "taxableAmount": 500.00, "taxAmount": 105.00}],
"totalNetAmount": 500.00,
"totalTaxAmount": 105.00,
"totalGrossAmount": 605.00,
},
)
# `xml` is the same document curl writes to stdout.
print(generated.xml)See the Peppol BIS Billing 3.0 reference for what fields Beliq emits and what the validator checks.