-
Notifications
You must be signed in to change notification settings - Fork 18
Receiving Process
Philip Helger edited this page Feb 24, 2026
·
21 revisions
The receiving process handles inbound Peppol documents arriving at the AP (C3) via AS4 from a remote sending AP (C2) and forwards them to the Receiver Backend (an internal system within C3).
- Receive via AS4 - phase4 servlet receives the AS4 message. Duplicate detection is applied (configurable: reject or store-and-flag).
-
Store in database - The document, metadata, and phase4 Incoming ID are persisted to the
inbound_transactiontable in PostgreSQL. - If storage fails - Respond with an AS4 error to the remote sending AP (C2). The transaction is not recorded.
-
Forward to Receiver Backend - Deliver the document via the configured forwarding mode (per AP instance):
- HTTP POST (async reporting)
- HTTP POST with sync response (C4 country code in response)
- S3 + link forwarding
- SFTP
-
Record forwarding attempt - Insert a row into
inbound_forwarding_attemptwith the outcome (success or failure + error details). Update the parentinbound_transactionstatus accordingly. -
If forwarding fails - The document will be retried by a periodic scheduler. Each retry creates a new
inbound_forwarding_attemptrow. - Reporting - Either triggered synchronously (from HTTP POST response containing C4 country code) or asynchronously (Receiver Backend calls reporting API with AS4 Message ID + C4 country code).
- On permanent forwarding failure - Notification via generic interface.
┌──────────┐ ┌────────┐ ┌────────┐ ┌───────────┐ ┌──────────┐
│ Remote │ │ phase4 │ │ DB │ │Forwarding │ │Receiver │
│ AP (C2) │ │Servlet │ │ │ │ Module │ │ Backend │
└────┬─────┘ └───┬────┘ └───┬────┘ └─────┬─────┘ └────┬─────┘
│ │ │ │ │
│ AS4 UserMessage │ │ │ │
│────────────────>│ │ │ │
│ │ │ │ │
│ │ 1. Duplicate │ │ │
│ │ check │ │ │
│ │───────────────>│ │ │
│ │ result │ │ │
│ │<───────────────│ │ │
│ │ │ │ │
│ │ [if duplicate and reject mode: return AS4 error] │
│ │ │ │ │
│ │ 2. Store doc │ │ │
│ │ in inbound_ │ │ │
│ │ transaction │ │ │
│ │───────────────>│ │ │
│ │ │ │ │
│ │ [if store fails: return AS4 error] │ │
│ │ │ │ │
│ │ stored OK │ │ │
│ │<───────────────│ │ │
│ │ │ │ │
│ AS4 Receipt │ │ │ │
│<────────────────│ │ │ │
│ │ │ │ │
│ │ 3. Forward │ │ │
│ │───────────────────────────────────>│ │
│ │ │ │ │
│ │ │ │ Deliver doc │
│ │ │ │─────────────────>│
│ │ │ │ │
│ │ │ │ [sync mode: │
│ │ │ │ C4 country │
│ │ │ │ in response] │
│ │ │ │<─────────────────│
│ │ │ │ │
│ │ 4. Insert │ │ │
│ │ forwarding │ │ │
│ │ attempt row │ │ │
│ │───────────────>│ │ │
│ │ │ │ │
│ │ 5. Update │ │ │
│ │ inbound_ │ │ │
│ │ transaction │ │ │
│ │ status │ │ │
│ │───────────────>│ │ │
│ │ │ │ │
│ │ [sync mode: │ │ │
│ │ store │ │ │
│ │ reporting │ │ │
│ │ record] │ │ │
│ │───────────────>│ │ │
│ │ │ │ │
┌──────────┐ ┌──────────┐ ┌────────┐
│Receiver │ │Reporting │ │ DB │
│ Backend │ │ API │ │ │
└────┬─────┘ └────┬─────┘ └───┬────┘
│ │ │
│ Report message │ │
│ (SBDH Instance ID, │ │
│ C4 country code) │ │
│────────────────────>│ │
│ │ │
│ │ Lookup inbound │
│ │ transaction by │
│ │ SBDH Instance ID │
│ │───────────────────>│
│ │ │
│ │ transaction data │
│ │<───────────────────│
│ │ │
│ │ Store reporting │
│ │ record (C4 country │
│ │ + data from SBDH) │
│ │───────────────────>│
│ │ │
│ OK │ │
│<────────────────────│ │
│ │ │
┌──────────┐ ┌────────┐ ┌───────────┐ ┌──────────┐
│Scheduler │ │ DB │ │Forwarding │ │Receiver │
│ │ │ │ │ Module │ │ Backend │
└────┬─────┘ └───┬────┘ └─────┬─────┘ └────┬─────┘
│ │ │ │
│ Query inbound_ │ │ │
│ transaction where │ │ │
│ status = failed │ │ │
│───────────────────>│ │ │
│ │ │ │
│ list of pending │ │ │
│<───────────────────│ │ │
│ │ │ │
│ For each: │ │ │
│ │ │ │
│ Forward │ │ │
│─────────────────────────────────────────>│ │
│ │ │ Deliver doc │
│ │ │────────────────────>│
│ │ │ result │
│ │ │<────────────────────│
│ result │ │ │
│<─────────────────────────────────────────│ │
│ │ │ │
│ Insert forwarding │ │ │
│ attempt row │ │ │
│───────────────────>│ │ │
│ │ │ │
│ Update inbound_ │ │ │
│ transaction status │ │ │
│───────────────────>│ │ │
│ │ │ │
│ [if max retries │ │ │
│ exhausted: notify]│ │ │
│ │ │ │
| Field | Description |
|---|---|
| Incoming ID | Unique ID assigned by phase4 on receipt |
| AS4 Message ID | The AS4 Message ID from the inbound message |
| SBDH Instance ID | The Peppol SBDH Instance Identifier |
| Business Document ID | Optional: the ID from the business document itself |
| Receiving timestamp | Date and time when the message was received |
| Document bytes | The raw received document payload |
| Transaction Status | Current state (received, forwarded, forward_failed, permanently_failed) |
| Duplicate flag | Whether this message was detected as a duplicate |
| Reporting status | Whether the reporting record has been created (pending, reported) |
| C4 Country Code | Country of the final receiver (C4), provided via reporting API or sync response |
| Field | Description |
|---|---|
| Inbound Transaction ID | FK to the parent inbound transaction |
| Attempt timestamp | Date and time of this forwarding attempt |
| Attempt status | Outcome of this attempt (success, failed) |
| Error details | Error message or reason for failure (null on success) |
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