Can I send webhook events to multiple URLs?
Yes. Bead supports two layers of webhook delivery, and you can combine them to fan-out each event to several destinations:
Terminal webhook
PUT /Terminals/{terminalId}/webhook
All payments created by the terminal
Core order-management system, accounting queue
Per-payment overrides
webhookUrls array in POST /payments/crypto
Only the payment being created
A/B testing, partner-specific listener, analytics hook
When you include a webhookUrls array, Bead POSTs the same JSON payload to all of these endpoints:
The terminal's default webhook URL
Every URL listed in
webhookUrls
No extra configuration is needed—just add the array to your create-payment request:
{
"...": "...other fields...",
"webhookUrls": [
"https://orders.example.com/bead/events",
"https://analytics.example.com/hooks/bead"
]
}Delivery behavior
Fan-out: events are sent to every destination in parallel.
Success criteria: each URL must return HTTP 2xx; any non-2xx triggers retries for that endpoint only (exponential back-off, 24 h window).
Same body, different signature per delivery: the JSON body is identical for every recipient, so your parsing logic doesn't need to branch by destination. The
x-webhook-signatureheader, however, is generated fresh for each individual delivery (a new timestamp each time), so the signature value differs across recipients even though the body and the underlying secret are the same. Your verification code should recompute the signature per delivery rather than comparing signature values against each other.
Tips & best practices
Idempotency – process webhooks idempotently (e.g., by
trackingId+statusCode) in case one URL retries while another succeeds.Environment isolation – point sandbox terminals to test URLs, then add production URLs in
webhookUrlsonly when you go live.Signing secrets – the HMAC uses the terminal's
signingSecret, for both the terminal's own webhook and every URL inwebhookUrls. Share that secret securely with every service that needs to verify events.Set a terminal webhook first, even if
webhookUrlsis your primary path – a terminal only has asigningSecretonce you've calledPUT /Terminals/{terminalId}/webhookon it at least once. If you only ever usewebhookUrlsand never set a terminal-level default, that terminal has no signing secret, and itswebhookUrlsdeliveries are sent without anx-webhook-signatureheader — silently, with no error or warning. Set the terminal-level webhook first to establish the secret, then rely onwebhookUrlsfor additional routing.Performance – acknowledge quickly (under 1 s) and offload heavy work to background jobs.
Testing multiple endpoints
Sandbox first – set a sandbox webhook URL on the terminal (this also establishes the
signingSecret).Include a second test URL in
webhookUrls.Create a payment in sandbox and complete it with a test wallet.
Confirm both endpoints receive the same event body, each with a valid (but distinct)
x-webhook-signature, and that retries stop after 2xx.
Last updated