Gestire i webhook
Ricevi fatture ed esiti sul tuo backend e recupera via API gli aggiornamenti che non arrivano.
Configurare gli endpoint#
I due URL si configurano con PATCH /machine/accounts/me, autenticato con la chiave dell’azienda:
PATCH /machine/accounts/me HTTP/1.1
x-api-key: <API_KEY>
Content-Type: application/json
{
"invoiceStatusWebhookUrl": "https://gestionale.example/webhooks/SEGRETO_CASUALE/stati",
"inboundInvoiceWebhookUrl": "https://gestionale.example/webhooks/SEGRETO_CASUALE/ricevute"
}Sostituisci gli URL di esempio con endpoint HTTPS pubblici e un segreto casuale lungo, diverso per account. Invia una stringa vuota nel relativo campo per disabilitarlo. Il servizio esegue un POST JSON con Content-Type: application/json.
Eventi e payload#
invoice.status.updated viene inviato quando una notifica SdI cambia lo stato della fattura. Esempio completo:
{
"event": "invoice.status.updated",
"invoice": {
"id": "invoice_123",
"accountId": "account_123",
"direction": "OUTBOUND",
"status": "DELIVERED",
"filename": "IT12345678901A2026_00001.xml",
"senderFilename": "fattura.xml",
"invoiceNumber": "FT-2026-001",
"sdiIdentifier": "123456789",
"counterpartyVat": "00000000000",
"counterpartyFiscal": null,
"totalAmount": "100.00",
"issuedAt": "2026-10-01T00:00:00.000Z",
"receivedAt": "2026-10-01T10:00:00.000Z"
},
"previousStatus": "SENT",
"currentStatus": "DELIVERED",
"notificationId": "notification_456"
}invoice.received viene inviato dopo la memorizzazione di una nuova fattura in ingresso. Contiene event e lo stesso oggetto invoice, con direzione INBOUND e stato RECEIVED; non contiene previousStatus, currentStatus o notificationId.
totalAmount è una stringa decimale o null. I dati fiscali, le date e gli identificativi non disponibili possono essere nulli; anche previousStatus e notificationId possono esserlo. Il webhook non contiene i file: recuperali dal dettaglio macchina.
Accettazione, duplicati e recupero#
La consegna è best effort: il timeout predefinito è cinque secondi, configurabile dal gestore. Errori di rete, timeout e risposte non 2xx vengono registrati; non è prevista una coda di ritentativi automatici. Un problema del ricevitore non blocca la memorizzazione della fattura.
- Associa l’URL segreto al tuo account locale; non scegliere la chiave API basandoti soltanto sul payload ricevuto.
- Valida il JSON, accoda in modo persistente il lavoro e restituisci rapidamente un
2xx. - Per gli stati, deduplica usando account, tipo evento e
notificationIdquando presente. Per le ricevute usa account, tipo evento einvoice.id. In assenza di notificationId, rendi idempotente l’aggiornamento per fattura. - Nel worker rileggi
GET /machine/invoices/{id}e aggiorna il gestionale dal dato corrente. Evita di applicare ciecamente gli stati nell’ordine di arrivo dei webhook. - Ignora i tipi evento sconosciuti e prevedi una riconciliazione periodica: lista delle ricevute con finestre sovrapposte e rilettura delle fatture in attesa di esito.
Endpoint di test#
La rotta di test invia un campione all’URL già configurato: POST /accounts/me/webhooks/test, che richiede un JWT dell’account, non la chiave API:
POST /accounts/me/webhooks/test HTTP/1.1
Authorization: Bearer <JWT_ACCOUNT>
Content-Type: application/json
{
"kind": "invoiceStatus",
"scenario": "deliveryReceipt"
}Scenari disponibili: deliveryReceipt, deliveryFailure, rejection, outcomeAccepted, outcomeRefused, deadlineExpiry, transmissionCertification. Per una ricevuta usa { "kind": "inboundInvoice" }.
I campioni includono l’header x-fttel-webhook-test: true e i campi JSON test: true, sentAt e account, oltre a dati dimostrativi. Questi elementi non sono garantiti nei webhook di produzione. Mantieni separata l’elaborazione dei test e non considerarne gli id come record reali da recuperare.