FlowAlp

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 POST HTTP 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: 8925 significa 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 dati invoice.

Eventi di transazione

Il payload racchiude un singolo oggetto transaction. I campi più importanti:

CampoTipoDescrizione
id / uuidint / stringID interno e ID pubblico della transazione
statusstringStato della transazione, vedi tabella sotto
amountintImporto elaborato in unità minime
referenceIdstringIl tuo riferimento ordine
timestringTimestamp di creazione in formato ISO 8601
modestringTEST o LIVE
psp / pspIdstring / intIdentificativi del provider di pagamento
typestringE-Commerce, POS-Terminal o Tap to Pay
refundable / partiallyRefundableboolSe è possibile un rimborso (parziale)
invoiceobjectDati dell'ordine: currency, products, originalAmount, refundedAmount, custom_fields, …
contactobject o nullDati del cliente e dell'indirizzo di consegna
paymentobjectMezzo di pagamento, ad es. brand e wallet
subscriptionobject o nullPresente quando la transazione appartiene a una subscription
instanceobjectIl tuo account merchant: name e uuid
payoutUuidstring o nullUUID del payout che contiene questa transazione
preAuthorizationIdintSolo per tokenization/addebiti: ID della tokenization di origine
originalTransactionId / -Uuidint / stringSolo 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.

StatoSignificato
waitingOrdine creato, pagamento non ancora completato
confirmedPagamento riuscito
cancelledPagamento annullato dal cliente
declined3-D Secure fallito o rifiuto della banca emittente
authorizedTokenization riuscita
reservedPrenotazione riuscita (pre-authorization)
refundedRimborso totale
partially-refundedRimborso parziale
refund_pendingRimborso in elaborazione
chargebackIl titolare della carta ha richiamato l'importo
disputedÈ stata aperta una contestazione per questa transazione
errorSi è verificato un problema durante il pagamento
expiredPagamento interrotto per inattività
Esempio: transazione confirmedJSON
{
  "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.

StatoSignificato
activeLa subscription è attiva, seguiranno altri addebiti
failedCreazione fallita, oppure un addebito e il suo retry sono falliti entrambi
cancelledAnnullata dal merchant con effetto immediato — nessun altro addebito
in_noticeDisdetta dal cliente prima della data di fine; gli addebiti rimanenti seguono comunque
overdueUn addebito è fallito e viene ritentato; un secondo fallimento porta a failed
Esempio: subscription attivaJSON
{
  "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.

StatoSignificato
processingIl file del payout è stato consegnato alla banca
sentPayout trasmesso con successo alla banca
failedPayout fallito e restituito dalla banca

Per gli stati interni initiated, pending e under-review non vengono inviati webhook — il primo evento che ricevi è processing.

Esempio: payout inviato (abbreviato)JSON
{
  "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:

Conferma minimalePHP
<?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 (o uuid) della transazione più status prima di applicare modifiche.
  • Le consegne possono arrivare fuori ordine — ignora un evento se lo stato salvato è già definitivo (ad es. refunded dopo confirmed).
  • 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.