Skip to main content

Overview

Webhooks allow you to receive real-time notifications about events that occur during the ZBD Ramp lifecycle. From session initialization to payment completion, webhooks provide crucial updates about your users’ transactions. ZBD Ramp sends webhook events to your specified endpoint as HTTP POST requests. Each event contains detailed information about what occurred, allowing you to update your systems accordingly.

Webhook URL Setup

Configure your webhook URL when creating a session:
import { initRampSession, QuoteCurrencyEnum, BaseCurrencyEnum } from '@zbdpay/ramp-ts';

const response = await initRampSession({
  apikey: process.env.ZBD_API_KEY,
  email: 'user@example.com',
  destination: 'lightning-address@zbd.gg',
  quote_currency: QuoteCurrencyEnum.USD,
  base_currency: BaseCurrencyEnum.BTC,
  webhook_url: 'https://app.xyz/webhooks/zbd',  // <---- YOUR WEBHOOK URL HERE
  reference_id: 'order-123',
  metadata: {
    userId: 'user-456',
    plan: 'premium'
  }
});

const sessionToken = response.data.session_token;

Event Categories

Webhook events are organized into six main categories:

Session

Widget lifecycle events

Authentication

User verification events

KYC

Identity verification events

Bank

Bank connection events

Payment

Transaction events

Withdrawal

Crypto delivery events

Event Structure

All webhook events follow a consistent structure:
{
  "event": "RAMP_WIDGET.V1.EVENT_NAME",
  "data": {
    "email": "user@example.com",
    "session_id": "sess_abc123xyz789",
    // Event-specific data
    "metadata": {
      // Your custom metadata
    }
  },
  "url": "https://partner.com/webhooks",
  "created_at": "2025-01-18T10:30:00Z"
}

Complete Event Reference

Session Events

Event: RAMP_WIDGET.V1.SESSION.INITIATEDTriggered when a Ramp session is successfully initiated.
{
  "event": "RAMP_WIDGET.V1.SESSION.INITIATED",
  "data": {
    "email": "user@example.com",
    "session_id": "sess_abc123xyz789"
  },
  "url": "https://partner.com/webhooks",
  "created_at": "2025-01-18T10:30:00Z"
}
Event: RAMP_WIDGET.V1.SESSION.CLOSEDFired when a Ramp session is closed, either by unmount, user action, or completion.
{
  "event": "RAMP_WIDGET.V1.SESSION.CLOSED",
  "data": {
    "email": "user@example.com",
    "session_id": "sess_abc123xyz789"
  },
  "url": "https://partner.com/webhooks",
  "created_at": "2025-01-18T11:15:00Z"
}

Authentication Events

Event: RAMP_WIDGET.V1.CODE_VERIFICATION.SUCCEEDEDSent when a user successfully verifies their 6-digit code.
{
  "event": "RAMP_WIDGET.V1.CODE_VERIFICATION.SUCCEEDED",
  "data": {
    "email": "user@example.com",
    "session_id": "sess_abc123xyz789"
  },
  "url": "https://partner.com/webhooks",
  "created_at": "2025-01-18T10:32:00Z"
}
Event: RAMP_WIDGET.V1.CODE_VERIFICATION.FAILEDTriggered when a 6-digit code verification attempt fails.
{
  "event": "RAMP_WIDGET.V1.CODE_VERIFICATION.FAILED",
  "data": {
    "email": "user@example.com",
    "session_id": "sess_abc123xyz789"
  },
  "url": "https://partner.com/webhooks",
  "created_at": "2025-01-18T10:33:00Z"
}
Event: RAMP_WIDGET.V1.USER_ACCESS_TOKEN.CREATEDFired when user access and refresh tokens are generated.
{
  "event": "RAMP_WIDGET.V1.USER_ACCESS_TOKEN.CREATED",
  "data": {
    "email": "user@example.com",
    "session_id": "sess_abc123xyz789",
    "access_token_id": "tok_abc123",
    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "access_token_expires_at": "2025-01-18T11:45:00Z",
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refresh_token_expires_at": "2025-02-18T10:45:00Z",
    "metadata": {
      "customer_id": "cust_123",
      "source": "widget"
    }
  },
  "url": "https://partner.com/webhooks",
  "created_at": "2025-01-18T10:45:00Z"
}

KYC Events

Event: RAMP_WIDGET.V1.KYC.INITIATEDFired when KYC (Know Your Customer) verification process is initiated.
{
  "event": "RAMP_WIDGET.V1.KYC.INITIATED",
  "data": {
    "email": "user@example.com",
    "session_id": "sess_abc123xyz789",
    "metadata": {
      "customer_id": "cust_123",
      "source": "widget"
    }
  },
  "url": "https://partner.com/webhooks",
  "created_at": "2025-01-18T10:35:00Z"
}
Event: RAMP_WIDGET.V1.KYC.PROCESSINGIndicates that KYC verification is being processed.
{
  "event": "RAMP_WIDGET.V1.KYC.PROCESSING",
  "data": {
    "email": "user@example.com",
    "session_id": "sess_abc123xyz789",
    "metadata": {
      "customer_id": "cust_123",
      "source": "widget"
    }
  },
  "url": "https://partner.com/webhooks",
  "created_at": "2025-01-18T10:36:00Z"
}
Event: RAMP_WIDGET.V1.KYC.COMPLETEDSent when KYC verification is successfully completed.
{
  "event": "RAMP_WIDGET.V1.KYC.COMPLETED",
  "data": {
    "email": "user@example.com",
    "session_id": "sess_abc123xyz789",
    "metadata": {
      "customer_id": "cust_123",
      "source": "widget"
    }
  },
  "url": "https://partner.com/webhooks",
  "created_at": "2025-01-18T10:40:00Z"
}
Event: RAMP_WIDGET.V1.KYC.REJECTEDTriggered when KYC verification is rejected or fails.
{
  "event": "RAMP_WIDGET.V1.KYC.REJECTED",
  "data": {
    "email": "user@example.com",
    "session_id": "sess_abc123xyz789",
    "metadata": {
      "customer_id": "cust_123",
      "source": "widget"
    }
  },
  "url": "https://partner.com/webhooks",
  "created_at": "2025-01-18T10:41:00Z"
}

Bank Connection Events

Event: RAMP_WIDGET.V1.BANK_CONNECTION.INITIATEDTriggered when bank connection flow is initiated.
{
  "event": "RAMP_WIDGET.V1.BANK_CONNECTION.INITIATED",
  "data": {
    "email": "user@example.com",
    "session_id": "sess_abc123xyz789",
    "metadata": {
      "customer_id": "cust_123",
      "source": "widget"
    }
  },
  "url": "https://partner.com/webhooks",
  "created_at": "2025-01-18T10:50:00Z"
}
Event: RAMP_WIDGET.V1.BANK_CONNECTION.COMPLETEDSent when bank connection is successfully established.
{
  "event": "RAMP_WIDGET.V1.BANK_CONNECTION.COMPLETED",
  "data": {
    "email": "user@example.com",
    "session_id": "sess_abc123xyz789",
    "metadata": {
      "customer_id": "cust_123",
      "source": "widget"
    }
  },
  "url": "https://partner.com/webhooks",
  "created_at": "2025-01-18T10:55:00Z"
}
Event: RAMP_WIDGET.V1.BANK_CONNECTION.FAILEDFired when bank connection attempt fails.
{
  "event": "RAMP_WIDGET.V1.BANK_CONNECTION.FAILED",
  "data": {
    "email": "user@example.com",
    "session_id": "sess_abc123xyz789",
    "metadata": {
      "customer_id": "cust_123",
      "source": "widget"
    }
  },
  "url": "https://partner.com/webhooks",
  "created_at": "2025-01-18T10:56:00Z"
}

Payment Events

Event: RAMP_WIDGET.V1.PAYMENT.INITIATEDTriggered when a payment transaction is initiated.
{
  "event": "RAMP_WIDGET.V1.PAYMENT.INITIATED",
  "data": {
    "email": "user@example.com",
    "session_id": "sess_abc123xyz789",
    "base_amount": "100.00",
    "base_currency": "USD",
    "quote_amount": "0.0025",
    "quote_currency": "BTC",
    "metadata": {
      "customer_id": "cust_123",
      "source": "widget"
    }
  },
  "url": "https://partner.com/webhooks",
  "created_at": "2025-01-18T11:00:00Z"
}
Event: RAMP_WIDGET.V1.PAYMENT.SETTLEDSent when a payment transaction is successfully settled.
{
  "event": "RAMP_WIDGET.V1.PAYMENT.SETTLED",
  "data": {
    "email": "user@example.com",
    "session_id": "sess_abc123xyz789",
    "base_amount": "100.00",
    "base_currency": "USD",
    "quote_amount": "0.0025",
    "quote_currency": "BTC",
    "metadata": {
      "customer_id": "cust_123",
      "source": "widget"
    }
  },
  "url": "https://partner.com/webhooks",
  "created_at": "2025-01-18T11:05:00Z"
}
Event: RAMP_WIDGET.V1.PAYMENT.FAILEDFired when a payment transaction fails.
{
  "event": "RAMP_WIDGET.V1.PAYMENT.FAILED",
  "data": {
    "email": "user@example.com",
    "session_id": "sess_abc123xyz789",
    "base_amount": "100.00",
    "base_currency": "USD",
    "quote_amount": "0.0025",
    "quote_currency": "BTC",
    "metadata": {
      "customer_id": "cust_123",
      "source": "widget"
    }
  },
  "url": "https://partner.com/webhooks",
  "created_at": "2025-01-18T11:06:00Z"
}

Withdrawal Events

Event: RAMP_WIDGET.V1.WITHDRAWAL.SUCCEEDEDTriggered when a withdrawal is successfully completed.
{
  "event": "RAMP_WIDGET.V1.WITHDRAWAL.SUCCEEDED",
  "data": {
    "email": "user@example.com",
    "session_id": "sess_abc123xyz789",
    "base_amount": "100.00",
    "base_currency": "USD",
    "quote_amount": "0.0025",
    "quote_currency": "BTC",
    "destination": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
    "metadata": {
      "customer_id": "cust_123",
      "source": "widget"
    }
  },
  "url": "https://partner.com/webhooks",
  "created_at": "2025-01-18T11:10:00Z"
}
Event: RAMP_WIDGET.V1.WITHDRAWAL.FAILEDSent when a withdrawal attempt fails.
{
  "event": "RAMP_WIDGET.V1.WITHDRAWAL.FAILED",
  "data": {
    "email": "user@example.com",
    "session_id": "sess_abc123xyz789",
    "base_amount": "100.00",
    "base_currency": "USD",
    "quote_amount": "0.0025",
    "quote_currency": "BTC",
    "destination": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
    "metadata": {
      "customer_id": "cust_123",
      "source": "widget"
    }
  },
  "url": "https://partner.com/webhooks",
  "created_at": "2025-01-18T11:11:00Z"
}

Webhook Implementation

Basic Handler Examples

Here are webhook handler implementations in popular frameworks:
// app/api/webhooks/zbd/route.ts
import { NextRequest, NextResponse } from 'next/server';

export async function POST(request: NextRequest) {
  const event = await request.json();

  // Log the event
  console.log(`Received webhook: ${event.event}`);

  // Handle different event types
  switch(event.event) {
    case 'RAMP_WIDGET.V1.PAYMENT.SETTLED':
      // Update user balance, send confirmation, etc.
      await handlePaymentSettled(event.data);
      break;

    case 'RAMP_WIDGET.V1.KYC.COMPLETED':
      // Update user verification status
      await handleKYCCompleted(event.data);
      break;

    case 'RAMP_WIDGET.V1.WITHDRAWAL.SUCCEEDED':
      // Log successful withdrawal
      await handleWithdrawalSuccess(event.data);
      break;

    default:
      console.log(`Unhandled event type: ${event.event}`);
  }

  // Always respond with 200 OK
  return NextResponse.json({ received: true }, { status: 200 });
}

async function handlePaymentSettled(data: any) {
  // Your payment processing logic
  console.log('Payment settled:', data);
}

async function handleKYCCompleted(data: any) {
  // Your KYC completion logic
  console.log('KYC completed:', data);
}

async function handleWithdrawalSuccess(data: any) {
  // Your withdrawal success logic
  console.log('Withdrawal succeeded:', data);
}

Security Best Practices

Important: Always validate webhook authenticity before processing events.

Webhook Verification

  1. Use HTTPS Only - Always use HTTPS endpoints for webhooks
  2. Verify Signatures - Validate webhook signatures when provided
  3. IP Allowlisting - Restrict webhook access to ZBD IP addresses
  4. Idempotency - Handle duplicate events gracefully
  5. Timeout Handling - Respond quickly (within 5 seconds)

Error Handling

  • Always respond with 200 OK status, even if processing fails
  • Log all webhook events for debugging
  • Implement retry logic for critical operations
  • Use message queues for asynchronous processing

Testing Webhooks

Local Development

Use tools like ngrok to expose your local webhook endpoint:
ngrok http 3000
Then use the ngrok URL as your webhook endpoint during development.

Webhook Testing Checklist

  • Required Events
  • Optional Events
Essential events to handle:
  • ✅ PAYMENT.SETTLED
  • ✅ WITHDRAWAL.SUCCEEDED
  • ✅ PAYMENT.FAILED
  • ✅ WITHDRAWAL.FAILED

Troubleshooting

Common Issues

  • Verify your webhook URL is publicly accessible
  • Check for firewall or security rules blocking requests
  • Ensure your endpoint responds with 200 status
  • Confirm webhook URL was correctly set during session creation
  • Implement idempotency using the session_id
  • Store processed event IDs to prevent reprocessing
  • Use database transactions for critical operations
  • Process webhooks asynchronously using queues
  • Respond immediately with 200 OK
  • Move heavy processing to background jobs

Next Steps

I