{
  "info": {
    "_postman_id": "5f0c7a52-3b8e-4d7e-9a61-7a1d2c9e4b10",
    "name": "xmlvalid API",
    "description": "Validate XML documents and e-invoices (UBL, CII, Peppol BIS, XRechnung, Factur-X, FatturaPA, KSeF and more) against XSD, DTD, RelaxNG and Schematron business rules (EN 16931, Peppol, national CIUS), with the same engine as the [xmlvalid.com](https://xmlvalid.com) validator.\n\n## Getting started\n\n1. Sign up at [xmlvalid.com](https://xmlvalid.com/register) and confirm your email. The Free plan includes 100 API validations a month.\n2. Create an API key under [Dashboard → API](https://xmlvalid.com/dashboard/api).\n3. Fork this collection, open its **Variables** and paste the key into `apiKey` (current value). Requests send it as `Authorization: Bearer xv_…`.\n4. Send **Validate an e-invoice by URL**: it checks a sample Peppol invoice. Then try **Validate XML sent as the body** with your own document.\n\nEach validate request stores the validation's id in `validationId`, so **Fetch a validation** and the report requests work right after it.\n\n## Results\n\n`result.outcome` is `valid`, `warnings` (valid, with warnings), `invalid`, `schema` (the schema or rules could not be loaded), `input` (the document could not be read) or `failed`. Each error has its `line`, `type` (`syntax`, `xsd`, `dtd`, `relaxng`, `schematron` for a business rule, `pdf`…), the business rule's id in `rule`, and links to an explanation (`help_url`) or the rule's page (`rule_url`).\n\n## Links\n\n- [API reference](https://xmlvalid.com/docs/api) and [OpenAPI description](https://xmlvalid.com/docs/api/openapi.yaml)\n- [Schema catalog](https://xmlvalid.com/schemas)\n- [CLI and GitHub Action](https://xmlvalid.com/docs/ci)\n- Support: support@xmlvalid.com",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{apiKey}}",
        "type": "string"
      }
    ]
  },
  "item": [
    {
      "name": "Validate",
      "description": "Send a document by URL, as the body or as a file.",
      "item": [
        {
          "name": "Validate an e-invoice by URL",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/validations",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "validations"
              ]
            },
            "description": "Our server downloads the document from a public http(s) address and validates it. `schema=auto` picks the catalog profile the e-invoice names (here Peppol BIS Billing 3.0: UBL 2.1 XSD plus the EN 16931 and Peppol business rules). `wait` is how many seconds to wait for the result (up to 60); a longer run answers 202, then poll **Fetch a validation**.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"url\": \"https://xmlvalid.com/schemas/peppol-bis-3-invoice/example\",\n  \"schema\": \"auto\",\n  \"wait\": 30\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const body = pm.response.json();",
                  "pm.test('Accepted', () => pm.expect(pm.response.code).to.be.oneOf([200, 202]));",
                  "if (body.id) pm.collectionVariables.set('validationId', body.id);",
                  "if (body.status === 'done') {",
                  "    console.log(`${body.result.outcome}: ${body.result.errors_total} errors, ${body.result.warnings_total} warnings`);",
                  "} else if (body.status) {",
                  "    console.log(`Still ${body.status}: run \"Fetch a validation\" to poll it`);",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Validate XML sent as the body",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/xml"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/validations?schema=auto&wait=30&name=invoice.xml",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "validations"
              ],
              "query": [
                {
                  "key": "schema",
                  "value": "auto"
                },
                {
                  "key": "wait",
                  "value": "30"
                },
                {
                  "key": "name",
                  "value": "invoice.xml"
                }
              ]
            },
            "description": "The document is the request body (any content type other than multipart and JSON; gzip is decompressed). Options go in the query. Change an amount in the invoice and send it again to see a business rule fail.",
            "body": {
              "mode": "raw",
              "raw": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Invoice xmlns:cac=\"urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2\"\n    xmlns:cbc=\"urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2\"\n    xmlns=\"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2\">\n    <cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0</cbc:CustomizationID>\n    <cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>\n    <cbc:ID>Snippet1</cbc:ID>\n    <cbc:IssueDate>2017-11-13</cbc:IssueDate>\n    <cbc:DueDate>2017-12-01</cbc:DueDate>\n    <cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>\n    <cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>\n    <cbc:AccountingCost>4025:123:4343</cbc:AccountingCost>\n    <cbc:BuyerReference>0150abc</cbc:BuyerReference>\n    <cac:AccountingSupplierParty>\n        <cac:Party>\n            <cbc:EndpointID schemeID=\"0088\">9482348239847239874</cbc:EndpointID>\n            <cac:PartyIdentification>\n                <cbc:ID>99887766</cbc:ID>\n            </cac:PartyIdentification>\n            <cac:PartyName>\n                <cbc:Name>SupplierTradingName Ltd.</cbc:Name>\n            </cac:PartyName>\n            <cac:PostalAddress>\n                <cbc:StreetName>Main street 1</cbc:StreetName>\n                <cbc:AdditionalStreetName>Postbox 123</cbc:AdditionalStreetName>\n                <cbc:CityName>London</cbc:CityName>\n                <cbc:PostalZone>GB 123 EW</cbc:PostalZone>\n                <cac:Country>\n                    <cbc:IdentificationCode>GB</cbc:IdentificationCode>\n                </cac:Country>\n            </cac:PostalAddress>\n            <cac:PartyTaxScheme>\n                <cbc:CompanyID>GB1232434</cbc:CompanyID>\n                <cac:TaxScheme>\n                    <cbc:ID>VAT</cbc:ID>\n                </cac:TaxScheme>\n            </cac:PartyTaxScheme>\n            <cac:PartyLegalEntity>\n                <cbc:RegistrationName>SupplierOfficialName Ltd</cbc:RegistrationName>\n                <cbc:CompanyID>GB983294</cbc:CompanyID>\n            </cac:PartyLegalEntity>\n        </cac:Party>\n    </cac:AccountingSupplierParty>\n    <cac:AccountingCustomerParty>\n        <cac:Party>\n            <cbc:EndpointID schemeID=\"0002\">FR23342</cbc:EndpointID>\n            <cac:PartyIdentification>\n                <cbc:ID schemeID=\"0002\">FR23342</cbc:ID>\n            </cac:PartyIdentification>\n            <cac:PartyName>\n                <cbc:Name>BuyerTradingName AS</cbc:Name>\n            </cac:PartyName>\n            <cac:PostalAddress>\n                <cbc:StreetName>Hovedgatan 32</cbc:StreetName>\n                <cbc:AdditionalStreetName>Po box 878</cbc:AdditionalStreetName>\n                <cbc:CityName>Stockholm</cbc:CityName>\n                <cbc:PostalZone>456 34</cbc:PostalZone>\n                <cac:Country>\n                    <cbc:IdentificationCode>SE</cbc:IdentificationCode>\n                </cac:Country>\n            </cac:PostalAddress>\n            <cac:PartyTaxScheme>\n                <cbc:CompanyID>SE4598375937</cbc:CompanyID>\n                <cac:TaxScheme>\n                    <cbc:ID>VAT</cbc:ID>\n                </cac:TaxScheme>\n            </cac:PartyTaxScheme>\n            <cac:PartyLegalEntity>\n                <cbc:RegistrationName>Buyer Official Name</cbc:RegistrationName>\n                <cbc:CompanyID schemeID=\"0183\">39937423947</cbc:CompanyID>\n            </cac:PartyLegalEntity>\n            <cac:Contact>\n                <cbc:Name>Lisa Johnson</cbc:Name>\n                <cbc:Telephone>23434234</cbc:Telephone>\n                <cbc:ElectronicMail>lj@buyer.se</cbc:ElectronicMail>\n            </cac:Contact>\n        </cac:Party>\n    </cac:AccountingCustomerParty>\n    <cac:Delivery>\n        <cbc:ActualDeliveryDate>2017-11-01</cbc:ActualDeliveryDate>\n        <cac:DeliveryLocation>\n            <cbc:ID schemeID=\"0088\">9483759475923478</cbc:ID>\n            <cac:Address>\n                <cbc:StreetName>Delivery street 2</cbc:StreetName>\n                <cbc:AdditionalStreetName>Building 56</cbc:AdditionalStreetName>\n                <cbc:CityName>Stockholm</cbc:CityName>\n                <cbc:PostalZone>21234</cbc:PostalZone>\n                <cac:Country>\n                    <cbc:IdentificationCode>SE</cbc:IdentificationCode>\n                </cac:Country>\n            </cac:Address>\n        </cac:DeliveryLocation>\n        <cac:DeliveryParty>\n            <cac:PartyName>\n                <cbc:Name>Delivery party Name</cbc:Name>\n            </cac:PartyName>\n        </cac:DeliveryParty>\n    </cac:Delivery>\n    <cac:PaymentMeans>\n        <cbc:PaymentMeansCode name=\"Credit transfer\">30</cbc:PaymentMeansCode>\n        <cbc:PaymentID>Snippet1</cbc:PaymentID>\n        <cac:PayeeFinancialAccount>\n            <cbc:ID>IBAN32423940</cbc:ID>\n            <cbc:Name>AccountName</cbc:Name>\n            <cac:FinancialInstitutionBranch>\n                <cbc:ID>BIC324098</cbc:ID>\n            </cac:FinancialInstitutionBranch>\n        </cac:PayeeFinancialAccount>\n    </cac:PaymentMeans>\n    <cac:PaymentTerms>\n        <cbc:Note>Payment within 10 days, 2% discount</cbc:Note>\n    </cac:PaymentTerms>\n        <cac:AllowanceCharge>\n            <cbc:ChargeIndicator>true</cbc:ChargeIndicator>\n            <cbc:AllowanceChargeReason>Insurance</cbc:AllowanceChargeReason>\n            <cbc:Amount currencyID=\"EUR\">25</cbc:Amount>\n            <cac:TaxCategory>\n                <cbc:ID>S</cbc:ID>\n                <cbc:Percent>25.0</cbc:Percent>\n                <cac:TaxScheme>\n                    <cbc:ID>VAT</cbc:ID>\n                </cac:TaxScheme>\n            </cac:TaxCategory>\n        </cac:AllowanceCharge>\n    <cac:TaxTotal>\n        <cbc:TaxAmount currencyID=\"EUR\">331.25</cbc:TaxAmount>\n        <cac:TaxSubtotal>\n            <cbc:TaxableAmount currencyID=\"EUR\">1325</cbc:TaxableAmount>\n            <cbc:TaxAmount currencyID=\"EUR\">331.25</cbc:TaxAmount>\n            <cac:TaxCategory>\n                <cbc:ID>S</cbc:ID>\n                <cbc:Percent>25.0</cbc:Percent>\n                <cac:TaxScheme>\n                    <cbc:ID>VAT</cbc:ID>\n                </cac:TaxScheme>\n            </cac:TaxCategory>\n        </cac:TaxSubtotal>\n    </cac:TaxTotal>\n    <cac:LegalMonetaryTotal>\n        <cbc:LineExtensionAmount currencyID=\"EUR\">1300</cbc:LineExtensionAmount>\n        <cbc:TaxExclusiveAmount currencyID=\"EUR\">1325</cbc:TaxExclusiveAmount>\n        <cbc:TaxInclusiveAmount currencyID=\"EUR\">1656.25</cbc:TaxInclusiveAmount>\n        <cbc:ChargeTotalAmount currencyID=\"EUR\">25</cbc:ChargeTotalAmount>\n        <cbc:PayableAmount currencyID=\"EUR\">1656.25</cbc:PayableAmount>\n    </cac:LegalMonetaryTotal>\n    \n<cac:InvoiceLine>\n        <cbc:ID>1</cbc:ID>\n    <cbc:InvoicedQuantity unitCode=\"DAY\">7</cbc:InvoicedQuantity>\n    <cbc:LineExtensionAmount currencyID= \"EUR\">2800</cbc:LineExtensionAmount>\n        <cbc:AccountingCost>Konteringsstreng</cbc:AccountingCost>\n       <cac:OrderLineReference>\n            <cbc:LineID>123</cbc:LineID>\n        </cac:OrderLineReference>\n    <cac:Item>\n            <cbc:Description>Description of item</cbc:Description>\n            <cbc:Name>item name</cbc:Name>\n            <cac:StandardItemIdentification>\n                <cbc:ID schemeID=\"0088\">21382183120983</cbc:ID>\n            </cac:StandardItemIdentification>\n            <cac:OriginCountry>\n                <cbc:IdentificationCode>NO</cbc:IdentificationCode>\n            </cac:OriginCountry>\n            <cac:CommodityClassification>\n                <cbc:ItemClassificationCode listID=\"SRV\">09348023</cbc:ItemClassificationCode>\n            </cac:CommodityClassification>\n            <cac:ClassifiedTaxCategory>\n                <cbc:ID>S</cbc:ID>\n                <cbc:Percent>25.0</cbc:Percent>\n                <cac:TaxScheme>\n                    <cbc:ID>VAT</cbc:ID>\n                </cac:TaxScheme>\n            </cac:ClassifiedTaxCategory>\n        </cac:Item>\n    <cac:Price>\n        <cbc:PriceAmount currencyID=\"EUR\">400</cbc:PriceAmount>\n    </cac:Price>\n    </cac:InvoiceLine>\n<cac:InvoiceLine>\n    <cbc:ID>2</cbc:ID>\n    <cbc:InvoicedQuantity unitCode=\"DAY\">-3</cbc:InvoicedQuantity>\n    <cbc:LineExtensionAmount currencyID=\"EUR\">-1500</cbc:LineExtensionAmount>\n    <cac:OrderLineReference>\n        <cbc:LineID>123</cbc:LineID>\n    </cac:OrderLineReference>\n    <cac:Item>\n        <cbc:Description>Description 2</cbc:Description>\n        <cbc:Name>item name 2</cbc:Name>\n        <cac:StandardItemIdentification>\n            <cbc:ID schemeID=\"0088\">21382183120983</cbc:ID>\n        </cac:StandardItemIdentification>\n        <cac:OriginCountry>\n            <cbc:IdentificationCode>NO</cbc:IdentificationCode>\n        </cac:OriginCountry>\n        <cac:CommodityClassification>\n            <cbc:ItemClassificationCode listID=\"SRV\">09348023</cbc:ItemClassificationCode>\n        </cac:CommodityClassification>\n        <cac:ClassifiedTaxCategory>\n            <cbc:ID>S</cbc:ID>\n            <cbc:Percent>25.0</cbc:Percent>\n            <cac:TaxScheme>\n                <cbc:ID>VAT</cbc:ID>\n            </cac:TaxScheme>\n        </cac:ClassifiedTaxCategory>\n    </cac:Item>\n    <cac:Price>\n        <cbc:PriceAmount currencyID=\"EUR\">500</cbc:PriceAmount>\n    </cac:Price>\n</cac:InvoiceLine>\n</Invoice>\n",
              "options": {
                "raw": {
                  "language": "xml"
                }
              }
            }
          },
          "response": [
            {
              "name": "Valid Peppol invoice",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/xml"
                  }
                ],
                "url": {
                  "raw": "{{baseUrl}}/validations?schema=auto&wait=30&name=invoice.xml",
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "path": [
                    "validations"
                  ],
                  "query": [
                    {
                      "key": "schema",
                      "value": "auto"
                    },
                    {
                      "key": "wait",
                      "value": "30"
                    },
                    {
                      "key": "name",
                      "value": "invoice.xml"
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"id\": \"val_01m55cj82mxaj40a8j4xkzerbp\",\n  \"status\": \"done\",\n  \"progress\": 100,\n  \"created_at\": \"2026-10-17T16:54:17+00:00\",\n  \"finished_at\": \"2026-10-17T16:54:17+00:00\",\n  \"document\": {\n    \"source\": \"body\",\n    \"name\": \"invoice.xml\",\n    \"size\": 9228\n  },\n  \"schema\": {\n    \"kind\": \"xsd\",\n    \"catalog\": \"peppol-bis-3-invoice\",\n    \"name\": \"Peppol BIS Billing 3.0 Invoice\",\n    \"detected\": true\n  },\n  \"rules\": null,\n  \"result\": {\n    \"valid\": true,\n    \"outcome\": \"valid\",\n    \"errors_total\": 0,\n    \"warnings_total\": 0,\n    \"errors_truncated\": false,\n    \"errors\": [],\n    \"warnings\": [],\n    \"bytes\": 9228,\n    \"duration_ms\": 37\n  },\n  \"error\": null,\n  \"links\": {\n    \"self\": \"https://xmlvalid.com/api/v1/validations/val_01m55cj82mxaj40a8j4xkzerbp\",\n    \"report\": \"https://xmlvalid.com/api/v1/validations/val_01m55cj82mxaj40a8j4xkzerbp/report\"\n  }\n}"
            },
            {
              "name": "Business rule broken (BR-CO-16)",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/xml"
                  }
                ],
                "url": {
                  "raw": "{{baseUrl}}/validations?schema=auto&wait=30&name=invoice.xml",
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "path": [
                    "validations"
                  ],
                  "query": [
                    {
                      "key": "schema",
                      "value": "auto"
                    },
                    {
                      "key": "wait",
                      "value": "30"
                    },
                    {
                      "key": "name",
                      "value": "invoice.xml"
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"id\": \"val_01m55cj8kha3h9m652rt5ce2j0\",\n  \"status\": \"done\",\n  \"progress\": 100,\n  \"created_at\": \"2026-10-17T16:54:17+00:00\",\n  \"finished_at\": \"2026-10-17T16:54:18+00:00\",\n  \"document\": {\n    \"source\": \"body\",\n    \"name\": \"invoice.xml\",\n    \"size\": 9227\n  },\n  \"schema\": {\n    \"kind\": \"xsd\",\n    \"catalog\": \"peppol-bis-3-invoice\",\n    \"name\": \"Peppol BIS Billing 3.0 Invoice\",\n    \"detected\": true\n  },\n  \"rules\": null,\n  \"result\": {\n    \"valid\": false,\n    \"outcome\": \"invalid\",\n    \"errors_total\": 1,\n    \"warnings_total\": 0,\n    \"errors_truncated\": false,\n    \"errors\": [\n      {\n        \"line\": 139,\n        \"column\": 0,\n        \"level\": \"error\",\n        \"type\": \"schematron\",\n        \"rule\": \"BR-CO-16\",\n        \"message\": \"Amount due for payment (BT-115) = Invoice total amount with VAT (BT-112) -Paid amount (BT-113) +Rounding amount (BT-114).\",\n        \"message_en\": null,\n        \"help_url\": null,\n        \"rule_url\": \"https://xmlvalid.com/rules/BR-CO-16\"\n      }\n    ],\n    \"warnings\": [],\n    \"bytes\": 9227,\n    \"duration_ms\": 33\n  },\n  \"error\": null,\n  \"links\": {\n    \"self\": \"https://xmlvalid.com/api/v1/validations/val_01m55cj8kha3h9m652rt5ce2j0\",\n    \"report\": \"https://xmlvalid.com/api/v1/validations/val_01m55cj8kha3h9m652rt5ce2j0/report\"\n  }\n}"
            }
          ],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const body = pm.response.json();",
                  "pm.test('Accepted', () => pm.expect(pm.response.code).to.be.oneOf([200, 202]));",
                  "if (body.id) pm.collectionVariables.set('validationId', body.id);",
                  "if (body.status === 'done') {",
                  "    console.log(`${body.result.outcome}: ${body.result.errors_total} errors, ${body.result.warnings_total} warnings`);",
                  "} else if (body.status) {",
                  "    console.log(`Still ${body.status}: run \"Fetch a validation\" to poll it`);",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Validate a file",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/validations",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "validations"
              ]
            },
            "description": "Upload the document as `document` (pick a file). `schema` is a catalog name (see **List schemas**), one of your saved schemas (`my-12`) or `auto`. A .zip is validated document by document; a Factur-X or ZUGFeRD PDF has its XML invoice taken out and checked.",
            "body": {
              "mode": "formdata",
              "formdata": [
                {
                  "key": "document",
                  "type": "file",
                  "src": []
                },
                {
                  "key": "schema",
                  "value": "auto",
                  "type": "text"
                },
                {
                  "key": "wait",
                  "value": "30",
                  "type": "text"
                }
              ]
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const body = pm.response.json();",
                  "pm.test('Accepted', () => pm.expect(pm.response.code).to.be.oneOf([200, 202]));",
                  "if (body.id) pm.collectionVariables.set('validationId', body.id);",
                  "if (body.status === 'done') {",
                  "    console.log(`${body.result.outcome}: ${body.result.errors_total} errors, ${body.result.warnings_total} warnings`);",
                  "} else if (body.status) {",
                  "    console.log(`Still ${body.status}: run \"Fetch a validation\" to poll it`);",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Validate against your own schema",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/validations",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "validations"
              ]
            },
            "description": "Send the schema with the request as `schema_file`: one XSD, DTD or RelaxNG (.rng, .rnc) file up to 20 MB, its language read from its content. To keep a schema with imports, save it in the dashboard and pass its name as `schema`.",
            "body": {
              "mode": "formdata",
              "formdata": [
                {
                  "key": "document",
                  "type": "file",
                  "src": []
                },
                {
                  "key": "schema_file",
                  "type": "file",
                  "src": []
                },
                {
                  "key": "wait",
                  "value": "30",
                  "type": "text"
                }
              ]
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const body = pm.response.json();",
                  "pm.test('Accepted', () => pm.expect(pm.response.code).to.be.oneOf([200, 202]));",
                  "if (body.id) pm.collectionVariables.set('validationId', body.id);",
                  "if (body.status === 'done') {",
                  "    console.log(`${body.result.outcome}: ${body.result.errors_total} errors, ${body.result.warnings_total} warnings`);",
                  "} else if (body.status) {",
                  "    console.log(`Still ${body.status}: run \"Fetch a validation\" to poll it`);",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Validate with your own Schematron rules",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/validations",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "validations"
              ]
            },
            "description": "Add an ISO Schematron file (query binding xslt2 or xslt3) as `rules_file`. The rules run after the schema check, and after a catalog profile's own rules, on a document that passed it. Findings have the type `schematron` and the rule's id.",
            "body": {
              "mode": "formdata",
              "formdata": [
                {
                  "key": "document",
                  "type": "file",
                  "src": []
                },
                {
                  "key": "schema",
                  "value": "auto",
                  "type": "text"
                },
                {
                  "key": "rules_file",
                  "type": "file",
                  "src": []
                },
                {
                  "key": "wait",
                  "value": "30",
                  "type": "text"
                }
              ]
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const body = pm.response.json();",
                  "pm.test('Accepted', () => pm.expect(pm.response.code).to.be.oneOf([200, 202]));",
                  "if (body.id) pm.collectionVariables.set('validationId', body.id);",
                  "if (body.status === 'done') {",
                  "    console.log(`${body.result.outcome}: ${body.result.errors_total} errors, ${body.result.warnings_total} warnings`);",
                  "} else if (body.status) {",
                  "    console.log(`Still ${body.status}: run \"Fetch a validation\" to poll it`);",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "Results",
      "description": "Fetch, cancel and share validations.",
      "item": [
        {
          "name": "Fetch a validation",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/validations/{{validationId}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "validations",
                "{{validationId}}"
              ]
            },
            "description": "A validation, finished or not; `validationId` is set by the last validate request. Results are kept for 24 hours."
          },
          "response": [
            {
              "name": "Finished, invalid",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/validations/{{validationId}}",
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "path": [
                    "validations",
                    "{{validationId}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"id\": \"val_01m55cj8kha3h9m652rt5ce2j0\",\n  \"status\": \"done\",\n  \"progress\": 100,\n  \"created_at\": \"2026-10-17T16:54:17+00:00\",\n  \"finished_at\": \"2026-10-17T16:54:18+00:00\",\n  \"document\": {\n    \"source\": \"body\",\n    \"name\": \"invoice.xml\",\n    \"size\": 9227\n  },\n  \"schema\": {\n    \"kind\": \"xsd\",\n    \"catalog\": \"peppol-bis-3-invoice\",\n    \"name\": \"Peppol BIS Billing 3.0 Invoice\",\n    \"detected\": true\n  },\n  \"rules\": null,\n  \"result\": {\n    \"valid\": false,\n    \"outcome\": \"invalid\",\n    \"errors_total\": 1,\n    \"warnings_total\": 0,\n    \"errors_truncated\": false,\n    \"errors\": [\n      {\n        \"line\": 139,\n        \"column\": 0,\n        \"level\": \"error\",\n        \"type\": \"schematron\",\n        \"rule\": \"BR-CO-16\",\n        \"message\": \"Amount due for payment (BT-115) = Invoice total amount with VAT (BT-112) -Paid amount (BT-113) +Rounding amount (BT-114).\",\n        \"message_en\": null,\n        \"help_url\": null,\n        \"rule_url\": \"https://xmlvalid.com/rules/BR-CO-16\"\n      }\n    ],\n    \"warnings\": [],\n    \"bytes\": 9227,\n    \"duration_ms\": 33\n  },\n  \"error\": null,\n  \"links\": {\n    \"self\": \"https://xmlvalid.com/api/v1/validations/val_01m55cj8kha3h9m652rt5ce2j0\",\n    \"report\": \"https://xmlvalid.com/api/v1/validations/val_01m55cj8kha3h9m652rt5ce2j0/report\"\n  }\n}"
            }
          ],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('Found', () => pm.response.to.have.status(200));"
                ]
              }
            }
          ]
        },
        {
          "name": "Cancel a validation",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/validations/{{validationId}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "validations",
                "{{validationId}}"
              ]
            },
            "description": "Cancels a validation that is still queued or running. A finished one is returned as it is."
          },
          "response": []
        },
        {
          "name": "Fetch the HTML report",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/validations/{{validationId}}/report",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "validations",
                "{{validationId}}",
                "report"
              ]
            },
            "description": "The finished result as one self-contained HTML page: the verdict, the schema, and every finding with its line and links to the rule's page and the error guide. Open it in a browser and print it to save a PDF."
          },
          "response": []
        },
        {
          "name": "Share a report link (Pro)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/reports",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "reports"
              ]
            },
            "description": "Stores the HTML report of one or more finished validations and returns a public link that works for 30 days, without an API key. The documents themselves are not kept.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"validations\": [\n    \"{{validationId}}\"\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        }
      ]
    },
    {
      "name": "Account",
      "description": "Schemas and usage.",
      "item": [
        {
          "name": "List schemas",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/schemas",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "schemas"
              ]
            },
            "description": "Your saved schemas and the public catalog, with the value to pass as `schema`."
          },
          "response": [
            {
              "name": "Some of the catalog",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/schemas",
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "path": [
                    "schemas"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"saved\": [],\n  \"catalog\": [\n    {\n      \"schema\": \"ubl-2.1-invoice\",\n      \"name\": \"UBL 2.1 Invoice\",\n      \"kind\": \"xsd\",\n      \"namespace\": \"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2\",\n      \"version\": \"2.1\",\n      \"rules\": []\n    },\n    {\n      \"schema\": \"peppol-bis-3-invoice\",\n      \"name\": \"Peppol BIS Billing 3.0 Invoice\",\n      \"kind\": \"xsd\",\n      \"namespace\": \"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2\",\n      \"version\": \"3.0.21\",\n      \"rules\": [\n        \"EN 16931 rules 1.3.16 (UBL)\",\n        \"Peppol BIS Billing 3.0 rules\"\n      ]\n    },\n    {\n      \"schema\": \"xrechnung-3-cii\",\n      \"name\": \"XRechnung 3.0 Invoice (CII)\",\n      \"kind\": \"xsd\",\n      \"namespace\": \"urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100\",\n      \"version\": \"3.0.2, rules 2.6.0\",\n      \"rules\": [\n        \"EN 16931 rules 1.3.16 (CII)\",\n        \"XRechnung 3.0 rules (CII)\"\n      ]\n    },\n    {\n      \"schema\": \"factur-x-en16931\",\n      \"name\": \"Factur-X / ZUGFeRD EN 16931\",\n      \"kind\": \"xsd\",\n      \"namespace\": \"urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100\",\n      \"version\": \"1.09\",\n      \"rules\": [\n        \"Factur-X EN 16931 rules\"\n      ]\n    },\n    {\n      \"schema\": \"atom-1.0\",\n      \"name\": \"Atom 1.0\",\n      \"kind\": \"rnc\",\n      \"namespace\": \"http://www.w3.org/2005/Atom\",\n      \"version\": \"RFC 4287\",\n      \"rules\": []\n    }\n  ]\n}"
            }
          ]
        },
        {
          "name": "Usage this month",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/usage",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "usage"
              ]
            },
            "description": "Your plan, the validations used this month (UTC) and the limits. Every validate request counts, whatever its outcome; validating in the browser on xmlvalid.com does not."
          },
          "response": [
            {
              "name": "Free plan",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/usage",
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "path": [
                    "usage"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"plan\": \"free\",\n  \"period\": {\n    \"start\": \"2026-10-01\",\n    \"reset_at\": \"2026-11-01T00:00:00+00:00\"\n  },\n  \"validations\": {\n    \"used\": 2,\n    \"limit\": 100\n  },\n  \"limits\": {\n    \"max_file_bytes\": 10485760,\n    \"requests_per_minute\": 10\n  }\n}"
            },
            {
              "name": "No API key",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}/usage",
                  "host": [
                    "{{baseUrl}}"
                  ],
                  "path": [
                    "usage"
                  ]
                }
              },
              "status": "Unauthorized",
              "code": 401,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"error\": {\n    \"code\": \"unauthenticated\",\n    \"message\": \"Send an API key as \\\"Authorization: Bearer xv_…\\\". Keys are made in the dashboard; the account needs a confirmed email, and only as many keys as the plan allows work (the oldest ones).\"\n  }\n}"
            }
          ]
        }
      ]
    }
  ],
  "variable": [
    {
      "key": "baseUrl",
      "value": "https://xmlvalid.com/api/v1",
      "type": "string"
    },
    {
      "key": "apiKey",
      "value": "",
      "type": "string",
      "description": "Your API key (xv_…), from Dashboard → API."
    },
    {
      "key": "validationId",
      "value": "",
      "type": "string",
      "description": "Set by the validate requests."
    }
  ]
}
