Webhook Event Reference

Webhook notifications let your backend react in real time when a payment statusCode changes. This page explains where events are delivered, how to configure terminal webhooks, what the payload looks like, and how delivery and retries work.

1. Where events go

Destination

Destination
How it is configured
Scope

Terminal webhook

PUT /Terminals/{terminalId}/webhook

All payments created by the terminal

Per payment overrides

webhookUrls array in POST /payments/crypto

That single payment only

Fan out behaviour Bead sends the same event payload to the terminal webhook and to each URL listed in webhookUrls.

2. Set or update the terminal webhook

Example

PUT /Terminals/{terminalId}/webhook
Authorization: Bearer {access_token}
Content-Type: application/json
Accept: application/json

Request body

{
  "url": "https://example.com/bead/webhooks",
  "signingSecret": "b5b9ee11f2b447c9b3294ff9a8f6f53c"
}

Field notes

  • url must be an https URL

  • signingSecret is a 32 byte hex string; store it securely. Every event is HMAC signed with this secret

Success responses

  • 200 OK with a body that includes url and signingSecret

  • 202 Accepted or 204 No Content may also be returned when the update is accepted without a response body

3. Event payload and signature

Header

  • t is a Unix epoch timestamp in seconds

  • s is HMAC-SHA256(signingSecret, rawBody)

Always verify the signature before processing the JSON body.

Body (abbreviated example)

statusCode enum values

Value
Meaning

created

Payment record opened; waiting for funds

processing

Funds detected but not yet confirmed

underpaid

Received less than the requested amount

overpaid

Received more than the requested amount

completed

Full amount confirmed (or overpay auto accepted)

expired

Payment window elapsed, no settlement

invalid

On chain transaction cannot be matched

cancelled

Shopper cancelled checkout

4. Delivery mechanics

Item
Value

Method

HTTP POST with application/json body

Timeout

10 seconds per attempt

Retries

Exponential backoff for 24 hours (about 10 attempts) until any 2xx status

Source IPs

Will be published; until then, rely on signature checks

5. Best practice checklist

  1. Verify signature and timestamp (x-webhook-signature) to block spoofed or replayed messages

  2. Respond with HTTP 200 quickly, ideally under one second. Do heavy work asynchronously

  3. Treat delivery as idempotent. Use trackingId plus statusCode to ignore duplicates

  4. Use different webhook URLs for development, staging, and production environments

  5. Handle enum statusCode strings; numeric status codes were deprecated in May 2025

6. Roadmap

Upcoming enhancements that will remain backward compatible:

  • JSON envelope such as {"eventId","eventType","created","data":{...}}

  • Additional event types such as terminal.status.changed and payment.refund.completed

Your current HMAC logic will continue to work; the signature will cover the new envelope.

Last updated