FlowAlp

É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 POST HTTP 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 : 8925 signifie 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ées invoice.

Événements de transaction

Le payload contient un unique objet transaction. Les champs les plus importants :

ChampTypeDescription
id / uuidint / stringID interne et ID public de la transaction
statusstringStatut de la transaction, voir tableau ci-dessous
amountintMontant traité en unités mineures
referenceIdstringVotre référence de commande
timestringHorodatage de création au format ISO 8601
modestringTEST ou LIVE
psp / pspIdstring / intIdentifiants du prestataire de paiement
typestringE-Commerce, POS-Terminal ou Tap to Pay
refundable / partiallyRefundableboolSi un remboursement (partiel) est possible
invoiceobjectDonnées de commande : currency, products, originalAmount, refundedAmount, custom_fields, …
contactobject ou nullDonnées du client et de l'adresse de livraison
paymentobjectMoyen de paiement, p. ex. brand et wallet
subscriptionobject ou nullPrésent quand la transaction appartient à une subscription
instanceobjectVotre compte marchand : name et uuid
payoutUuidstring ou nullUUID du versement qui contient cette transaction
preAuthorizationIdintUniquement pour les tokenizations/débits : ID de la tokenization source
originalTransactionId / -Uuidint / stringUniquement 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.

StatutSignification
waitingCommande créée, paiement pas encore terminé
confirmedPaiement réussi
cancelledPaiement interrompu par le client
declinedÉchec 3-D Secure ou refus de la banque émettrice
authorizedTokenization réussie
reservedRéservation réussie (préautorisation)
refundedRemboursement intégral
partially-refundedRemboursement partiel
refund_pendingRemboursement en cours de traitement
chargebackLe titulaire de la carte a récupéré l'argent
disputedUn litige a été ouvert pour cette transaction
errorUn problème est survenu pendant le paiement
expiredPaiement interrompu pour cause d'inactivité
Exemple : transaction confirméeJSON
{
  "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.

StatutSignification
activeLa subscription est active, d'autres prélèvements suivront
failedCréation échouée, ou un prélèvement et sa nouvelle tentative ont tous deux échoué
cancelledRésiliée par le marchand avec effet immédiat — plus aucun prélèvement
in_noticeRésiliée par le client avant la date de fin ; les prélèvements restants suivent encore
overdueUn prélèvement a échoué et est retenté ; un deuxième échec passe le statut à failed
Exemple : subscription activeJSON
{
  "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.

StatutSignification
processingLe fichier de versement a été remis à la banque
sentVersement transmis avec succès à la banque
failedVersement é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.

Exemple : versement envoyé (abrégé)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"
      }
    }
  ]
}

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 :

Acquittement minimalPHP
<?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 le status avant 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. refunded après confirmed).
  • 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.