Skip to navigation

Webhook event types

This page lists event types accepted by merchant-public WebhookEndpoints. Availability still depends on whether the source product can emit the event.

How to read this catalog

Each type has an implementation status inside the platform:

StatusMeaning
ImplementedThe internal projection is emitted by normal payment flows.
Flow-dependentEmitted internally only when a payment reaches the corresponding state.
DormantProjection/routing code exists, but its source product is unavailable.

Internal routing

Each merchant-public endpoint has an enabled_events allow-list. Use an exact type below or the * wildcard.

Stripe-shaped types (19)

TypeWhen it firesdata.objectStatus
payment_intent.succeededa payment is authorized and capturedPaymentIntentImplemented
payment_intent.payment_faileda payment attempt is declined or errorsPaymentIntentImplemented
payment_intent.requires_actiona payment needs customer action (e.g. 3DS)PaymentIntentImplemented
charge.refundeda refund succeedsChargeImplemented
payment_intent.canceleda payment is canceled before capturePaymentIntentFlow-dependent
payment_intent.amount_capturable_updatedan authorization is held for later capture (manual capture)PaymentIntentFlow-dependent
payment_intent.processinga payment enters async processing — bank debits; cards do not rest herePaymentIntentFlow-dependent
refund.faileda refund fails at the connectorRefundFlow-dependent
charge.succeededa card charge succeeds (or is authorized, for manual capture)ChargeFlow-dependent
charge.captureda manual-capture charge is capturedChargeFlow-dependent
charge.updatedan automatic-capture charge gets its balance transactionChargeFlow-dependent
charge.faileda charge attempt is declinedChargeFlow-dependent
charge.dispute.createda dispute is openedDisputeDormant
charge.dispute.updateda dispute is challenged or updatedDisputeDormant
charge.dispute.closeda dispute is resolved (won, lost, or expired)DisputeDormant
charge.dispute.funds_withdrawnStripe withdraws a disputed amount (US Stripe Connect only)DisputeDormant
charge.dispute.funds_reinstatedStripe returns a disputed amount after a won dispute (US Stripe Connect only)DisputeDormant
mandate.updateda mandate becomes active or is revokedMandateDormant
payout.paida payout completesPayoutDormant
payout.faileda payout failsPayoutDormant
payout.createda payout is created and processingPayoutDormant
payout.canceleda payout is canceledPayoutDormant

Charge events

charge.succeeded, charge.captured, charge.failed and charge.updated are published by the payment event of the same moment. Their id is that event’s id plus a suffix (_chs, _chc, _chf, _chu) and never changes, so deduplicate on it. charge.succeeded has balance_transaction: null, as at Stripe; for an automatic capture, charge.updated follows with the txn_ and previous_attributes {balance_transaction: null}. charge.pending is never sent: no Fluveo payment creates a pending Charge. The Charge is the GET /v1/charges/{id} body without the shopper’s name, email, phone or address. amount_captured, captured, amount_refunded and refunded keep their values from when the event happened. These four types are sent for US Stripe Connect stores only; a BR store cannot subscribe to them. On a US Stripe Connect store every refund also sends refund.created once, when it is created. Its Refund keeps the processor’s status at that moment, so it can say succeeded while GET /v1/refunds/{id} still reads pending until Fluveo’s books confirm it. A later status change of the refund sends charge.refund.updated (and refund.updated when it is not a failure; a failure sends refund.failed), with previous_attributes. A metadata update (POST /v1/refunds/{id}) sends charge.refund.updated and refund.updated with previous_attributes {metadata: ...}.

A few types collapse several states

Some Stripe types intentionally cover more than one underlying platform state — branch on a field of data.object, not on a finer-grained type:

  • payment_intent.succeeded covers both a one-step sale and a captured authorization.
  • charge.dispute.closed covers a dispute that was won, lost, or expired — read the dispute’s status to tell which.
  • mandate.updated covers a mandate becoming active or being revoked — read the mandate’s status.

Example bodies — implemented internal projections

The data.object is always a clean public shape. See delivery safety. Abbreviated examples:

// payment_intent.succeeded
{ "type": "payment_intent.succeeded",
"data": { "object": {
"object": "payment_intent", "id": "pi_…", "status": "succeeded",
"amount": 4242, "currency": "usd", "latest_charge": "ch_…" } } }
// payment_intent.payment_failed
{ "type": "payment_intent.payment_failed",
"data": { "object": {
"object": "payment_intent", "id": "pi_…", "status": "requires_payment_method",
"last_payment_error": { "code": "card_declined", "decline_code": "generic_decline",
"message": "Your card was declined." } } } }
// payment_intent.requires_action
{ "type": "payment_intent.requires_action",
"data": { "object": {
"object": "payment_intent", "id": "pi_…", "status": "requires_action",
"next_action": null } } }
// charge.refunded — data.object is a Charge, not a Refund
{ "type": "charge.refunded",
"data": { "object": {
"object": "charge", "id": "ch_…", "amount": 4242, "amount_refunded": 4242,
"refunded": true, "payment_intent": "pi_…" } } }

Payment events never carry next_action; retrieve the PaymentIntent to read it.

For Dormant types, the example body will be published when the source resource ships; the data.object will be the public Stripe shape of that resource.

These shapes are internal implementation evidence. See the webhook migration boundary before planning a public integration.

Platform-native types (9 hs.*)

Internal projections with no Stripe equivalent use a stable hs.<snake_case> name rather than being dropped. The three hs.payment_* types carry the same PaymentIntent object as payment_intent.* (object: "payment_intent", a pi_ id, no shopper fields); each of the other six carries a named public object too: on webhook endpoints, never the stored customer’s personal data (the legacy profile URL is never sent to; events go only to webhook endpoints). This naming is not a merchant-public delivery promise.

TypeWhen it firesdata.objectStatus
hs.payment_cancelled_post_capturea payment is cancelled after capturePaymentIntent (object: "payment_intent")Flow-dependent
hs.payment_partially_authorizeda payment is partially authorizedPaymentIntent (object: "payment_intent")Flow-dependent
hs.payment_expireda payment expires before completionPaymentIntent (object: "payment_intent")Flow-dependent
hs.dispute_accepteda dispute is acceptedDispute (object: "dispute") with the charge registry’s ch_Dormant
hs.dispute_cancelleda dispute is cancelledDispute (object: "dispute") with the charge registry’s ch_Dormant
hs.invoice_paidan invoice is paidInvoice (object: "invoice")Dormant
hs.payout_initiateda payout is initiatedPayout (object: "payout")Dormant
hs.payout_expireda payout expiresPayout (object: "payout")Dormant
hs.payout_reverseda payout is reversedPayout (object: "payout")Dormant

The Invoice carries exactly object, id, subscription, customer, payment_intent, amount_due, currency and status (draft, open, paid or void); never the subscription’s payment or billing details.

The internal * wildcard

The platform routing model recognizes * as a merchant-public subscription to every event type that the merchant and mode are allowed to receive.

Hidden from the public API

Each item below is hidden because it does not follow the Stripe parity ADR (ADR 0004 as amended). The hidden public /v1 registry lists every hidden item. Public /v1 answers a hidden operation as an unknown URL, refuses a hidden request parameter or value with Stripe’s invalid_request_error, and omits a hidden response key.

  • the query parameter object of GET /v1/events (HIDE0-047)
  • the query parameter payment_intent of GET /v1/events (HIDE0-048)