Peppol Validator API & Agent Skill

Validate Peppol UBL and CII / Factur-X XML invoices programmatically. No signup, no API key. Just send XML and get results.

API endpoint

Send a UBL or CII XML invoice and receive validation results as JSON. The format is detected automatically. UBL invoices are validated against CEN EN16931 and Peppol BIS Billing 3.0 rules. CII / Factur-X invoices are validated against CEN EN16931 (CII binding) rules.

POST https://peppolvalidator.com/api/v1/validate

Option 1: Raw XML body

Send the XML directly as the request body with a Content-Type: application/xml header.

curl -X POST https://peppolvalidator.com/api/v1/validate \
  -H "Content-Type: application/xml" \
  -d @invoice.xml

Option 2: Multipart form data

Upload the file as a file field in a multipart request.

curl -X POST https://peppolvalidator.com/api/v1/validate \
  -F "file=@invoice.xml"

JavaScript / Node.js

const xml = fs.readFileSync("invoice.xml", "utf-8");

const res = await fetch("https://peppolvalidator.com/api/v1/validate", {
  method: "POST",
  headers: { "Content-Type": "application/xml" },
  body: xml,
});

const result = await res.json();
console.log(result.status); // "valid" | "invalid" | "error"

Python

import requests

with open("invoice.xml") as f:
    xml = f.read()

res = requests.post(
    "https://peppolvalidator.com/api/v1/validate",
    headers={"Content-Type": "application/xml"},
    data=xml,
)

result = res.json()
print(result["status"])  # "valid" | "invalid" | "error"

Response format

The API returns a JSON object with the validation result. The status field is either "valid", "invalid", or "error".

FieldTypeDescription
statusstring"valid", "invalid", or "error"
formatstring?"ubl" or "cii" (detected automatically)
specificationstring?e.g. "Peppol BIS Billing 3.0" or "EN16931 (CII / Factur-X)"
errorsarrayValidation errors (rule, message, XPath location)
warningsarrayValidation warnings
infosarrayInformational messages
invoiceNumberstring?Extracted invoice number
sellerCountrystring?Seller country code (ISO 3166-1 alpha-2)
validatedAtstringISO 8601 timestamp
errorMessagestring?Present when status is "error"
resultsUrlstringLink to shareable results page

Example response

{
  "fileId": "a1b2c3d4-...",
  "filename": "invoice.xml",
  "status": "invalid",
  "format": "ubl",
  "specification": "Peppol BIS Billing 3.0",
  "sellerCountry": "BE",
  "invoiceNumber": "INV-2026-001",
  "errors": [
    {
      "id": "1",
      "severity": "error",
      "rule": "BR-16",
      "location": "/Invoice",
      "message": "An Invoice shall have at least one Invoice line (BG-25)."
    }
  ],
  "warnings": [
    {
      "id": "2",
      "severity": "warning",
      "rule": "PEPPOL-EN16931-R080",
      "location": "/Invoice/cac:TaxTotal",
      "message": "Tax category tax amount must equal..."
    }
  ],
  "infos": [],
  "validatedAt": "2026-02-17T12:00:00.000Z",
  "resultsUrl": "https://peppolvalidator.com/r/a1b2c3d4-..."
}

Quickstart

  1. No signup or API keys needed. Start calling the API immediately.
  2. Send a UBL or CII XML invoice to POST /api/v1/validate with the XML as the request body.
  3. Check the status field in the JSON response: "valid", "invalid", or "error".
  4. If "invalid", iterate over the errors array for rule IDs, XPath locations, and fix guidance.
  5. Share the resultsUrl with your team to view results in the browser.

HTTP status codes

CodeMeaning
200Validation completed (check status field for result)
400Bad request (empty body, missing file field, exceeds 5MB)
500Server error during validation
503Validation rules temporarily unavailable

Error codes

All error responses include a machine-readable code field alongside the human-readable error message.

CodeHTTPDescription
EMPTY_BODY400No XML content in the request body
MISSING_FILE400No "file" field in multipart form data
FILE_TOO_LARGE400Uploaded file exceeds the 5MB limit
BODY_TOO_LARGE400Raw request body exceeds the 5MB limit
RULES_UNAVAILABLE503Schematron rules are loading; retry after 5-10 seconds
VALIDATION_FAILED500Internal error during validation; retry with exponential backoff
PDF_GENERATION_FAILED400XML could not be parsed or converted to PDF

Retry guidance

  • 400 errors: Do not retry. Fix the request based on the error code.
  • 500 errors: Retry with exponential backoff (1s, 2s, 4s). Maximum 3 retries.
  • 503 errors: Schematron rules are loading into memory. Retry after 5-10 seconds.

Monitor service health at /status or via the GET /api/v1/health endpoint.

Authentication

No authentication required. All API endpoints are publicly accessible without API keys, tokens, or signup. Send requests directly with no authorization headers.

Rate limiting may be introduced in the future. For high-volume usage (thousands of invoices per hour), reach out at hello@peppolvalidator.com.

CORS

The API sets Access-Control-Allow-Origin: * so you can call it from any domain, including browser-based applications.

XML to PDF conversion

Convert a UBL XML invoice or credit note to a professional PDF document. Send the XML and receive a PDF file in return.

POST https://peppolvalidator.com/api/v1/xml-to-pdf

cURL example

curl -X POST https://peppolvalidator.com/api/v1/xml-to-pdf \
  -H "Content-Type: application/xml" \
  -d @invoice.xml \
  -o invoice.pdf

Response

Returns application/pdf with a Content-Disposition: attachment header. On error, returns JSON with an error field and a 400 status code. Supports both raw XML body and multipart form upload (same as the validation endpoint).

MCP Server

Peppol Validator exposes a Model Context Protocol (MCP) server so AI agents like Claude, ChatGPT, and others can call validation tools natively. The server uses Streamable HTTP transport.

https://peppolvalidator.com/mcp

Available tools

ToolDescription
validate_invoiceValidate a Peppol UBL or CII XML invoice against EN16931 and BIS Billing 3.0 schematron rules
xml_to_pdfConvert a UBL or CII XML invoice to a human-readable PDF
get_verification_challengeGet a HATCHA challenge to prove the caller is an AI agent (required before submitting feedback)
submit_feedbackReport validation accuracy issues, API problems, or general feedback (requires HATCHA verification)

Configuration

Add this to your MCP client configuration (e.g. claude_desktop_config.json or .cursor/mcp.json):

{
  "mcpServers": {
    "peppol-validator": {
      "url": "https://peppolvalidator.com/mcp"
    }
  }
}

Discovery

MCP-compatible agents can discover the server automatically via:

  • /.well-known/mcp: server URL and metadata
  • /.well-known/mcp/server-card.json: full server card with tool schemas

Test it

curl -X POST https://peppolvalidator.com/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Agent Skill

An Agent Skill is a structured instruction file that teaches AI coding agents how to use a tool. Add the Peppol Validator skill to your project and your agent can validate invoices automatically.

Download and place in your project. For Claude Code, use .claude/skills/. For other agents, use .agents/skills/.

.claude/skills/validating-peppol-invoices/SKILL.md

Or create the file manually with these contents:

---
name: validating-peppol-invoices
description: Validates Peppol UBL XML invoices and credit notes
  against EN16931 (CEN) and Peppol BIS Billing 3.0 schematron
  rules via the Peppol Validator API. Use when validating
  e-invoices, checking Peppol compliance, debugging UBL XML
  validation errors, or verifying invoices before sending via
  the Peppol network.
---

# Validating Peppol Invoices

POST XML to the Peppol Validator API and parse the JSON result.

## Endpoint

\`POST https://peppolvalidator.com/api/v1/validate\`

Send raw XML with \`Content-Type: application/xml\`:

```bash
curl -X POST https://peppolvalidator.com/api/v1/validate \
  -H "Content-Type: application/xml" \
  -d @invoice.xml
```

Returns JSON with status ("valid" / "invalid" / "error"),
errors, warnings, and invoice metadata.

What your agent can do with it

  • Validate XML invoices during development and flag issues inline
  • Run validation as part of CI/CD before deploying invoice generation code
  • Debug Peppol validation errors by examining rule IDs and locations
  • Verify fixes by re-validating after changes

Try it now

Validate an invoice via the web UI or send one to the API. No signup needed.

Common questions

Is the API free?

Yes. The API is free with no signup or API key required. We may introduce rate limits in the future if needed, but casual and CI/CD usage is welcome.

What validation rules are applied?

For UBL invoices: CEN EN16931 business rules (BR-*) and Peppol BIS Billing 3.0 rules (PEPPOL-EN16931-*). For CII / Factur-X invoices: CEN EN16931 business rules, syntax rules (CII-SR-*), and code list validation. The format is detected automatically.

What file formats are supported?

UBL 2.1 XML invoices and credit notes (Peppol BIS Billing 3.0) and CII XML invoices (EN16931 / Factur-X / ZUGFeRD). The format is detected automatically from the XML namespace.

Is there a rate limit?

There is no hard rate limit today. Please be reasonable. If you need to validate thousands of invoices per hour, reach out first.

What is an Agent Skill?

An Agent Skill is a structured instruction file that tells AI coding agents (like Claude Code, Cursor, Windsurf, etc.) how to use a tool. By adding the Peppol Validator skill to your project, your AI agent can validate invoices during development without manual steps.