POST call TapiPay makes to an endpoint of yours when something you care about happens: a payment settles, a charge is declined, or a charge is reversed. That way you find out right away, without polling the API.
Webhooks are not emitted by the API, which does not implement them. They are emitted by TapiPay’s charging platforms, and they are configured during onboarding: there is no endpoint to register them or change the URL.
The events
The payment notification comes from the referenced payment platform and has its own contract, different from the rest: its
status is lowercase, its type identifies the kind of operation rather than the event, and its configuration is documented on that page. The other five share everything below.A failure and a chargeback are not the same
The five events in this family split into two groups, and it is worth not confusing them: they say different things about the same charge.Failure
The charge never went through. These arrive with
status: "FAILED".Chargeback
The charge had gone through and was later reversed. These carry no
status, because they do not describe the state of a payment but a later fact about an already processed charge.Common fields
The five events share this base:The verification hash
Your endpoint is public, so anyone can call it. Thehash field lets you confirm the request comes from TapiPay and that the payload was not tampered with.
It is generated by encrypting with RSA against the public key you hand over during onboarding. If you do not configure a publicKey, the field still arrives, with a null value.
The hash is one mechanism among several. The others (API key, bearer token, IP allowlist, mTLS) are configured the same way for every webhook and are detailed in Payment notification.
Error detail is optional
Card events can include the error code and message the provider returned, inside anadditionalData object. Whether they arrive depends on a flag in your configuration, sendErrorInfo, set during onboarding.
It is dropped in two cases: when sendErrorInfo is off, and when it is on but the provider reported no detail.
Bank debit events work differently: the decline detail (
bankErrorCode, bankErrorDescription) always travels, at the root of the payload and without depending on sendErrorInfo.Idempotency
TapiPay can retry a notification, so your endpoint has to tolerate receiving the same event more than once. The key isoperationId.
Your endpoint requirements (return 2xx, in under 5 seconds, reachable from TapiPay’s IPs) are the same for every webhook and live in Payment notification.

