Checkout Payments Webhook

View as Markdown

Real-time webhook notifications sent when payments are completed via BlockBee's hosted checkout solution. These webhooks notify you when a customer has successfully paid for their order and you should fulfill the purchase.

Method: You choose when creating the payment:

  • GET (default) - Webhook data sent as URL query parameters
  • POST (set post=1) - Webhook data sent in request body

Content-Type: You choose when creating the payment:

  • application/x-www-form-urlencoded (default) - Standard form encoding
  • application/json (set json=1) - JSON format in request body

Webhook Overview

Unlike custom payment flow webhooks, checkout payment webhooks are sent only once when the payment is complete and confirmed. There are no separate pending and confirmed states - you receive a single notification when the payment is ready to be processed.

The webhook contains all the information you need to:

  • Verify the payment was legitimate
  • Update your order status
  • Fulfill the customer's purchase
  • Store transaction details for your records

Webhook Fields

payment_urlstringRequired

Payment link where the payment came from.

Example: https://pay.blockbee.io/payment/fG78jtx96ugjtu0eIbeLmFB9z0feJf9N

redirect_urlstringRequired

Redirect URL provided when requesting a new payment link.

Note: Any query parameters you add to this URL (like ?order_id=12345) will be included in the webhook payload, allowing you to track which order the payment belongs to.

Example: https://example.com/success/?order_id=12345

valuenumberRequired

Amount in FIAT you requested when creating the payment link.

Example: 20000 (represents $200.00 in cents)

payment_idstringRequired

Unique identifier for the payment that can be used to track and identify the transaction.

Important: You can use this unique identifier for idempotency to prevent processing duplicate webhooks. Store this ID when creating the payment and verify it matches in the webhook to ensure you're processing the correct transaction.

Example: fG78jtx96ugjtu0eIbeLmFB9z0feJf9N

currencystringRequired

FIAT currency. Should be the same that you set in your Payment Settings at BlockBee's Dashboard.

Example: usd

is_paidstringRequired

Should always be 1 for completed payments.

Example: 1

received_amountstringRequired

Value forwarded to you, after fees deducted.

Note: The cryptocurrency/token used to make the payment is described in the parameter paid_coin.

Example: 9.24

received_amount_fiatstringRequired

Value forwarded to you, after fees deducted in the FIAT currency selected.

Note: FIAT currency. Should be the same that you set in your Payment Settings at BlockBee's Dashboard.

Example: 9.24 (represents $9.24)

exchange_ratenumberRequired

Exchange rate at the time of the payment.

Example: 20000

txidstringRequired

Transaction hash(es) of your client's payment(s).

Note: If multiple, it means your customer had to make multiple transactions to fulfill the payment, since the Checkout page supports partial payments.

Example: 0xa7551df44e487f9c0507d68d90193cde2604dfcefdc975bae54535a2e0f80b32,0x6e8b278e3db1948d2c694b7f709dd4e864ae80d516970ebfd05a98629b6efe15

addressstringRequired

Address generated by BlockBee where your client's payment was received.

Example: 3PFoGK63cVVUWnd2vu7W1kM83NXUfvzMqM

typestringRequired

Type of the IPN.

Example: payment

statusstringRequired

Status of the transaction.

Example: done


Security: Verify Webhook Signatures


Reliability and Best Practices

For important information on how BlockBee handles webhook delivery, retries, and timeouts, along with essential best practices for building a reliable webhook handler, please see our main guide.

➡️ Read the Webhooks Overview


Implementation Examples

// Express.js webhook handler
app.post('/webhook', express.json(), (req, res) => {
  // 1. Verify the webhook signature
  if (!verifyWebhookSignature(req)) {
    return res.status(401).send('Unauthorized');
  }

  // 2. Extract data from the payload
  const { 
    is_paid, 
    payment_id, 
    value, 
    paid_amount_fiat, 
    paid_coin, 
    txid, 
    status,
    redirect_url 
  } = req.body;

  // 3. Check for duplicates using payment_id
  if (isWebhookAlreadyProcessed(payment_id)) {
    return res.status(200).send('*ok*');
  }

  // 4. Verify the payment is complete
  if (is_paid !== '1' || status !== 'done') {
    return res.status(200).send('*ok*');
  }

  // 5. Verify the payment ID matches your records
  if (!verifyPaymentId(payment_id)) {
    console.error('Invalid payment ID received');
    return res.status(200).send('*ok*');
  }

  // 6. Extract order ID from redirect URL
  const urlParams = new URLSearchParams(redirect_url.split('?')[1]);
  const orderId = urlParams.get('order_id');

  // 7. Process the successful payment
  // Update order status, fulfill purchase, etc.
  processSuccessfulPayment({
    orderId,
    amount: paid_amount_fiat,
    coin: paid_coin,
    txid: txid
  });

  // 8. Mark this webhook as processed using the payment_id
  markWebhookAsProcessed(payment_id);

  // Always respond to stop retries
  res.status(200).send('*ok*');
});

Key Security Checks

  1. Verify Webhook Signature - Ensure the request is from BlockBee
  2. Check Payment Status - Only process when is_paid=1 and status=done
  3. Validate Payment ID - Match against your stored payment ID to ensure you're processing the correct transaction
  4. Extract Order ID - Use the redirect_url to get your order identifier

Best Practices

  • Idempotency: Use the payment_id to ensure you only process each payment once
  • Respond Quickly: Always respond with *ok* and a 200 status code
  • Asynchronous Processing: Handle long-running tasks in background jobs
  • Error Handling: Log errors but don't fail the webhook response
  • Validation: Verify all critical fields before processing the payment