Disputes have no test mode: dispute webhooks are registered with a live secret key and are sent for live payments only (the same as the Disputes API).
How They Work
1
Register an endpoint
Register a dispute webhook for each KSA merchants call
merchant_code — the merchant code is passed in the X-Merchant-Code header, which is required on every dispute-webhook request:https://api.tabby.sa/api/v1/dispute-webhooks. Each merchant_code can have up to 4 dispute webhooks — the limit is separate from payment webhooks. The optional header is added to every notification so you can verify its origin.Registration is self-service. The same operations as for payment webhooks — register, list, retrieve, update and remove — are available under
/api/v1/dispute-webhooks, see the API reference. A dispute webhook receives all dispute events of the merchant; there is no event filter.2
Receive notifications
Tabby sends a POST request to your URL whenever a dispute is opened on one of your payments or its status changes.
3
Acknowledge with 200
Respond with a
200 HTTP status code to confirm the reception, and check the auth header to verify the request. Any other response (or no response) counts as a delivery error and triggers retries.Differences From Payment Webhooks
A few rules to keep in mind when managing dispute webhooks:
- URLs must be publicly reachable.
localhost, raw IP addresses and host names that do not resolve are rejected with400 invalid webhook url. Use HTTPS — the secret inheadertravels with every notification. - URLs are normalised and unique per merchant. The scheme and host are lower-cased, a default port and a trailing slash are dropped before the URL is stored —
https://Store.com/hook/andhttps://store.com/hookare the same webhook, and registering it twice returns400 webhook already exists. The path itself is case-sensitive. PUTreplaces the whole object. Send bothurlandheaderwhen updating; a request withoutheaderremoves the header.- The header value is a secret. Tabby stores it in full but returns it masked in every response — keep your own copy of the value your endpoint validates against.
Payload
A dispute webhook is a POST request with a JSON body that links the dispute to the affected payment:Dispute statuses
Thestatus field tells you what happened to the dispute:
Delivery
Dispute webhooks are delivered to the URLs you registered under/api/v1/dispute-webhooks (separate from your payment webhooks), using the same delivery mechanism as payment webhooks — optional authentication header, retry policy, and server IPs. In particular:
- Acknowledge each delivery with
200and process it asynchronously — see Best Practices. - Delivery order is not guaranteed and a notification may occasionally be delivered twice — deduplicate by
dispute_id+status. - Failed deliveries are retried — see Retry Attempts.