Register your endpoint
whsec_.
The URL must be HTTPS. Plain HTTP is rejected except for localhost and
127.0.0.1, allowed for local development. An invalid URL returns
400 WEBHOOK_URL_INVALID.
Requires the webhooks:manage scope.
Per-payout override
Setnotification_url on an individual payout and that payout’s events go there
instead of your default URL. Your tenant secret signs both, so verification does not
change.
Useful for routing a specific payout’s events to a different consumer without
standing up a second account. Everything else still goes to the default.
Verify every delivery
Each request carries these headers:
The signature is an HMAC-SHA256 over
<timestamp>.<raw_request_body>, keyed with
your signing secret.
If no secret is configured for your account, deliveries are sent unsigned —
the signature headers are simply absent. Treat a missing
X-Spendin-Signature as
a failure in production rather than as “nothing to check”, and confirm
GET /v1/webhooks/config reports a secret before you go live.Responding
Return any2xx, quickly. Anything else — or no response within 10 seconds —
counts as a failure.
Do your real work asynchronously: acknowledge first, process after. A handler that
runs a slow database write inline will eventually time out and cause duplicate
deliveries.
Retries
Failed deliveries are retried up to 5 attempts total (the first attempt plus four retries), with exponential backoff starting at 10 seconds. Every attempt is logged, whether it succeeded or not. After the fifth the delivery is markedDEAD and not retried again.
Idempotency on your side
The same event may be delivered more than once. Useevent_id as the dedupe key —
it is stable across every retry.
created_at or on arrival order. Deliveries can arrive out of
order; treat status in the payload as the truth and ignore an event that would
move a payout backwards from where your record already is.
Debugging
This is the fastest way to tell “we never sent it” from “your endpoint rejected
it”.
failure_reason carries the HTTP status or the transport error — a timeout, a
DNS failure, a TLS problem.