Skip to main content

Overview

Paper Channel uses pn-external-channel (also called CarrierPigeon) as the downstream system that physically dispatches paper mail. When a send request passes the prepare phase and a final delivery address is confirmed, Paper Channel hands off the shipment to External Channel over HTTP and then receives asynchronous progress events back through an SQS queue.

Outbound: HTTP PUT

Paper Channel calls sendPaperEngageRequest to submit a new paper delivery engagement.

Inbound: SQS

External Channel pushes PaperProgressStatusEvent events to the Paper Channel SQS queue.

When Paper Channel calls External Channel

Paper Channel invokes External Channel in two scenarios:
  1. Send phase — after the prepare phase resolves a valid delivery address, the service layer calls ExternalChannelClient.sendEngageRequest(...) to submit the paper delivery request.
  2. Notification rework — when a previously sent request must be re-opened, Paper Channel calls ExternalChannelClient.initNotificationRework(requestIdx) to patch the request metadata.

Operations used

sendEngageRequest

Defined in ExternalChannelClient and implemented in ExternalChannelClientImpl. Internally calls:
  • PaperMessagesApi.sendPaperEngageRequest(requestIdx, xPagopaExtchCxId, dto) — HTTP PUT to /external-channels/v1/paper-deliveries-engagements/{requestIdx}
// ExternalChannelClientImpl.java
public Mono<Void> sendEngageRequest(SendRequest sendRequest, List<AttachmentInfo> attachments, Boolean applyRasterization) {
    return Mono.defer(() -> {
        var dto = buildPaperEngageRequest(sendRequest, attachments, applyRasterization);
        return this.paperMessagesApi.sendPaperEngageRequest(
            requestIdx,
            this.pnPaperChannelConfig.getXPagopaExtchCxId(),
            dto
        );
    });
}

initNotificationRework

Calls:
  • PaperRequestMetadataPatchApi.patchRequestMetadata(requestIdx, xPagopaExtchCxId, dto) with isOpenReworkRequest = true

Request fields — PaperEngageRequestDto

requestId
string
required
Unique identifier of the paper delivery request.
requestPaId
string
required
Identifier of the Public Administration that originated the notification. Can be overridden by pn.paper-channel.request-pa-id-override.
productType
string
required
Postal product type (e.g. AR, RS, 890, RIR).
receiverFiscalCode
string
required
Recipient fiscal code.
printType
string
required
Print specification for the physical letter.
attachments
array
Ordered list of document attachments. Each entry contains:
  • uri — the Safe Storage file key (cleaned via AttachmentsConfigUtils.cleanFileKey)
  • documentTypeAAR (Avviso di Avvenuta Ricezione) or ATTO
  • sha256 — SHA-256 checksum of the file
  • order — zero-based ordering index
receiverName / receiverAddress / receiverCap / receiverCity / receiverPr / receiverCountry
string
Full delivery address of the recipient.
senderName / senderAddress / senderCity / senderPr
string
Return address of the sender.
applyRasterization
boolean
When true, External Channel applies rasterization to attached PDFs before printing.

Inbound SQS events

External Channel pushes PaperProgressStatusEvent events asynchronously to the queue configured in pn.paper-channel.queue-external-channel. Paper Channel processes these events in its queue consumer.

Key status codes

CodeMeaning
RECAG001ARECAG015Raccomandata A/R (890 law) progress milestones
RECRN001ARECRN006CRaccomandata Semplice / Normale progress milestones
PNAG012Mandatory demat event for 890 products — triggers structured handling
CON996Postal item taken in charge — retry-eligible event
The set of status codes that allow automatic redrive after an OK is sent to Delivery Push is controlled by pn.paper-channel.allowed-redrive-progress-status-codes (default: RECAG005C,RECAG006C,RECAG007C,RECAG008C).
If External Channel returns a 409 Conflict for a given requestIdx, the request is treated as a duplicate. Only one engagement per requestId succeeds.

Configuration

PropertyDescriptionExample
pn.paper-channel.client-external-channel-basepathBase URL of the External Channel servicehttp://localhost:1080
pn.paper-channel.x-pagopa-extch-cx-idClient identity header sent on every requestpn-cons-000
pn.paper-channel.queue-external-channelSQS queue name for incoming status eventslocal-ext-channels-outputs
pn.paper-channel.attempt-queue-external-channelMax consumer retry attempts on the inbound queue3
pn.paper-channel.request-pa-id-overrideOptional override for requestPaId in all engage requests15376371009
pn.paper-channel.enable-retry-con996Whether to retry on CON996 eventstrue
pn.paper-channel.disabled-retry-send-engage-status-codesComma-separated status codes that must not trigger a retry send(empty)

Error handling

ConditionBehaviour
EXTERNAL_CHANNEL_API_EXCEPTIONThrown when the HTTP call to External Channel fails. The error is logged and propagated upstream.
EXTERNAL_CHANNEL_LISTENER_EXCEPTIONThrown when the inbound SQS event cannot be processed.
ERROR_NOT_FOUND_EXTERNAL_CHANNELThrown when a requestId is not found on External Channel during a status check.
HTTP 4xx / 5xx from External ChannelWebClientResponseException is caught; the response body is logged at ERROR level and the exception is re-emitted.
All outbound calls are logged with PnLogger.EXTERNAL_SERVICES.PN_EXTERNAL_CHANNELS at the async-invoke level so they appear in the structured audit trail.

Build docs developers (and LLMs) love