Payment Webhooks

Payment webhooks let Bead send real time payment status updates to your system. Instead of polling, your server receives an HTTP POST whenever a payment’s status changes.

Webhook notifications are configured at the terminal level and are typically used together with the Payments and Reporting APIs.

When to use payment webhooks

Use payment webhooks when you want to:

  • Update orders or invoices as soon as a payment completes

  • React to underpaid, overpaid, expired, invalid, or cancelled outcomes

  • Trigger downstream workflows such as fulfilment, refunds, customer notifications, or support tickets

  • Track payments without polling GET /Payments/tracking/{trackingId}

Webhooks provide the event feed. The Payments and Reporting APIs provide the full history and current state if you need to re read data.

Configuring the webhook URL

Payment webhooks are configured per terminal.

You can set the webhook URL in two ways:

  1. Using the Terminal APIs (OAuth)

  • When creating or updating a terminal, provide the webhook URL field.

  • You can also update the webhook URL directly using the terminal webhook endpoints.

Terminal webhook endpoints:

  • PUT /Terminals/{id}/webhook

  • GET /Terminals/{id}/webhook

  • DELETE /Terminals/{id}/webhook

Note: Terminal management endpoints use OAuth. They do not use the Payments API key.

Example (set terminal webhook, OAuth):

  1. Through Bead support

If you do not have access to the Terminal APIs or prefer assistance, contact Bead with:

  • terminalId

  • desired webhook URL

Once configured, every payment associated with that terminal will send status updates to the configured webhook URL.

Sending events to multiple URLs

Bead can deliver payment events to multiple endpoints:

  • Terminal default webhook URL (configured on the terminal)

  • Optional per payment webhook URLs supplied when creating a payment (the webhookUrls field on POST /Payments/crypto)

Use the terminal webhook for your primary system of record, and use per payment webhookUrls only when you have a clear reason to route a specific payment’s events elsewhere.

Event delivery

For each payment update, Bead sends a POST request to your webhook URL.

General behavior:

  • Method: POST

  • Content type: application/json

  • One event per status change for a payment

  • Retries occur if your endpoint does not return 200 OK

Your webhook handler should:

  • Log every webhook request for debugging and audit

  • Validate and parse the payload before acting on it

  • Return 200 OK as soon as you have safely processed the event (or queued it for processing)

If you do not return 200 OK quickly, Bead may retry the same event.

Payload format

Payment status events are delivered as JSON. The exact shape aligns conceptually with the payment status response model and includes identifiers that let you correlate events to your own order or invoice.

Typical fields include:

  • trackingId Identifier created when you call POST /Payments/crypto. Use it to correlate requests, webhooks, and status checks.

  • paymentCode Short code that identifies the payment on the hosted page and in Reporting.

  • statusCode Payment lifecycle state such as created, processing, completed, underpaid, overpaid, expired, invalid, or cancelled.

  • updated Timestamp for when the payment record was updated.

Example payload:

How to process webhook events

Recommended processing flow:

  1. Parse the request body as JSON.

  2. Validate required fields are present (at minimum, trackingId and statusCode).

  3. Persist the event or enqueue it for processing.

  4. Update your internal order or invoice state based on statusCode.

  5. Return 200 OK.

Best practices:

  • Treat webhook delivery as at least once. You may see the same status event again during retries.

  • Make your handler idempotent. Use trackingId plus statusCode (and updated when present) to avoid duplicate work.

  • Do not assume events arrive in perfect order. Your handler should tolerate out of order delivery and always converge on the latest known state.

Confirming status with the Tracking endpoint

If you need to confirm the current state (for example, during support, reconciliation, or if you missed an event), call the tracking endpoint using the same API key approach as POST /Payments/crypto.

Endpoint:

  • GET /Payments/tracking/{trackingId}

Headers:

  • X-Api-Key: {apiKey}

  • Accept: application/json

Example:

Notes:

  • apiKey is the secret credential.

  • maskedApiKey is not usable.

  • The header name must be exactly X-Api-Key.

Testing webhooks in Sandbox

  1. Configure a webhook URL for your Sandbox terminal.

  2. Create a Sandbox payment with POST /Payments/crypto.

  3. Complete the payment on the hosted page.

  4. Confirm your webhook received status updates.

  5. Optionally confirm the final state using GET /Payments/tracking/{trackingId}.

Troubleshooting

Webhook not received

  • Confirm the terminal has a webhook URL configured.

  • Confirm your endpoint is publicly reachable over HTTPS.

  • Confirm your endpoint returns 200 OK quickly.

  • Check your server logs for inbound requests and any parsing errors.

Receiving repeated webhook events

  • Your endpoint is likely returning a non 200 response or timing out.

  • Return 200 OK after you have safely persisted or queued the event.

  • Ensure your processing is idempotent.

401 Unauthorized when checking status

  • Payments endpoints use X-Api-Key. Confirm the API key is present and valid for the environment.

  • Confirm the header name is exactly X-Api-Key.

403 Forbidden when checking status

  • The API key is valid but not permitted for the payment’s context, or you are mixing environments.

  • Confirm you are using the correct environment base URL and the correct terminal API key.

Next steps

  • Review Payment Statuses for the full list of statusCode values and how to interpret them.

  • Review Create Payment for webhookUrls support if you need per payment delivery.

  • Use Reporting and Settlement for historical views and reconciliation.

Last updated