apyhub
Back
▣ FILE CONVERSION · FINANCE

Create, Validate & Parse E-Invoice API

What it does

E-Invoice Suite creates, validates, and reads EN 16931 e-invoices in JSON, XML, or PDF form. Send invoice data to generate a ZUGFeRD/Factur-X PDF/A-3 file, XRechnung XML, or Peppol BIS Billing 3.0 XML; send an XML or base64-encoded XML/PDF back to validate or parse it.

When you create an invoice, the input includes the invoice header, seller, buyer, line items, and optional payment and reference fields such as currency, issue_date, due_date, buyer_reference, order_reference, and vat_exemption_reason. The response includes the rendered file as XML or a data URI, plus totals, file size, page count for PDF output, warnings, and processing metadata such as cache, engine, and render timing.

Use validation when you need to check an incoming document against XSD, EN 16931, XRechnung, or Peppol rules. The response tells you whether the document is valid and returns the checks performed, structured errors and warnings, the detected syntax, container, profile, standard, document type, and specification ID.

Use parsing when you need invoice data back in JSON. E-Invoice Suite returns the invoice object, totals, notes for content not represented in the core invoice fields, and the detected syntax, container, profile, standard, document type, and specification ID. That makes it useful for accounting pipelines, procurement systems, and public-sector invoicing flows where you need both compliant output and reliable document inspection.

▣ ENDPOINT 01 / 03
POST
Create an e-invoice from JSON
https://api.eu.apyhub.com/callable-labs/create-validate-parse-e-invoices/v1/einvoice/create

QUICKSTART

GUIDE

Quickstart

Create a minimal e-invoice from the required invoice details and return it as XML.

curl -X POST "https://api.eu.apyhub.com/callable-labs/create-validate-parse-e-invoices/v1/einvoice/create" \
  -H "apy-token: $APY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "invoice": {
    "number": "RE-2026-0042",
    "issue_date": "2026-09-23",
    "currency": "EUR",
    "seller": {
      "name": "Callable Labs GmbH",
      "street": "Example Street 1",
      "city": "Berlin",
      "postal_code": "10115",
      "country": "DE",
      "vat_id": "DE123456789"
    },
    "buyer": {
      "name": "Acme GmbH",
      "street": "Example Street 2",
      "city": "Munich",
      "postal_code": "80331",
      "country": "DE"
    },
    "lines": [
      {
        "description": "Consulting",
        "quantity": 12,
        "unit": "HUR",
        "unit_price": 95,
        "vat_rate": 19
      }
    ]
  }
}'

What you'll get back

Returns a JSON object with fields such as xml and format; xml is the invoice XML, and format is the returned format. Other top-level fields like bytes, cache, pages, engine, totals, data_uri, standard, warnings, queued_ms, render_ms, media_type, and engine_version may also be present.

{
  "xml": "<Invoice>...</Invoice>",
  "format": "xml"
}
TRY ITLIVE · 100 ATOMS
Loading your default key…
The full key is used to call the gateway and stays in this tab — never sent to orbit or saved.
CreateRequest*
invoice*
buyer*
lines*
lines-1*
seller*

About this endpoint

What it does

Creates an e-invoice from the JSON request body and returns the generated invoice output in the format described by the response schema. The request includes the invoice data, and the response includes the rendered file content plus metadata and calculated totals.

Request Body

ParameterTypeMandatoryDescription
formatENUMNoOutput format. Allowed values: pdf, xml, json.
pdf is the default for zugferd/facturx.
xml is the default for xrechnung/peppol, and returns the bare CII for zugferd/facturx.
json returns the file as a data URI plus the XML, totals, and warnings.
invoiceObjectYesInvoice data. Required fields: number, issue_date, seller, buyer, lines. See nested fields below.
invoice.noteStringNoFree-text note (BT-22). Max 1000 characters.
invoice.typeENUMNoInvoice type. Allowed values: invoice, credit_note. Default: invoice.
invoice maps to type code 380, credit_note to 381.
invoice.buyerObjectYesBuyer party details. Required fields: name, city, postal_code, country.
invoice.buyer.cityStringYesCity. Min 1, max 200 characters.
invoice.buyer.nameStringYesLegal name (BT-27 / BT-44). Min 1, max 200 characters.
invoice.buyer.emailStringNoEmail address. Max 200 characters.
invoice.buyer.phoneStringNoPhone number. Max 64 characters.
invoice.buyer.streetStringNoStreet address. Max 200 characters.
invoice.buyer.vat_idStringNoVAT identifier (BT-31 / BT-48). Max 64 characters.
invoice.buyer.countryStringYesISO 3166-1 alpha-2 country code. Must match ^[A-Z]{2}$.
invoice.buyer.tax_numberStringNoSeller's national tax number, e.g. German Steuernummer (BT-32). Seller only. Max 64 characters.
invoice.buyer.postal_codeStringYesPostal code. Min 1, max 32 characters.
invoice.buyer.contact_nameStringNoContact name. Max 200 characters.
invoice.buyer.registration_idStringNoCompany register number, e.g. HRB 12345 or SIREN (BT-30 / BT-47). Max 64 characters.
invoice.buyer.electronic_addressStringNoDelivery address for e-invoices (BT-34 / BT-49). Must be either an email address or a Peppol participant ID in scheme:id form, matching `^([0-9]{4}:\S+
invoice.linesObject ArrayYesInvoice lines. At least 1 item, at most 500. Each item requires description, quantity, unit_price, vat_rate.
invoice.lines[].noteStringNoLine note (BT-127). Max 1000 characters.
invoice.lines[].unitStringNoUnit code. Default: C62.
UN/ECE Rec 20 unit code such as C62, HUR, DAY, MON, KGM, LTR, or a plain name like hour.
invoice.lines[].quantityNumberYesLine quantity. Must be greater than -1000000000 and less than 1000000000.
invoice.lines[].vat_rateNumberYesVAT percent for this line (BT-152). Must be between 0 and 100.
invoice.lines[].unit_priceNumberYesNet price per unit, before VAT (BT-146). Must be at least 0 and less than 1000000000.
invoice.lines[].descriptionStringYesItem name (BT-153). Min 1, max 1000 characters.
invoice.lines[].vat_categoryENUMNoEN 16931 VAT category (BT-151). Allowed values: S, Z, E, AE, K, G, O, L, M.
Defaults to S when vat_rate > 0.
Required when the rate is 0: Z zero rated, E exempt, AE reverse charge, K intra-EU, G export, O outside the scope of VAT.
invoice.numberStringYesInvoice number (BT-1). Min 1, max 64 characters.
invoice.sellerObjectYesSeller party details. Required fields: name, city, postal_code, country.
invoice.seller.cityStringYesCity. Min 1, max 200 characters.
invoice.seller.nameStringYesLegal name (BT-27 / BT-44). Min 1, max 200 characters.
invoice.seller.emailStringNoEmail address. Max 200 characters.
invoice.seller.phoneStringNoPhone number. Max 64 characters.
invoice.seller.streetStringNoStreet address. Max 200 characters.
invoice.seller.vat_idStringNoVAT identifier (BT-31 / BT-48). Max 64 characters.
invoice.seller.countryStringYesISO 3166-1 alpha-2 country code. Must match ^[A-Z]{2}$.
invoice.seller.tax_numberStringNoSeller's national tax number, e.g. German Steuernummer (BT-32). Seller only. Max 64 characters.
invoice.seller.postal_codeStringYesPostal code. Min 1, max 32 characters.
invoice.seller.contact_nameStringNoContact name. Max 200 characters.
invoice.seller.registration_idStringNoCompany register number, e.g. HRB 12345 or SIREN (BT-30 / BT-47). Max 64 characters.
invoice.seller.electronic_addressStringNoDelivery address for e-invoices (BT-34 / BT-49). Must be either an email address or a Peppol participant ID in scheme:id form, matching `^([0-9]{4}:\S+
invoice.paymentObjectNoPayment details. If provided, includes fields such as bic, iban, terms, means_code, and account_name.
invoice.payment.bicStringNoPayee BIC (BT-86). Max 11 characters.
invoice.payment.ibanStringNoPayee IBAN (BT-84). Max 34 characters.
invoice.payment.termsStringNoPayment terms (BT-20). Max 1000 characters.
invoice.payment.means_codeStringNoUNCL 4461 payment means (BT-81). Must be 1 to 3 digits. Defaults to 58 with an IBAN, otherwise 1.
invoice.payment.account_nameStringNoAccount holder (BT-85). Max 200 characters.
invoice.currencyStringNoISO 4217 currency code (BT-5). Must match ^[A-Z]{3}$. Default: EUR.
invoice.due_dateStringNoDue date in YYYY-MM-DD format (BT-9).
invoice.issue_dateStringYesIssue date in YYYY-MM-DD format (BT-2).
invoice.delivery_dateStringNoDate goods or services were delivered (BT-72).
invoice.buyer_referenceStringNoBuyer's reference (BT-10). Required by XRechnung for German public buyers as the Leitweg-ID; Peppol needs this or order_reference. Max 200 characters.
invoice.order_referenceStringNoPurchase order number (BT-13). Max 200 characters.
invoice.preceding_invoiceStringNoInvoice that a credit note corrects (BT-25). Max 64 characters.
invoice.vat_exemption_reasonStringNoReason VAT is not charged (BT-120). Required when any line uses E, AE, K, G, or O. Max 1000 characters.
downloadBooleanNoAdd Content-Disposition: attachment. Default: false.
standardENUMNoInvoice standard. Allowed values: zugferd, facturx, xrechnung, peppol.
Default: zugferd.
zugferd / facturx produce a PDF/A-3 invoice with embedded XML for Germany and France.
xrechnung produces XRechnung 3.0 XML (UBL), required by German public buyers.
peppol produces Peppol BIS Billing 3.0 XML (UBL).

Response

Returns a JSON object with xml, bytes, cache, pages, engine, format, totals, data_uri, standard, warnings, queued_ms, render_ms, media_type, and engine_version fields. The format field indicates whether the response payload is pdf or xml, and xml contains the invoice XML, which is also embedded in the PDF for zugferd/facturx.

ParameterTypeMandatoryDescription
xmlStringNoThe invoice XML. Also embedded in the PDF for zugferd/facturx.
bytesIntegerNoResponse size in bytes.
cacheENUMNoCache result. Allowed values: hit, miss.
pagesIntegerNoPDF page count. Nullable; null for DOCX/HTML.
engineStringNoRendering engine used.
formatENUMNoOutput format. Allowed values: pdf, xml.
totalsObjectNoComputed totals and VAT breakdown.
data_uriStringNodata:<media_type>;base64,… payload.
standardStringNoInvoice standard used.
warningsString ArrayNoWarning messages returned by the service.
queued_msIntegerNoTime spent queued, in milliseconds.
render_msIntegerNoRendering time, in milliseconds.
media_typeStringNoMedia type of the returned content.
engine_versionStringNoVersion of the rendering engine.
▣ ENDPOINT 02 / 03
POST
Validate an e-invoice
https://api.eu.apyhub.com/callable-labs/create-validate-parse-e-invoices/v1/einvoice/validate

QUICKSTART

GUIDE

Quickstart

Validate an e-invoice by sending the invoice XML in a JSON body.

curl -X POST "https://api.eu.apyhub.com/callable-labs/create-validate-parse-e-invoices/v1/einvoice/validate" \
  -H "apy-token: $APY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "xml": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><rsm:CrossIndustryInvoice xmlns:rsm=\"urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100\" xmlns:ram=\"urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100\" xmlns:udt=\"urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100\"><rsm:ExchangedDocumentContext><ram:GuidelineSpecifiedDocumentContextParameter><ram:ID>urn:cen.eu:en16931:2017</ram:ID></ram:GuidelineSpecifiedDocumentContextParameter></rsm:ExchangedDocumentContext><rsm:ExchangedDocument><ram:ID>INV-001</ram:ID><ram:TypeCode>380</ram:TypeCode><ram:IssueDateTime><udt:DateTimeString format=\"102\">20261007</udt:DateTimeString></ram:IssueDateTime></rsm:ExchangedDocument></rsm:CrossIndustryInvoice>"
}'

What you'll get back

Returns a JSON object with fields such as valid (boolean), checks (array), errors (array), syntax (cii or ubl), profile (string), standard (xrechnung, peppol, facturx, en16931, or unknown), warnings (array), container (xml or pdf), document_type (invoice or credit_note), and specification_id (string).

{
  "valid": false,
  "standard": "facturx",
  "profile": "Factur-X / ZUGFeRD EN 16931",
  "syntax": "cii",
  "document_type": "invoice",
  "specification_id": "urn:cen.eu:en16931:2017",
  "container": "xml",
  "checks": [
    {
      "name": "xsd",
      "title": "XML Schema (CII D16B (Factur-X EN16931))",
      "passed": false,
      "errors": 1,
      "warnings": 0
    },
    {
      "name": "en16931",
      "title": "EN 16931 business rules (CEN)",
      "version": "1.3.16",
      "passed": false,
      "errors": 7,
      "warnings": 0
    }
  ],
  "errors": [
    {
      "rule": "XSD",
      "check": "xsd",
      "message": "Element '{urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100}ApplicableHeaderTradeAgreement': This element is not expected. Expected is ( {urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100}IncludedSupplyChainTradeLineItem ).",
      "location": "line 1"
    },
    {
      "rule": "BR-08",
      "check": "en16931",
      "message": "[BR-08]-An Invoice shall contain the Seller postal address (BG-5).",
      "location": "/*:CrossIndustryInvoice[namespace-uri()='urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100']"
    },
    {
      "rule": "BR-09",
      "check": "en16931",
      "message": "[BR-09]-The Seller postal address (BG-5) shall contain a Seller country code (BT-40).",
      "location": "/*:CrossIndustryInvoice[namespace-uri()='urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100']"
    },
    {
      "rule": "BR-10",
      "check": "en16931",
      "message": "[BR-10]-An Invoice shall contain the Buyer postal address (BG-8).",
      "location": "/*:CrossIndustryInvoice[namespace-uri()='urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100']"
    },
    {
      "rule": "BR-11",
      "check": "en16931",
      "message": "[BR-11]-The Buyer postal address shall contain a Buyer country code (BT-55).",
      "location": "/*:CrossIndustryInvoice[namespace-uri()='urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100']"
    },
    {
      "rule": "BR-16",
      "check": "en16931",
      "message": "[BR-16]-An Invoice shall have at least one Invoice line (BG-25).",
      "location": "/*:CrossIndustryInvoice[namespace-uri()='urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100']"
    },
    {
      "rule": "BR-CO-15",
      "check": "en16931",
      "message": "[BR-CO-15]-Invoice total amount with VAT (BT-112) = Invoice total amount without VAT (BT-109) + Invoice total VAT amount (BT-110).",
      "location": "/*:CrossIndustryInvoice[namespace-uri()='urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100']"
    },
    {
      "rule": "BR-CO-26",
      "check": "en16931",
      "message": "[BR-CO-26]-In order for the buyer to automatically identify a supplier, the Seller identifier (BT-29), the Seller legal registration identifier (BT-30) and/or the Seller VAT identifier (BT-31) shall be present.",
      "location": "/*:CrossIndustryInvoice[namespace-uri()='urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100']/*:SupplyChainTradeTransaction[namespace-uri()='urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100']/*:ApplicableHeaderTradeAgreement[namespace-uri()='urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100']/*:SellerTradeParty[namespace-uri()='urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100']"
    }
  ],
  "warnings": []
}
TRY ITLIVE · 20 ATOMS
Loading your default key…
The full key is used to call the gateway and stays in this tab — never sent to orbit or saved.
The e-invoice to read or validate. Choose XML or Base64 from the dropdown and provide exactly one.
XML*
The e-invoice XML as a string (CII or UBL). Max 10 MiB.

About this endpoint

What it does

Validates an e-invoice sent as XML or as a base64-encoded XML/PDF document. The response returns a validation summary plus any checks, errors, warnings, and detected document metadata found in the submitted file.

Request Body

ParameterTypeMandatoryDescription
xmlStringNoThe e-invoice XML as a string. Maximum length: 10485760 characters. Default: null.
file_base64StringNoAn XML or PDF (ZUGFeRD/Factur-X) file, base64-encoded. Maximum length: 14680064 characters. Default: null.

Response

Returns a JSON object with valid as a boolean, checks and errors as arrays, syntax and standard as ENUM strings, profile as a string, warnings as an array, container as an ENUM string, document_type as an ENUM string, and specification_id as a string. The valid field indicates whether the e-invoice passed validation.

ParameterTypeMandatoryDescription
validBooleanNoWhether the e-invoice is valid.
checksObject ArrayNoOne entry per check run: xsd, en16931, then xrechnung or peppol.
errorsObject ArrayNoValidation errors. Each item may include rule, check, message, and location.
syntaxENUMNoDetected syntax format. Allowed values: cii, ubl.
profileStringNoDetected profile name, if available. Example: XRechnung 3.0.
standardENUMNoDetected standard. Allowed values: xrechnung, peppol, facturx, en16931, unknown. facturx covers ZUGFeRD 2.x and Factur-X.
warningsObject ArrayNoValidation warnings. Each item may include rule, check, message, and location.
containerENUMNoDetected container type. Allowed values: xml, pdf.
document_typeENUMNoDetected document type. Allowed values: invoice, credit_note.
specification_idStringNoBT-24 as found in the document.
▣ ENDPOINT 03 / 03
POST
Read an e-invoice into JSON
https://api.eu.apyhub.com/callable-labs/create-validate-parse-e-invoices/v1/einvoice/parse

QUICKSTART

GUIDE

Quickstart

Send the e-invoice as XML text or a base64-encoded XML/PDF so the API can parse the document.

curl -X POST "https://api.eu.apyhub.com/callable-labs/create-validate-parse-e-invoices/v1/einvoice/parse" \
  -H "apy-token: $APY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "xml": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><rsm:CrossIndustryInvoice xmlns:rsm=\"urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100\" xmlns:ram=\"urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100\" xmlns:udt=\"urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100\"><rsm:ExchangedDocumentContext><ram:GuidelineSpecifiedDocumentContextParameter><ram:ID>urn:cen.eu:en16931:2017</ram:ID></ram:GuidelineSpecifiedDocumentContextParameter></rsm:ExchangedDocumentContext><rsm:ExchangedDocument><ram:ID>INV-001</ram:ID><ram:TypeCode>380</ram:TypeCode><ram:IssueDateTime><udt:DateTimeString format=\"102\">20261007</udt:DateTimeString></ram:IssueDateTime></rsm:ExchangedDocument></rsm:CrossIndustryInvoice>"
}'

What you'll get back

Returns a JSON object with fields such as notes (array of strings), syntax (cii or ubl), totals (object), invoice (object), profile (string), standard (xrechnung, peppol, facturx, en16931, or unknown), container (xml or pdf), document_type (invoice or credit_note), and specification_id (string).

{
  "standard": "facturx",
  "profile": "Factur-X / ZUGFeRD EN 16931",
  "syntax": "cii",
  "document_type": "invoice",
  "specification_id": "urn:cen.eu:en16931:2017",
  "container": "xml",
  "invoice": {
    "type": "invoice",
    "number": "INV-001",
    "issue_date": "2026-10-07",
    "currency": "EUR",
    "seller": {
      "name": "ABC GmbH"
    },
    "buyer": {
      "name": "XYZ GmbH"
    },
    "lines": []
  },
  "totals": {
    "line_total": null,
    "tax_total": null,
    "total": null,
    "amount_due": null,
    "vat": []
  },
  "notes": []
}
TRY ITLIVE · 20 ATOMS
Loading your default key…
The full key is used to call the gateway and stays in this tab — never sent to orbit or saved.
The e-invoice to read. Choose XML or Base64 from the dropdown and provide exactly one.
XML*
The e-invoice XML as a string (CII or UBL). Max 10 MiB.

About this endpoint

What it does

Parses an e-invoice from XML or a base64-encoded file and returns a JSON object with the document’s extracted metadata and parsed content. The request accepts either xml or file_base64 in the body.

Request Body

ParameterTypeMandatoryDescription
xmlStringNoThe e-invoice XML as a string. Maximum length: 10,485,760 characters.
file_base64StringNoAn XML or PDF (ZUGFeRD/Factur-X) file, base64-encoded. Maximum length: 14,680,064 characters.

Response

Returns a JSON object with these top-level fields: notes as a string array, syntax as a string enum, totals as an object, invoice as an object, profile as a string, standard as a string enum, container as a string enum, document_type as a string enum, and specification_id as a string. The schema allows additional properties beyond these documented fields.

ParameterTypeMandatoryDescription
notesString ArrayNoContent that is not represented in invoice (allowances, charges, other type codes).
syntaxENUMNoAllowed values: cii, ubl.
totalsObjectNoTotals and VAT breakdown exactly as stated in the document.
invoiceObjectNoSame fields as create's invoice.
profileStringNoExample: XRechnung 3.0.
standardENUMNoAllowed values: xrechnung, peppol, facturx, en16931, unknown. facturx covers ZUGFeRD 2.x and Factur-X.
containerENUMNoAllowed values: xml, pdf.
document_typeENUMNoAllowed values: invoice, credit_note.
specification_idStringNoBT-24 as found in the document.
▣ COMMON ERRORS

Errors any endpoint can return

400bad_request

Required parameter missing or malformed body.

401unauthorized

API key missing, revoked, or not authorized for this service.

429rate_limited

Your plan's per-second rate exceeded. Retry with exponential backoff.

503upstream_busy

Backend temporarily unavailable. Try again in a few seconds.