Event types
Webhook event types
Every event type matches its status transition and carries the same payload shape ({ event_id, event_type, created_at, livemode, data: { invoice } }).
| Event type | Fired when | May fire more than once? |
|---|---|---|
invoice.created | New invoice via POST /v1/invoices | no |
invoice.payment_seen | Payment in mempool, 0 conf | no, once per invoice |
invoice.paid | Cumulative confirmed amount lands within tolerance, before expiry | no |
invoice.late_paid | Cumulative confirmed amount lands within tolerance, after expiry but inside grace | no |
invoice.expired | pending invoice's expires_at elapsed with no payment. Note: seen invoices never receive invoice.expired; if you got invoice.payment_seen, wait for the next event. | no |
invoice.underpaid | Cumulative confirmed amount is below amount_sats − tolerance. Fires on every short payment, so a top-up flow can produce two of these followed by invoice.paid. | yes — see top-up |
invoice.overpaid | Cumulative confirmed amount exceeds amount_sats + tolerance | no |
invoice.payment_reverted | A reorg orphaned the block containing the payment. Reverse fulfillment if you already shipped. Rare. | very rare |
invoice.requires_review | Routing produced "no-match" or cross-check disagreed | rare |
invoice.cancelled | Vendor or admin cancelled | no |
Always deduplicate by
event_id, never byinvoice.id+event_type. Top-up payments will produce repeatedinvoice.underpaidevents, and retries from our dispatcher produce repeated events with the sameevent_id(your dedupe target).