Event catalog
The notification event types and their payload classes.
The notification_class field selects the meaning of a notification. There are four classes. All share the payload envelope; the table below fixes how the two conditional fields are populated per class.
Notification classes
notification_class | Meaning | finality_outcome | hold_reason |
|---|---|---|---|
payment_observed | The payment was observed on-chain at the observed threshold. Progress signal, not settlement. | null | null |
payment_finalized | The payment reached finality and a terminal outcome was published. | paid | refunded | failed | null |
payment_held | The payment is held; no funds have moved and no outcome is finalized. | null | sanctions | kyt_timeout |
duplicate_payment_incident | Informational: an additional finalized payment was detected for a payment_intent_id that was already settled. | null | null |
finality_outcome values
Populated only on payment_finalized.
| Value | Meaning |
|---|---|
paid | The payment swept to the merchant's approved destination; protocol fee collected on-chain. |
refunded | The merchant returned a reject decision with a refund destination; the payment was refunded; protocol fee collected on-chain. |
failed | The payment reached a terminal failure state without settlement or merchant-directed refund. No funds moved. |
hold_reason values
Populated only on payment_held.
| Value | Meaning |
|---|---|
sanctions | The source address matched the sanctions list. Resolution requires a merchant-supplied refund destination through the KYT response channel. |
kyt_timeout | The merchant KYT endpoint did not respond within its configured window, and the merchant's timeout policy resolved to hold. |
A payment_held notification is not terminal. Once the hold is resolved, a separate payment_finalized notification is delivered for the same payment_intent_id, as a distinct record.
Records produced per scenario
One record produces one notification identity per endpoint. A single payment_intent_id may produce more than one record.
| Scenario | Records delivered |
|---|---|
| Clean payment | payment_finalized (paid) |
| Merchant-rejected payment | payment_finalized (refunded) |
| Failed payment | payment_finalized (failed) |
| Held — sanctions | payment_held (sanctions), then payment_finalized once resolved |
| Held — KYT timeout | payment_held (kyt_timeout), then payment_finalized once resolved |
| Duplicate detected after settlement | payment_finalized (paid) and duplicate_payment_incident (null) |
Duplicate-payment caveat
duplicate_payment_incident is the merchant-actionable signal for reconciling an extra on-chain payment. It is delivered as its own record, alongside the canonical payment_finalized (paid) record for the same payment_intent_id — the settlement record already carries the authoritative outcome and is not re-issued.
This notification-plane signal is distinct from the duplicate_payment value of finality_outcome you may see on the API status projection. A losing attempt can surface there as status FAILED with finality_outcome duplicate_payment — that is not a failed payment; it means the attempt lost winner selection while the intent is already PAID. See Statuses and projections.