eliDocs
API Reference

POST /v1/generate

POST/v1/generate

Generate an e-invoice from invoice data: EN 16931 UBL or CII, Peppol, hybrid PDF, or a national XML format (FatturaPA FPR12, Facturae, e-SLOG, KSeF FA(3)).

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

Quick copy examples

Generate XML:

generate-xml.sh
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:

generate-pdf.sh
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.pdf
import { 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

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), ksef (Poland KSeF FA(3) XML, ordinary VAT invoices in PLN; see the scope); the four 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, ksef), 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, because 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 the hybrid’s visible page gets this layout whether you set it or not, unless a pdfTemplateId replaces it. 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
ksef fa3 fa3

extended-ctc-fr is the AFNOR XP Z12-012 France CTC overlay and exists on facturx only, because ZUGFeRD has no branded counterpart to map it onto. It is returned as XML only: with output: "pdf" the request is rejected with the same 422 PROFILE_STANDARD_MISMATCH, and details.allowedProfiles then lists the facturx profiles that can be returned as a hybrid PDF (minimum, basicwl, basic, en16931, extended). 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 and Poland KSeF FA(3) for fa3.

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 CII D16B Visualization PDF (needs template) CII (D16B). No request field picks UBL; convert writes it
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
ksef KSeF FA(3) (Poland VAT invoice 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, e-SLOG and KSeF namespaces are national extensions, and franceCtc is a Beliq switch. A term that does not appear anywhere on this page has no field yet, and EN 16931 field coverage is the list of which ones those are: all 164 business terms the standard defines, each with its field or with nothing.

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
vatPointDate string optional YYYY-MM-DD, not together with vatPointDateCode BT-7. VAT point date: the date the VAT becomes accountable, when you know it and it is not the issue date. cbc:TaxPointDate on UBL. On CII it is ram:TaxPointDate on the first ram:ApplicableTradeTax only, because CII-SR-461 allows one. Sending it together with vatPointDateCode is a 400 VALIDATION_ERROR on UBL and CII output (BR-CO-03).
vatPointDateCode string optional "3", "35" or "432", not together with vatPointDate BT-8. VAT point date code, for when the date is not known yet: 3 the invoice date, 35 the delivery date, 432 the payment date. These are the UNTDID 2005 codes BR-CL-06 lists for UBL, which writes the code as sent to cac:InvoicePeriod/cbc:DescriptionCode. BR-CL-06 takes UNTDID 2475 on CII, so Beliq writes 5, 29 or 72 there, as ram:DueDateTypeCode on the first ram:ApplicableTradeTax.
invoicingPeriod object optional startDate, endDate: YYYY-MM-DD, at least one of the two BG-14, with startDate as BT-73 and endDate as BT-74. The period the invoice bills, such as a month of service. cac:InvoicePeriod on UBL, ram:ApplicableHeaderTradeSettlement/ram:BillingSpecifiedPeriod on CII. An object with neither date is a 400 (BR-CO-19), and on UBL and CII output so is an end before the start (BR-29).
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, and sets the default type code, 380 or 381; typeCode below sets another. Supported when standard accepts CreditNote payloads: peppol-bis, facturx, xrechnung, zugferd, and eslog (e-SLOG emits document type code 381 in S_BGM). fatturapa, facturae and ksef accept invoices only: use documentType: "invoice" or omit the field. See DOCUMENT_TYPE_STANDARD_MISMATCH, the format overview, and Peppol Credit notes.
typeCode string optional 2 or 3 digits, a code documentType admits BT-3. The UNTDID 1001 document type code, when it is not the default: 384 for a corrected invoice, 389 for a self-billed invoice, 326 for a partial invoice. documentType still picks the document and this picks the code within it: ram:TypeCode on CII, cbc:InvoiceTypeCode or cbc:CreditNoteTypeCode on UBL. The code has to be one UBL admits for that document type (BR-CL-01 splits UNTDID 1001 between Invoice and CreditNote, with 81 in both). Beliq holds CII to the same split, so any other code is a 400 VALIDATION_ERROR on either syntax. The CIUS lists are narrower, and validation checks them: Peppol BIS Billing 3.0 takes a shorter list with no 389 (PEPPOL-EN16931-P0100, P0101) and keeps 326 and 384 to a German seller and buyer (P0112), and XRechnung warns outside 326, 380, 381, 384, 389, 875, 876 and 877 (BR-DE-17). Accepted on facturx, zugferd, xrechnung and peppol-bis. fatturapa, facturae and eslog write their own document type, so typeCode there is a 422 DOCUMENT_TYPE_STANDARD_MISMATCH rather than a document without it.
precedingInvoiceReference object optional, required on a peppol-bis credit note id: 1-200 chars (the earlier invoice’s number); issueDate (optional): YYYY-MM-DD BG-3, with id as BT-25 and issueDate as BT-26. The invoice issued earlier that this document refers to: the one a credit note corrects, or the one a corrected invoice (typeCode 384) replaces. Written on every document type, as cac:BillingReference / cac:InvoiceDocumentReference on UBL outputs (Peppol BIS Billing 3.0) and ram:InvoiceReferencedDocument on CII outputs (XRechnung, ZUGFeRD, Factur-X). The Factur-X and ZUGFeRD minimum profile has no slot for it and drops it. eslog, fatturapa, facturae and ksef write it nowhere, so they answer 400 VALIDATION_ERROR when it is sent. A peppol-bis credit note without it is a 400 VALIDATION_ERROR. That is Beliq’s rule: the Peppol BIS Schematron does not require the reference, and no other ruleset requires it on a credit note either, so elsewhere a credit note without one verifies. On a corrected invoice XRechnung (BR-DE-26) and Peppol (DE-R-026) warn without it, and the French CTC (BR-FR-CO-04) rejects the document. The block needs its id (BR-55).
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
salesOrderReference string optional 1-200 chars BT-14. Sales order reference, the seller’s own order number. cac:OrderReference/cbc:SalesOrderID on UBL, ram:SellerOrderReferencedDocument/ram:IssuerAssignedID on CII. On UBL it cannot stand alone: cac:OrderReference/cbc:ID, the purchase order reference, is mandatory in the schema. So without an orderReference Beliq writes NA there, the value the Peppol BIS syntax binding gives for this case. NA is a placeholder in the slot of BT-13 and your buyer’s software reads it as the purchase order reference, so send a real orderReference when you have one. It does not count as one: a peppol-bis invoice still needs buyerReference or orderReference (PEPPOL-EN16931-R003) and is a 400 with neither. CII has no such constraint and writes no placeholder.
contractReference string optional 1-200 chars BT-12. Contract reference. cac:ContractDocumentReference/cbc:ID on UBL, ram:ContractReferencedDocument/ram:IssuerAssignedID on CII.
projectReference string optional 1-200 chars BT-11. Project reference. cac:ProjectReference/cbc:ID on a UBL invoice. A UBL credit note has no such element, so there it is a cac:AdditionalDocumentReference with document type code 50, which UBL-SR-43 allows on a credit note only. On CII it is ram:SpecifiedProcuringProject/ram:ID, with the fixed text Project reference in the ram:Name the schema requires beside it; EN 16931 has no term for that name.
receivingAdviceReference string optional 1-200 chars BT-15. Receiving advice reference. cac:ReceiptDocumentReference/cbc:ID on UBL, ram:ReceivingAdviceReferencedDocument/ram:IssuerAssignedID in the CII delivery block. It needs no delivery object.
despatchAdviceReference string optional 1-200 chars BT-16. Despatch advice reference. cac:DespatchDocumentReference/cbc:ID on UBL, ram:DespatchAdviceReferencedDocument/ram:IssuerAssignedID in the CII delivery block. It needs no delivery object.
tenderReference string optional 1-200 chars BT-17. Tender or lot reference. cac:OriginatorDocumentReference/cbc:ID on UBL, a ram:AdditionalReferencedDocument with type code 50 on CII.
invoicedObjectIdentifier object optional id: required, 1-200 chars; schemeId (optional): 1-10 chars BT-18, with schemeId as BT-18-1. Invoiced object identifier: what the invoice is for, such as a meter or a subscription number. A cac:AdditionalDocumentReference with document type code 130 and the scheme as @schemeID on UBL, a ram:AdditionalReferencedDocument with type code 130 and the scheme as ram:ReferenceTypeCode on CII. schemeId comes from the UNTDID 1153 code list (BR-CL-07), which validation checks.
buyerAccountingReference string optional 1-200 chars BT-19. Buyer accounting reference, such as the buyer’s cost centre. cbc:AccountingCost on UBL, ram:ReceivableSpecifiedTradeAccountingAccount/ram:ID on CII.
supportingDocuments SupportingDocument[] optional Max 50 items BG-24. Additional supporting documents, such as a timesheet or a usage report: a reference, and optionally a URL, an attached file or both. Written in the order sent.
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 VALIDATION_ERROR whose message names the party and the fields.
buyer Party required BG-7. Buyer/customer details. Same electronic-address requirement as seller.
payee Payee optional BG-10. The party paid when it is not the seller, such as a factoring company. Omit it when the seller is paid. With a payee, UBL writes the SEPA creditor identifier (paymentMeans.creditorId) on the payee rather than on the seller.
taxRepresentative TaxRepresentative optional BG-11. The party that accounts for VAT on the seller’s behalf, typically for a seller not established in the country of supply.
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
allowances DocumentAllowanceCharge[] optional Max 50 BG-20. Amounts taken off the whole invoice rather than off one line, such as a volume rebate. cac:AllowanceCharge with a cbc:ChargeIndicator of false on UBL, ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge on CII, and their sum is written to BT-107 (cbc:AllowanceTotalAmount, ram:AllowanceTotalAmount). Each entry needs a VAT category, so it also changes the VAT breakdown you send in taxSummary.
charges DocumentAllowanceCharge[] optional Max 50 BG-21. The same, added to the invoice rather than taken off it, such as packaging or freight. The indicator is true and the sum is written to BT-108 (cbc:ChargeTotalAmount, ram:ChargeTotalAmount).
totalNetAmount number required BT-106. The sum of the line net amounts, and only that: do not fold allowances or charges into it. Beliq derives BT-109, the invoice total without VAT, as totalNetAmount minus the allowances plus the charges (BR-CO-13), and writes that to cbc:TaxExclusiveAmount and ram:TaxBasisTotalAmount. With neither list the two numbers are equal, which is what every document sent before this field existed carries.
totalTaxAmount number required BT-110. Total VAT amount
totalGrossAmount number required BT-112. Total including VAT. Unchecked on an invoice with no allowances or charges; with either, it must equal the derived BT-109 plus totalTaxAmount to within two cents (BR-CO-15), or the request is a 400. It is not the amount due: Beliq derives BT-115 as totalGrossAmount minus paidAmount plus roundingAmount (BR-CO-16) and writes that to cbc:PayableAmount and ram:DuePayableAmount. With neither field sent the two are equal, which is what every document sent before those fields existed carries.
paidAmount number optional BT-113. The sum already paid in advance, which comes off the amount due. cbc:PrepaidAmount on UBL, ram:TotalPrepaidAmount on CII. No rule restricts its sign, so neither does Beliq.
roundingAmount number optional BT-114. The amount added to the amount due to round it, positive or negative, for example -0.02. cbc:PayableRoundingAmount on UBL, ram:RoundingAmount on CII.
franceCtc boolean optional French CTC mode, on Factur-X and ZUGFeRD output. Beliq then writes BT-23: your businessProcessId, or B1 when you leave it out. With verify: true (the default), the check that follows runs the FNFE-MPE BR-FR-CTC Flux 2 overlay, and the EXTENDED-CTC-FR overlay too on the extended and extended-ctc-fr profiles, because the document carries that code, as the validation pipeline describes. No document Beliq generates passes them today, so that request is refused with 422 INVALID_INVOICE and the failing rules listed; What Beliq covers today says which. With verify: false, no overlay runs. Sent as true with any other standard (xrechnung, peppol-bis, fatturapa, facturae, eslog or ksef), the request is refused with a 400, because Beliq writes no French CTC document there; false is the same as leaving the field out. To check a document you already have, send franceCtc=true to POST /v1/validate.
businessProcessId string optional S8, B8, or M8 BT-23. An AFNOR XP Z12-012 cadre de facturation code; the three accepted here are the multi-vendor codes. Written on Factur-X and ZUGFeRD output when franceCtc is true or the profile is extended-ctc-fr. Left out, those documents carry B1. Any other request that sends it, every other standard included, is refused with a 400.
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.
poland object optional Poland KSeF FA(3) document defaults when standard is "ksef". See Poland (KSeF) fields.

paidAmount and roundingAmount change the amount due, so a standard that cannot carry them refuses them rather than stating the wrong sum. The FatturaPA, Facturae, e-SLOG and KSeF FA(3) builders state totalGrossAmount as the amount due and have no slot for either, so with those standards a value other than 0 is a 400 VALIDATION_ERROR. On Factur-X and ZUGFeRD, basicwl and basic carry paidAmount but declare no rounding amount, so a roundingAmount other than 0 is a 400 there that names en16931 and extended, which carry it. minimum carries neither and drops both, but still states the amount due they produce.

payee and taxRepresentative reach UBL and CII output only; the FatturaPA, Facturae, e-SLOG and KSeF FA(3) builders do not read them. On Factur-X and ZUGFeRD they reach basicwl and up, and minimum, which declares neither party, drops both.

vatPointDate, vatPointDateCode, invoicingPeriod, the line’s invoicingPeriod, the eight references from salesOrderReference to buyerAccountingReference and supportingDocuments reach UBL and CII output only. The FatturaPA, Facturae, e-SLOG and KSeF FA(3) builders do not read them, so those documents are the same with or without them, and the checks below do not run there. peppol-bis and xrechnung write all of them. On Factur-X and ZUGFeRD a field needs a profile whose schema declares its element, and is dropped below that:

Term Fields minimum basicwl basic en16931 and up
BG-14, BT-8, BT-12, BT-16, BT-19 invoicingPeriod, vatPointDateCode, contractReference, despatchAdviceReference, buyerAccountingReference dropped written written written
BG-26 invoicingPeriod on a line dropped no lines written written
BT-7, BT-11, BT-14, BT-15, BT-17, BT-18 vatPointDate, projectReference, salesOrderReference, receivingAdviceReference, tenderReference, invoicedObjectIdentifier dropped dropped dropped written
BG-24 supportingDocuments dropped dropped dropped written

On facturx, zugferd, xrechnung and peppol-bis, Beliq checks the two VAT point fields and the invoice’s period on every profile, including one that drops them. vatPointDate together with vatPointDateCode (BR-CO-03) and a period that ends before it starts (BR-29) are a 400 VALIDATION_ERROR. A line’s period is checked where lines are written, so not on minimum and basicwl.

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. The five codes in the first rows each take one value, the invoice Beliq builds, and an omitted code writes that same value; any other value answers 400 VALIDATION_ERROR. Fields are forwarded to the engine and should follow the official Facturae format documentation.

Field Type Description
modality string I, a single invoice. Beliq builds no batch (L).
invoiceIssuerType string EM, issued by the seller. Beliq builds no invoice issued by the recipient (RE) or a third party (TE).
invoiceDocumentType string FC, a complete invoice. Beliq builds no simplified (FA) or self-billed (AF) invoice.
invoiceClass string OO, an original invoice. Beliq builds no other class of the Facturae XSD.
taxTypeCode string 01, VAT (IVA). The engine writes the code on every line as an output tax, so it takes no other: some codes, such as 04 (IRPF), are taxes withheld.
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.

Poland (KSeF) fields

Use the optional invoice.poland object with standard: "ksef" (profile fa3, the default). Every field is optional and has a default. Flags take "1" (yes) or "2" (no), the FA(3) TWybor1_2 values. The Poland KSeF FA(3) reference states what the builder covers and refuses.

Field Type Description
adnotacje object Overrides for the Adnotacje markers P_16 (cash accounting), P_17 (self-billing), P_18 (reverse charge), P_18A (split payment) and P_23 (simplified triangular procedure). Each defaults to "2". P_18 and P_23 take "2" only: Beliq builds no reverse-charge lines and no second buyer, so a "1" answers 400 VALIDATION_ERROR.
jst string Podmiot2/JST: the buyer is a subordinate unit of a local-government unit. "2" only: a "1" needs a Podmiot3 with role 8, which Beliq does not build, and answers 400 VALIDATION_ERROR.
gv string Podmiot2/GV: the buyer is a VAT-group member. "2" only: a "1" needs a Podmiot3 with role 10, which Beliq does not build, and answers 400 VALIDATION_ERROR.
placeOfIssue string Place of issue, written as P_1M. Up to 256 characters. Not written when omitted.
dataWytworzenia string Creation timestamp, written as DataWytworzeniaFa. Defaults to the time Beliq generates the document, in UTC.

The seller’s vatId must be a Polish NIP (10 digits, PL prefix optional). The buyer’s is a Polish NIP or absent.

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 on the seller. The registration a seller holds with a tax authority that is not a VAT number. ram:SpecifiedTaxRegistration/ram:ID[@schemeID="FC"] on CII, cac:PartyTaxScheme with cac:TaxScheme/cbc:ID of FC on UBL. EN 16931 has no buyer term for it. On the buyer, the CII and UBL builders write it in the same place, except on Factur-X and ZUGFeRD basicwl, basic, en16931 and extended: the FNFE-MPE rules of those profiles (FX-SCH-A-000427, FX-SCH-A-000497, FX-SCH-A-000570 and BR-FXEXT-03) allow the buyer a VAT registration only, so a buyer taxId there is a 400 naming the rule. FatturaPA reads the buyer’s value as the codice fiscale and not the seller’s; Facturae, e-SLOG and KSeF FA(3) do not read the field.
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, plus any charges and minus any allowances on the line (PEPPOL-EN16931-R120). Beliq does not compute it for you. On a line carrying either list it checks your figure against that formula to within two cents and answers 400 when it does not match; on a line carrying neither it is yours unchecked, as before.
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, use allowances (BG-27) below.
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.
allowances LineAllowanceCharge[] optional Max 50 BG-27. Amounts taken off this line as a whole, such as a loyalty discount. cac:AllowanceCharge on the UBL line with a cbc:ChargeIndicator of false, ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge on CII. Not the same thing as priceDiscount, which comes off the unit price: these change what lineTotal has to be, and Beliq checks it (see the lineTotal row). Sub-lines carry the field too.
charges LineAllowanceCharge[] optional Max 50 BG-28. The same, added to the line rather than taken off it. The indicator is true.
invoicingPeriod object optional startDate, endDate: YYYY-MM-DD, at least one of the two BG-26, with startDate as BT-134 and endDate as BT-135. The period this line covers. cac:InvoicePeriod on the UBL line, ram:SpecifiedLineTradeSettlement/ram:BillingSpecifiedPeriod on CII. An object with neither date is a 400 (BR-CO-20), and on UBL and CII output so is an end before the start (BR-30). When the invoice has an invoicingPeriod too, a line period that starts before it or ends after it is a 400 there as well. PEPPOL-EN16931-R110 and R111 are the rules, which only Peppol BIS and XRechnung enforce; Beliq applies them on every UBL and CII output, so the same request does not pass on one standard and fail on another. Sub-lines carry the field too, and a sub-line’s period is not held to the invoice’s. Output reach and profile floors are in the table under the invoice object.

The nine fields from grossPrice to charges reach UBL and CII output only; the FatturaPA, Facturae, e-SLOG and KSeF FA(3) builders do not read them, except that all four refuse allowances and charges (see the document allowance and charge object). On Factur-X and ZUGFeRD, grossPrice, priceDiscount, priceBaseQuantity, standardItemId, allowances and charges 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.

Document allowance and charge object

One entry in the invoice’s allowances (BG-20) or charges (BG-21) list. Both lists take the same object; which list an entry sits in is what says whether it lowers or raises the invoice total, so there is no indicator field to set and no way to send a charge as an allowance by mistake. Allowances are written before charges in the output.

Three things Beliq refuses at the door, because JSON Schema cannot express them, each returning 400 VALIDATION_ERROR with a message that names the rule:

  • baseAmount and percentage are a pair. One without the other is PEPPOL-EN16931-R041 or R042, both fatal on Peppol and XRechnung.
  • With both, amount must equal baseAmount × percentage ÷ 100 to within two cents (R040). Beliq checks the two-decimal figures the document will carry, not the ones you sent, because that is what the rule reads: a percentage of 2.375 is written as 2.38, and on a base of 1000.00 those two readings are five cents apart.
  • An entry needs a reason or a reasonCode (BR-33, BR-38, restated as BR-CO-21 and BR-CO-23). An entry with neither is rejected by every ruleset, so Beliq does not build the document.
Field Type Required Constraints Description
amount number required ≥ 0 BT-92 on an allowance, BT-99 on a charge. The amount without VAT. cbc:Amount on UBL, ram:ActualAmount on CII. A negative value is a 400: the two lists carry the sign, so a negative allowance is a charge in the wrong list, and the totals still add up, which is why nothing downstream would catch it.
baseAmount number optional ≥ 0, pairs with percentage BT-93 / BT-100. The amount the percentage applies to. cbc:BaseAmount on UBL, ram:BasisAmount on CII.
percentage number optional 0–100, pairs with baseAmount BT-94 / BT-101. cbc:MultiplierFactorNumeric on UBL, ram:CalculationPercent on CII.
reason string optional 1–1000 chars, this or reasonCode BT-97 / BT-104. Why the amount is there, in words, for example Annual volume rebate. cbc:AllowanceChargeReason on UBL, ram:Reason on CII.
reasonCode string optional 1–10 chars, this or reason BT-98 / BT-105. The same reason as a code: UNCL 5189 for an allowance (BR-CL-19), UNCL 7161 for a charge (BR-CL-20). Validation checks the code list; the request schema only checks that you sent something.
vatCategoryCode string required 1–10 chars BT-95 / BT-102. The VAT category the amount is taxed under, for example S. Required, not optional: BR-32 and BR-37 demand it, and the Factur-X basicwl profile schema declares the element mandatory, so an entry without one could not be built there at all. Its value has to appear in your taxSummary, because the allowance or charge moves that category’s taxable amount.
vatRate number optional 0–100 BT-96 / BT-103. The rate for that category. Written as 0 when you leave it out, so send it for any category that carries a rate. Dropped when vatCategoryCode is O, which is not subject to VAT.

These reach UBL and CII output only. The FatturaPA, Facturae, e-SLOG and KSeF FA(3) builders write allowances and charges at neither level, so with standard: "fatturapa", "facturae", "eslog" or "ksef" an invoice or line that carries allowances or charges is a 400 VALIDATION_ERROR whose message names the lists, rather than a document without them. On Factur-X and ZUGFeRD they reach basicwl and up. The minimum profile declares no allowance element, so the detail is dropped there, but the total it feeds is not: minimum still states the derived BT-109 with the allowances and charges applied.

Line allowance and charge object

One entry in a line’s allowances (BG-27) or charges (BG-28) list. The same object as the document level one minus the VAT category: EN 16931 gives these two groups no VAT term, because the line’s own vatCategoryCode (BT-151) applies. The same three refusals apply, under BR-42 and BR-44 for the reason, and a line carrying either list also has its lineTotal checked against PEPPOL-EN16931-R120.

Field Type Required Constraints Description
amount number required ≥ 0 BT-136 on an allowance, BT-141 on a charge. The amount without VAT, off or on the line as a whole.
baseAmount number optional ≥ 0, pairs with percentage BT-137 / BT-142.
percentage number optional 0–100, pairs with baseAmount BT-138 / BT-143.
reason string optional 1–1000 chars, this or reasonCode BT-139 / BT-144. For example Loyalty discount.
reasonCode string optional 1–10 chars, this or reason BT-140 / BT-145. UNCL 5189 (BR-CL-19) or UNCL 7161 (BR-CL-20).

Same output reach as the document level object, except that these need a profile that has lines: basic and up on Factur-X and ZUGFeRD.

Supporting document object

One additional supporting document (BG-24): a reference, and optionally a description, a URL the document can be fetched from, an attached file, or both a URL and a file. A cac:AdditionalDocumentReference with no document type code on UBL, a ram:AdditionalReferencedDocument with type code 916 on CII.

Field Type Required Constraints Description
id string required 1-200 chars BT-122. Supporting document reference. cbc:ID on UBL, ram:IssuerAssignedID on CII. A reference of spaces, tabs or line breaks alone is a 400 VALIDATION_ERROR (BR-52).
description string optional 1-1000 chars BT-123. Supporting document description. cbc:DocumentDescription on UBL, ram:Name on CII.
externalLocation string optional 1-2048 chars BT-124. External document location: a URL the document can be fetched from. cac:Attachment/cac:ExternalReference/cbc:URI on UBL, ram:URIID on CII. XRechnung wants it to start with a URL scheme, such as https: (BR-TMP-2).
attachment object optional content: required, base64; mimeCode: required, 1-100 chars; filename: required, 1-255 chars BT-125. Attached document: the file itself, with its mime code and its filename. cac:Attachment/cbc:EmbeddedDocumentBinaryObject on UBL, ram:AttachmentBinaryObject on CII, each with @mimeCode and @filename.

attachment.content is the file as base64: the standard alphabet, padded with =. Whitespace between characters is accepted and is left out of the document. Content that does not decode, or decodes to no bytes, is a 400 VALIDATION_ERROR, and so is a mimeCode or a filename of whitespace alone. Beliq makes these checks on every UBL and CII output, including the Factur-X and ZUGFeRD profiles that drop the group.

Size. An attachment counts toward the request body limit of 1 MiB (request size limits), on XML and on PDF output alike. Base64 takes four characters for every three bytes of the file, so a file can be at most three quarters of that limit, less the invoice around it. A larger body is a 413 and is not read.

Mime codes. BR-CL-24 allows application/pdf, image/png, image/jpeg, text/csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet and application/vnd.oasis.opendocument.spreadsheet. Beliq does not check mimeCode against that list itself: validation does, so with verify on, any other code is a 422 INVALID_INVOICE. The one exception is application/xml on the Factur-X and ZUGFeRD extended profile, whose own code list has it.

Filenames. XRechnung refuses two attachments with the same filename (BR-DE-22), and so does Peppol BIS between a German seller and a German buyer (DE-R-022). Both rules compare the names as written, so two names that differ only in case pass.

More than one document on CII. A CII invoice with several supporting documents is valid. The EN 16931 CII rules CII-SR-475 and CII-SR-476 still raise a warning when more than one of them has a description, or more than one has an attached file, because they count across the whole invoice (eInvoicing-EN16931 issue 508). POST /v1/generate returns them with the document: in validationResult.warnings of the JSON envelope, as warnings on CII and Factur-X and as information on XRechnung, and counted on the x-validation header of a binary response.

Payee object

The party paid when it is not the seller (BG-10). Omit the whole object when the seller is paid. A name or registrationId equal to the seller’s is a 400 VALIDATION_ERROR, because BR-17 requires the payee to be a different party and UBL-SR-19 to UBL-SR-21 compare the names on UBL. Beliq refuses it on every UBL and CII output, including the Factur-X profiles whose copy of BR-17 does not catch it.

Field Type Required Constraints Description
name string required 1-200 chars BT-59. Payee name. cac:PayeeParty/cac:PartyName/cbc:Name on UBL, ram:PayeeTradeParty/ram:Name on CII.
identifier object optional id: required, 1-200 chars; schemeId (optional): 1-10 chars, not SEPA BT-60, with schemeId as BT-60-1. An identifier for the payee, such as a GLN with schemeId 0088. UBL writes it to cac:PayeeParty/cac:PartyIdentification/cbc:ID with any scheme, and validation checks the scheme against the ISO 6523 ICD list (BR-CL-10). On CII a scheme from that list goes to ram:PayeeTradeParty/ram:GlobalID; any other scheme, or none, sends the identifier to the unqualified ram:ID without it. SEPA is a 400: the SEPA creditor identifier is BT-90, sent as paymentMeans.creditorId, and a document carries one (UBL-SR-29).
registrationId string optional Max 50 chars BT-61. The payee’s entry in an official business register, as registrationId is on a party. cac:PayeeParty/cac:PartyLegalEntity/cbc:CompanyID on UBL, ram:PayeeTradeParty/ram:SpecifiedLegalOrganization/ram:ID on CII.

Tax representative object

The party that accounts for VAT on the seller’s behalf (BG-11). All three fields are required, by BR-18, BR-19, BR-20 and BR-56. The Factur-X profiles allow this party one tax registration, its VAT identifier, so there is no taxId, contact or electronic address here.

Field Type Required Constraints Description
name string required 1-200 chars BT-62. Tax representative name. cac:TaxRepresentativeParty/cac:PartyName/cbc:Name on UBL, ram:SellerTaxRepresentativeTradeParty/ram:Name on CII.
vatId string required 2-letter country prefix + 2-18 alphanumeric chars BT-63. Tax representative VAT identification number, e.g. DE123456789. cac:PartyTaxScheme/cbc:CompanyID with tax scheme VAT on UBL, ram:SpecifiedTaxRegistration/ram:ID with schemeID="VA" on CII.
address DeliveryAddress required countryCode required BG-12, with street as BT-64, additionalStreet as BT-65, city as BT-66, postalCode as BT-67, countrySubentity as BT-68 and countryCode as BT-69. The tax representative’s postal address, in the shape of a deliver-to address: only the country is required (BR-20), and UBL writes no empty city or postal code.

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, e-SLOG and KSeF FA(3) 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 or an invoicing period on an intra-community supply (vatCategoryCode K). So send date or the invoice’s invoicingPeriod: with verify at its default of true a K invoice with neither 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. The tax representative’s address takes the same shape under its own term numbers, BT-64 to BT-69: see the tax representative object.

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 party collecting the direct debit, part of BG-19. Written on a party, not inside the payment means. On UBL it is cac:PartyIdentification/cbc:ID with schemeID="SEPA" on the payee when you send one and on the seller otherwise; BR-DE-30 and DE-R-030 accept either. On CII it is ram:CreditorReferenceID in the 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, e-SLOG and KSeF FA(3) builders do not read them.

Response

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, present only where CEN’s EN 16931 pack judged the generated document: it is absent for the Factur-X MINIMUM, BASIC WL, BASIC and EXTENDED profiles, which their own Factur-X pack judges in its place. 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.16
  • x-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. Before it is returned, veraPDF checks the file.
  • 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 with output: "xml". Returned only when you supply a template or pdfTemplateId.

The PDF/A check on a hybrid PDF

After the XML is embedded, the engine runs veraPDF 1.30.3 on the finished file and returns the file only when veraPDF reports no violation of its PDF/A-3b profile. The check runs on every ZUGFeRD and Factur-X PDF this endpoint builds, also with verify: false, which skips the validation of the XML only.

  • A violation ends the request with 422 PDFA_VIOLATION. The answer lists the rules veraPDF reported, no PDF comes back, and the quota unit is refunded.
  • A check that could not finish, because veraPDF did not answer in time or failed, ends the request with 503 ENGINE_UNAVAILABLE. No PDF is returned unchecked.
  • What a pass says: this version of veraPDF found no violation of its PDF/A-3b profile in the file. It does not say that every recipient’s validator accepts the file.
  • Test mode: a test-mode PDF goes through the same check and is watermarked after it. The watermarked file does not pass veraPDF’s PDF/A-3b profile.

Styling the PDF

A hybrid PDF always carries a rendered invoice page. Without template and without pdfTemplateId that page is Beliq’s built-in layout. Choose the layout with one of:

  • template: "standard": Beliq’s built-in invoice layout, and the default for a hybrid PDF. 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 over template. 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, and the template only controls presentation. The page is drawn from the same invoice data as the XML but is not compared with it: the page renderer and the XML builder each round amounts on their own, and the text of a read-only template field prints as you typed it.

generate-pdf-styled.sh
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.pdf
import { 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.

validationResult is the verdict validation reached on the generated document, the same result POST /v1/validate returns for those bytes. A document can be valid and still carry warnings. verificationTier, verificationBadge and verificationBadgeLabel say how deep the check went for the rules that judged it. All three are left out, rather than guessed, in two cases: when a rule set that judged the document has no tier on record, and with verify: false, where no rule set ran. Verification tiers names documents the catalog holds no tier for.

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 names the document’s syntax: "cii" for XRechnung, ZUGFeRD and Factur-X, "ubl" for Peppol BIS Billing 3.0, and for the national formats "fatturapa", "facturae", "eslog" or "poland_ksef_fa3".

generate-envelope.sh
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

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

Error responses

HTTP Status Error Code When
400 VALIDATION_ERROR Request body fails JSON schema validation (missing fields, wrong types, constraint violations), with details.fields; or the engine refuses a value the schema allows, such as a rule this page names, with no details and the reason in message
422 INVALID_INVOICE Invoice data is structurally valid but fails validation (EN 16931 / CIUS Schematron for UBL/CII, or authority XSD for fatturapa)
422 VALIDATION_ERROR The engine refused the request before validating anything, such as invoice lines whose subLines nest deeper than 64 levels. No details; the message names the reason where Beliq knows it.
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), or a typeCode with a standard that writes its own document type (fatturapa, facturae, eslog, ksef). details: standard plus either documentType and creditNoteCapableStandards, or typeCode and typeCodeCapableStandards.
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, or fails the checks the dashboard designer applies on save. The message names the field at fault; fix it in the designer and save.
422 PDFA_VIOLATION A hybrid PDF was built and veraPDF reported a violation of its PDF/A-3b profile in it. The PDF is not returned and the quota unit is refunded. details.failedRules lists the rules: see PDFA_VIOLATION details
413 VALIDATION_ERROR Request body is larger than this endpoint’s 1 MiB size limit. The cap is enforced before the body is read, so nothing was validated and no quota unit is spent. A body within the limit that the engine refuses as too large to process is also a 413, and its message says so: that body was read, and a live key’s quota unit is refunded
500 INTERNAL_ERROR The PDF could not be produced: its page could not be rendered, or the engine could not build the hybrid PDF on that page. Nothing is returned, the quota unit is refunded, and error.incidentId names the incident
503 ENGINE_UNAVAILABLE The validation engine is temporarily unavailable
503 DATABASE_UNAVAILABLE Beliq’s database could not serve the request. Retry after Retry-After. Quota refunds says whether a spent unit comes back

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

Full example

generate-full.sh
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

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.

generate-fatturapa.sh
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

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.

generate-peppol.sh
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.