eliDocs
API Reference

POST /v1/parse

POST/v1/parse

Parse an e-invoice XML or hybrid PDF into JSON, with a list of what the document holds beyond it.

Upload an invoice or credit note (XML or PDF) and get its main fields back as JSON.

The JSON is a subset of the document. What the document holds beyond it is listed in warnings, in every response.

Both XML documents and hybrid PDFs are supported.

Quick copy examples

Quick copy examples

Parse XML:

parse-xml.sh
curl -X POST https://api.beliq.eu/v1/parse \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/xml" \
  --data-binary @invoice.xml
import { readFile } from 'node:fs/promises';

import { Beliq } from '@beliq/sdk';

const beliq = new Beliq({ apiKey: process.env.BELIQ_API_KEY! });

const parsed = await beliq.parse(await readFile('invoice.xml'));

console.log(parsed.format, parsed.profileDetected);
console.log(parsed.invoice);
import os
from pathlib import Path

from beliq import Beliq

beliq = Beliq(api_key=os.environ["BELIQ_API_KEY"])

parsed = beliq.parse(Path("invoice.xml").read_bytes())

print(parsed.format, parsed.profile_detected)
print(parsed.invoice)

Parse PDF:

parse-pdf.sh
curl -X POST https://api.beliq.eu/v1/parse \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @invoice.pdf
import { readFile } from 'node:fs/promises';

import { Beliq } from '@beliq/sdk';

const beliq = new Beliq({ apiKey: process.env.BELIQ_API_KEY! });

const parsed = await beliq.parse(await readFile('invoice.pdf'));

console.log(parsed.format, parsed.profileDetected);
console.log(parsed.invoice);
import os
from pathlib import Path

from beliq import Beliq

beliq = Beliq(api_key=os.environ["BELIQ_API_KEY"])

parsed = beliq.parse(Path("invoice.pdf").read_bytes())

print(parsed.format, parsed.profile_detected)
print(parsed.invoice)
Request

Request

POST /v1/parse
Content-Type: application/xml | application/octet-stream
Authorization: Bearer <api-key>

Headers

Header Required Description
Authorization required Bearer <api-key> or use X-API-Key header
Content-Type required application/xml for XML input, application/octet-stream for PDF or binary input

Query parameters

Parameter Type Required Description
format string optional Has no effect on the result: Beliq always detects the format from the document itself, whatever you send here. The value is still checked. Anything other than auto, cii, ubl, fatturapa, sdi_messaggio, facturae, eslog, poland_ksef_fa3 or poland_ksef_fa2 (the values POST /v1/validate accepts) answers 400 VALIDATION_ERROR. Sending one of them does not widen what this endpoint parses: see the supported input formats above

A query parameter this table does not list answers 400 VALIDATION_ERROR, and error.details.fields names it as a JSON Pointer, such as /formt.

Request body

The raw XML or PDF file content as the request body. Do not JSON-encode it.

parse.sh
curl -X POST https://api.beliq.eu/v1/parse \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/xml" \
  --data-binary @invoice.xml
import { readFile } from 'node:fs/promises';

import { Beliq } from '@beliq/sdk';

const beliq = new Beliq({ apiKey: process.env.BELIQ_API_KEY! });

const parsed = await beliq.parse(await readFile('invoice.xml'));

console.log(parsed.format, parsed.profileDetected);
console.log(parsed.invoice);
import os
from pathlib import Path

from beliq import Beliq

beliq = Beliq(api_key=os.environ["BELIQ_API_KEY"])

parsed = beliq.parse(Path("invoice.xml").read_bytes())

print(parsed.format, parsed.profile_detected)
print(parsed.invoice)
Response

Response

Alongside the JSON body below, the response reports the detected syntax and profile as headers. See the Response headers reference.

Success (200)

{
  "success": true,
  "data": {
    "format": "cii",
    "profileDetected": "xrechnung",
    "profileUrn": "urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0",
    "businessProcessId": "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0",
    "invoice": {
      "number": "INV-2026-001",
      "issueDate": "2026-04-13",
      "currencyCode": "EUR",
      "documentType": "invoice",
      "typeCode": "380",
      "buyerReference": "04011000-12345-03",
      "seller": {
        "name": "Acme GmbH",
        "address": {
          "street": "Musterstraße 1",
          "city": "Berlin",
          "postalCode": "10115",
          "countryCode": "DE"
        },
        "vatId": "DE123456789"
      },
      "buyer": {
        "name": "Bundesministerium für Beispiele",
        "address": {
          "street": "Beispielweg 42",
          "city": "Bonn",
          "postalCode": "53113",
          "countryCode": "DE"
        }
      },
      "lines": [
        {
          "description": "IT consulting, April 2026",
          "quantity": 20.0,
          "unitCode": "HUR",
          "unitPrice": 120.0,
          "lineTotal": 2400.0,
          "vatRate": 19.0,
          "vatCategoryCode": "S"
        }
      ],
      "totalNetAmount": 2400.0,
      "totalTaxAmount": 456.0,
      "totalGrossAmount": 2856.0
    },
    "warnings": [
      {
        "code": "PARSE_NOT_RETURNED",
        "message": "The document holds elements that this response does not return. elements lists each one by its path, with the number of times it occurs. terms names these EN 16931 business groups when one is among them: BG-3, BG-16, BG-20, BG-21, BG-23, BG-27, BG-28, BG-32. Attributes of an element that was read are not listed.",
        "elements": [
          {
            "path": "/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:URIUniversalCommunication",
            "count": 1
          },
          {
            "path": "/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:URIUniversalCommunication",
            "count": 1
          },
          {
            "path": "/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax",
            "count": 1
          },
          {
            "path": "/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradePaymentTerms",
            "count": 1
          },
          {
            "path": "/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:DuePayableAmount",
            "count": 1
          },
          {
            "path": "/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:TaxBasisTotalAmount",
            "count": 1
          },
          {
            "path": "/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans",
            "count": 1
          },
          {
            "path": "/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:AssociatedDocumentLineDocument",
            "count": 1
          },
          {
            "path": "/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:ApplicableTradeTax/ram:TypeCode",
            "count": 1
          }
        ],
        "terms": [
          "BG-16",
          "BG-23"
        ]
      }
    ]
  }
}

The document behind this example also carries a due date, payment terms, payment means and both parties’ electronic addresses. None of them is in invoice, and each is in warnings.

Parse response object

Field Type Description
format string Detected syntax: cii or ubl
profileDetected string? A label for the specification identifier when Beliq knows it: xrechnung, peppol, en16931, facturx-<profile> or extended-ctc-fr
profileUrn string? BT-24. The specification identifier as the document carries it
businessProcessId string? BT-23. The business process type as the document carries it. This is not invoice.businessProcessId, a generate input that takes the three French codes only
franceCtcDetected boolean? true when BT-23 is one of the French cadre de facturation codes or BT-24 is the EXTENDED-CTC-FR identifier. Absent otherwise
invoice Invoice The fields read from the document
warnings Warning[] What this response says about itself. Always present, and empty only when the parser read every element that holds something

Parsed invoice object

The parsed invoice uses the field names of the generate request invoice object and returns the fields in the tables below, whether the input was UBL or CII. It returns no other field of that object.

Every field but lines is returned only when the document states a value for it.

Field Type Always present Description
number string optional BT-1. Invoice number
issueDate string optional BT-2. Issue date, read as a date
currencyCode string optional BT-5. Document currency code
documentType string optional invoice or creditnote. On UBL the root element decides it and it is always present. On CII the type code decides it: a code that EN 16931 rule BR-CL-01 admits for an invoice only or for a credit note only. For a code it admits for both (81) or for neither, and for a document with no type code, the field is absent. Absent does not mean invoice
typeCode string optional BT-3. The type code as the document carries it, such as 380 or 381
buyerReference string optional BT-10. Buyer reference
seller Party optional Seller name, identifiers and postal address. Left out when the document states no field of the party object
buyer Party optional Buyer name, VAT identifier and postal address. Left out when the document states no field of the party object
lines InvoiceLine[] always BG-25. The invoice lines, or the credit note lines of a UBL credit note. Empty for a document that has none, such as Factur-X MINIMUM
delivery Delivery optional BG-13. Delivery information. Present only when the document carries at least one of the values below
totalNetAmount number optional BT-106. Sum of the line net amounts
totalTaxAmount number optional BT-110. The total VAT amount in the document currency: the amount whose currencyID is the document currency code, which is how EN 16931 rule BR-CO-15 selects it. When the document holds no such amount the field is left out, and no PARSE_VALUE_NOT_FOUND warning is sent. When it holds more than one, none of them is returned and a PARSE_VALUE_NOT_FOUND warning says so. An amount with no currencyID, and the amount in the VAT accounting currency (BT-111), are not returned here: they come under PARSE_NOT_RETURNED
totalGrossAmount number optional BT-112. Total with VAT

Parsed party object

Field Type Always present Description
name string optional BT-27 or BT-44. On UBL the registration name, cac:PartyLegalEntity/cbc:RegistrationName. The trading name in cac:PartyName is another term and is not returned as name: it comes under PARSE_NOT_RETURNED. On CII ram:Name
vatId string optional BT-31 or BT-48. On UBL the cbc:CompanyID of the party tax scheme whose scheme is VAT; on CII the tax registration with scheme VA
taxId string optional BT-32. CII only: the tax registration with scheme FC. On UBL it is not returned
address.street string optional BT-35 or BT-50
address.additionalStreet string optional BT-36 or BT-51. CII only. On UBL it is not returned
address.city string optional BT-37 or BT-52
address.postalCode string optional BT-38 or BT-53
address.countryCode string optional BT-40 or BT-55

address is left out when the postal address states none of its values.

Parsed invoice line object

Field Type Always present Description
description string optional BT-153. Item name
quantity number optional BT-129. Invoiced quantity, or the credited quantity on a UBL credit note
unitCode string optional BT-130. Unit of measure code
unitPrice number optional BT-146. Item net price
lineTotal number optional BT-131. Line net amount
vatRate number optional BT-152. Line VAT rate
vatCategoryCode string optional BT-151. Line VAT category code

A line that states none of these values is an empty object, so a line’s position in lines is its position in the document.

Numbers and dates

A number is returned when the element’s text is a decimal number as XML Schema writes one (xs:decimal): digits, with an optional sign and an optional fraction after a point, such as 1200, -5.50 or .5. Text in any other form, such as 1e3 or 1,200.00, is not read as a number. The response carries the number as a floating-point number. A decimal with more digits than that holds comes back as the nearest number it can hold.

A date is read by the form the document’s syntax prescribes:

  • UBL: the text must be an xs:date, a calendar date written YYYY-MM-DD. It is returned as the document writes it, with its time zone when it has one (2026-04-13+02:00). A day the month does not have, such as 2026-02-30, is not a date.
  • CII: the udt:DateTimeString must carry format="102" and hold YYYYMMDD, and it is returned as YYYY-MM-DD. Text under another format, or under none, is not read as a date. The day is not held to the month: CEN’s rule for this form, CII-DT-097, admits days 01 to 31 in every month, so 20260230 comes back as 2026-02-30.

Text that is not read as a number or a date leaves the field out, and a PARSE_VALUE_NOT_FOUND warning names the field and the element. So does a decimal too large for a floating-point number.

Warnings

Each entry of warnings has a code and a message, and the fields its code calls for.

Field Type Description
code string PARSE_NOT_RETURNED or PARSE_VALUE_NOT_FOUND
message string The warning in words
field string? PARSE_VALUE_NOT_FOUND: the invoice field the warning is about, as a path from invoice, such as totalGrossAmount or delivery.date. A field of an invoice line is written lines[].unitPrice, with no index
terms string[]? EN 16931 business term or group ids the warning is about
elements object[]? The elements of the document the warning is about, each as path and count. PARSE_NOT_RETURNED: those the response does not return. PARSE_VALUE_NOT_FOUND: those whose text was not read as a value

PARSE_NOT_RETURNED

Lists every element of the document that holds text or an attribute and that the parser did not read. An element whose text was read and refused as a number or a date is not listed here: it comes under PARSE_VALUE_NOT_FOUND. An element is listed once, at the top of the part that was not read: payment means with five children are one entry. path is written with the usual prefixes (/Invoice/cac:PaymentMeans, /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/...), and count is how often that path occurs. An element in a namespace outside UBL and CII is written with its namespace in braces. An attribute of an element that was read, such as a schemeID or a currencyID, is not listed.

terms names the business groups below when one is among the listed elements. Other terms are not named: find them by path.

Group Name UBL element CII element
BG-3 Preceding invoice reference cac:BillingReference ram:InvoiceReferencedDocument
BG-16 Payment instructions cac:PaymentMeans ram:SpecifiedTradeSettlementPaymentMeans
BG-20 Document level allowances cac:AllowanceCharge with cbc:ChargeIndicator false or 0 ram:SpecifiedTradeAllowanceCharge in the header settlement, indicator false
BG-21 Document level charges the same element, indicator true or 1 the same element, indicator true
BG-23 VAT breakdown cac:TaxTotal/cac:TaxSubtotal ram:ApplicableTradeTax in the header settlement
BG-27 Invoice line allowances cac:AllowanceCharge on a line, indicator false or 0 ram:SpecifiedTradeAllowanceCharge in the line settlement, indicator false
BG-28 Invoice line charges the same element, indicator true or 1 the same element, indicator true
BG-32 Item attributes cac:AdditionalItemProperty ram:ApplicableProductCharacteristic

Each group is found the way the rule context of that name selects it in CEN’s EN 16931 validation artefacts, the ones POST /v1/validate runs. An allowance or charge whose indicator is none of the values above is listed by its path and named as neither.

PARSE_VALUE_NOT_FOUND

The document holds something where field is read from, and it is not one value the response can return. field is then left out of invoice. The warning has two shapes:

  • With elements and no terms: an element holds text that was not read as a number or a date. elements lists each such element by path, and count is the number of elements at that path whose text was not read. The text itself is not repeated. There is one warning per field and reason, not one per occurrence. For a field of an invoice line, field is written without an index (lines[].unitPrice), so the warning covers every line whose value was not read and does not say which lines they are.
  • With terms ["BT-110"] and no elements: the document holds several total VAT amounts in its document currency, and the parser does not choose among them. field is totalTaxAmount. EN 16931 rule BR-CO-15 requires exactly one such amount on UBL, and on CII unless the total with VAT (BT-112) equals the total without VAT (BT-109).

A value the document does not state draws no PARSE_VALUE_NOT_FOUND: an element that is missing, is empty or holds only white space leaves its field out.

Parsed delivery object

The deliver-to party, place and date, read from cac:Delivery on UBL and from ram:ApplicableHeaderTradeDelivery on CII. The field names are those of the generate delivery object. A field is returned only when the document has a value for it.

Field Type Always present Description
name string optional BT-70. Deliver-to party name: cac:DeliveryParty/cac:PartyName/cbc:Name on UBL, ram:ShipToTradeParty/ram:Name on CII
locationId object optional BT-71, as id, with schemeId (BT-71-1) when the document carries a scheme. Read from cac:DeliveryLocation/cbc:ID on UBL. On CII it is ram:ShipToTradeParty/ram:GlobalID with its scheme, or the unqualified ram:ID, which has none
date string optional BT-72. Actual delivery date, read as a date: cbc:ActualDeliveryDate on UBL, ram:ActualDeliverySupplyChainEvent on CII
address DeliveryAddress optional BG-15. Deliver-to address. Present only when the document’s address carries at least one value

Parsed delivery address object

Field Type Always present Description
street string optional BT-75. Deliver-to street and house number
additionalStreet string optional BT-76. Additional deliver-to address line
city string optional BT-77. Deliver-to city
postalCode string optional BT-78. Deliver-to postal/ZIP code
countrySubentity string optional BT-79. Deliver-to country subdivision: cbc:CountrySubentity on UBL, ram:CountrySubDivisionName on CII
countryCode string optional BT-80. Deliver-to country code. Left out when the address states no country. EN 16931 rule BR-57 says each deliver-to address shall contain one

One value sent to POST /v1/generate does not come back from a CII document: a locationId.schemeId outside the ISO 6523 ICD list. Generate writes such an identifier to the unqualified ram:ID, because BR-CL-26 rejects a non-ICD scheme on ram:GlobalID, so the document holds no scheme to read. UBL keeps it.

Error responses

Error responses

HTTP Status Error Code When
400 VALIDATION_ERROR Request body is empty or not a valid file, the format query parameter is not one of its allowed values, or a query parameter is undeclared
400 PARSE_FAILED The input could not be parsed as a valid e-invoice (malformed XML, unsupported format, no embedded XML in PDF)
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
415 VALIDATION_ERROR The Content-Type is not one this route reads. Send application/xml, text/xml, application/octet-stream or application/pdf. Two other types get no 415: a JSON object or array sent as application/json gets a 400, and text/plain is read as UTF-8 text, which works for a UTF-8 XML document but not for a PDF. The free public demo is narrower: XML only, and PDF bytes are refused even when labelled as XML
503 ENGINE_UNAVAILABLE The 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

400 PARSE_FAILED example

{
  "success": false,
  "error": {
    "code": "PARSE_FAILED",
    "message": "Could not parse XML: element 'Invoice' not found in expected namespace"
  }
}
Notes

Notes

  • The parsed JSON uses the field names of the generate endpoint input. It is a subset of the document, so a document generated from it is not the document that was parsed: everything warnings lists is missing from it.
  • A field the document states no value for is left out of the response. It is not set to null, 0 or an empty string: see what an absent field means.
  • For hybrid PDFs, Beliq reads the embedded XML attachment automatically.