{"id":42775090,"url":"https://github.com/easybill/peppol-bis-billing-validator","last_synced_at":"2026-01-29T22:05:32.726Z","repository":{"id":243645114,"uuid":"811783981","full_name":"easybill/peppol-bis-billing-validator","owner":"easybill","description":"A small service which allows to validate XML against PEPPOL BIS Billing schematron rules","archived":false,"fork":false,"pushed_at":"2024-08-24T11:16:54.000Z","size":103,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-08-24T12:28:45.195Z","etag":null,"topics":["docker","docker-compose","e-invoice","e-invoicing","en16931","peppol","peppol-bis","schematron","schematron-validation"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/easybill.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-07T09:43:43.000Z","updated_at":"2024-08-24T12:28:49.154Z","dependencies_parsed_at":"2024-08-24T12:38:47.986Z","dependency_job_id":null,"html_url":"https://github.com/easybill/peppol-bis-billing-validator","commit_stats":null,"previous_names":["easybill/peppol-bis-billing-validator"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/easybill/peppol-bis-billing-validator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/easybill%2Fpeppol-bis-billing-validator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/easybill%2Fpeppol-bis-billing-validator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/easybill%2Fpeppol-bis-billing-validator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/easybill%2Fpeppol-bis-billing-validator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/easybill","download_url":"https://codeload.github.com/easybill/peppol-bis-billing-validator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/easybill%2Fpeppol-bis-billing-validator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28886887,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-29T21:06:44.224Z","status":"ssl_error","status_checked_at":"2026-01-29T21:06:42.160Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","docker-compose","e-invoice","e-invoicing","en16931","peppol","peppol-bis","schematron","schematron-validation"],"created_at":"2026-01-29T22:05:31.823Z","updated_at":"2026-01-29T22:05:32.717Z","avatar_url":"https://github.com/easybill.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# peppol-bis-billing-validator\n![Docker Image Version](https://img.shields.io/docker/v/easybill/peppol-bis-billing-validator)\n[![Generic badge](https://img.shields.io/badge/License-MIT-blue.svg)]()\n\n## Introduction\n`peppol-bis-billing-validator` is a small service for validating XML against the official\nPeppol BIS Billing 3.0 schematron rules. It exposes a validation endpoint which takes the \nto be validated XML and returns the schematron report. The HTTP status code indicates if the\nprovided XML is valid (200) or has issues (400).\n\n## Usage\nThis service was mainly designed with containerization in mind. So general idea is to use the following\ndocker image and make HTTP-Requests from the main application to the service for validation.\n\n- modifying / creating docker-compose.yaml\n\n\u003e The service exposes a health endpoint which can be used to check if the service ready to be used\n\n\u003e You can find a OpenAPI documentation after you started the service at /swagger\n```yaml\n  peppol-validator:\n    image: 'easybill/peppol-bis-billing-validator:latest'\n    ports:\n      - '8081:8080'\n    environment:\n        JAVA_TOOL_OPTIONS: -Xmx512m\n    healthcheck:\n      test: curl --fail http://localhost:8081/health || exit 0\n      interval: 10s\n      retries: 6\n```\n\n- starting docker compose\n```\ndocker compose up --detach --wait --wait-timeout 30\n```\n\n- Example of using this service (PHP)\n```PHP\n\u003c?php\n\ndeclare(strict_types=1);\n\nfinal class PeppolValidator\n{\n    public function isValid(string $xml): ?bool\n    {\n        $httpClient = new Client();\n\n        $response = $httpClient-\u003erequest('POST', 'http://localhost:8081/validation', [\n            RequestOptions::HEADERS =\u003e [\n                'Content-Type' =\u003e 'application/xml',\n            ],\n            RequestOptions::BODY =\u003e $xml,\n            RequestOptions::TIMEOUT =\u003e 10,\n            RequestOptions::CONNECT_TIMEOUT =\u003e 10,\n            RequestOptions::HTTP_ERRORS =\u003e false,\n        ]);\n\n        return 200 === $response-\u003egetStatusCode();\n    }\n}\n```\n\n- Example response in case the XML is invalid\n\n\u003e The `svrl:failed-assert` elements are relevant to be inspected. They contain the error message. \n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003csvrl:schematron-output xmlns:svrl=\"http://purl.oclc.org/dsdl/svrl\" title=\"Rules for Peppol BIS 3.0 Billing\" schemaVersion=\"iso\"\u003e\n    \u003csvrl:ns-prefix-in-attribute-values prefix=\"cbc\" uri=\"urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2\" /\u003e\n    \u003csvrl:ns-prefix-in-attribute-values prefix=\"cac\" uri=\"urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2\" /\u003e\n    \u003csvrl:ns-prefix-in-attribute-values prefix=\"ubl-creditnote\" uri=\"urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2\" /\u003e\n    \u003csvrl:ns-prefix-in-attribute-values prefix=\"ubl-invoice\" uri=\"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2\" /\u003e\n    \u003csvrl:ns-prefix-in-attribute-values prefix=\"xs\" uri=\"http://www.w3.org/2001/XMLSchema\" /\u003e\n    \u003csvrl:ns-prefix-in-attribute-values prefix=\"u\" uri=\"utils\" /\u003e\n    \u003csvrl:active-pattern document=\"\" /\u003e\n    \u003csvrl:active-pattern document=\"\" /\u003e\n    \u003csvrl:active-pattern document=\"\" /\u003e\n    \u003csvrl:fired-rule context=\"ubl-creditnote:CreditNote | ubl-invoice:Invoice\" /\u003e\n    \u003csvrl:failed-assert id=\"PEPPOL-EN16931-R007\" location=\"/*:Invoice[namespace-uri()='urn:oasis:names:specification:ubl:schema:xsd:Invoice-2'][1]\" test=\"$profile != 'Unknown'\" flag=\"fatal\"\u003e\n        \u003csvrl:text\u003eBusiness process MUST be in the format 'urn:fdc:peppol.eu:2017:poacc:billing:NN:1.0' where NN indicates the process number.\u003c/svrl:text\u003e\n    \u003c/svrl:failed-assert\u003e\n    \u003csvrl:fired-rule context=\"cac:AccountingSupplierParty/cac:Party\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:EndpointID[@schemeID = '0088'] | cac:PartyIdentification/cbc:ID[@schemeID = '0088'] | cbc:CompanyID[@schemeID = '0088']\" /\u003e\n    \u003csvrl:fired-rule context=\"cac:AccountingCustomerParty/cac:Party\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:EndpointID[@schemeID = '0184'] | cac:PartyIdentification/cbc:ID[@schemeID = '0184'] | cbc:CompanyID[@schemeID = '0184']\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cac:TaxTotal[cac:TaxSubtotal]/cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cac:TaxTotal[cac:TaxSubtotal]/cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cac:TaxTotal[cac:TaxSubtotal]/cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cac:TaxTotal[cac:TaxSubtotal]/cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cac:TaxTotal[cac:TaxSubtotal]/cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cac:TaxTotal[cac:TaxSubtotal]/cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount\" /\u003e\n    \u003csvrl:fired-rule context=\"cac:InvoiceLine | cac:CreditNoteLine\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cac:TaxTotal[cac:TaxSubtotal]/cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cac:TaxTotal[cac:TaxSubtotal]/cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount\" /\u003e\n    \u003csvrl:active-pattern document=\"\" /\u003e\n    \u003csvrl:active-pattern document=\"\" /\u003e\n    \u003csvrl:active-pattern document=\"\" /\u003e\n    \u003csvrl:active-pattern document=\"\" /\u003e\n    \u003csvrl:active-pattern document=\"\" /\u003e\n    \u003csvrl:active-pattern document=\"\" /\u003e\n    \u003csvrl:active-pattern document=\"\" /\u003e\n    \u003csvrl:active-pattern document=\"\" /\u003e\n    \u003csvrl:active-pattern document=\"\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:IssueDate | cbc:DueDate | cbc:TaxPointDate | cbc:StartDate | cbc:EndDate | cbc:ActualDeliveryDate\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:InvoiceTypeCode\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:EndpointID[@schemeID]\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:EndpointID[@schemeID]\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount\" /\u003e\n    \u003csvrl:fired-rule context=\"cac:TaxCategory[upper-case(cbc:TaxExemptionReasonCode)='VATEX-EU-F']\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount\" /\u003e\n    \u003csvrl:fired-rule context=\"cbc:Amount | cbc:BaseAmount | cbc:PriceAmount | cbc:TaxAmount | cbc:TaxableAmount | cbc:LineExtensionAmount | cbc:TaxExclusiveAmount | cbc:TaxInclusiveAmount | cbc:AllowanceTotalAmount | cbc:ChargeTotalAmount | cbc:PrepaidAmount | cbc:PayableRoundingAmount | cbc:PayableAmount\" /\u003e\n\u003c/svrl:schematron-output\u003e\n```\n\n## Issues \u0026 Contribution\nFeel free to create pull-requests or issues if you have trouble with this service or any related resources. ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feasybill%2Fpeppol-bis-billing-validator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feasybill%2Fpeppol-bis-billing-validator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feasybill%2Fpeppol-bis-billing-validator/lists"}