Skip to content

Webhook event catalog

Every event type, what its data holds, and the order a payment's events arrive in.

Every change in your business is recorded as an event, and each webhook endpoint receives the types it subscribes to. GET /events lists the same events any time. This page shows what an event holds, every type, and the order they arrive in.

The envelope

Every event has the same fields around its data, whether it arrives as a webhook or from GET /events.

Event
{  "id": "evt_JxmQNXpkZZN8mpqE",  "kind": "event",  "type": "payment.succeeded",  "subject": {    "kind": "payment",    "id": "pmt_QI02vLdJGd48hBbg"  },  "data": {    "id": "pmt_QI02vLdJGd48hBbg",    "kind": "payment",    "status": "succeeded",    "amount": 4900,    "currency": "USD",    "fee_payer": "business",    "customer_fee": 0,    "amount_received": 4900,    "reporting": {      "currency": "USD",      "amount": 4900,      "fee": 0,      "transaction_fee": 25,      "customer_fee": 0,      "net": 4875    },    "fee_rate_bps": 0,    "method": {      "rail": "crypto",      "asset": "USDC",      "network": "polygon",      "amount": "49.00",      "expected_amount": "49.00",      "overpaid_amount": null,      "from_address": "0x136e44a2738dea5217e8d6745463d2a9a84d1421",      "tx_hash": "0xc16a611d90302ba917593ed9743f5e734a556e8d2f35bb0d60a2ca02ac99bb20",      "explorer_url": "https://polygonscan.com/tx/0xc16a611d90302ba917593ed9743f5e734a556e8d2f35bb0d60a2ca02ac99bb20"    },    "settlement": {      "destination": "wallet",      "asset": "USDC",      "network": "polygon",      "amount": "49.00",      "wallet_id": "wal_1fIGZOrILmsCO0jw",      "address": "0x9a3c416D4A81669C01f4515bBDEB93C45d3813fe",      "tx_hash": "0xc16a611d90302ba917593ed9743f5e734a556e8d2f35bb0d60a2ca02ac99bb20",      "explorer_url": "https://polygonscan.com/tx/0xc16a611d90302ba917593ed9743f5e734a556e8d2f35bb0d60a2ca02ac99bb20"    },    "customer_id": "cst_gWFWcc7Ga0Pv7LSC",    "link_id": null,    "url": "https://checkout.402pay.co/checkout/2jrsrcxv7k",    "reference": "order_1042",    "metadata": {      "order_id": "1042"    },    "success_url": "https://example.com/thanks",    "cancel_url": "https://example.com/cart",    "expires_at": "2026-09-27T21:22:47.038Z",    "canceled_at": null,    "checkout_id": "chk_C5yhPQvPqpYgdDgj",    "description": "Pro plan, monthly",    "country": "US",    "failure_code": null,    "failure_message": null,    "confirmed_at": "2026-09-26T21:23:13.447Z",    "created_at": "2026-09-26T21:22:47.038Z",    "updated_at": "2026-09-26T21:23:13.447Z",    "events": [      {        "type": "created",        "created_at": "2026-09-26T21:22:47.038Z",        "data": null      },      {        "type": "method_selected",        "created_at": "2026-09-26T21:22:47.047Z",        "data": {          "rail": "crypto",          "asset": "USDC",          "network": "polygon"        }      },      {        "type": "detected",        "created_at": "2026-09-26T21:23:07.047Z",        "data": {          "amount": "49.00",          "network": "polygon",          "tx_hash": "0xc16a611d90302ba917593ed9743f5e734a556e8d2f35bb0d60a2ca02ac99bb20"        }      },      {        "type": "confirmation",        "created_at": "2026-09-26T21:23:08.647Z",        "data": {          "current": 1,          "required": 4        }      },      {        "type": "confirmation",        "created_at": "2026-09-26T21:23:10.247Z",        "data": {          "current": 2,          "required": 4        }      },      {        "type": "confirmation",        "created_at": "2026-09-26T21:23:11.847Z",        "data": {          "current": 3,          "required": 4        }      },      {        "type": "confirmation",        "created_at": "2026-09-26T21:23:13.447Z",        "data": {          "current": 4,          "required": 4        }      },      {        "type": "succeeded",        "created_at": "2026-09-26T21:23:13.447Z",        "data": null      }    ]  },  "actor": {    "kind": "system",    "id": null,    "name": null  },  "mode": "live",  "api_version": "v1",  "created_at": "2026-09-26T21:23:15.256Z"}
FieldMeaning
idThe event's ID, which is also the webhook-id header of every delivery of it.
kindAlways event.
typeWhat happened, such as payment.succeeded. The catalog below lists them all.
subjectThe kind and id of the object it's about.
dataA snapshot of the subject when the event fired. See below.
actorWho caused it: user, api_key, customer or system, with an id and name where there is one. A customer's name is their email, when checkout had one.
modetest or live. Always live during the beta.
api_versionThe version of the event's shape, v1 today.
testOnly on test deliveries, and then true.
created_atWhen it happened.

What data holds

data is the subject as the API returns it elsewhere, frozen when the event fired. A delivery sends those exact bytes every time, resends included, so fetch the object again when you need its state now.

subject.kinddata
paymentThe payment, as GET /payments/{id} returns it, timeline included.
linkThe link, with its payment count and volume.
customerThe customer, with their stats.
walletOnly id, kind, name and created_at. Balances and keys are never included.
wallet_transactionThe wallet transaction.
api_keyThe key with its name, mode and permissions. Its secret is redacted, never sent.
webhookThe endpoint with its secret_hint. The signing secret is never sent.
businessThe business profile.
checkout_settingsYour checkout settings. subject.id is the business's ID, and data has no ID of its own.
referralA business you referred, as your Partners page shows it: its name, status, when it joined and what you've earned from it. Nothing else about the other business is included.
referral_payoutA month of referral earnings: its period, amount, and the wallet address and tx_hash it was sent with.
feeA fee entry of type collection, with the balance you owed right after it.
Snapshots
{  "id": "evt_Lq3VnB8xR2mK7tYc",  "kind": "event",  "type": "link.created",  "subject": {    "kind": "link",    "id": "lnk_nt842tPNne3lf0ka"  },  "data": {    "id": "lnk_nt842tPNne3lf0ka",    "kind": "link",    "code": "v6e4mrczwg",    "url": "https://checkout.402pay.co/checkout/v6e4mrczwg",    "name": "Team plan, monthly",    "description": "Everything in Pro for up to 10 people.",    "amount": 19900,    "currency": "USD",    "success_url": null,    "status": "active",    "disabled_at": null,    "payments_count": 0,    "volume": {      "amount": 0,      "currency": "USD"    },    "created_at": "2026-09-26T21:22:46.992Z",    "updated_at": "2026-09-26T21:22:46.992Z"  },  "actor": {    "kind": "api_key",    "id": "key_7fQm2VxL0cR9tB4n",    "name": "Order server"  },  "mode": "live",  "api_version": "v1",  "created_at": "2026-09-26T21:22:46.992Z"}
  • link.deleted and webhook.deleted carry the object as it was just before it went. wallet.deleted, and any event whose subject was already gone when it fired, carries only id, kind and deleted: true.
  • A link's payments_count and volume, a customer's stats, and a referral's payments_count, volume, fees and earned are running totals. A delivery carries them as they were when it was sent; GET /events shows them as they are now.

Event types

Every type below can be sent to a webhook. GET /event-types returns the same list.

Payments

TypeWhen
payment.createdA payment was created and is waiting for the customer. For an API payment, when you create it. For a link, when checkout collects the customer's email, or when the transfer arrives if it never asked for one.
payment.succeededA payment was paid in full, or accepted, and its funds landed in the wallet or went to 402pay to pay the fees this business owes. That includes when the rest of an underpaid payment arrives.
payment.underpaidA payment received less than the amount due.
payment.overpaidA payment received more than the amount due and succeeded, or received a further transfer after it succeeded. Always right after payment.succeeded.
payment.needs_reviewA payment needs a decision before it counts as paid.
payment.failedA payment was canceled, by the business or by the customer at a link's checkout, or a declined card had no route left or wasn't retried within 30 minutes. No funds landed in the wallet. A decline with another card route left adds to the timeline instead.
payment.expiredA payment expired before any funds arrived.

Links

TypeWhen
link.createdA payment link was created.
link.updatedA payment link's details changed.
link.archivedA payment link stopped taking payments.
link.restoredAn archived payment link started taking payments again.
link.deletedA payment link was deleted.

Customers

TypeWhen
customer.createdA customer was added, by hand or when checkout collected their email.
customer.updatedA customer's details changed.
customer.blockedA customer can no longer pay.
customer.unblockedA blocked customer can pay again.

Wallet

TypeWhen
wallet.createdThe business wallet was created.
wallet.deletedThe business wallet was removed.
wallet_transaction.createdA send from the wallet started. Payments that land in the wallet send payment events instead.
wallet_transaction.confirmedA send from the wallet was confirmed on chain.
wallet_transaction.failedA send from the wallet failed on chain. When a send relayed from the dashboard fails on the network or is never seen there. A simulated business never sends it.

Business

TypeWhen
business.updatedThe business profile changed. A new alert_email counts once its code is confirmed, not while it waits in pending_alert_email.
business.activatedThe business finished setup and can take payments.
checkout_settings.updatedCheckout settings changed.

Billing

TypeWhen
fee.collectedA payment's funds went to 402pay to pay the fees this business owes, instead of to the wallet. Right before payment.succeeded for a payment whose funds went to pay your fees. See fees and billing.

Developers

TypeWhen
api_key.createdAn API key was created.
api_key.updatedAn API key's name or permissions changed.
api_key.revokedAn API key was revoked and stopped working.
webhook.createdA webhook endpoint was added.
webhook.updatedA webhook endpoint's settings or signing secret changed.
webhook.deletedA webhook endpoint was removed.
An endpoint created with a restricted key can only subscribe to types whose subject that key can read. API key, business and referral events aren't covered by any permission, so only the dashboard or a key with full access can subscribe to them.

Account events

These belong to a person, not to a business. They're recorded for the person's own security history, so webhooks never carry them and API keys can't list them.

TypeWhen
password.changedThe password was changed in settings.
password.resetThe password was reset from an emailed link.
email.changedThe account's email address changed after the new one was confirmed.
email.change_undoneThe email address was switched back from a link sent to the old one.
passkey.addedA passkey was added for signing in.
passkey.removedA passkey was removed and can't sign in anymore.
two_factor.enabledSign-in now asks for an authenticator code.
two_factor.disabledSign-in no longer asks for an authenticator code.
two_factor.recovery_code_usedA recovery code stood in for the authenticator code.
two_factor.recovery_codes_regeneratedNew recovery codes were made and the old ones stopped working.
session.revokedA signed-in device was signed out from settings.

Sequences

What a payment sends, from creation to the end, in each case.

CaseEvents
Paid in fullpayment.created, then payment.succeeded
Paid in full and collected as feespayment.created, then fee.collected, then payment.succeeded
Paid too muchpayment.created, then payment.succeeded, then payment.overpaid
Paid too little, then the rest arrived or you acceptedpayment.created, then payment.underpaid, then payment.succeeded
Late or on another network, then acceptedpayment.created, then payment.needs_review, then payment.succeeded
Canceled, or declined on every card routepayment.created, then payment.failed
Nothing arrived in timepayment.created, then payment.expired
  • A card declined with another attempt available isn't a webhook: the payment stays pending and its timeline gains a card_attempt_failed event.
  • Each delivery is retried on its own schedule, so a retried payment.created can land after payment.succeeded. Go by the event's created_at, or fetch the payment, rather than the order deliveries arrive in.
  • A new customer's customer.created arrives alongside their first payment's events, when checkout collects their email or you pass customer_email.

Test events

POST /webhooks/{id}/test sends a signed sample of a type the endpoint receives, with test: true, a made-up subject such as pmt_test_wcKbRA2NP8gXhlmr, and only that ID in data. It checks your signature code and routing, not your handling of real data, so build against the shapes on this page.

See webhooks for signatures, retries and resends.