This repository contains a simple, standalone validation service (Phorm) accessible by API only.
The implementation of the validation is based on the open source validation engine phive and the collection of rules phive-rules.
"Phorm" is a combination of "PH + form + conform" and is all about standards, compliance, and correctness.
- Requires Java 17 or newer - Java 21 or later is recommended
- Apache Maven is used as the build tool. May be abstracted by a Docker image.
- Coding language: English
The services offers the following APIs.
- POST
/api/validate/{vesid}- Validate the provided payload in the body against the validation rules, identified by
{vesid} - Requires the HTTP header
X-Tokento have the configured value (see below forphorm.api.requiredtoken) - If the HTTP Request Header
Acceptwith valueapplication/xmlis present, the result is an XML structure. Else the result is a JSON structure - Test invocation (replace
XXXwith real token):curl -X POST -H "Content-Type: application/xml" -H "X-Token: XXX" -d @src/test/resources/testfiles/peppol-bis3/base-example.xml http://localhost:8080/api/validate/eu.peppol.bis3:invoice:latest
- Validate the provided payload in the body against the validation rules, identified by
- GET
/api/get/vesids- Get a list of all registered VESIDs
- The optional URL parameter
include-deprecatedcan be used to also return registered, but deprecated VES IDs. No parameter value is needed - The result is a JSON structure
curl -X GET http://localhost:8080/api/get/vesids
- POST
/api/determinedoctype- Try to detect the format and payload specifics of a document instance.
- The document instance must be the POST payload.
- Requires the HTTP header
X-Tokento have the configured value (see below forphorm.api.requiredtoken) - The result is a JSON structure
- Test invocation (replace
XXXwith real token):curl -X POST -H "Content-Type: application/xml" -H "X-Token: XXX" -d @src/test/resources/testfiles/peppol-bis3/base-example.xml http://localhost:8080/api/determinedoctype
- Example output:
{
"syntaxID":"ubl2-invoice",
"syntaxVersion":"2.1",
"sender":"iso6523-actorid-upis::0088:9482348239847239874",
"receiver":"iso6523-actorid-upis::0002:FR23342",
"doctype":"busdox-docid-qns::urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1",
"process":"cenbii-procid-ubl::urn:fdc:peppol.eu:2017:poacc:billing:01:1.0",
"customizationID":"urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0",
"bdid":"Snippet1",
"senderName":"SupplierTradingName Ltd.",
"senderCountryCode":"GB",
"receiverName":"BuyerTradingName AS",
"receiverCountryCode":"SE",
"vesid":"eu.peppol.bis3:invoice:latest-active",
"profileName":"Peppol BIS Billing UBL Invoice V3"
}- POST
/api/dd_and_validate- Determine the document type and afterwards validate the provided payload in the body against the determined validation rules
- Requires the HTTP header
X-Tokento have the configured value (see below forphorm.api.requiredtoken) - If the HTTP Request Header
Acceptwith valueapplication/xmlis present, the result is an XML structure. If the HTTP Request HeaderAcceptwith valuetext/htmlis present, the result is an HTML file. Else the result is a JSON structure - Test invocation (replace
XXXwith real token):curl -X POST -H "Content-Type: application/xml" -H "X-Token: XXX" -d @src/test/resources/testfiles/peppol-bis3/base-example.xml http://localhost:8080/api/dd_and_validate/
Phorm comes with one configuration file called application.properties.
The lookup rules for the file is defined in https://github.com/phax/ph-commons/wiki/ph-config
It supports the following settings:
global.debug: overall debug mode. This enables additional checks that should not be executed every time (e.g. because they are slow or because they are spamming the logfile etc.). This flag has no impact on the logging level! This flag should be set totruein development mode, but tofalsein production mode. The value of this field is internally maintained in classcom.helger.commons.debug.GlobalDebug.global.production: overall production mode. If this flag is set tofalsecertain functionality not applicable in development environment (like mass mail sending) is disabled. This flag should be set totruein production mode.webapp.datapath: the path where all relevant data and settings are stored. This can e.g. be a relative path (likeconf- relative to the web application directory) for development purposes but should be an absolute path (e.g./config/phorm) in production. Make sure the user running Phorm has write access to this folder.webapp.checkfileaccess: a flag that determines whether the directory of the web application should be checked for read and write access. This is only required if the data path inside the web application and should therefore always befalse.webapp.testversion: a special indicator for the web application whether the version should be highlighted as a "test" version. Set totruein debug mode andfalsein production mode.phorm.statusapi.enabled: a flag that indicates, if the status API (/status) should deliver data or not.phorm.api.requiredtoken: the specific value of theX-Tokenheader that must be provided to access the API. Customize this once and don't share it. The development default isphorm-dev-token.phorm.api.response.onfailure.http400: a flag to indicate, whether the API should return HTTP 400 (Bad Request) on failed validations or not. The default istruefor backwards compatibility reasons.phorm.api.response.log.payload: a flag to indicate, whether the validation response should be logged in the console or not. The default isfalse.
-
Requires Java 17 or higher
-
Build with Apache Maven 3.x - via
mvn clean install -
Alternatively build with a Docker Maven image:
build-with-docker.cmd clean install
or
./build-with-docker.sh clean install
Building:
docker build --pull -t phelger/phorm .The old image tag phelger/valsvc is also maintained for backwards compatibility:
docker tag phelger/phorm phelger/valsvcRunning:
docker run -d --name phorm -p 8080:8080 phelger/phormExample curl command (use the correct "X-Token" and the right address):
curl -d "@base-example.xml" -H "Content-Type: application/xml" -H "X-Token: XXX" -X POST http://localhost:8080/api/validate/eu.peppol.bis3:invoice:latest
Pre-built Docker images are available on Docker Hub:
phelger/phorm— for linux/amd64phelger/phorm-arm64— for linux/arm64
Both images are tagged with the specific version (e.g. 2.0.0) as well as latest.
The multi-architecture build script is located in docker/build-all.sh.
If an update is made to the validation, you have to do a git pull and recompile.
To make sure your own configuration is kept unchanged, my suggestion is to create a file private-application.properties
in the src/main/resources folder of your checked-out copy (same folder as application.properties),
where you can adjust or change all the configuration entries that are important to you.
The file with this specific name and within this folder has a higher priority than the default
application.properties file and is also marked as "ignored" in git, i.e. changes to this file
are not overwritten during updates from the repository.
If the file is in the correct folder, it will also be included in the compilation process and
is therefore available out of the box for Phorm.
As an alternative to using private-application.properties you may also consider using
environment variables or Java system properties for the configuration -
see https://github.com/phax/ph-commons/wiki/ph-config for details.
v2.0.1 - 2026-03-25
- Updated to phive-rules 4.2.5
v2.0.0 - 2026-03-18
- Made the repository public - thanks for all the supporters!!!
- Starting to use semantic versioning
2026-03-17
- Updated to phive 12.0.1 and phive-rules 4.2.3
2026-03-12
- Rebranding: the project has been renamed from "Validation Service" / "valsvc" to Phorm
- The Maven artifact ID changed from
validation-servicetophorm, so the WAR file is nowphorm.warinstead ofvalidation-service.war - The Java package was renamed from
com.helger.valsvctocom.helger.phorm - The Docker image is now
phelger/phorm(the old tagphelger/valsvcis still provided for backwards compatibility) - Configuration property keys were renamed from
valsvc.*tophorm.*(e.g.valsvc.api.requiredtoken→phorm.api.requiredtoken). The oldvalsvc.*keys are still accepted as fallback values. - The log prefix changed from
[VAL-SVC]to[PHORM] - The default Docker data path changed from
/config/valsvcto/config/phorm
2026-02-22
- Updated to phive 12.0.0 and phive-rules 4.2.0
- Both
/api/validate/and/api/dd_and_validateare now able to create HTML results (first draft)
2026-02-18
- Updated to phive-rules 4.1.8
2025-09-02
- The API
/api/determinedoctypecan now also return XML payload - Fixed an error with the document type ID scheme for PINT document types in determination
2025-08-29
- The minimum requirement is now Java 17
2025-03-23
- Added new API
/api/dd_and_validateto run document type detection and validation in one call - Changed the default value of
phorm.api.response.log.payload(formerlyvalsvc.api.response.log.payload) tofalse
2025-03-10
- Added the new phive-rules-zatca for Saudi Arabian invoice
2025-03-08
- Added all other remaining validation rules from phive-rules
2025-03-04
- Added Danish OIOUBL rules to the ruleset
2025-01-09
- The API
/api/validate/{vesid}can return JSON or XML (depending on theAcceptheader)
2024-12-06
- Added new API
/api/determinedoctypeto auto detect payload details
2024-12-05
- the new configuration property
phorm.api.response.log.payload(formerlyvalsvc.api.response.log.payload) can be used to disable logging of the result JSON - Added support for German ZuGFERD XML invoices
2024-12-03
- the new configuration property
phorm.api.response.onfailure.http400(formerlyvalsvc.api.response.onfailure.http400) can be used to disable returning HTTP 400 on validation failure
2024-09-17
- updated to phive v10 and ph-diver v3
2024-05-23
- added UBL.BE rules as well
2024-01-10
- added XRechnung rules as well
My personal Coding Styleguide | It is appreciated if you star the GitHub project if you like it.