Payment Webhooks

Payment webhooks let Bead send real time payment status updates to your system. Instead of polling the API, your server receives a POST request 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, or invalid states

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

  • Track payments without polling /Payments/tracking/{trackingId} or Reporting endpoints

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 or Boarding APIs

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

    • This tells Bead where to send payment status updates for that terminal.

  2. Through Bead support

    • If you do not have access to the Boarding API or prefer assistance, contact Bead with your terminal identifier and desired webhook URL.

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

Event delivery

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

General behaviour:

  • Method: POST

  • Content type: application/json

  • One event per status change for a payment

  • Retries if your endpoint does not return 200 OK

You should:

  • Log every webhook request for debugging and audit

  • Validate the request and payload before acting on it

  • Return 200 OK as soon as you have safely processed the event. Failing to do so may result in repeated attempts.

Payload format

Payment status events are delivered as JSON. The exact shape depends on the internal payment status response, but conceptually it matches the PaymentStatusResponse schema in the API.

Typical fields include:

  • trackingId Identifier created when you call POST /Payments/crypto. Used to correlate requests and webhooks.

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

  • statusCode Current payment status. Uses the PaymentStatus enum:

    • created

    • processing

    • completed

    • underpaid

    • overpaid

    • fullyRefunded

    • partiallyRefunded

    • expired

    • invalid

    • cancelled

  • amounts Object that contains requested and paid amounts, including currency details. It mirrors the PaymentUpdatePaymentAmounts structure.

  • reference and description Optional fields that echo the reference and description you passed when creating the payment.

  • receivedTime Timestamp for when the payment reached its final or current state.

An example payload in the integration guide is simplified as:

{
  "trackingId": "4f181348293946cfa39b5846078c9bbc",
  "paymentCode": "bAKbqtcuP5",
  "statusCode": 2,
  "amounts": {
    ...
  }
}

In the public API, statusCode is represented as a PaymentStatus string value such as "completed" rather than a numeric code.

Status codes

Internally, the integration guide references numeric status codes, but in the API and webhooks you will use the PaymentStatus enum values. The important statuses for webhooks are:

  • completed Payment completed successfully.

  • underpaid Crypto amount received is below the requested amount.

  • overpaid Crypto amount received is above the requested amount.

  • expired The payment expired before being fully paid.

  • invalid The payment reached an invalid state, for example due to conflicting or incorrect on-chain activity.

For user facing behaviour, you can map these to friendly descriptions, for example “Payment expired” or “Payment amount too low”.

When your webhook endpoint receives a payment status event:

  1. Log the request

    • Store headers and payload for debugging and reconciliation.

  2. Validate the request

    • Verify the request came from Bead, using your preferred verification strategy.

    • Validate that required fields such as trackingId, paymentCode, and statusCode are present.

  3. Look up the related order or invoice

    • Use paymentCode or trackingId to locate the corresponding order.

  4. Apply business logic based on statusCode

    A typical mapping is:

    • completed

      • Mark the order as paid

      • Trigger fulfilment or access delivery

    • underpaid

      • Mark the order as partially paid

      • Notify the customer or support about the remaining amount

    • overpaid

      • Mark the order as overpaid

      • Queue a refund or contact the customer according to your policies

    • expired or invalid

      • Mark the order as expired or invalid

      • Notify your support team or prompt the customer to create a new payment

  5. Respond to the webhook

    • Return HTTP 200 as soon as processing succeeds.

    • If you encounter an error, return an appropriate status code and log the failure for later inspection.

Retry behaviour

Bead will retry webhook delivery if your endpoint does not return 200 OK. Exact retry timing is subject to change and is not guaranteed to be strictly linear. Recommended patterns:

  • Treat all webhook deliveries as idempotent

    • Use trackingId or paymentCode as an idempotency key

    • If you have already processed an event for this payment and status, return 200 OK without side effects

  • Avoid long running operations inside the webhook handler

    • Enqueue work to a background job and return 200 OK quickly

Using webhooks with other APIs

Webhooks are often used together with:

  • Payment status APIs

    • GET /Payments/tracking/{trackingId}

    • GET /Payments/get-by-payment-code/{paymentCode}

  • Reporting APIs

    • GET /Merchants/{id}/payments

    • GET /Partners/{id}/payments

    • GET /Terminals/{id}/payments

  • Settlement APIs

    • Merchant settlements to see how payments were batched

    • Payment settlements to see settlement amounts and available times

Typical patterns:

  • Use the webhook as the trigger, then call a status or Reporting endpoint if you need more detail.

  • For reconciliation, run daily Reporting or Settlement jobs and use webhooks only for real time operational reactions.

Testing webhooks

To test your webhook integration:

  • Use the sandbox environment with a test terminal and webhook URL.

  • Create payments through the Hosted Payment Page or POST /Payments/crypto.

  • Complete payments using test wallets so that different statuses are produced, such as completed, underpaid, and overpaid.

  • Verify that your webhook endpoint receives events and that your system updates orders and logs correctly.

Once testing is complete and you are ready for production, update the webhook URL for your production terminal and repeat basic validation tests in the live environment.

Last updated