Eventi e payload dei webhook
July 30, 2026
Riferimento per gli eventi webhook FlowAlp Pay: payload di transazioni, subscription e payout con esempi JSON e consigli per l'idempotenza.
FlowAlp Pay consegna tre tipi di eventi webhook all'URL che hai configurato: eventi di transazione, di subscription e di payout. Questa pagina documenta il payload di ciascuno e come il tuo endpoint deve confermarli.
Nozioni di base sulla consegna
- Ogni evento è un
POSTHTTP verso il tuo URL webhook, codificato come JSON o form data a seconda della configurazione. - Tutti gli importi sono interi nell'unità minima della valuta:
8925significa CHF 89.25. - Gli eventi di transazione e subscription partono a ogni cambio di stato; gli eventi di payout partono quando un payout viene effettivamente elaborato.
- Identifica il tuo ordine tramite
referenceId— oppure tramite l'ID del payment link nei datiinvoice.
Eventi di transazione
Il payload racchiude un singolo oggetto transaction. I campi più importanti:
| Campo | Tipo | Descrizione |
|---|---|---|
| id / uuid | int / string | ID interno e ID pubblico della transazione |
| status | string | Stato della transazione, vedi tabella sotto |
| amount | int | Importo elaborato in unità minime |
| referenceId | string | Il tuo riferimento ordine |
| time | string | Timestamp di creazione in formato ISO 8601 |
| mode | string | TEST o LIVE |
| psp / pspId | string / int | Identificativi del provider di pagamento |
| type | string | E-Commerce, POS-Terminal o Tap to Pay |
| refundable / partiallyRefundable | bool | Se è possibile un rimborso (parziale) |
| invoice | object | Dati dell'ordine: currency, products, originalAmount, refundedAmount, custom_fields, … |
| contact | object o null | Dati del cliente e dell'indirizzo di consegna |
| payment | object | Mezzo di pagamento, ad es. brand e wallet |
| subscription | object o null | Presente quando la transazione appartiene a una subscription |
| instance | object | Il tuo account merchant: name e uuid |
| payoutUuid | string o null | UUID del payout che contiene questa transazione |
| preAuthorizationId | int | Solo per tokenization/addebiti: ID della tokenization di origine |
| originalTransactionId / -Uuid | int / string | Solo sulle transazioni di rimborso: la transazione originale addebitata |
Nota che la valuta fa parte dell'oggetto invoice (invoice.currency), non è un campo di primo livello.
| Stato | Significato |
|---|---|
waiting | Ordine creato, pagamento non ancora completato |
confirmed | Pagamento riuscito |
cancelled | Pagamento annullato dal cliente |
declined | 3-D Secure fallito o rifiuto della banca emittente |
authorized | Tokenization riuscita |
reserved | Prenotazione riuscita (pre-authorization) |
refunded | Rimborso totale |
partially-refunded | Rimborso parziale |
refund_pending | Rimborso in elaborazione |
chargeback | Il titolare della carta ha richiamato l'importo |
disputed | È stata aperta una contestazione per questa transazione |
error | Si è verificato un problema durante il pagamento |
expired | Pagamento interrotto per inattività |
{
"transaction": {
"id": 1234,
"uuid": "1122aabb",
"status": "confirmed",
"amount": 8925,
"referenceId": "ORDER-975382",
"time": "2026-07-30T09:36:07+00:00",
"lang": "de",
"psp": "Native_PSP",
"pspId": 44,
"mode": "TEST",
"type": "E-Commerce",
"refundable": true,
"partiallyRefundable": true,
"instance": {
"name": "demo-shop",
"uuid": "aabb1122"
},
"metadata": {},
"invoice": {
"number": "IV_2041",
"currency": "CHF",
"test": 1,
"referenceId": "ORDER-975382",
"originalAmount": 8925,
"refundedAmount": 0,
"shippingAmount": null,
"paymentLink": null,
"paymentRequestId": null,
"products": [
{
"name": "Season pass",
"quantity": 1,
"price": 8925,
"sku": null,
"vatRate": "8.1",
"description": ""
}
],
"discount": {
"code": null,
"amount": 0,
"percentage": null
},
"custom_fields": [
{
"type": "email",
"name": "E-Mail",
"value": "buyer@example.com"
}
]
},
"contact": {
"id": 1234,
"uuid": "aabb1122",
"firstname": "Jane",
"lastname": "Doe",
"company": "Alpina Sport AG",
"street": "Burgstrasse 20",
"zip": "3600",
"place": "Thun",
"country": "Switzerland",
"countryISO": "CH",
"phone": "0335500010",
"email": "buyer@example.com"
},
"payment": {
"brand": "visa",
"wallet": null
},
"subscription": null,
"payoutUuid": null
}
}Eventi di subscription
Gli eventi di subscription partono quando cambia lo stato di un rapporto di fatturazione ricorrente. Campi: id, uuid, status, start, end, valid_until (la prossima data di addebito), paymentInterval (una durata come P1M, secondo la specifica DateInterval di PHP), più gli oggetti invoice e contact.
| Stato | Significato |
|---|---|
active | La subscription è attiva, seguiranno altri addebiti |
failed | Creazione fallita, oppure un addebito e il suo retry sono falliti entrambi |
cancelled | Annullata dal merchant con effetto immediato — nessun altro addebito |
in_notice | Disdetta dal cliente prima della data di fine; gli addebiti rimanenti seguono comunque |
overdue | Un addebito è fallito e viene ritentato; un secondo fallimento porta a failed |
{
"id": 5678,
"uuid": "ccdd3344",
"status": "active",
"start": "2026-01-01",
"end": null,
"valid_until": "2026-12-31",
"paymentInterval": "P1M",
"invoice": {
"currency": "CHF",
"referenceId": "SUB-2026-042",
"originalAmount": 1990,
"refundedAmount": 0,
"products": [
{
"name": "Monthly membership",
"price": 1990,
"quantity": 1,
"sku": null,
"vatRate": "8.1",
"description": ""
}
],
"discount": {
"code": null,
"amount": 0,
"percentage": null
},
"custom_fields": []
},
"contact": {
"id": 1234,
"uuid": "aabb1122",
"firstname": "Jane",
"lastname": "Doe",
"email": "buyer@example.com"
}
}Eventi di payout
Gli eventi di payout descrivono il denaro che lascia il tuo saldo FlowAlp Pay verso il tuo conto bancario. Campi principali: uuid, mode, object (sempre payout), amount, total_fees, currency (ISO 4217), date, statement (testo dell'estratto conto), payer (chi ha avviato il payout), status, destination (ad esempio un conto bancario con IBAN), transfers (le transazioni e commissioni incluse), merchant e is_manual_payout.
| Stato | Significato |
|---|---|
processing | Il file del payout è stato consegnato alla banca |
sent | Payout trasmesso con successo alla banca |
failed | Payout fallito e restituito dalla banca |
Per gli stati interni initiated, pending e under-review non vengono inviati webhook — il primo evento che ricevi è processing.
{
"uuid": "AABB1122",
"mode": "LIVE",
"object": "payout",
"amount": 29390,
"total_fees": 610,
"currency": "CHF",
"date": "2026-07-28",
"statement": "Alpina Sport AG Thun",
"status": "sent",
"is_manual_payout": false,
"destination": {
"type": "bank_account",
"iban": "CH00 0000 0000 0000 0000 0",
"account_holder": "Alpina Sport AG"
},
"transfers": [
{
"type": "payout-fee",
"amount": -10,
"date_time": "2026-07-28T05:00:00+00:00",
"items": [
{ "type": "payout-fee", "amount": -10 }
],
"transaction": {}
},
{
"type": "transaction",
"amount": 29400,
"date_time": "2026-07-27T13:44:30+00:00",
"items": [
{ "type": "transaction", "amount": 30000 },
{ "type": "transaction-fee", "amount": -600 }
],
"transaction": {
"type": "transaction",
"uuid": "1122aabb",
"amount": 30000,
"currency": "CHF",
"reference_id": "ORDER-975382"
}
}
]
}Conferma con HTTP 200
Rispondi con uno stato 2xx entro 20 secondi. Qualsiasi altra risposta — o un timeout — conta come consegna fallita e viene ritentata secondo la tua configurazione dei retry. Mantieni minima la parte sincrona:
<?php
$rawBody = file_get_contents('php://input');
// 1. Verify the signature first (see the signature verification guide)
// 2. Queue the raw event for asynchronous processing
http_response_code(200);Elabora gli eventi in modo idempotente
- I retry generano duplicati: deduplica su
id(ouuid) della transazione piùstatusprima di applicare modifiche. - Le consegne possono arrivare fuori ordine — ignora un evento se lo stato salvato è già definitivo (ad es.
refundeddopoconfirmed). - Conserva il payload grezzo e l'esito dell'elaborazione, così gli incidenti si possono rieseguire e verificare.
- Non elaborare mai un evento prima di averne verificato la firma.
Prossimo passo: metti in sicurezza il tuo endpoint con la verifica della firma dei webhook prima del go-live.