Complete reference for all ZBD Onramp API endpoints and webhook events.

Base URL

All API requests should be made to:

https://api.zebedee.io

Authentication

All requests require an API key in the header:

apikey: YOUR_API_KEY

Get your API keys by scheduling a call with our sales team.

Create Widget Session

Initialize a new onramp widget session for a user.

POST /api/v1/ramp-widget

curl -X POST https://api.zebedee.io/api/v1/ramp-widget \
  -H "Content-Type: application/json" \
  -H "apikey: YOUR_API_KEY" \
  -d '{
    "email": "user@example.com",
    "webhook_url": "https://yourapp.com/webhooks/zbd"
  }'

Request Body

ParameterTypeRequiredDescription
emailstringYesUser’s email address for verification
webhook_urlstringYesURL to receive webhook notifications
access_tokenstringNoExisting user session token (for returning users)
quote_currencystringNoFiat currency code (default: “USD”)
base_currencystringNoCryptocurrency: “BTC” or “USDC” (default: “BTC”)
destinationstringNoURL to redirect after successful purchase
reference_idstringNoYour internal reference ID for this session
metadataobjectNoCustom key-value pairs (max 10 keys, 500 chars per value)

Response

{
  "success": true,
  "data": {
    "session_token": "eyJraWQiOiJzLWE1OWNkMjc4...",
    "widget_url": "https://ramp.zbdpay.com/?session=eyJraWQiOiJzLWE1OWNkMjc4...",
    "session_id": "ses_9n3f7h2u4b",
    "expires_at": "2025-06-09T12:00:00Z"
  }
}

Error Responses

{
  "success": false,
  "error": {
    "code": "INVALID_EMAIL",
    "message": "Please provide a valid email address"
  }
}

Common error codes:

  • INVALID_EMAIL - Email format is invalid
  • INVALID_WEBHOOK_URL - Webhook URL is not accessible
  • UNAUTHORIZED - Invalid API key
  • RATE_LIMITED - Too many requests

Webhook Events

Webhooks are sent as POST requests to your specified webhook_url.

Event Structure

All webhook events follow this structure:

{
  "id": "evt_2n4f8gu3nf",
  "type": "onramp.purchase.completed",
  "created_at": "2025-06-09T10:30:00Z",
  "livemode": true,
  "data": {
    // Event-specific data
  }
}

Event Types

onramp.session.created

Fired when a widget session is initialized.

{
  "type": "onramp.session.created",
  "data": {
    "session_id": "ses_9n3f7h2u4b",
    "reference_id": "your_reference_123",
    "email": "user@example.com",
    "metadata": {
      "custom_field": "value"
    }
  }
}

onramp.email.verified

Fired when user completes email verification.

{
  "type": "onramp.email.verified",
  "data": {
    "session_id": "ses_9n3f7h2u4b",
    "user_id": "usr_8h3d6f9k2m",
    "email": "user@example.com",
    "is_new_user": true
  }
}

onramp.kyc.completed

Fired when KYC verification is successfully completed (first-time users only).

{
  "type": "onramp.kyc.completed",
  "data": {
    "session_id": "ses_9n3f7h2u4b",
    "user_id": "usr_8h3d6f9k2m",
    "kyc_level": "full",
    "verified_at": "2025-06-09T10:25:00Z"
  }
}

onramp.purchase.completed

Fired when a purchase is successfully completed and crypto is delivered.

{
  "type": "onramp.purchase.completed",
  "data": {
    "session_id": "ses_9n3f7h2u4b",
    "reference_id": "your_reference_123",
    "user_id": "usr_8h3d6f9k2m",
    "email": "user@example.com",
    "transaction": {
      "id": "txn_7g2d5c8j1n",
      "amount": 50.00,
      "currency": "USD",
      "crypto_amount": 0.00052,
      "crypto_currency": "BTC",
      "exchange_rate": 96153.85,
      "fees": {
        "platform_fee": 2.50,
        "network_fee": 0.50,
        "total": 3.00
      },
      "delivery": {
        "method": "lightning",
        "address": "user@zbd.gg",
        "transaction_id": "lntx_8j3k5m7p9q",
        "delivered_at": "2025-06-09T10:29:55Z"
      },
      "payment_method": "ach_debit",
      "status": "completed",
      "created_at": "2025-06-09T10:28:00Z",
      "completed_at": "2025-06-09T10:29:55Z"
    },
    "metadata": {
      "custom_field": "value"
    }
  }
}

onramp.purchase.failed

Fired when a purchase fails at any stage.

{
  "type": "onramp.purchase.failed",
  "data": {
    "session_id": "ses_9n3f7h2u4b",
    "reference_id": "your_reference_123",
    "user_id": "usr_8h3d6f9k2m",
    "reason": "payment_declined",
    "error_message": "Insufficient funds in bank account",
    "failed_at": "2025-06-09T10:29:00Z",
    "metadata": {
      "custom_field": "value"
    }
  }
}

Webhook Security

All webhooks include a signature header for verification:

X-ZBD-Signature: sha256=7d38cdd689735b008b3c702edd92eea23791c5f6

Verify webhooks using HMAC-SHA256:

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  
  const provided = signature.replace('sha256=', '');
  
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(provided)
  );
}

Webhook Retry Policy

Failed webhook deliveries are retried with exponential backoff:

  • Attempt 1: Immediate
  • Attempt 2: 5 seconds
  • Attempt 3: 30 seconds
  • Attempt 4: 2 minutes
  • Attempt 5: 10 minutes
  • Attempt 6: 1 hour

Webhooks are considered failed if:

  • Response status is not 2xx
  • No response within 5 seconds
  • Connection error

Error Codes

HTTP Status Codes

CodeDescription
200Success
400Bad Request - Invalid parameters
401Unauthorized - Invalid API key
403Forbidden - Access denied
404Not Found - Resource doesn’t exist
429Too Many Requests - Rate limited
500Internal Server Error

Application Error Codes

CodeDescriptionResolution
INVALID_EMAILEmail format is invalidProvide valid email address
INVALID_CURRENCYCurrency code not supportedUse USD for fiat, BTC/USDC for crypto
SESSION_EXPIREDWidget session has expiredCreate a new session
USER_BLOCKEDUser failed fraud checksContact support
KYC_REQUIREDUser needs to complete KYCUser will be guided through KYC flow
PURCHASE_LIMIT_EXCEEDEDAmount exceeds limitsReduce purchase amount
PAYMENT_METHOD_UNAVAILABLESelected payment method not availableTry different payment method

Rate Limits

API endpoints are rate limited to ensure platform stability:

EndpointLimitWindow
/api/v1/ramp-widget100 requests1 minute
All endpoints (per API key)1000 requests1 hour

Rate limit headers are included in responses:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1623456789

Testing

Sandbox environment is coming soon. Currently, all integrations use production mode. Test with small amounts during development.

Support


This API is in active development. Subscribe to our changelog for updates.