Skip to content

Peppol MLS Update

Arun Kumar edited this page Oct 4, 2026 · 2 revisions

Peppol MLS Update

Contents

OpenPeppol MLS – Current Status & Migration

Message Level Status (MLS) is the Peppol mechanism by which a receiving Access Point (C3) reports the outcome of its processing of a business document back to the sending Access Point (C2). OpenPeppol has published the specifications and guidelines required to operationalize MLS, and Service Providers must plan their implementation ahead of the deadlines below.

Key Specifications

MLS Migration Timeline

Milestone Description Date
T1 Phase-In starts July 1st, 2026
T2 Implementation period. MLS receiving capability MUST be in production. The MLS sending activation window opens. Implementation time until February 28th, 2027
T3 MLS mandatory. MLS sending is mandatory and SLRs become enforceable (T2 + 1 month activation period). March 31st, 2027

Phase-In Guideline

The Peppol MLS Phase-In v1.0.0 guideline:

  • Defines the transition from the current model to mandatory MLS.
  • Service Providers should plan implementation ahead of the T2/T3 deadlines.

OpenPeppol Support Activities

OpenPeppol is conducting support sessions and webinars to help Service Providers prepare for MLS.

Upcoming webinars

Date Topic
6 October 2026 MLS impact on existing APs and SMPs
10 November 2026 MLS Basics
26 January 2027 MLS impact on existing APs and SMPs (repeat session)

MLS in the Four-Corner Model

MLS at two levels in Access Point Service Provider implementation:

Level What happens
Messaging Level Status (AP Message Handler) SML/SMP lookup for MLS support.
Validation (incoming document and MLS).
MLS generation and transmission, based on the resolved MLS_TO address for the default/specified MLS_TYPE.
Transport Level Message (AP Protocol Handler) AS4 message (payload + SBDH).
The SBDH carries the optional MLS_TO and MLS_TYPE.
Fallback: as per SPOG if MLS_TO and MLS_TYPE are missing.

The business document flows from C1 through C2 and C3 to C4 as usual. The MLS flows in the reverse direction, from C3 back to C2.

Oxalis-NG Capabilities

Transport Level (AS4)

Supported since Oxalis-NG v1.5.0:

  • MLS sending and receiving
  • MLS_TO and MLS_TYPE in the SBDH (optional in the SBDH)
  • MLS_TO and MLS_TYPE automatic resolution if not provided as part of the SBDH

MLS Message Handling (Generation and Validation)

Capability Status
MLS Generation – programmatic read and write of MLS using the peppol-mls library, part of vefa-peppol (since vefa-peppol v4.4.0) Supported
MLS Structural & Integrity Check – structural validation using the peppol-mls library, part of vefa-peppol (since vefa-peppol v4.4.0) Supported
Schematron validation – will be supported with the Oxalis Community Validation Engine - Available ONLY to Oxalis Community Members In progress

MLS_TO and MLS_TYPE Resolution

Every inbound Peppol AS4 message passes through HeaderMlsEnricher. MLS_TO and MLS_TYPE are resolved independently.

Core principle: SBDH values are preferred when valid, otherwise Oxalis-NG applies the field-specific fallback/default policy as per SPOG.

One inbound AS4 message → two independent resolution paths → effective MLS_TO + MLS_TYPE.

MLS_TO Resolution

Resolved by MlsToResolver.resolve():

  1. SBDH MLS_TO present?

    • NO → fallback to AP certificate
    • YES → continue
  2. Syntactically valid?

    • YES → continue
    • NO → ignore value → fallback

    Expected format: iso6523-actorid-upis / 0242:<6 digits>-UseCase[-Suffix]

  3. Main ID correlates with the sender AP certificate?

    • YES → continue
    • NO → redirect attempt → fallback
  4. SMP validation enabled?

    • OFF (default) → preserve
    • ON → check SMP registration
  5. Registered in SMP for the MLS document type?

    • YES → preserve the SBDH MLS_TO
    • NO → fallback
Outcome Result
PRESERVED The validated SBDH MLS_TO is used.
FALLBACK AP certificate Subject CN → 0242:<Main ID>

MLS_TYPE Resolution

Resolved by MlsTypeResolver.resolve():

  1. SBDH MLS_TYPE present?
    • NO → configured default
    • YES → continue to value validation
  2. Exact value (case-sensitive)? Must be ALWAYS_SEND or FAILURE_ONLY.
    • YES → preserve as-is
    • NO → configured default
Outcome Result
PRESERVED The sender's MLS_TYPE remains unchanged.
DEFAULT APPLIED MlsResolutionPolicy.defaultMlsType

Key distinction: MLS_TYPE falls back to the configured default.

Test Scenarios

Possible inbound AS4 message combinations and the resulting values after Oxalis-NG MLS resolution.

Scenario SBDH MLS_TO SBDH MLS_TYPE Resulting MLS_TO Resulting MLS_TYPE
Both present & valid (1. bis3-invoice-mls-both-present-valid.xml) 0242:000723 ALWAYS_SEND 0242:000723 – preserved ALWAYS_SEND – preserved
Both missing (2. bis3-invoice-mls-both-absent.xml) absent absent 0242:000723 – from cert CN P0000723 FAILURE_ONLY – default
MLS_TO missing, MLS_TYPE present (3. bis3-invoice-mls-type-only.xml) absent FAILURE_ONLY 0242:000723 – from cert FAILURE_ONLY – preserved
MLS_TO present, MLS_TYPE missing (4. bis3-invoice-mls-to-only.xml) 0242:000723 absent 0242:000723 – preserved FAILURE_ONLY – default
Both present but invalid – wrong SP / bad grammar (5. bis3-invoice-mls-both-present-invalid.xml) 0242:999999 (not sender's SP) always_send (wrong case) 0242:000723 – sender's value ignored, cert value used FAILURE_ONLY – invalid value ignored
MLS_TO present (Use Case), MLS_TYPE missing (6. bis3-invoice-mls-to-specific-usecase.xml) 0242:000723-MLS absent 0242:000723-MLS – preserved FAILURE_ONLY – default

Key rules

  • MLS_TO falls back to the sender AP certificate when the SBDH value is missing or unusable.
  • MLS_TYPE falls back to the configured default when missing or invalid.

Retrieving the Resolved MLS_TO and MLS_TYPE (Inbound)

After HeaderMlsEnricher has run, the effective (resolved) MLS_TO and MLS_TYPE are available to the Header (of PayloadPersister) and to the Header in InboundMetadata (of ReceiptPersister). A sample implementation using ReceiptPersister below:

Sample Inbound MLS fields code snippet

// SampleReceiptPersister class which extends network.oxalis.ng.api.persist.ReceiptPersister


@Singleton
@Type("SampleReceiptPersister")
public class SampleReceiptPersister implements ReceiptPersister {

    private static final Logger LOGGER = LoggerFactory.getLogger(SampleReceiptPersister.class);
    private final X509Certificate myAccessPointCertificate;

    //Additional variable below if required


    @Inject
    public SampleReceiptPersister (@Named("inbound") Path inboundFolder,
        X509Certificate myAccessPointCertificate, EvidenceFactory evidenceFactory) {
        this.inboundFolder = inboundFolder;
        this.myAccessPointCertificate = myAccessPointCertificate;
        this.evidenceFactory = evidenceFactory;
    }


    @Override
    public void persist(InboundMetadata inboundMetadata, Path payloadPath) throws IOException {


        //Other code omitted below and above, only MLS specific code for illustration purpose

        String mlsToId = null;
        String mlsToSchmeId = null;
        String mlsType = null;
        if (Objects.nonNull(inboundMetadata.getHeader().getMlsToIdentifier())) {
            mlsToId = inboundMetadata.getHeader().getMlsToIdentifier().getIdentifier();
            if (Objects.nonNull(inboundMetadata.getHeader().getMlsToIdentifier().getScheme())) {
                mlsToSchmeId = inboundMetadata.getHeader().getMlsToIdentifier().getScheme().getIdentifier();
            }
        }
        if (Objects.nonNull(inboundMetadata.getHeader().getMlsTypeIdentifier())) {
            mlsType = inboundMetadata.getHeader().getMlsTypeIdentifier().getIdentifier();
        }
        LOGGER.info("PEPPOL-Inbound: MLS Information - mlsToId={}, mlsToSchmeId={}, mlsType={}", mlsToId, mlsToSchmeId, mlsType);

        // Additional receipt and MLS data persistance logic below.


    }
}

Next Steps

Oxalis-NG Team will continue provide implementation guidelines to Oxalis Community Member, including:

  • Technical Dialog meeting explaining MLS support (Available ONLY to Oxalis Community Members)
  • Practical integration approaches (Like this wiki page to all Oxalis-NG users)

Reference

Clone this wiki locally