Automation MCP Server Features Blog Pricing Contact

CII Validation API Reference

Technical reference for validating standalone UN/CEFACT Cross Industry Invoice (CII) XML. The endpoint runs the CII D16B XSD, then the business rules matching the profile declared in BT-24: the EN 16931 Schematron for core documents, the official Factur-X / ZUGFeRD per-profile rules for MINIMUM through EXTENDED, and the KoSIT rules for XRechnung CII. Findings are returned as structured JSON.

POST /v1/validate/cii

Code Example

curl -X POST https://api.invoicexml.com/v1/validate/cii \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "[email protected]"

The invoice profile and version are detected automatically from the uploaded file, so you never need to pass them. The detected values are returned in the response.

Try it out online, no coding required

Upload an invoice and get a full compliance report instantly, right in your browser.

Try It Online

Request

Parameter Type Description
file * binary The invoice file to validate. Accepted format: standalone CII XML document. PDFs are not accepted here; upload hybrid files to POST /v1/validate/facturx or /v1/validate/zugferd.

Content-Type: multipart/form-data

That is the whole request. The syntax and the conformance profile (Peppol BIS, XRechnung, NLCIUS, PINT, or the Factur-X/ZUGFeRD profile ladder) are detected automatically from the document's specification identifier (BT-24), the matching rule set is applied, and the response reports what was validated against in data.profile and data.customizationId.

Headers

Header Value
Authorization * Bearer YOUR_API_KEY
Content-Type multipart/form-data

Response

200 Valid invoice

The invoice passed every check. valid is true and errors is empty.

Content-Type: application/json
{
  "valid": true,
  "detail": "Your invoice is cii compliant and meets the EN 16931 specifications.",
  "data": {
    "schemaValid": true,
    "schematronValid": true,
    "conformanceLevel": "EN16931",
    "profile": "en16931",
    "customizationId": "urn:cen.eu:en16931:2017"
  },
  "errors": [],
  "warnings": [],
  "report": [
    { "code": "BT-1", "name": "Invoice number", "section": "header", "path": "invoiceNumber", "value": "INV-2026-001", "isValid": true, "errors": [], "warnings": [] },
    { "code": "BT-2", "name": "Invoice issue date", "section": "header", "path": "issueDate", "value": "2026-05-19", "isValid": true, "errors": [], "warnings": [] }
    // ... one row per EN 16931 Business Term. See the Validation Report section below.
  ]
}

200 Invalid invoice

Validation still returns HTTP 200. valid is false and the findings are in the errors array.

{
  "valid": false,
  "detail": "Validation failed with 3 error(s)",
  "data": {
    "schemaValid": true,
    "schematronValid": false,
    "conformanceLevel": "EN16931",
    "profile": "en16931",
    "customizationId": "urn:cen.eu:en16931:2017"
  },
  "errors": [
    {
      "rule": "BR-01",
      "layer": "en16931",
      "line": null,
      "message": "The invoice is missing a specification identifier (BT-24).",
      "btCodes": ["BT-24"],
      "fields": ["specificationId"],
      "raw": "[BR-01] EN16931: An invoice shall have a specification identifier. (at /*:CrossIndustryInvoice)"
    },
    {
      "rule": "BR-06",
      "layer": "en16931",
      "line": null,
      "message": "The seller must have a name (BT-27). Add the seller's name.",
      "btCodes": ["BT-27"],
      "fields": ["seller.name"],
      "raw": "[BR-06] EN16931: An invoice shall contain the seller name. (at /*:CrossIndustryInvoice/*:SupplyChainTradeTransaction/*:ApplicableHeaderTradeAgreement/*:SellerTradeParty)"
    },
    {
      "rule": "BR-23",
      "layer": "en16931",
      "line": 2,
      "message": "Line item 2: Each invoice line must have a net amount.",
      "btCodes": ["BT-131"],
      "fields": ["lines[1].lineNetAmount"],
      "raw": "[BR-23] EN16931: An Invoice line shall have an Invoice line net amount. (at /*:CrossIndustryInvoice/*:SupplyChainTradeTransaction/*:IncludedSupplyChainTradeLineItem[2])"
    }
  ],
  "warnings": [
    {
      "rule": "BR-CL-01",
      "layer": "en16931",
      "line": null,
      "message": "The document type code should use a recognised UNTDID 1001 value.",
      "btCodes": ["BT-3"],
      "fields": ["typeCode"],
      "raw": "[BR-CL-01] EN16931-codelist: The document type code MUST be coded according to UNTDID 1001. (at /*:CrossIndustryInvoice/*:ExchangedDocument/*:TypeCode)"
    }
  ],
  "report": [
    // ... one row per EN 16931 Business Term. See the Validation Report section below.
    { "code": "BT-27", "name": "Seller name", "section": "seller", "path": "seller.name", "value": null, "isValid": false, "errors": ["The seller must have a name (BT-27). Add the seller's name."], "warnings": [] }
  ]
}

Error Reference

When an invoice fails validation, the top-level errors array contains one "finding" object per violated business rule. The warnings array uses the same finding shape for non-blocking advisory issues that do not cause valid to become false. On a valid invoice errors is an empty array, while warnings may still contain entries.

Each finding object carries both a friendly, user-facing message and the verbatim technical raw validator output. Each object contains:

Field Type Description
rule string The business rule identifier (e.g. BR-01, BR-DE-15).
layer string The validation layer that produced the finding: xsd (XML schema), en16931 (EN 16931 core business rules), or cius (profile overlay rules such as Peppol BIS or BR-DE). The PDF embedding findings (PDF-EMBED, PDF-EMBED-SYNTAX) report upload problems rather than rule violations and omit this field.
line int | null The 1-based invoice line item number the error relates to, or null when the error applies to the document level.
message string A plain-language explanation of the violation, suitable for displaying directly to end users.
btCodes string[] The EN 16931 Business Term / Business Group codes the rule references (e.g. ["BT-27"]). Empty when the rule maps to no specific term.
fields string[] Dotted JSON paths into the invoice document that the error applies to (e.g. ["seller.name"], ["lines[1].lineNetAmount"]). Derived from btCodes; line-scoped paths carry a zero-based lines[N] index. Empty when no field could be resolved.
raw string The verbatim technical message from the validator, including the rule id, layer and XPath location.

The fields array is intended for client UIs: each path matches the request body structure, so a front-end form can map a validation error straight onto the input that produced it. Highlight that input, attach message beside it, and the user can correct the exact field without reading the raw rule text. Line-scoped paths use a zero-based index (lines[1] is the second line item) to match JavaScript array indexing.

Status Meaning Action
200 Validation completed. Check valid to determine compliance. If valid is false, inspect the errors array.
401 Missing or invalid API key. Check the Authorization header.
422 File is not a valid PDF or XML document. Ensure you are uploading a supported file format.

Validation Report

Every response, whether the invoice is valid or not, includes a top-level report array. It contains one row per EN 16931 Business Term present on the parsed invoice, pairing each term with its current value and a pass/fail flag. This gives a complete, field-by-field picture of the document, not just the rules that failed, which is useful for rendering a compliance table or a side-by-side review UI. The snippets above show report truncated to a couple of rows to avoid repeating the full structure.

Each row in the array is an object with the following fields:

Field Type Description
code string The EN 16931 Business Term code (e.g. BT-1).
name string The human-readable name of the Business Term.
section string Logical grouping for display: header, seller, buyer, lines, payment, totals, or tax.
path string Dotted JSON path into the invoice document (e.g. lines[0].priceDetails.netPrice). Same path scheme as errors[].fields.
value string | null The current value of the term as a string, or null when the field is absent.
isValid boolean true when this row has no errors, otherwise false.
errors string[] Every error message referencing this Business Term; empty when none.
warnings string[] Every warning message referencing this Business Term; empty when none.

A single report row looks like this:

{
  "code": "BT-1",
  "name": "Invoice number",
  "section": "header",
  "path": "invoiceNumber",
  "value": "INV-2026-001",
  "isValid": true,
  "errors": [],
  "warnings": []
}

Frequently Asked Questions

Which rule sets does POST /v1/validate/cii run?

The CII D16B XSD first, then the rule set the document declares in its GuidelineSpecifiedDocumentContextParameter (BT-24). Plain EN 16931 documents get the full EN 16931 Schematron. Documents declaring a Factur-X / ZUGFeRD profile get that profile's official XSD and rules instead, so an EXTENDED invoice is never wrongly failed for using extended fields. XRechnung CII is routed to the KoSIT rules. Each finding's layer field shows which step produced it.

What do data.profile and data.customizationId contain?

data.customizationId echoes the BT-24 identifier exactly as declared. data.profile is the slug of the rule set that was applied: en16931, minimum, basic-wl, basic, extended, or xrechnung. If the identifier is unknown, profile is null, the EN 16931 base rules run, and a PROFILE-DETECTION warning explains the fallback; the document is never auto-failed just for declaring an exotic identifier.

Can I upload a ZUGFeRD or Factur-X PDF to this endpoint?

No, this endpoint expects standalone XML and rejects other uploads with HTTP 422. Hybrid PDFs go to POST /v1/validate/facturx or /v1/validate/zugferd, which extract the embedded XML automatically and then apply exactly the same profile routing as this endpoint.

What does the PROFILE-SCOPE warning mean?

It appears when the document declares the MINIMUM or BASIC WL profile. Both validate against their own official rules, but they are header-only booking aids: under the German B2B e-invoicing rules they do not qualify as e-invoices, and the warning makes that visible to your users before it becomes a compliance problem.

Which CII schema version is validated against?

CII D16B, the version referenced by EN 16931. The validator covers the CrossIndustryInvoice root element and all associated complex types; the retired CrossIndustryDocument root used by ZUGFeRD 1.0 is reported as schema-invalid.