-
Notifications
You must be signed in to change notification settings - Fork 18
Message Level Status
MLS is a Peppol-defined asynchronous feedback mechanism that allows the receiving Access Point (C3) to inform the sending Access Point (C2) about the processing outcome of a received business document. MLS messages are themselves regular Peppol documents sent via AS4, reusing the existing outbound transaction infrastructure including retry logic.
The AP handles MLS in both roles:
- As C3 (receiving): After determining the forwarding outcome, the AP generates and sends an MLS response back to C2.
- As C2 (sending): The AP receives MLS responses asynchronously via AS4, correlates them with outbound transactions, and updates the MLS status.
| Code | Name | When sent |
|---|---|---|
| AP | Approved | Successful delivery with confirmation (forwarding mode http_post_sync or http_post_async) |
| AB | Accepted Blind | Delivered without delivery confirmation (forwarding mode sftp, s3_link, or filesystem) |
| RE | Rejection | Document failed verification (status reason BV) or permanent forwarding failure to C4 (status reason FD) |
The choice between AP and AB depends on the Forwarding Process: HTTP modes provide delivery confirmation, while SFTP, S3, and Filesystem do not.
Included in MLS rejection (RE) response line items.
| Code | Name | Description |
|---|---|---|
| BV | Business Rule Violation (Fatal) | Fatal business rule violation -- document does not conform to required business rules |
| BW | Business Rule Warning | Non-fatal issue, may accompany a BV but cannot trigger rejection alone |
| FD | Failure of Delivery | Permanent inability to forward the document to C4 (error field is NA) |
| SV | Syntax Violation | XML schema or syntax validation failure |
When the AP receives an inbound business document and determines the forwarding outcome, it generates an MLS response and sends it back to C2.
| Trigger | MLS response code | Status reason |
|---|---|---|
| Successful forwarding via HTTP | AP (Approved) | -- |
| Successful forwarding via SFTP, S3, or Filesystem | AB (Accepted Blind) | -- |
| Document verification failure | RE (Rejection) | BV (Business Rule Violation) |
| Permanent forwarding failure (max retries exhausted) | RE (Rejection) | FD (Failure of Delivery) |
The mls.type configuration property controls when MLS responses are sent:
| Value | Behavior |
|---|---|
ALWAYS_SEND (default) |
MLS response is sent for all outcomes (RE, AP, or AB) |
FAILURE_ONLY |
MLS response is sent only on rejection (RE) |
The active strategy is captured per inbound transaction at reception time, so changing the configuration only affects newly received documents.
MLS sending (as C3) can be globally disabled via mls.sending.enabled=false -- see Configuration.
By default, the MLS response is sent to C2's Peppol Seat ID. The Sender Backend can override this per outbound transaction by providing the mlsTo query parameter on the submission API, which places an alternative Peppol participant ID in the SBDH extension. This is useful when C2 operates multiple access points.
The mlsTo value can be set on:
-
POST /api/outbound/submit/{senderID}/{receiverID}/{docTypeID}/{processID}/{countryC1}-- via themlsToquery parameter (see API Specification) -
POST /api/outbound/submit-auto/{senderID}/{receiverID}/{c1CountryCode}-- via themlsToquery parameter (see API Specification) -
POST /api/outbound/submit-s3-- via themlsTofield in the JSON body (see API Specification)
sequenceDiagram
participant AP as AP (C3)
participant DB as DB
participant P4 as phase4
participant RA as Remote AP (C2)
AP->>AP: Determine MLS response code (RE, AP, or AB)
AP->>AP: Check MLS_TYPE (ALWAYS_SEND or FAILURE_ONLY)
note over AP: If FAILURE_ONLY and outcome is success: skip MLS
AP->>DB: Create outbound_transaction (transaction_type = mls_response)
AP->>DB: Update inbound_transaction (mls_response_code, mls_outbound_transaction_id)
AP->>P4: Send MLS via AS4
P4->>RA: AS4 UserMessage (MLS)
RA-->>P4: AS4 Receipt
P4-->>AP: AS4 result
AP->>DB: Insert outbound_sending_attempt
AP->>DB: Update outbound_transaction status
The MLS sending is recorded as an outbound_transaction with transaction_type = mls_response, linked to the original inbound transaction via mls_inbound_transaction_id. The inbound transaction's mls_outbound_transaction_id is set to reference it back.
MLS response transactions follow the same retry logic as business document transactions -- see Retry and Resilience Patterns.
When the AP sends a business document to a remote C3, it expects an MLS response back. The MLS response arrives asynchronously as a separate AS4 message.
sequenceDiagram
participant RA as Remote AP (C3)
participant PS as phase4 Servlet
participant DB as DB
RA->>PS: AS4 UserMessage (MLS response)
PS->>PS: Parse MLS, extract SBDH Instance ID reference
PS->>DB: Lookup outbound_transaction by SBDH Instance ID
DB-->>PS: original transaction
PS->>DB: Update outbound_transaction MLS fields
PS-->>RA: AS4 Receipt
The AP correlates the incoming MLS response with the original outbound business document transaction using the SBDH Instance Identifier referenced in the MLS message. On successful correlation, the outbound transaction is updated with:
| Field | Value |
|---|---|
mls_status |
received_ap, received_ab, or received_re (mapped from the MLS response code) |
mls_received_dt |
The AS4 timestamp when the MLS response was received |
mls_id |
The MLS document's own ID (cbc:ID) |
mls_inbound_transaction_id |
FK to the inbound transaction representing the received MLS message |
If no matching outbound transaction is found, the AP logs a warning and triggers the onInboundMLSCorrelationError() notification.
Tracked on outbound business document transactions as mls_status:
| Value | Description |
|---|---|
pending |
MLS response has not yet been received |
received_ap |
MLS response received with code AP (Approved) |
received_ab |
MLS response received with code AB (Accepted Blind) |
received_re |
MLS response received with code RE (Rejection) |
not_applicable |
MLS is not expected for this transaction (e.g., MLS response transactions themselves) |
The Peppol Network Policy defines Service Level Requirements (SLRs) for MLS timing, measured monthly for payloads smaller than 10 MB.
All milestones are based on AS4 MessageInfo/Timestamp values (UTC).
| Milestone | Definition | Where captured in phoss-ap |
|---|---|---|
| M1 | AS4 Timestamp when the business document transmission is initiated at C2 |
outbound_sending_attempt.as4_timestamp (outbound) or inbound_transaction.as4_timestamp (inbound) |
| M2 | AS4 Timestamp when the MLS message transmission is initiated at C3 |
outbound_sending_attempt.as4_timestamp on the MLS response's successful sending attempt |
| M3 | Date/time when the MLS message is received at C2 | outbound_transaction.mls_received_dt |
| SLR | Constraint | Target | Measurement |
|---|---|---|---|
| SLR MLS-1 (Latest MLS Sending) | M2 - M1 <= 20 minutes | 99.5% | This AP as C3: time from receiving a business document to successfully sending the MLS response |
| SLR MLS-2 (Latest MLS Reception) | M3 - M1 <= 25 minutes | 99.5% | This AP as C2: time from successfully sending a business document to receiving the MLS response |
The AP provides dedicated API endpoints for monitoring SLR compliance:
-
GET /api/mls/sla/mls1-- MLS-1 SLA report (this AP as C3, measuring M2 - M1). See API Specification#mls-apis. -
GET /api/mls/sla/mls2-- MLS-2 SLA report (this AP as C2, measuring M3 - M1). See API Specification#mls-apis.
Both endpoints return:
| Field | Description |
|---|---|
totalCount |
Total number of MLS responses measured |
withinSlaCount |
Number within the threshold |
compliancePercent |
Actual compliance percentage |
targetPercent |
Required target (99.5) |
thresholdSeconds |
SLA threshold in seconds (1200 for MLS-1, 1500 for MLS-2) |
meetingSla |
Whether the target is met |
entries |
Individual measurements with sbdhInstanceID, m1, m2OrM3, durationSeconds, withinSla
|
All MLS-related API endpoints. Full details in API Specification.
| Method | Path | Description |
|---|---|---|
| GET | /api/mls/missing |
List inbound transactions that have not yet received an MLS response |
| GET | /api/mls/sla/mls1 |
MLS-1 SLR compliance report (C3 side: M2 - M1) |
| GET | /api/mls/sla/mls2 |
MLS-2 SLR compliance report (C2 side: M3 - M1) |
MLS-related fields are also returned on existing transaction status endpoints:
| Method | Path | MLS fields |
|---|---|---|
| GET | /api/outbound/status/{sbdhInstanceID} |
mlsTo, mlsStatus, mlsReceivedDT, mlsId
|
| GET | /api/inbound/status/{sbdhInstanceID} |
mlsTo, mlsType, mlsResponseCode, mlsOutboundTransactionID
|
| Field | Description |
|---|---|
mls_to |
MLS_TO target participant ID (from SBDH extension) |
mls_type |
MLS sending strategy at time of reception (FAILURE_ONLY or ALWAYS_SEND) |
mls_response_code |
MLS response code sent or to be sent (RE, AP, AB) |
mls_outbound_transaction_id |
FK to the outbound_transaction representing the MLS sending |
| Field | Description |
|---|---|
mls_to |
MLS_TO override participant ID (only for business_document transactions) |
mls_status |
MLS reception status: pending, received_ap, received_ab, received_re, not_applicable
|
mls_received_dt |
When the MLS response was received |
mls_id |
The MLS message's own ID (cbc:ID) |
mls_inbound_transaction_id |
FK to the inbound_transaction that represents the received MLS message (only for mls_response transactions) |
| Field | Description |
|---|---|
as4_timestamp |
AS4 MessageInfo/Timestamp (UTC). For business_document attempts this is MLS Milestone M1; for mls_response attempts this is MLS Milestone M2. |
See Database Design Notes for the full schema.
All MLS configuration properties. See Configuration Properties#mls for the full configuration reference.
| Property | Default | Description |
|---|---|---|
mls.sending.enabled |
true |
Global switch to enable or disable all outbound MLS sending. When false, no MLS responses are sent for any inbound transaction. |
mls.type |
ALWAYS_SEND |
MLS sending strategy: FAILURE_ONLY (only on rejection) or ALWAYS_SEND (for all outcomes). Captured per inbound transaction at reception time. |
The AP triggers notifications for MLS-related events via the IAPNotificationHandlerSPI:
| Event | Method | When |
|---|---|---|
| MLS correlation error | onInboundMLSCorrelationError() |
An inbound MLS response cannot be correlated to any outbound business document (no matching SBDH Instance ID found) |
It is appreciated if you star the GitHub project if you like it.
Donation link: https://paypal.me/PhilipHelger
- Home
- News and noteworthy
- Running phoss AP
- Architecture Overview
- API Specification
- Configuration Properties
- Code Lists
- Database Design Notes
- Maven Module Structure
- Runtime Extensions
- OpenTelemetry Integration
- Security Considerations
- Peppol Specifics
- Testing Without Peppol Network
- Known Users
- Migrating from phase4-peppol-standalone
- Contributing