Peppol Specifics - phax/phoss-ap GitHub Wiki
This page lists all aspects of phoss-ap that are specific to the Peppol network. If the AP were to be adapted for a different e-delivery network, these are the areas that would need review and likely modification.
Peppol defines its own participant identifier scheme (iso6523-actorid-upis) with specific format rules.
| Identifier | Peppol format | Used in |
|---|---|---|
| Participant ID (sender/receiver) | Scheme + value, e.g. 0088:1234567890
|
Outbound submission, SMP lookup, SBDH, reporting |
| Document Type ID | Peppol-defined URN scheme | SMP lookup, SBDH, reporting |
| Process ID | Peppol-defined URN scheme | SMP lookup, SBDH, reporting |
| Seat ID | AP registration ID, e.g. POP000000
|
Configuration, inbound metadata |
Difference in other networks: Identifier formats, schemes, and registries would differ entirely.
Peppol mandates the use of a Standard Business Document Header (SBDH) as the envelope around the business document. The combined package (SBDH + payload) is the Standard Business Document (SBD).
- The AP creates the SBDH when the Sender Backend submits a raw document + metadata
- The AP extracts metadata from the SBDH when receiving a pre-built SBD
- SBDH extensions carry Peppol-specific fields (e.g.,
MLS_TO, C1 country code) - The SBDH Instance Identifier is the primary correlation key across MLS, reporting, and duplicate detection
For standard XML business documents (e.g., UBL Invoice), the SBDH <Standard>, <TypeVersion>, and <Type> elements are auto-derived from the Peppol Document Type Identifier. However, for binary payloads such as PDF documents, these values must be explicitly provided because they cannot be inferred from the document type alone.
The deciding factor is the syntax specific ID — the part of the document type identifier before the ##. For XML document types it is <root NS>::<local name> (e.g. urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice), which yields the SBDH Standard and Type. Non-XML document types have no such structure (e.g. urn:peppol:doctype:pdf+xml), so nothing can be derived — not even the TypeVersion, because the underlying parser rejects the whole identifier.
Since 0.12.0 the submission APIs reject such a submission with 400 when any of the four parameters below is missing, naming the missing one. Before that, the transmission failed inside phase4 with Failed to parse payload InputStream to a DOM node (missing payloadMimeType) or with an INVALID_PARAMETERS sending result without any exception (missing sbdhTypeVersion). See #70.
The AP supports four optional SBDH override parameters on the raw document submission API:
| Parameter | Purpose | Example value |
|---|---|---|
sbdhStandard |
SBDH <Standard> element |
urn:peppol:doctype:pdf+xml |
sbdhTypeVersion |
SBDH <TypeVersion> element |
0 |
sbdhType |
SBDH <Type> element |
Invoice |
payloadMimeType |
MIME type for binary wrapping | application/pdf |
The example values above are the ones for the French Factur-X document type busdox-docid-qns::urn:peppol:doctype:pdf+xml##urn:cen.eu:en16931:2017#conformant#urn:peppol:france:billing:Factur-X:1.0::D22B, taken verbatim from the example SBDH in Peppol - France - Solution Architecture 1.3.0, section 6.1.1.
Note that TypeVersion is 0 and not D22B — i.e. it is not the version segment of the document type identifier, unlike for XML document types. This is precisely why the AP does not attempt to derive these values for non-XML document types: there is no mechanical rule, only the governing specification. Always take the values from the specification of the document type you are sending.
When payloadMimeType is set:
- The payload is wrapped as
<BinaryContent>(base64-encoded) instead of inline XML - The
sbdhStandard,sbdhTypeVersion, andsbdhTypeparameters must all be provided - The SBDH is constructed using these explicit values
Setting payloadMimeType for a document type with an XML syntax specific ID is still accepted but logs a warning, because the resulting <BinaryContent> envelope is most likely not what the receiver expects.
Example: Sending a French Factur-X PDF
POST /api/outbound/submit/{senderID}/{receiverID}/{docTypeID}/{processID}/{c1CountryCode}
?sbdhStandard=urn:peppol:doctype:pdf+xml
&sbdhTypeVersion=0
&sbdhType=Invoice
&payloadMimeType=application/pdf
Body: <raw PDF bytes>
When these parameters are omitted (the default), standard XML payload handling applies and SBDH fields are auto-derived from the document type identifier.
Difference in other networks: Different envelope formats (or none). SBDH extensions are Peppol-specific.
Peppol uses a two-tier discovery mechanism:
- SML (Service Metadata Locator): DNS-based lookup to find which SMP hosts a given participant
- SMP (Service Metadata Publisher): REST service that returns the AS4 endpoint URL, certificate, and supported document types for a participant
The AP queries the SMP before each outbound send to resolve the C3 endpoint. The receiver verification step (IReceiverCheck) may also query the AP's own SMP registration.
Configuration: smpclient.truststore.*, peppol.stage (test vs. prod determines SML endpoint).
Difference in other networks: Different or no discovery protocol. Endpoint resolution may be static, registry-based, or use a completely different mechanism.
Peppol defines a specific AS4 profile on top of the OASIS ebMS3/AS4 standard, including:
- Specific PMode parameters (agreement, service, action values)
- One-way push MEP (Message Exchange Pattern)
- Mandatory message signing and encryption
- Synchronous AS4 Receipt expected
- Specific error codes, e.g.
EBMS:0004witherrorDetail = PEPPOL:NOT_SERVICED
The phase4 library (phase4-peppol-client, phase4-peppol-servlet) implements this Peppol-specific AS4 profile.
Difference in other networks: Different AS4 profile, different PMode parameters, or a completely different transport protocol.
Peppol operates its own Public Key Infrastructure (PKI) with separate trust hierarchies for test and production:
- AP keystore: Contains the AP's Peppol-issued certificate and private key for AS4 signing/decryption
- AP truststore: Contains the Peppol root/intermediate CA certificates for validating remote AP signatures
- SMP client truststore: For validating SMP server TLS certificates
-
peppol.stage(testorprod) selects which PKI chain is active - CRL (Certificate Revocation List) downloads are Peppol-specific
Configuration: org.apache.wss4j.crypto.merlin.keystore.*, org.apache.wss4j.crypto.merlin.truststore.*
Difference in other networks: Different CA hierarchy, different certificate issuance process, potentially different crypto requirements.
MLS is a Peppol-defined asynchronous feedback mechanism:
- C3 sends an MLS response back to C2 after processing an inbound document
- MLS is itself sent as a regular Peppol AS4 message (reusing the sending infrastructure)
- Three response codes: RE (Rejection), AP (Approved), AB (Accepted Blind)
- The choice between AP and AB depends on the forwarding mode: HTTP modes provide delivery confirmation (AP), while SFTP and S3 do not (AB)
- RE is sent on verification failure (status reason BV) and on permanent forwarding failure (status reason FD)
- MLS_TO: Alternative participant ID for MLS routing (per-transaction, from SBDH extension). On receipt it is only accepted if its SPID Main ID correlates to the sending C2's Main ID; if the target is not reachable via SMP, the AP falls back to the default SPID receiver (see Message Level Status)
-
MLS_TYPE: Controls when MLS is sent —
FAILURE_ONLYorALWAYS_SEND(per AP instance)
The Peppol Network Policy defines timing requirements based on AS4 timestamps:
| Milestone | Definition |
|---|---|
| M1 | AS4 Timestamp when business document is sent at C2 |
| M2 | AS4 Timestamp when MLS message is sent at C3 |
| M3 | Date/time when MLS is received at C2 |
| SLR | Requirement |
|---|---|
| MLS-1 | 99.5%: M2 - M1 <= 20 minutes |
| MLS-2 | 99.5%: M3 - M1 <= 25 minutes |
Difference in other networks: MLS is entirely Peppol-specific. Other networks may have no delivery status mechanism, or use a different protocol (e.g., MDNs, polling).
Peppol requires APs to submit periodic Transaction Status Reports (TSR) and End User Statistics Reports (EUSR):
- Reports are generated using the
peppol-reportinglibrary - Submission is scheduled (configurable day/hour/minute)
- Each reported transaction needs: sender ID, receiver ID, document type ID, process ID, C1 country code (outbound) or C4 country code (inbound)
- Reporting status is tracked per transaction (
pending/reported) - The reporting sender ID is a Peppol Participant ID configured via
peppol.reporting.senderid
The EUSR counts unique End Users. The End User is C1 (the sender participant) for outbound transactions and C4 (the receiver participant) for inbound transactions.
Using the participant identifier directly as the End User ID would over-count End Users, because several countries run multiple identifier schemes in parallel that all address the same organisation. phoss AP therefore derives the End User ID via PeppolEndUserHelper of peppol-commons (called through APPeppolReportingHelper.getEffectiveEndUserID (...)). It unifies the identifier (case insensitive schemes are lower cased) and applies these default mappings:
| Source scheme | Target scheme | Value conversion |
|---|---|---|
9925 (Belgian VAT number) |
0208 (Belgian enterprise number) |
leading BE is removed, case insensitive |
9930 (German VAT number) |
0246 (German Electronic Business Address) |
unchanged |
0037 (Finnish OVT identifier, removed from the code list) |
0216 (Finnish OVT code) |
hyphen inside the Business ID is removed, a missing 0037 prefix is added |
So sending to 9925:BE0123456789 and to 0208:0123456789 counts as one single End User. The resulting End User ID is the URI encoded participant identifier - e.g. iso6523-actorid-upis::0208:0123456789.
The identifier factory used for the unification is the one selected via peppol.identifier.mode, so identifiers accepted by the AP are unified the same way. Participant identifiers that the identifier factory rejects are used unmodified (and logged as a warning).
Deployments that need additional mappings can adjust them at startup - e.g. from a Runtime Extensions SPI implementation - via PeppolEndUserHelper.registerMapping (...), PeppolEndUserHelper.unregisterMapping (...), PeppolEndUserHelper.unregisterAllMappingsOfSourceISO6523Code (...) and PeppolEndUserHelper.removeAllMappings (). See peppol-commons issue #80.
Difference in other networks: Different or no reporting requirements. Report formats, submission schedules, and required data points would differ.
Peppol requires country codes for reporting purposes:
-
C1 country code: Country of the original sender (C1). Provided by the Sender Backend (C2) at submission time (or extracted from SBDH). Stored in
outbound_transaction. -
C4 country code: Country of the final receiver (C4). Provided by the Receiver Backend (C3) either synchronously (HTTP response) or asynchronously (reporting API call). Stored in
inbound_transaction.
Difference in other networks: These are Peppol reporting requirements. Other networks may not need corner-specific country tracking.
Peppol requires that a receiving AP (C3) verifies it actually services the addressed receiver participant before accepting a document. If not, the specific AS4 error EBMS:0004 / PEPPOL:NOT_SERVICED must be returned.
Implementations: SMP self-query, local participant registry, or other pluggable mechanism (IReceiverCheck SPI).
Difference in other networks: Different error codes, different verification requirements, or no receiver check at all.
Peppol duplicate detection operates at two levels:
| Level | What it checks |
|---|---|
| AS4 Message ID | Exact AS4 message retransmission |
| SBDH Instance Identifier | Same Peppol envelope resent with a different AS4 Message ID |
Both levels are Peppol-relevant because the SBDH Instance Identifier is a Peppol concept.
Difference in other networks: Different envelope identifiers, potentially different duplicate detection granularity.
phoss-ap uses the Peppol 4-corner model throughout:
| Term | Meaning |
|---|---|
| C1 | Sender (business entity) |
| C2 | Sender Access Point |
| C3 | Receiver Access Point |
| C4 | Receiver (business entity) |
| Sender Backend | Internal system within C2 that submits documents to the AP |
| Receiver Backend | Internal system within C3 that receives documents from the AP |
Difference in other networks: Different terminology (e.g., "gateway", "connector", "node"), potentially a different number of corners (3-corner, 2-corner).
The outbound_transaction table has a transaction_type field distinguishing business_document from mls_response. MLS responses are tracked as outbound transactions with a link back to the originating inbound transaction.
Difference in other networks: Without MLS, there is no secondary transaction type. The outbound table would only contain business documents.
The following Maven dependencies are Peppol-specific:
| Dependency | Purpose |
|---|---|
phase4-peppol-client |
Peppol AS4 profile for sending |
phase4-peppol-servlet |
Peppol AS4 profile for receiving |
peppol-commons |
Peppol identifier handling, SBDH, SMP client |
peppol-reporting |
TSR/EUSR report generation and submission |
Difference in other networks: Would require different phase4 profile modules (or a different AS4 library entirely) and different reporting libraries.
| Property | Purpose |
|---|---|
peppol.stage |
test or prod (selects PKI and SML) |
peppol.owner.seatid |
This AP's Peppol Seat ID |
peppol.owner.countrycode |
Country code of the AP operator |
peppol.sending.enabled |
Enable/disable outbound sending |
peppol.receiving.enabled |
Enable/disable inbound receiving |
peppol.reporting.schedule.enabled |
Enable scheduled reporting |
peppol.reporting.schedule.* |
Reporting schedule (day, hour, minute) |
peppol.receiver-check.mode |
Receiver verification mode (none, smp, sml) |
peppol.dns.servers |
Custom DNS servers for Peppol NAPTR lookups |
peppol.identifier.mode |
Identifier validation mode (strict, lax) |
mls.sending.enabled |
Global MLS sending switch |
mls.type |
MLS sending strategy |
phase4.endpoint.address |
Public AS4 endpoint URL |
smpclient.truststore.* |
SMP client TLS trust |
Difference in other networks: Entirely different configuration namespace and semantics.