-
Notifications
You must be signed in to change notification settings - Fork 18
Sending Process
Philip Helger edited this page Apr 1, 2026
·
18 revisions
The sending process handles outbound Peppol document transmission from the Sender Backend (within C2) through the AP to the remote receiving AP (C3).
- Receive document via API - The Sender Backend provides data via the REST API (raw document + metadata, pre-built SBD, or S3 reference + metadata). Optionally includes an MLS_TO override. When an S3 reference is provided, the AP fetches the document from the sender's S3 bucket before proceeding.
-
Store document and metadata - The document is written to disk under
storage.outbound.pathand the file path and metadata are persisted to theoutbound_transactiontable in the database. -
Optional verification - The document is validated via the pluggable verification SPI (
IDocumentVerifier). If verification fails, the transaction status is set torejected, a notification is triggered, and no sending attempt is made. - AS4 sending via phase4 - SMP lookup, SBDH creation (if needed, including MLS_TO in SBDH extensions), AS4 message construction, signing, and transmission. The synchronous AS4 receipt is checked.
-
Record sending attempt - Insert a row into
outbound_sending_attemptwith the outcome (AS4 Message ID, Receipt Message ID, HTTP status code, or error details). Update the parentoutbound_transactionstatus accordingly. -
On success: trigger outbound reporting - The
onSuccessfulAS4Sendingcallback triggers Peppol reporting for the outbound transaction. - On failure: schedule retry - The transaction is marked for retry. The retry strategy (max attempts, backoff) is defined via customizable Java interfaces.
- On permanent failure: notify - When max retries are exhausted, the generic notification interface is invoked.
- Receive MLS response (asynchronous) - At a later point, the remote C3 may send an MLS response back via AS4. The AP receives it, correlates it with the original outbound transaction via the SBDH Instance Identifier, and updates the MLS status (received_ap, received_ab, or received_re).
sequenceDiagram
participant SB as Sender Backend
participant AP as AP API
participant DB as DB
participant P4 as phase4
participant RA as Remote AP (C3)
SB->>AP: 1. Submit doc (raw+meta, SBD, or S3 ref+meta, optional mlsTo)
AP->>DB: 2. Insert into outbound_transaction
DB-->>AP: stored OK
AP->>AP: 3. Verify doc (optional)
note over AP: If rejected: update DB, notify, return error
AP->>P4: 4. Trigger AS4 send
P4->>RA: AS4 UserMessage
RA-->>P4: AS4 Receipt
P4-->>AP: AS4 result (Receipt MsgID, HTTP status)
AP->>DB: 5. Insert into outbound_sending_attempt
AP->>DB: Update outbound_transaction status
AP-->>SB: API response (queued/not queued + SBDH Instance ID)
opt On success
AP->>AP: 6. Trigger outbound reporting callback
AP->>DB: Store reporting record
end
sequenceDiagram
participant S as Scheduler
participant DB as DB
participant P4 as phase4
participant RA as Remote AP (C3)
S->>DB: Query outbound_transaction where status = failed
DB-->>S: list of pending
loop For each failed transaction
S->>P4: Trigger AS4 send
P4->>RA: AS4 UserMessage
RA-->>P4: AS4 Receipt/Error
P4-->>S: AS4 result
S->>DB: Insert sending attempt row
S->>DB: Update outbound_transaction status
opt On success
S->>S: Trigger reporting callback
end
opt Max retries exhausted
S->>S: Trigger notification
end
end
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 (mls_status, mls_received_dt, mls_id)
PS-->>RA: AS4 Receipt
| Field | Description |
|---|---|
| transaction_type | Type of outbound transaction: business_document or mls_response |
| sender_id | Peppol Participant ID of the sender |
| receiver_id | Peppol Participant ID of the receiver |
| doc_type_id | Peppol Document Type Identifier |
| process_id | Peppol Process Identifier |
| sbdh_instance_id | Peppol SBDH Instance Identifier |
| source_type | How the document was submitted: payload_only (AP creates SBDH) or prebuilt_sbd (SBDH already present) |
| document_path | Path to the document file — either an absolute filesystem path or an s3://bucket/key URI depending on storage.mode
|
| document_size | Size of the document in bytes |
| document_hash | SHA-256 hash of the document payload for integrity verification |
| c1_country_code | Country of the sender (C1) |
| sbdh_standard | SBDH Standard override for non-XML payloads (e.g. urn:peppol:doctype:pdf+xml). Null if auto-derived. Set via sbdhStandard query parameter on the submit endpoint. |
| sbdh_type_version | SBDH TypeVersion override (e.g. 0). Null if auto-derived. Set via sbdhTypeVersion query parameter on the submit endpoint. |
| sbdh_type | SBDH Type override (e.g. factur-x). Null if auto-derived. Set via sbdhType query parameter on the submit endpoint. |
| payload_mime_type | MIME type for binary payloads (e.g. application/pdf). Null for XML payloads. Set via payloadMimeType query parameter on the submit endpoint. When set, the payload is wrapped in <BinaryContent> instead of being embedded as XML. |
| status | pending, rejected, sending, sent, failed, permanently_failed |
| attempt_count | Total number of sending attempts (default 0) |
| created_dt | When the transaction was initially created |
| completed_dt | When the transaction reached its final successful state |
| reporting_status | Whether outbound reporting has been triggered (pending, reported) |
| next_retry_dt | Planned date/time of the next sending retry (null unless status is failed) |
| error_details | Summary error from the permanently failed attempt |
| mls_to | MLS_TO override (only for business_document) |
| mls_status | MLS reception status: pending, received_ap, received_ab, received_re, not_applicable (only for business_document) |
| mls_received_dt | When the MLS response was received (only for business_document) |
| mls_id | The MLS message ID from the received MLS (only for business_document) |
| mls_inbound_transaction_id | FK to the inbound_transaction that triggered this MLS response (only for mls_response) |
| Field | Description |
|---|---|
| outbound_transaction_id | FK to the parent outbound transaction |
| as4_message_id | AS4 Message ID used for this attempt |
| as4_timestamp | AS4 MessageInfo/Timestamp from this attempt (UTC). MLS Milestone M1 for business documents; M2 for MLS responses. |
| receipt_message_id | AS4 Message ID from the synchronous receipt |
| http_status_code | HTTP status code from the AS4 response |
| attempt_dt | Date and time of this sending attempt |
| attempt_status | Outcome of this attempt (success, failed) |
| error_details | Error message or reason for failure |
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