Subscribe
The response includes a
secretKey — a 64-character hex string (32 random bytes), with no prefix:
POST returns 409 — Webhook config already exists for this partner scope. Use PATCH to update. Use PATCH /v1/webhooks/config to change the URL, the event list, or active.
PATCH cannot change partnerId. Re-scoping a subscription across partners would redirect another partner’s deliveries, so it is rejected by design.POST /v1/webhooks/config/rotate-secret. Deliveries signed with the old secret stop verifying the moment the new one is issued, so deploy the new secret before rotating.
Verify every delivery
A delivery arrives asPOST to your callbackUrl:
Compare digests in constant time — a plain
=== on the hex string leaks timing information that can be used to forge a signature one byte at a time.
Retries, and what your status code means
Your response code decides whether a failed delivery is ever retried. The delivery times out after 10 seconds.
Because of the 10-second timeout, acknowledge first and process afterwards. A handler that finishes its work before responding will start timing out under load, and every timeout becomes a redelivery.
Deduplicate on id
Retries redeliver the same event with the same id, so handlers must be idempotent. Record the id and ignore one you have already processed.
The two event families
Money-movement events exist under two names. Which one you receive depends on your subscription’s scope.- Partner-scoped — the subscription carries a
partnerId. Money-movement events are remapped toemployee.*names and delivered only for users belonging to that partner. This is what you want. - Legacy global — the subscription omits
partnerId. It receives the originalwallet.*names for every user.
Event types
Money movement
Onboarding and identity
Employer linking
Cards
The legacy
wallet.* names — wallet.deposit.completed, wallet.deposit.failed, wallet.deposit.refunded, wallet.withdrawal.completed, wallet.withdrawal.failed, wallet.withdrawal.processing — are accepted only by the global subscription. Do not use them in a partner-scoped one.Inspect delivery history
When an event seems missing, check whether it was delivered before assuming it was never produced.status is pending, delivered, or failed. When it is failed, errorMessage carries the reason — a timeout, a TLS failure, or the status code your endpoint returned. That is usually enough to tell a subscription problem from a handler problem.
There is no on-demand test trigger yet, so you cannot currently fire a synthetic event at your endpoint. Until one exists, exercise your handler by driving a real sandbox action — a small deposit produces
employee.deposit.completed. Adding a test trigger is tracked as platform work.Related
- Errors and status codes — including the read-before-retry rule that webhooks let you avoid.
- Integration flow — the lifecycle these events track.
- Sandbox test data — driving a real event in the sandbox.
Last reviewed: 7 August 2026.

