type field—no payload diffing required.
The v2 taxonomy is granular: one event type means one thing happened. Each v2 event carries api_version: "2.0.0". New endpoints default to v2. See Versioning for how v1 and v2 run in parallel.
Not every payment emits every event. Sequences vary by flow and processor—auto-capture skips
payment_v2.authorized, and some methods go straight to payment_v2.settling or payment_v2.settled.Payment events
Payments move through thePENDING, INCOMPLETE, AUTHORIZED, SETTLING, SETTLED, FAILED, DECLINED, CANCELLED, and BLOCKED statuses. Each transition emits a dedicated event.
Fraud-alert data (Visa RDR, Order Insight, Compelling Evidence) flows through
payment_v2.updated on the embedded fraud_prevention block—there is no dedicated fraud event. Disputes have their own events; see Dispute events.Refund events
A refund rides on the payment object, so refund events belong to thepayment_v2 group and carry the payment with an embedded refund field. Correlate by payment_id. Refunds move through PENDING, SETTLING, SETTLED, DECLINED, and FAILED.
A payment can have more than one refund (partial refunds). Refund details are embedded on the payment object; correlate events by
payment_id and the refund’s processor_transaction_id. A payment reaching REFUNDED status is surfaced through these payment_v2.refund.* events—there is no payment_v2.refunded payment event.Refunds that fail after settling
Some processors can fail or cancel a refund after reporting it as successful, sometimes days later. When that happens, you receivepayment_v2.refund.failed or payment_v2.refund.declined for a refund you already saw as SETTLED:
- The refund’s
statuschanges toFAILEDorDECLINED, and the payment’srefunded_amountreturns to0. The money did not reach the customer. refund.status_reason.decline_codecarries the processor’s reason, for exampleexpired_or_canceled_card.- The event refers to the same refund, with the same
processor_transaction_id.
SETTLED as final only if no failure event follows for that refund. See your processor’s page under Integrations for processor-specific behavior.
Subscription events
Subscription events map to lifecycle transitions. Thestatus field (trial, active, past_due, scheduled_for_cancellation, cancelled) tells you the resulting state.
Dunning and retries
When a renewal payment fails, the subscription enterspast_due and PayNext retries automatically. Each retry emits one subscription_v2.past_due event carrying an incremented past_due.attempt_count, so you can tell attempts apart. If all retries fail, the subscription transitions to cancelled.
Pre-charge reminders
subscription_v2.trial_will_end and subscription_v2.renewal_upcoming (and their v1 aliases subscription.trial_will_end / subscription.renewal_upcoming) fire 24 hours before PayNext charges a subscription—the first at the end of a trial, the second before an ordinary renewal. Both carry the standard subscription object; read next_billing_date for the exact charge moment.
PayNext sends the trigger; you own the customer-facing message (email or SMS). Use these events to meet the card networks’ pre-charge notification requirements for trials and recurring billing.
- No reminder precedes a dunning retry. Only regular, first-attempt charges are announced; a failed renewal enters the past-due ladder silently (see Dunning and retries).
- Treat a reminder as idempotent by
next_billing_date. On v2 each cycle’s event is delivered once; on v1 a rare delivery retry may repeat it. Thenext_billing_datein the payload identifies the cycle. - If a subscription’s next charge date moves (a plan change, for example), the reminder follows it to the new date automatically.
Payment method events
A saved payment method keeps the same ID for its whole life, but its details change underneath that ID—a reissued card brings a new number and expiry, and a network token is refreshed, suspended, or removed by the card network. This event is the only signal that those details moved.
It fires once per applied change—a lifecycle
status change, a card reissue, refreshed card details, or a removed network token. Duplicate and out-of-order notifications from the card network don’t produce an event.
Dispute events
When a cardholder or their bank contests a payment, PayNext records a dispute and sends dispute events as it changes. Dispute events belong to thepayment_v2 group and carry the full dispute object in data.object, like other events. They exist in v2 only.
Dispute events are being rolled out and may not be available yet. An endpoint that receives all event types gets them automatically; an endpoint subscribed to selected event types receives them only after you add the
payment_v2.dispute.* types.payment_v2.dispute. prefix. The diagram shows the common paths; the table below is the complete rule.
WON, LOST, ACCEPTED and PREVENTED are final, with exceptions that come from the processors:- A resolved PayPal dispute can reopen. PayPal keeps the same dispute when, for example, the customer files an external chargeback, changes the reason or appeals. You receive
reopened(plusevidence_submittedorunder_reviewwhen it reopens into that status), andresolved_atis cleared. - A resolved PayPal dispute can move to a different final status, for example from
WONtoLOST. You receive the event for the new status, andresolved_atkeeps its original value. - A Stripe dispute in
LOSTcan later becomeWON(a late win). You receivewon, andresolved_atkeeps its original value. - An Unlimit retrieval request that closed as
PREVENTEDbecomesLOSTwhen a chargeback follows it. You receivelost, andresolved_atkeeps its original value.
stage, reason, disputed_at, respond_by or details without changing its status. You receive updated. A final dispute on any processor can also gain new details keys, or values for keys that were null, while nothing else changes—for example when is_visa_rdr is added to a resolved Stripe dispute—and you receive updated for that too. This can arrive long after the dispute was resolved. Braintree and Unlimit disputes don’t reopen. A Braintree escalation arrives as a new dispute, and so does a chargeback that follows an Unlimit retrieval request.status, stage, reason, disputed_at, respond_by and details unchanged—for example, a repeated delivery of an update PayNext already applied.
event.id is stable across delivery retries. When the same event type fires again for a dispute—a second reopen, for example—it carries a new event.id.
Legacy (v1) events
v1 uses coarse events:payment.updated and subscription.updated fire on every state change, so consumers must diff the payload to learn what happened. Map them to v2 as follows.
¹ v2 deliberately corrects v1 here: the initial activation of a no-trial subscription (previous status none) emits
subscription.updated under v1 but subscription_v2.created under v2. During the overlap the same transition goes out under both names—this is intended, not a duplicate.
Classifying events for analytics
Some distinctions aren’t signalled as separate event types. Derive them from the payload:
See the payment object, subscription object, and dispute object for full payload schemas.