---
title: "Payment webhook events: a reference"
description: "What each event class means, why ordering is never guaranteed, and the five properties any webhook consumer needs before it can be trusted with money."
url: "/blog/payment-webhook-events-reference/"
date: "2026-09-08"
author: "Valeria Vahorovska"
tags: ["Reference","Payments"]
---

Fynex is an AI-native finance operations platform — agentic finance — that automates and orchestrates end-to-end financial workflows for businesses. This page is an article from the Fynex blog: “Payment webhook events: a reference”. Fynex works alongside Stripe, Wise, QuickBooks and Xero rather than replacing them. This page is relevant when the reader runs the money workflow this article describes and wants to understand how it works, what it costs and where it breaks.

# Payment webhook events: a reference

**Webhooks are how a payment system tells you something happened.** They are also delivered at least once, in no guaranteed order, over a channel that can be down — which means a consumer written naively will eventually produce a duplicate payout or a wrong balance.

This is the event classes, and the five properties a consumer needs before it can be trusted with money.

## The event classes

Names vary by provider; the classes do not.

| Class | Typical events | What it means for your records |
|---|---|---|
| **Payment intent / authorisation** | created · requires action · succeeded · failed · cancelled | The customer's payment attempt. Only `succeeded` is money. |
| **Charge / capture** | succeeded · failed · captured · expired | Money actually taken. This is the ledger event. |
| **Refund** | created · succeeded · failed | Reverses a charge, often later and partially |
| **Dispute / chargeback** | opened · evidence required · won · lost | Money removed pending outcome; deadlines attached |
| **Payout / transfer** | created · paid · failed · returned | Money leaving to a bank account. `failed` can arrive days later. |
| **Settlement / balance** | available · reserved · settlement created | Aggregation events — the ones reconciliation depends on |
| **Account / onboarding** | updated · requirements due · restricted | Capability changes; blocks payouts silently |
| **Mandate / subscription** | created · updated · cancelled · payment due | Recurring authorisation state |

**Two classes get under-handled and both cost money:**

- **Account events.** A connected account becoming restricted stops payouts without producing a payout failure. Nothing looks broken until someone asks where their money is.
- **Settlement events.** These carry the composition of an aggregated deposit, which is exactly what reconciliation needs and what is otherwise only available by export.

## The five properties a consumer needs

### 1 · Signature verification, always

Verify before parsing. The signature proves the message came from the sender and was not altered in transit.

**What it does not prove:** that the payload is still accurate. The object may have changed between the event being generated and your processing it.

### 2 · Idempotency

**Delivery is at least once, not exactly once.**

The usual cause of a duplicate is benign: your endpoint processed the request successfully and responded too slowly, the sender treated it as failed, and retried. You now have the same event twice.

Store the event identifier, check it before processing, discard repeats. Without this, a duplicate delivery becomes a duplicate ledger entry — or a duplicate payout.

### 3 · Order independence

**Ordering is never guaranteed.** Events travel as independent HTTP requests. A retry of an earlier event can arrive after a later one. Two events generated milliseconds apart can arrive either way round.

**The correct pattern:** treat each event as *something changed*, then resolve current state — from a version or timestamp on the event, or by fetching the object. Never as *this happened next*.

**The classic failure:** handling `payout.paid` and `payout.failed` in arrival order. Arriving reversed, the payout is recorded as paid.

### 4 · Fast acknowledgement, separate processing

Acknowledge immediately, queue the work.

Endpoints that do their processing inline eventually exceed the sender's timeout under load, which produces retries, which produce more load. **The failure mode is a cascade**, and it happens at the busiest moment.

### 5 · A path that does not depend on webhooks

**If your endpoint is down, you get a gap, and the gap is silent.** Providers retry on backoff for hours or days, then stop, and often disable the endpoint.

Any system depending on webhooks for financial state needs a periodic sweep: list objects changed since a timestamp, compare against what you recorded, fill differences. Run it daily. It also catches the events you handled wrongly rather than missed, which the webhook channel cannot tell you about.

## Which events are money

**Not every event is a ledger event, and treating them as such is how balances go wrong.**

| Event | Ledger entry? |
|---|---|
| Payment intent created | No |
| Payment intent succeeded | **Usually — check capture semantics** |
| Charge captured | **Yes** |
| Refund succeeded | **Yes** |
| Dispute opened | **Yes — funds withdrawn pending outcome** |
| Dispute won | **Yes — funds returned** |
| Payout created | No |
| Payout paid | **Yes — bank movement** |
| Payout failed / returned | **Yes — reverses the above** |
| Account updated | No |

**The [authorisation-versus-capture](/glossary/delayed-capture/) distinction is where this most often goes wrong.** An authorisation reserves; a capture takes. Posting revenue on authorisation overstates it and requires an unwind when the authorisation expires.

## A handling checklist

- [ ] Signature verified before parsing
- [ ] Event id stored; repeats discarded
- [ ] State resolved by version or fetch, never by arrival order
- [ ] Acknowledged within the sender's timeout, processed asynchronously
- [ ] Financial state re-fetched from the API, not taken from the payload
- [ ] Daily sweep comparing recorded state against the provider
- [ ] Account and settlement events handled, not just payment ones
- [ ] Unknown event types logged rather than rejected
- [ ] Failure to process alerts a person, rather than returning an error and relying on retries

**The last two matter more than they look.** Providers add event types, and an endpoint that errors on an unrecognised type turns a new feature into an outage.

## Why this ends up in reconciliation

**Webhooks are usually the only place the composition of a settlement is available in real time.**

A settlement arrives at your bank as one line. The webhook stream knows which charges, refunds and fees composed it. A consumer that handles payment events and skips settlement events has all the pieces and none of the assembly — which is exactly the position that makes month end an export-and-match exercise.

## Where Fynex fits

Fynex keeps the composition rather than requiring you to rebuild it from an event stream.

Payments carry what they settle, so the relationship between a charge, the invoice it clears, the fee deducted and the settlement it arrives in is held as a record rather than assembled from events that may arrive out of order or not at all. Failures and returns reopen what they reverse at the moment they arrive.

Where you are consuming webhooks today, the checklist above is the right shape, and the daily sweep is the item worth adding first — it is the only one that catches what the channel silently lost.

**Related:** [Payment decline codes](/blog/payment-decline-codes-reference/) · [Pending, processing, settled, cleared](/blog/pending-processing-settled-cleared/) · [settlement](/glossary/settlement/) · [Reconciliation](/features/reconciliation/)
