openapi: 3.0.3 info: termsOfService: https://notifichedigitali.pagopa.it/pubbliche-amministrazioni/index.html x-api-id: api-external-b2b-pa title: 'Piattaforma Notifiche: API B2B per le Pubbliche Amministrazioni' x-summary: 'Piattaforma Notifiche: API B2B per le Pubbliche Amministrazioni' version: 1.0.0 description: >- ## Abstract API utilizzate dalle pubbliche amministrazioni per __inviare richieste di notifiche__ e __ottenere informazioni in modalità pull__ sullo stato della _"richiesta di notifica"_ (accettata o rifiutata) e, in caso di richiesta accettata, sulle comunicazioni effettuate, o solo tentate, nei confronti dei destinatari della notifica. ## Operazioni utilizzate, in sequenza temporale
#### 3. Verifica accettazione richiesta di invio notifica Per questa verifica possono essere utilizzate due modalità: 1. __richiesta puntale__: consigliato solo ai fini di test 2. __lettura da stream configurato__: consigliato per ambienti di produzione La differenza tra le due modalità è nell'interazione e nell'efficienza. Con la modalità _"richiesta puntuale"_ è necessario l'invocazione per ogni notifica, mentre con la modalità _"stream"_ è possibile avere gli aggiornamenti di stato di più notifiche con una sola invocazione. #### 3.1 Richiesta puntuale di verifica accettazione Questa modalità è resa disponibile solo ai fini di test o di eventuali operazioni di allineamento poiché richiede l'invio di una richiesta per ogni notifica. Se il passo (2) avviene con successo si utilizza l'operazione [getNotificationRequestStatus](#/SenderReadB2B/retrieveNotificationRequestStatusV21) per ottenere informazioni riguardo allo stato della "richiesta di invio di notifica". Nel campo _notificationRequestStatus_ sarà indicato: >\- WAITING: se la validazione è ancora in corso. \- ACCEPTED: se richiesta di notifica accettata, lo _IUN_ è valorizzato. \- REFUSED: se richiesta di notifica rifiutata, è valorizzato il campo _errors_. #### 3.2 Richiesta avanzamento via "stream" di verifica di accettazione Questa modalità è consigliata. Per essere fruita è necessaria un'operazione preliminare tramite la chiamata alla API [createEventStream](https://petstore.swagger.io/?url=https%3A%2F%2Fraw.githubusercontent.com%2Fpagopa%2Fpn-delivery-push%2Fmain%2Fdocs%2Fopenapi%2Fapi-external-b2b-webhook.yaml#/Streams/createEventStream) per configurare uno "stream" che registri il cambio di stato della notifica con il seguente payload:`` { "title": "NotificationAccepted", "eventType": "STATUS", "filterValues": [ "ACCEPTED" ] } `` Successivamente si possono ottenere i dati richiamando la API [consumeEventStream](https://petstore.swagger.io/?url=https%3A%2F%2Fraw.githubusercontent.com%2Fpagopa%2Fpn-delivery-push%2Fmain%2Fdocs%2Fopenapi%2Fapi-external-b2b-webhook.yaml#/Events/consumeEventStream) __NOTA__ saranno disponibili i dati di cambiamento di stato occorsi solo successivamente alla configurazione dello stream. |
### Ciclo di vita della notifica lato mittente
#### 1. Caricamento dei documenti della notifica
Prima di invocare la richiesta di notifica è necessario caricare i documenti della notifica (documenti e bollettini/metadati di pagamento).
[Schema Metadata F24](#/components/schemas/F24Metadata)
#### 1.a. Richiesta presigned Url
Invocare l'operazione [presignedUploadRequest](#/NewNotification/presignedUploadRequest)
con cui prenotare il caricamento. Possono essere effettuate un massimo di 15 prenotazioni di caricamento
per ogni richiesta.
In risposta si ottengono le seguenti informazioni: \- httpMethod \- secret \- url L'url restituito ha una validità di 1h. #### 1.b Upload documenti della notifica Per ogni documento utilizzare un richiesta HTTP con metodo _httpMethod_ (POST o PUT) all'url indicato dal campo _url_. In tale richiesta vanno aggiunti i seguenti header: \- _content-type_: valorizzato come il campo "contentType" della richiesta di cui al punto (1.a) \- _x-amz-meta-secret_: valorizzato con il valore del campo "secret" della risposta di cui al punto (1.a) \- _trailer_: valorizzato con ```x-amz-checksum-sha256``` \- _x-amz-checksum-sha256_: valorizzato con il checksum sha256, codificato in base 64, del contenuto binario del file che verrà caricato. (__N.B.__ questo è un trailer HTTP non un header). Vedi [HTTP Trailer](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Trailer) __NOTA:__ se l'operazione di upload è stata eseguita con successo, si otterrà come risposta _status 200 OK_. Nell'header di questa risposta, si otterrà il campo __x-amz-version-id__ che dovrà essere utilizzato durante l'inserimento della notifica, nel campo ref.__versionToken__ in corrispondenza del documento ad esso associato. #### 2. Richiesta di invio della notifica Per effettuare una richiesta di invio notifica, invocare l'operazione [sendNewNotification](#/NewNotification/sendNewNotificationV21) utilizzando i riferimenti dei file caricati ottenuti al punto (1.b). |
{Iun}
della notifica di interesse: all'interno del campo timeline della response è possibile trovare l'elenco degli eventi di quella notifica ed i legalFactType e legalFactId in corrispondenza degli eventi che generano documenti.
### 1) Creazione dello stream ed inserimento notifica
In questo esempio creo 2 stream con il servizio di [creazione stream](#/Streams/createEventStream): uno per gli status e l'altro per gli eventi di timeline. Vedesi le request a) di esempio con le relative response b), Da notare che sono presenti dei filtri per ottenere solo specifici status o eventi; se si vogliono ottenere tutte le variazioni limitatamente agli eventi della v1, non bisogna inserire alcun filtro:
"filterValues": []
Una volta creati gli stream, bisogna utilizzare il servizio di [inserimento nuova notifica](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/pagopa/pn-delivery/develop/docs/openapi/api-external-b2b-pa-v1.yaml#/NewNotification/sendNewNotification) sulla Piattaforma. A questo punto bisognerà attendere che vengano completati i controlli di validazione e se questi avranno esito positivo e la notifica verrà accettata, comincerà il workflow di consegna della stessa. Con l'avanzare del tempo verranno generati degli eventi e dei cambiamenti di stato che verranno puntualmente registrati negli stream configurati precedentemente a partire già dal primo evento che certifica l'accettazione o il rifiuto della notifica appena inserita con il relativo passaggio allo stato ACCEPTED.
### 2) Prima interrogazione degli stream appena creati
Col passare del tempo, potremo interrogare gli stream appena creati per leggere gli eventi registrati, a partire già dall'evento di accettazione della notifica. Si possono interrogare gli eventi registrati all'interno di uno stream con il servizio di [lettura degli eventi](#/Events/consumeEventStream) passando il valore desiderato nello {streamId} ed otterremo la response c) che contiene un array con un numero massimo di 50 eventi corrispondenti a quelli che impattano tutte le notifiche inserite dalla creazione dello stream in poi e che potranno essere salvati sul database del client chiamante. Da notare che ogni evento contiene l'eventId ad esso associato.
A questo punto bisogna controllare il parametro retry-after contenuto nell'header della response per capire quanto tempo attendere prima di richiamare lo stream ed ottenere nuovi risultati:
retry-after ≠ 0 ; infatti tale parametro regola la cadenza di chiamata al servizio, mentre il consumo degli eventi deve avvenire in ogni chiamata nella quale si ottengono eventi in risposta.
### 3) Successive interrogazioni degli stream appena creati
Se la response della prima interrogazione degli stream restituisce nell'header: retry-after = 0 significa che lo stream contiene altri eventi che possono essere consumati subito con un'ulteriore chiamata al servizio di [lettura degli eventi](#/Events/consumeEventStream), ma questa volta per consumare gli eventi successivi, bisogna valorizzare nei query params della request il parametro lastEventId con l'eventId ottenuto nella precedente chiamata. Così facendo il servizio eliminerà dallo stream tutti gli eventi precedenti a quello inserito nel lastEventId e restituirà nella response d) solamente quelli successivi.
A questo punto si potrà capire, sempre dal valore del retry-after contenuto nell'header se chiamare subito il servizio ed inserire il lastEventId di questa ulteriore chiamata o attendere il tempo indicato nell'header
NOTA: gli eventi eliminati dallo stream in seguito alla chiamata del servizio di [lettura degli eventi](#/Events/consumeEventStream) con il query param lastEventId valorizzato, non potranno più essere recuperati dallo stream in nessun modo. E' quindi fondamentale salvare di volta in volta gli eventi che si ottengono all'interno database del chiamante, rispettando la logica del producer/consumer di eventi proposta dagli stream. In caso di eliminazione degli eventi avvenuta per errore, sarà possibile come ultima istanza chiamare il servizio di [lettura dettaglio notifica](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/pagopa/pn-delivery/develop/docs/openapi/api-external-b2b-pa-v1.yaml#/SenderReadB2B/retrieveSentNotification) che però esporrà tutti gli eventi di timeline e lo stato attuale della singola notifica ed è quindi meno performante delle stream.
|
#### a) Request di POST /delivery-progresses/streams
{ {
"title": "stream-status-prova", "title": "stream-timeline-prova",
"eventType": "STATUS", "eventType": "TIMELINE",
"filterValues": [ "filterValues": [
"ACCEPTED" "REQUEST_ACCEPTED"
] ]
} }
#### b) Response di POST /delivery-progresses/streams
{ {
"title": "stream-status-prova", "title": "stream-timeline-prova",
"eventType": "STATUS", "eventType": "TIMELINE",
"filterValues": [ "filterValues": [
"ACCEPTED" "REQUEST_ACCEPTED"
], ],
"streamId": "streamId":
"4e6d5e59-85fc-4ef7-bad8", "6d87ree59-31ff-2rr7-lok1",
"activationDate": "activationDate":
"2022-12-12T14:52:23.362454Z" "2022-12-12T14:53:23.362454Z"
} }
#### c) Response di GET /delivery-progresses/streams/{streamId} /events
Headers: { "retry-after": "60000" }
[
{
"eventId": "0000000000000000000001",
"timestamp": "2022-12-06T08:14:26.140041Z",
"notificationRequestId": "QUJDRC1BQkNELUFCQ0QtMjAyMjEyLVYtMQ==",
"iun": "ABCD-ABCD-ABCD-202212-V-1",
"newStatus": "ACCEPTED",
"timelineEventCategory": "REQUEST_ACCEPTED",
"recipientIndex": "0",
"analogCost": "0",
"channel": "PEC",
"legalfactIds": [
"PN_LEGAL_FACTS-0002-9G2S-RK3M-JI62-JK9Q",
"PN_LEGAL_FACTS-0002-9G2S-RK3M-JI62-JK9E"
]
},
... // altri eventi nell'array
]
#### d) Response di GET /delivery-progresses/streams/{streamId} /events chiamato valorizzando nei query params il parametro lastEventId con l'eventId dell'ultimo evento nella precedente chiamata.
Headers: { "retry-after": "60000" }
[
{
"eventId": "0000000000000000000011",
"timestamp": "2022-12-07T10:13:22.158041Z",
"notificationRequestId": "QUJDRC1BQkNELUFCQ0QtMjAyMjEyLVYtMQ==",
"iun": "ABCD-ABCD-ABCD-202212-V-1",
"newStatus": "DELIVERED",
"timelineEventCategory": "DIGITAL_SUCCESS_WORKFLOW",
"recipientIndex": "0",
"analogCost": "0",
"channel": "PEC",
"legalfactIds": [
"PN_LEGAL_FACTS-0002-9G2S-RK3M-JI62-JK9Q",
"PN_LEGAL_FACTS-0002-9G2S-RK3M-JI62-JK9E"
]
},
... // altri eventi nell'array
]
|