eliDocs
API Reference

POST /v1/validate

POST/v1/validate

Validate an e-invoice: EN 16931 and CIUS Schematron for UBL and CII; XSD only for FatturaPA, Facturae, e-SLOG, KSeF FA(3) and the SDI file messaggio.

Upload an invoice file (XML or PDF) and receive a validation result.

A PDF is judged by the invoice XML embedded in it, and only by that. Beliq looks for an embedded file named factur-x.xml, zugferd-invoice.xml or xrechnung.xml: first among the files the PDF lists as associated files (/AF), then among all its embedded files. Failing those it takes the first .xml file whose content starts like an invoice. When a PDF holds more than one such file, one is read and the others are not looked at. The response says which file was read, how it was found and how many there were, in pdfInput. The PDF itself is not checked: there is no PDF/A-3 conformance check, no check of how the XML is attached (AFRelationship), and no comparison of the XMP metadata with the XML. A PDF that carries no invoice XML returns 400.

For UBL and CII documents in the EN 16931 family, checks include:

  1. XML structure (XSD)
  2. EN 16931 business rules (Schematron)
  3. Country- or network-specific rules when applicable: XRechnung for Germany, Peppol BIS Billing 3.0 for cross-border / Peppol Network invoices

For Italy FatturaPA XML (Agenzia namespaces: FatturaElettronica / FatturaElettronicaSemplificata), Beliq validates against the published W3C XML Schema graph bundled in the engine. That path is XSD only (no EN 16931 Schematron; no BR-* rule IDs). Additional normative constraints from the Italian technical specification (tables / regole) are not implemented as code in this release.

For Italy SDI file messaggio XML (namespace http://www.fatturapa.gov.it/sdi/messaggi/v1.0, roots such as NotificaScarto, RicevutaConsegna, … per MessaggiTypes_v1.1), Beliq validates against the authority Messaggi XSD vendored in the engine. Use format=sdi_messaggio or rely on auto-detect when the root element matches. This is interchange notification / receipt structural validation only. It is not FatturaPA invoice-body validation and not a substitute for SDI transport (which remains outside Beliq; SDI submission is not implemented).

For Spain Facturae XML (MINECO namespace http://www.facturae.gob.es/formato/Versiones/Facturaev3_2_2.xml, root Facturae), Beliq validates against the published Facturae 3.2.2 XSD bundled in the engine. Use format=facturae or rely on auto-detect. That path is XSD only (no EN 16931 Schematron; no BR-* rule IDs). VeriFactu / FACe submission and XAdES signing remain outside Beliq (BYOC).

For Slovenia e-SLOG 2.0 XML (namespace urn:eslog:2.00, root Invoice wrapping M_INVOIC), Beliq validates against the GZS/ePOS e-SLOG 2.0 XSD bundled in the engine. Use format=eslog or rely on auto-detect. That path is XSD only (no EN 16931 Schematron; no BR-* rule IDs). UJP submission, e-route provider services, and XML-DSig signing remain outside Beliq (BYOC).

For Poland KSeF FA(3) XML (namespace http://crd.gov.pl/wzor/2025/06/25/13775/, root Faktura), Beliq validates against the Ministerstwo Finansów FA(3) XSD bundled in the engine. Use format=poland_ksef_fa3 or rely on auto-detect. That path is the XSD plus the MF’s document-level KSeF acceptance checks (no EN 16931 Schematron; no BR-* rule IDs), and KSeF applies its business rules only at submission, which Beliq does not operate: transmission goes via your chosen intermediary. An FA(2) document (namespace http://crd.gov.pl/wzor/2023/06/29/12648/) is recognised but never passes: FA(2) is superseded by FA(3) and rejected by KSeF, so the result is valid: false with a leading POLAND_KSEF_FA2_SUPERSEDED error.

Quick copy examples

Quick copy examples

Validate XML:

validate-xml.sh
curl -X POST "https://api.beliq.eu/v1/validate?format=auto" \
  -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 result = await beliq.validate(await readFile('invoice.xml'), { format: 'auto' });

console.log(result.valid, result.format, result.schematronVersion);
for (const issue of result.errors) console.log(issue.ruleId, issue.message);
import os
from pathlib import Path

from beliq import Beliq

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

result = beliq.validate(Path("invoice.xml").read_bytes(), format="auto")

print(result.valid, result.format, result.schematron_version)
for issue in result.errors:
    print(issue.rule_id, issue.message)

Validate PDF:

validate-pdf.sh
curl -X POST https://api.beliq.eu/v1/validate \
  -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 result = await beliq.validate(await readFile('invoice.pdf'));

console.log(result.valid, result.format, result.schematronVersion);
for (const issue of result.errors) console.log(issue.ruleId, issue.message);
import os
from pathlib import Path

from beliq import Beliq

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

result = beliq.validate(Path("invoice.pdf").read_bytes())

print(result.valid, result.format, result.schematron_version)
for issue in result.errors:
    print(issue.rule_id, issue.message)
Request

Request

POST /v1/validate
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
Beliq-Ruleset optional Pin the validation ruleset for this request to a channel (latest or previous) or to exact artifact versions, overriding your org’s default channel. The applied ruleset is echoed in the Beliq-Ruleset-Resolved response header. See Ruleset versioning.

Query parameters

Parameter Type Required Description
format string optional Format hint: auto, cii, ubl, fatturapa, facturae (Spain Facturae 3.2.2 XML, XSD only), eslog (Slovenia e-SLOG 2.0 XML, XSD only), poland_ksef_fa3 (Poland KSeF FA(3) XML, XSD and KSeF acceptance checks), poland_ksef_fa2 (Poland KSeF FA(2), superseded by FA(3): always valid: false with POLAND_KSEF_FA2_SUPERSEDED), or sdi_messaggio (Italy SDI file messaggio XML, XSD only, not a FatturaPA invoice). When set to auto (default), the engine detects the format automatically (including FatturaPA, Facturae, e-SLOG, KSeF FA(3), KSeF FA(2) and SDI messaggi when the root element matches).
franceCtc boolean optional true applies FNFE-MPE’s BR-FR-CTC Flux 2 overlay to a CII or UBL document the engine would not otherwise put in CTC mode. Defaults to false. The France guide says when the overlay runs.

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.

validate.sh
curl -X POST "https://api.beliq.eu/v1/validate?format=auto" \
  -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 result = await beliq.validate(await readFile('invoice.xml'), { format: 'auto' });

console.log(result.valid, result.format, result.schematronVersion);
for (const issue of result.errors) console.log(issue.ruleId, issue.message);
import os
from pathlib import Path

from beliq import Beliq

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

result = beliq.validate(Path("invoice.xml").read_bytes(), format="auto")

print(result.valid, result.format, result.schematron_version)
for issue in result.errors:
    print(issue.rule_id, issue.message)
Response

Response

Alongside the JSON body below, the response carries the verdict, the detected syntax and profile, and the ruleset seal as headers. See the Response headers reference.

Success (200)

{
  "success": true,
  "data": {
    "valid": true,
    "format": "cii",
    "profileDetected": "XRechnung",
    "schematronVersion": "1.3.16",
    "ciusVersion": "XRechnung-2.6.0",
    "errors": [],
    "warnings": []
  }
}

Validation result object

Field Type Description
valid boolean true if the invoice passes all validation stages with no fatal/error-level violations
verified boolean? Whether a ruleset actually executed. false only when verify: false skipped validation on POST /v1/generate, in which case errors and warnings are empty because nothing looked at the document
format string Detected format: cii, ubl, fatturapa, facturae, eslog, poland_ksef_fa3, poland_ksef_fa2 (superseded, never valid), sdi_messaggio, or unknown
profileDetected string? Detected profile label when applicable (e.g. xrechnung, peppol, romania-ro-cius, netherlands-nlcius, en16931, Italy FatturaPA labels such as italy-fatturapa-ordinaria-fpr12, Spain Facturae label spain-facturae-v3-2-2, Slovenia e-SLOG label slovenia-eslog-v2-0, Poland KSeF FA(3) label poland-ksef-fa3-13775, or messaggio labels such as italy-sdi-notifica-scarto)
sha256 string Lowercase-hex SHA-256 of the exact request body validated. Reproduce with sha256sum on your file. Always present.
rulesetSha256 string? Single fingerprint of the rule artifacts that judged the document, the syntax schema it was checked against included. Present whenever a ruleset ran, which includes a document the syntax schema rejected; reconstructable from rulesetArtifacts.
rulesetArtifacts object[]? The component rows behind rulesetSha256, { key, version, fileSha256 } each. For an EN 16931 document one row is the syntax schema: cii_xsd, cii_xsd_d22b or ubl_xsd, or a Factur-X profile’s own schema under facturx_schematron. See Verify a hash for the reconstruction and catalog cross-check.
driftCheckedAt string? ISO 8601 UTC instant reporting when the pinned artifacts that judged the document were last confirmed to still match their upstream authority sources (the nightly drift check). A conservative lower bound: “verified at least as recently as this instant.” Present alongside rulesetSha256 only when every pinned artifact cleared a clean, matching check; omitted otherwise. See When the ruleset was last drift-checked.
rulesetChannel string? The ruleset channel applied to this request (latest or previous), present when a channel was selected via the Beliq-Ruleset header or when your org default is previous. See Ruleset versioning.
rulesetFellBack boolean? true when previous was requested and nothing the request resolved had a retained ruleset for the channel to reach, so the request ran exactly what latest would have run. Two things leave an artifact with nothing to reach: it retains no prior ruleset at all, or the one it retains has been superseded, meaning the authority’s own mandatory date for the successor has passed and Beliq stops picking the older ruleset on your behalf. An exact pin still reaches a superseded version until its sunset date. One document resolves several rule artifacts and previous reaches each out of what that artifact still offers, so a request can run a retained artifact beside one that fell back. That is not a fallback: this field, rulesetChannel, rulesetSunsetsOn and Beliq-Ruleset-Resolved each collapse the whole resolution to one answer, and rulesetArtifacts is what names the version every artifact that judged the document ran at. Present only alongside rulesetChannel.
rulesetSunsetsOn string? ISO date (YYYY-MM-DD) the retained ruleset that served this request stops being served. Present only when a retained ruleset actually ran, so never on a default request; the earliest date when several ran. After it an exact pin returns 422, so treat it as your deadline to migrate off the pin. It bounds the pin, not the channel: previous stops reaching the version on this date or on the authority’s mandatory date for the successor, whichever comes first. See Ruleset versioning.
verificationTier string? How the rules that judged this document are backed: conformance-verified, builder-round-trip, reconstructed-rules or xsd-structural. Where several rule packs judged the document, it is the weakest of theirs. Left out, rather than guessed, unless every rule set that judged the document has a tier on record. Also left out when any rule set gave no verdict, because its run failed, timed out or produced a report over the size limit: valid is then false, and the rule sets that did judge the document are not the whole check. See Verification tiers.
verificationBadge string? The badge for verificationTier, as an id: authority-verified, independently-rule-checked or structure-checked. Present only beside verificationTier. Compare this field in code.
verificationBadgeLabel string? The label of verificationBadge in English, the same one the coverage cards show for that badge. Display text: print it as it is, and compare verificationBadge, not this string. Present only beside verificationBadge.
schematronVersion string? Version of CEN’s EN 16931 Schematron, present only where that pack judged the document. Omitted for the Factur-X MINIMUM, BASIC WL, BASIC and EXTENDED profiles, which their own Factur-X pack judges in its place; for a document its syntax schema rejected; when the EN 16931 pack ran and gave no verdict; and for FatturaPA, Facturae, e-SLOG, KSeF FA(3), and SDI file messaggio (XSD-only validation).
ciusVersion string? CIUS Schematron version used (e.g. "XRechnung-2.6.0" or "PeppolBIS-Billing-3.0.21")
peppolVersion string? Peppol BIS Billing 3.0 CIUS version used. Only present when profileDetected === "peppol"; mirrors ciusVersion for Peppol-specific consumers
romaniaRoCiusVersion string? Romania CIUS-RO Schematron version used. Only present when profileDetected === "romania-ro-cius"; mirrors ciusVersion for Romania-specific consumers. See Romania format reference.
netherlandsNlciusVersion string? Netherlands NLCIUS (SI-UBL 2.0) Schematron version used. Only present when profileDetected === "netherlands-nlcius"; mirrors ciusVersion for NL-specific consumers. See Netherlands NLCIUS format reference.
facturxProfile string? Detected Factur-X profile, when the document’s CustomizationID names one
facturxVersion string? Factur-X / ZUGFeRD package version the engine used
italyFatturapaXsdBundle string? Present for FatturaPA invoice XML: human-readable label of the authority XSD bundle used (no Schematron).
italyFatturapaRuntimeVersion string? Present for FatturaPA invoice XML: the pinned bundle version.
italySdiMessaggiXsdBundle string? Present for SDI file messaggio XML: human-readable label of the MessaggiTypes XSD bundle (not FatturaPA invoices).
italySdiMessaggiXsdVersion string? Present for SDI file messaggio XML: the pinned bundle version.
spainFacturaeXsdBundle string? Present for Facturae invoice XML: human-readable label of the authority XSD bundle used (no Schematron).
spainFacturaeRuntimeVersion string? Present for Facturae invoice XML: the pinned bundle version.
sloveniaEslogXsdBundle string? Present for e-SLOG XML: human-readable label of the authority XSD bundle used (no Schematron).
sloveniaEslogRuntimeVersion string? Present for e-SLOG XML: the pinned bundle version.
polandKsefFa3XsdBundle string? Present for KSeF FA(3) XML: label of the authority XSD graph used.
polandKsefFa3RuntimeVersion string? Present for KSeF FA(3) XML: the pinned bundle version.
franceCtcApplied boolean? true when the BR-FR-CTC Flux 2 pack judged the document. Left out when the pack did not run, and when it ran and gave no verdict
franceCtcVersion string? France CTC Schematron version used
franceExtendedCtcApplied boolean? true when the EXTENDED-CTC-FR pack judged the document, in either syntax
franceCtcBlockingRuleIds string[]? The BR-FR-CTC Flux 2 rule ids the document trips, at any severity, sorted. A separate answer from valid, which follows the severity the rule pack assigns: Warnings are not all optional says why. Left out, and never an empty array, in three cases: the Flux 2 pack ran and no rule fired, with franceCtcApplied true; the pack did not run; and the pack ran and gave no verdict, because its run failed, timed out or produced a report over the size limit. In the last two franceCtcApplied is left out too. Rules of the EXTENDED-CTC-FR pack are not listed. The same ids are in an info entry FRANCE_CTC_FINDINGS_BLOCK_TRANSMISSION in warnings.
pdfInput PdfInput? Present only when the request body was a PDF: which embedded file the verdict is about, and that the PDF around it was not checked
errors ValidationError[] Violations at fatal or error severity
warnings ValidationError[] Violations at warning or info severity

PDF input object

Sent as pdfInput when the request body was a PDF, with a valid verdict and with an invalid one.

Field Type Description
containerChecked boolean Always false. Nothing checked the PDF itself: not its PDF/A conformance, not its XMP metadata, not how the invoice file is attached. The verdict is about the embedded XML only
attachmentName string? Name of the embedded file whose XML was read, as the PDF states it. Left out when that name is longer than 255 UTF-16 code units, or holds U+0000 or half of a surrogate pair
attachmentFoundBy string How that file was picked. The steps are tried in this order, and a step whose first file cannot be read hands over to the next. associated-file: the first entry of the catalog’s /AF array under one of the three names above. embedded-file: the first entry of the /EmbeddedFiles name tree under such a name. xml-content: the first *.xml file whose content starts like an invoice, whatever its name
attachmentCandidates integer How many embedded files the step in attachmentFoundBy accepts, the one that was read included. Above 1, the PDF holds another file that could be taken for the invoice, and nothing compared the two
"pdfInput": {
  "containerChecked": false,
  "attachmentName": "factur-x.xml",
  "attachmentFoundBy": "associated-file",
  "attachmentCandidates": 1
}

Validation error object

Field Type Description
ruleId string Official business rule ID (e.g. BR-01, BR-DE-15, PEPPOL-EN16931-R001), or a Beliq advisory ID (see Advisory findings)
severity string fatal, error, warning, or info
location string? XPath location of the violation in the source XML
message string Human-readable description of the violation

Peppol BIS Billing 3.0 example

When the input declares the Peppol BIS Billing 3.0 customization, Beliq runs the OpenPeppol Schematron in addition to EN 16931 and reports the Peppol version explicitly:

{
  "success": true,
  "data": {
    "valid": true,
    "format": "ubl",
    "profileDetected": "peppol",
    "schematronVersion": "1.3.16",
    "ciusVersion": "PeppolBIS-Billing-3.0.21",
    "peppolVersion": "PeppolBIS-Billing-3.0.21",
    "errors": [],
    "warnings": []
  }
}

Example with validation errors

{
  "success": true,
  "data": {
    "valid": false,
    "format": "cii",
    "profileDetected": "XRechnung",
    "schematronVersion": "1.3.16",
    "ciusVersion": "XRechnung-2.6.0",
    "errors": [
      {
        "ruleId": "BR-01",
        "severity": "error",
        "location": "/rsm:CrossIndustryInvoice/rsm:ExchangedDocumentContext",
        "message": "An Invoice shall have a Specification identifier (BT-24)."
      },
      {
        "ruleId": "BR-DE-15",
        "severity": "error",
        "location": "/rsm:CrossIndustryInvoice",
        "message": "An XRechnung invoice must contain a buyer reference (BT-10)."
      }
    ],
    "warnings": [
      {
        "ruleId": "BR-CL-01",
        "severity": "warning",
        "location": "/rsm:CrossIndustryInvoice/...",
        "message": "The currency code should be a valid ISO 4217 code."
      }
    ]
  }
}
Advisory findings

Advisory findings

A validation artifact does not always implement every rule its standard’s text carries. Where a rule is in the normative text, is absent from every artifact that judged your document, and is still enforced by other validators your invoice may reach, Beliq reports the violation as an advisory: severity: "info", in warnings.

An advisory never changes valid. That flag reflects only the artifacts that actually ran, so a document is never failed here by a rule the pinned artifacts do not carry. rulesetArtifacts names and rulesetSha256 fingerprints those of them that judged the document. Advisory IDs are deliberately not official rule IDs, so you can tell them apart: they read <STANDARD>_<RULE>_NOT_ENFORCED.

One rule qualifies today.

Advisory ID Rule What it means
EN16931_BR_CO_25_NOT_ENFORCED BR-CO-25, EN 16931-1 § 6.13.7 Amount due for payment (BT-115) is positive but neither the payment due date (BT-9) nor the payment terms (BT-20) is present. Removed from the EN 16931 Schematron in 1.3.16, and absent from the Factur-X 1.09.2 BASIC, BASIC-WL and EN 16931 packs. Still enforced by the Factur-X EXTENDED pack, the Factur-X 1.08 BASIC, BASIC-WL, EN 16931 and EXTENDED packs, the FNFE-MPE France EXTENDED-CTC-FR overlay and the Romanian RO-CIUS overlay.
{
  "ruleId": "EN16931_BR_CO_25_NOT_ENFORCED",
  "severity": "info",
  "location": "/rsm:CrossIndustryInvoice",
  "message": "Amount due for payment (BT-115) is positive but neither the Payment due date (BT-9) nor the Payment terms (BT-20) is present. ..."
}

Supplying a payment due date or payment terms clears it. Credit notes are out of scope for this rule and never draw the advisory. Neither does a Factur-X MINIMUM document: that profile has no element for a due date or payment terms, so it cannot carry either.

You will not see the advisory when an artifact that ran already enforces the rule. A Factur-X EXTENDED document is judged by a pack that carries BR-CO-25, so the violation arrives as an ordinary error from that pack instead. A BASIC or BASIC-WL document validated on the previous ruleset channel (Beliq-Ruleset: previous) gets it as an error too, under the pack’s own rule ID, while that channel runs the Factur-X 1.08 packs. The same happens to the documents any other artifact judges once a release of it reinstates the rule. For the full background, see Validation artifacts.

Response verifiability

Response verifiability

Every response carries two hashes so you can confirm the result yourself: sha256 (the exact bytes you sent) and rulesetSha256 (the rule artifacts that judged them), plus the rulesetArtifacts rows the ruleset hash is built from. For an EN 16931 document those rows include the syntax schema, because a document the schema rejects is judged by the schema alone and no business rule runs. Responses may also carry driftCheckedAt, a UTC timestamp reporting when those artifacts were last confirmed against their upstream authority sources.

{
  "success": true,
  "data": {
    "valid": false,
    "format": "ubl",
    "profileDetected": "netherlands-nlcius",
    "sha256": "8b508d3648dbee66ca6798e6bc812842204974328fd626e3d9cdf60c98782cd1",
    "rulesetSha256": "9f539954095415c7d9e8f1fb8459afe532d3ce3395fdd626d0e2fa73a4e4a887",
    "rulesetArtifacts": [
      { "key": "en16931_ubl_schematron", "version": "1.3.16", "fileSha256": "39f9d282867f1a49e7708d9e29a53da89643e1ee56f10cec1ebcf1277595fcbd" },
      { "key": "netherlands_nlcius_schematron", "version": "2.0.3.13", "fileSha256": "73da3db0b8cf6a37a8ad17051ac1603a83a695e2fa066820803aa1283a06e140" },
      { "key": "ubl_xsd", "version": "2.1", "fileSha256": "40fae8cb436f3a9506d7acce65ba162caef3b0bed4d5cbc0992b2153ded4edf4" }
    ],
    "driftCheckedAt": "2026-07-03T04:12:07Z"
  }
}

sha256sum your file to match sha256; sort the rulesetArtifacts "<key>@<version>=<fileSha256>" lines, join with newlines, and SHA-256 to reproduce rulesetSha256; then cross-check each component against GET /v1/rulesets. driftCheckedAt, when present, reports how recently that ruleset was drift-checked against its authority sources. Full walkthrough: Verify a hash.

Error responses

Error responses

HTTP Status Error Code When
400 VALIDATION_ERROR Request body is empty; its Content-Type is not a raw XML or PDF body; the PDF carries no embedded invoice XML (not a ZUGFeRD / Factur-X hybrid); the Beliq-Ruleset header is malformed; or a query parameter is undeclared or has a value it does not take
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
422 VALIDATION_ERROR A well-formed Beliq-Ruleset pin names a ruleset version or artifact that is no longer served, or pins xrechnung_schematron and xrechnung_severity_overrides at versions from two different KoSIT bundles
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

400 example

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request body must contain an XML or PDF file"
  }
}
Notes

Notes

  • valid: false is not an API error. It means validation ran successfully and found rule violations.
  • format tells you which syntax family was detected (cii, ubl, fatturapa, facturae, eslog, poland_ksef_fa3, or sdi_messaggio).
  • Rule IDs follow the official naming conventions where Schematron is used: BR-* for EN 16931 core rules, BR-DE-* for XRechnung rules, PEPPOL-* for Peppol-specific rules. FatturaPA, Facturae, e-SLOG, KSeF FA(3), and SDI file messaggio XSD violations use ruleId: "XSD" (structural). KSeF FA(3) acceptance-check failures use KSEF_* rule IDs, listed in the format reference. Messaggio validation does not imply FatturaPA invoice conformance or SDI operational interchange.
  • A document in no syntax Beliq recognises comes back as a normal validation result, not an error: HTTP 200, valid: false, format: "unknown", and a single fatal finding with ruleId: "UNSUPPORTED_FORMAT". Match on errors[].ruleId, not on error.code, which is absent on a 200.
  • See the validation artifacts page for details on which Schematron versions are currently in use.