Events reference
Each event is a JSON object containing a type, a unique ID, and the data for the resource involved. Subscribe to these events when creating a webhook endpoint.
Events are emitted with livemode: true in production
and livemode: false in sandbox. A given endpoint only
receives events for the mode matching its API key.
In the event of a retry, the same event may be delivered more than once with the same id. Store the IDs of events you’ve already processed and
ignore duplicates to keep your handler idempotent.
Payment events
| Event | Trigger |
|---|---|
payment_intent.created | PaymentIntent created. |
payment_intent.succeeded | Payment succeeded — trigger fulfillment. |
payment_intent.payment_failed | Payment failed after the last attempt. |
payment_intent.canceled | PaymentIntent canceled manually. |
checkout_session.completed | Checkout session moved to complete status. |
checkout_session.expired | Session expired without payment. |
transaction.succeeded | Transaction finalized on the operator's side. |
transaction.failed | Transaction failed on the operator's side. |
refund.created | Refund initiated. |
refund.succeeded | Refund returned to the buyer. |
refund.failed | Refund failed on the operator's side. |
payment_link.paid | Payment link successfully used. |
Customer events
| Event | Trigger |
|---|---|
customer.created | New |
customer.updated | Customer data updated. |
customer.deleted | Customer anonymized (GDPR compliance). |
payment_method.attached | Payment method attached to the customer. |
payment_method.detached | Payment method detached from the customer. |
Subscription events
| Event | Trigger |
|---|---|
subscription.created | New subscription created. |
subscription.updated | Subscription updated (plan, quantity, etc.). |
subscription.renewed | Renewal succeeded — invoice paid. |
subscription.past_due | Renewal failed — trigger dunning. |
subscription.canceled | Cancellation effective. |
subscription.trial_will_end | 3 days before the trial period ends. |
invoice.created | Invoice generated automatically. |
invoice.finalized | Invoice finalized and sent to the customer. |
invoice.paid | Invoice paid. |
invoice.payment_failed | Invoice payment failed. |
Account events
| Event | Trigger |
|---|---|
kyc.submitted | KYC application submitted for validation. |
kyc.approved | KYC approved — account fully operational. |
kyc.rejected | KYC rejected — action required from the merchant. |
payout.created | Transfer to the bank account initiated. |
payout.paid | Transfer completed successfully. |
payout.failed | Transfer failed — check the bank details. |
Structure of an event
Implementing a handler
Your webhook handler must respond with a 2xx HTTP status
code within 10 seconds. For long-running processing, queue the task
in an asynchronous queue and respond immediately.
Always start by verifying the Sangho-Signature
before any processing. See the signature verification guide
for complete examples in each language.
Your handler should silently ignore event types it doesn’t recognize and return a 200. Sangho may emit new event types without notice — a
handler that returns an error on an unknown type will be retried unnecessarily.
Use POST /webhooks/{id}/test/ to send a mock event to your
endpoint and validate your integration without triggering an actual payment. The test
event has livemode: false regardless of the environment.