Subscriptions Webhook

View as Markdown

Overview

BlockBee sends webhooks to notify your application about subscription events. There are two types of webhook notifications:

  1. Payment Notification (action=renew) - Sent when a user makes a payment to extend or create a subscription
  2. Expiration Notification (action=expired) - Sent when a subscription reaches its end date

Payment Notification Webhook

Sent when a user makes a payment (initial subscription payment or renewal).

Webhook Fields

actionstringRequired

Action performed: renew if user made a payment, either the initial one or the extension.

Notes:

  • Important to check the subscription_end_date_ts as it will be updated with the current subscription end date.
Example:renew

subscription_idstringRequired

Unique token of the subscription.

Example:I55hhRINHptLJPwsqwYNxJOKBItRiq1o

subscription_urlstringRequired

Link to the subscription page.

Example:https://pay.blockbee.io/subscription/I55hhRINHptLJPwsqwYNxJOKBItRiq1o

subscription_start_date_tsintegerRequired

Timestamp when the subscription started.

Example:1718131200

subscription_end_date_tsintegerRequired

Timestamp when the subscription will expire.

Example:1720723200

subscription_option_slugstringRequired

Slug of the subscription option selected by the user.

Example:pro-plan

subscription_option_duration_tsnumberRequired

Duration of the subscription option selected by the user, in seconds.

Example:2592000

subscription_option_valuenumberRequired

Value of the subscription option in fiat you selected in the Payment Settings.

Example:5

subscription_user_idstringRequired

User identifier of your system provided in the here.

Example:user_123

subscription_user_emailstringRequired

Email address of the user, provided here.

payment_urlstringRequired

Payment link associated with this subscription renewal.

Example:https://pay.blockbee.io/subscription/payment/ls25hhRINHptLJPwsqwYNxJOKBItRiq1o

payment_redirect_urlstringRequired

URL where the user will be redirected after payment.

Example:https://example.com/payment-successful

payment_valuenumberRequired

Value expected to be paid in fiat.

Example:5

payment_success_tokenstringRequired

Success token used to validate the payment.

Example:sU7EGOlRRxsxJu4zZoYLa69UXrSijzb73eP6nbQQgpJYAfSL3NiI407lpYqsMbR2

payment_currencystringRequired

Currency code (e.g. usd, eur).

Example:usd

payment_is_paidintegerRequired

Whether the payment is completed (1) or not (0).

Example:1

payment_paid_amountnumberRequired

Amount paid in crypto.

Example:5

payment_paid_amount_fiatnumberRequired

Amount paid in fiat.

Example:4.85

payment_received_amountnumberRequired

Amount received after fee deductions in crypto.

Example:5

payment_received_amount_fiatnumberRequired

Amount received after fee deductions in fiat.

Example:4.85

payment_paid_coinstringRequired

Coin used for payment (e.g. btc, trc20_usdt, etc...).

Example:btc

payment_exchange_ratenumberRequired

Exchange rate at the time of payment.

Example:0.97

payment_txidstringRequired

Comma-separated transaction IDs of the payment.

Example:0xa1234...,0xa5678...

payment_addressstringRequired

Blockchain address that received the payment.

Example:0xabc123...

payment_typestringRequired

Always payment for subscription renewals.

Example:payment

payment_statusstringRequired

Payment status string.

Example:done

Example Payload

JSON
{
  "action": "renew",
  "subscription_id": "I55hhRINHptLJPwsqwYNxJOKBItRiq1o",
  "subscription_url": "https://pay.blockbee.io/subscription/I55hhRINHptLJPwsqwYNxJOKBItRiq1o",
  "subscription_start_date_ts": 1718131200,
  "subscription_end_date_ts": 1720723200,
  "subscription_option_slug": "pro-plan",
  "subscription_option_duration_ts": 2592000,
  "subscription_option_value": 5,
  "subscription_user_id": "user_123",
  "subscription_user_email": "[email protected]",
  "payment_url": "https://pay.blockbee.io/subscription/payment/ls25hhRINHptLJPwsqwYNxJOKBItRiq1o",
  "payment_redirect_url": "https://example.com/payment-successful",
  "payment_value": 5,
  "payment_success_token": "sU7EGOlRRxsxJu4zZoYLa69UXrSijzb73eP6nbQQgpJYAfSL3NiI407lpYqsMbR2",
  "payment_currency": "usd",
  "payment_is_paid": 1,
  "payment_paid_amount": 5,
  "payment_paid_amount_fiat": 4.85,
  "payment_received_amount": 5,
  "payment_received_amount_fiat": 4.85,
  "payment_paid_coin": "btc",
  "payment_exchange_rate": 0.97,
  "payment_txid": "0xa1234...,0xa5678...",
  "payment_address": "0xabc123...",
  "payment_type": "payment",
  "payment_status": "done"
}

Expiration Notification Webhook

Sent when a subscription has reached its end date and is no longer active.

Webhook Fields

actionstringRequired

Indicates that the subscription has reached its end date and is no longer active. No further payments will be processed for expired subscriptions.

Example:expired

subscription_idstringRequired

Unique token of the subscription.

Example:I55hhRINHptLJPwsqwYNxJOKBItRiq1o

subscription_urlstringRequired

Link to the subscription page.

Example:https://pay.blockbee.io/subscription/I55hhRINHptLJPwsqwYNxJOKBItRiq1o

subscription_start_date_tsintegerRequired

Timestamp when the subscription started.

Example:1718131200

subscription_end_date_tsintegerRequired

Timestamp when the subscription will expire.

Example:1720723200

subscription_option_slugstringRequired

Slug of the subscription option selected by the user.

Example:pro-plan

subscription_option_duration_tsnumberRequired

Duration of the subscription option selected by the user, in seconds.

Example:2592000

subscription_option_valuenumberRequired

Value of the subscription option in fiat you selected in the Payment Settings.

Example:5

subscription_user_idstringRequired

User identifier of your system provided in the here.

Example:user_123

subscription_user_emailstringRequired

Email address of the user, provided here.

Example Payload

JSON
{
  "action": "expired",
  "subscription_id": "I55hhRINHptLJPwsqwYNxJOKBItRiq1o",
  "subscription_url": "https://pay.blockbee.io/subscription/I55hhRINHptLJPwsqwYNxJOKBItRiq1o",
  "subscription_start_date_ts": 1718131200,
  "subscription_end_date_ts": 1720723200,
  "subscription_option_slug": "pro-plan",
  "subscription_option_duration_ts": 2592000,
  "subscription_option_value": 5,
  "subscription_user_id": "user_123",
  "subscription_user_email": "[email protected]"
}

Webhook Handling

Here are code examples for handling subscription webhooks in different programming languages:

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

  const { action, subscription_id, subscription_user_id, payment_status } = req.body;

  // Use subscription_id to prevent duplicate processing
  if (isWebhookAlreadyProcessed(subscription_id)) {
    return res.status(200).send('*ok*');
  }

  if (action === 'renew' && payment_status === 'done') {
    // Grant or extend access for the user
    // Update subscription end date in your database
    // Send confirmation email to user
    console.log(`Subscription renewed for user: ${subscription_user_id}`);
  } else if (action === 'expired') {
    // Revoke access for the user
    // Update subscription status in your database
    // Send expiration notification to user
    console.log(`Subscription expired for user: ${subscription_user_id}`);
  }

  // Mark this webhook as processed
  markWebhookAsProcessed(subscription_id);

  // Always respond with *ok*
  res.status(200).send('*ok*');
});

Best Practices

  • Verify Signatures: Always verify webhook signatures to ensure requests are from BlockBee
  • Idempotency: Use the subscription_id to prevent processing the same webhook multiple times
  • Respond Quickly: Always respond with *ok* and a 200 status code to prevent BlockBee from resending the webhook
  • Asynchronous Processing: For long-running tasks, process them in a background job after responding to the webhook
  • Error Handling: Log errors but don't let them prevent the webhook response
  • Database Updates: Update your database with the new subscription end date when processing renewal webhooks

Webhook Verification

Always verify that webhooks are coming from BlockBee by checking the signature. This prevents malicious requests from impersonating BlockBee.

For implementation details, see our Verify Webhook Signature guide.