Événements et payloads des webhooks
July 30, 2026
Référence des événements webhook FlowAlp Pay : payloads de transactions, subscriptions et versements avec exemples JSON et conseils d'idempotence.
FlowAlp Pay livre trois types d'événements webhook à l'URL que vous avez configurée : événements de transaction, de subscription et de versement. Cette page documente le payload de chacun et la façon dont votre endpoint doit les acquitter.
Bases de la livraison
- Chaque événement est un
POSTHTTP vers votre URL webhook, encodé en JSON ou en données de formulaire selon votre configuration. - Tous les montants sont des entiers dans la plus petite unité de la devise :
8925signifie CHF 89.25. - Les événements de transaction et de subscription partent à chaque changement de statut ; les événements de versement partent quand un versement est réellement traité.
- Identifiez votre commande via
referenceId— ou via l'ID du lien de paiement dans les donnéesinvoice.
Événements de transaction
Le payload contient un unique objet transaction. Les champs les plus importants :
| Champ | Type | Description |
|---|---|---|
| id / uuid | int / string | ID interne et ID public de la transaction |
| status | string | Statut de la transaction, voir tableau ci-dessous |
| amount | int | Montant traité en unités mineures |
| referenceId | string | Votre référence de commande |
| time | string | Horodatage de création au format ISO 8601 |
| mode | string | TEST ou LIVE |
| psp / pspId | string / int | Identifiants du prestataire de paiement |
| type | string | E-Commerce, POS-Terminal ou Tap to Pay |
| refundable / partiallyRefundable | bool | Si un remboursement (partiel) est possible |
| invoice | object | Données de commande : currency, products, originalAmount, refundedAmount, custom_fields, … |
| contact | object ou null | Données du client et de l'adresse de livraison |
| payment | object | Moyen de paiement, p. ex. brand et wallet |
| subscription | object ou null | Présent quand la transaction appartient à une subscription |
| instance | object | Votre compte marchand : name et uuid |
| payoutUuid | string ou null | UUID du versement qui contient cette transaction |
| preAuthorizationId | int | Uniquement pour les tokenizations/débits : ID de la tokenization source |
| originalTransactionId / -Uuid | int / string | Uniquement sur les transactions de remboursement : la transaction d'origine débitée |
Notez que la devise fait partie de l'objet invoice (invoice.currency) et n'est pas un champ racine.
| Statut | Signification |
|---|---|
waiting | Commande créée, paiement pas encore terminé |
confirmed | Paiement réussi |
cancelled | Paiement interrompu par le client |
declined | Échec 3-D Secure ou refus de la banque émettrice |
authorized | Tokenization réussie |
reserved | Réservation réussie (préautorisation) |
refunded | Remboursement intégral |
partially-refunded | Remboursement partiel |
refund_pending | Remboursement en cours de traitement |
chargeback | Le titulaire de la carte a récupéré l'argent |
disputed | Un litige a été ouvert pour cette transaction |
error | Un problème est survenu pendant le paiement |
expired | Paiement interrompu pour cause d'inactivité |
{
"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
}
}Événements de subscription
Les événements de subscription partent dès que l'état d'une facturation récurrente change. Champs : id, uuid, status, start, end, valid_until (prochaine date de prélèvement), paymentInterval (une durée comme P1M, selon la spécification DateInterval de PHP), plus les objets invoice et contact.
| Statut | Signification |
|---|---|
active | La subscription est active, d'autres prélèvements suivront |
failed | Création échouée, ou un prélèvement et sa nouvelle tentative ont tous deux échoué |
cancelled | Résiliée par le marchand avec effet immédiat — plus aucun prélèvement |
in_notice | Résiliée par le client avant la date de fin ; les prélèvements restants suivent encore |
overdue | Un prélèvement a échoué et est retenté ; un deuxième échec passe le statut à 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"
}
}Événements de versement
Les événements de versement décrivent l'argent qui quitte votre solde FlowAlp Pay vers votre compte bancaire. Champs clés : uuid, mode, object (toujours payout), amount, total_fees, currency (ISO 4217), date, statement (libellé bancaire), payer (initiateur du versement), status, destination (par exemple un compte bancaire avec IBAN), transfers (transactions et frais inclus), merchant et is_manual_payout.
| Statut | Signification |
|---|---|
processing | Le fichier de versement a été remis à la banque |
sent | Versement transmis avec succès à la banque |
failed | Versement échoué et retourné par la banque |
Aucun webhook n'est envoyé pour les états internes initiated, pending et under-review — le premier événement que vous recevez est 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"
}
}
]
}Acquitter avec HTTP 200
Répondez avec un statut 2xx en moins de 20 secondes. Toute autre réponse — ou un timeout — compte comme une livraison échouée et est retentée selon votre configuration de retry. Gardez la partie synchrone minimale :
<?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);Traiter les événements de façon idempotente
- Les retries impliquent des doublons : dédupliquez sur l'
id(ou l'uuid) de la transaction plus lestatusavant d'appliquer des changements. - Les livraisons peuvent arriver dans le désordre — ignorez un événement si l'état stocké est déjà final (p. ex.
refundedaprèsconfirmed). - Conservez le payload brut et le résultat du traitement pour pouvoir rejouer et auditer les incidents.
- Ne traitez jamais un événement avant d'avoir vérifié sa signature.
Étape suivante : sécurisez votre endpoint avec la vérification de signature des webhooks avant la mise en production.