Webhooks enable your application to receive real-time notifications when events occur in your Devdraft account. Instead of continuously polling our API for updates, webhooks push event data to your application immediately when something happens, enabling efficient real-time integrations.

What are Webhooks?

Webhooks are HTTP callbacks that Devdraft sends to your application when specific events occur. When an event happens (like a payment completion or transfer update), Devdraft makes an HTTP POST request to a URL you specify, containing details about the event.

Key Benefits

Real-Time Updates

Receive instant notifications when events occur, enabling immediate response to critical changes

Efficient Integration

Eliminate the need for constant API polling, reducing server load and improving performance

Reliable Delivery

Built-in retry mechanisms and delivery confirmations ensure events reach your application

Secure Communication

Cryptographic signatures and optional encryption protect webhook payload integrity

How Webhooks Work

1

Event Occurs

An event happens in your Devdraft account (e.g., payment completed, transfer initiated)
2

Event Queued

Devdraft queues the event for delivery to all registered webhook endpoints
3

HTTP Request Sent

Devdraft sends an HTTP POST request to your webhook URL with event details
4

Your App Responds

Your application processes the event and returns an HTTP 200 status code
5

Delivery Confirmed

Devdraft marks the event as delivered and updates delivery statistics

Supported Event Types

Devdraft supports a comprehensive range of webhook events across different areas of functionality:

Payment Events

  • payment.created - New payment initiated
  • payment.pending - Payment is being processed
  • payment.completed - Payment successfully processed
  • payment.failed - Payment processing failed
  • payment.refunded - Payment has been refunded
  • payment.disputed - Payment dispute initiated

Transfer Events

  • transfer.initiated - Transfer process started
  • transfer.pending - Transfer being processed
  • transfer.completed - Transfer successfully completed
  • transfer.failed - Transfer processing failed
  • transfer.refunded - Failed transfer refunded
  • conversion.started - Conversion process initiated
  • conversion.completed - Conversion successfully completed
  • conversion.failed - Conversion failed
  • conversion.rate_expired - Exchange rate expired

Wallet Events

  • wallet.balance_updated - Wallet balance changed
  • wallet.deposit_received - New deposit detected
  • wallet.withdrawal_processed - Withdrawal completed
  • wallet.low_balance - Balance below threshold
  • wallet.created - New wallet created
  • wallet.activated - Wallet activated
  • wallet.suspended - Wallet suspended
  • wallet.archived - Wallet archived

Customer Events

  • customer.created - New customer registered
  • customer.updated - Customer profile updated
  • customer.verified - KYC verification completed
  • customer.suspended - Customer account suspended
  • kyc.submitted - KYC documents submitted
  • kyc.approved - KYC verification approved
  • kyc.rejected - KYC verification rejected
  • kyc.expired - KYC verification expired

Invoice Events

  • invoice.created - New invoice created
  • invoice.sent - Invoice sent to customer
  • invoice.paid - Invoice payment received
  • invoice.overdue - Invoice past due date
  • invoice.cancelled - Invoice cancelled
  • invoice.refunded - Invoice refunded

Webhook Configuration

Basic Setup

Create webhooks through the API or Devdraft console:
const webhook = await createWebhook({
  name: 'Payment Notifications',
  url: 'https://api.yourapp.com/webhooks/payments',
  isActive: true,
  encrypted: false
});

Advanced Configuration

  • Automatic retries: Failed deliveries are retried automatically
  • Exponential backoff: Increasing delays between retry attempts
  • Maximum attempts: Up to 5 retry attempts per event
  • Failure handling: Events marked as failed after all retries exhausted
  • Delivery rate: Up to 100 events per second per webhook
  • Burst handling: Short bursts of events handled efficiently
  • Queue management: Events queued during high-traffic periods
  • Priority delivery: Critical events prioritized in delivery queue
  • Event types: Subscribe to specific event categories
  • Conditional delivery: Filter based on event properties
  • Application scoping: Events filtered by application context
  • Custom filters: Advanced filtering based on business logic

Security Features

Signature Verification

Every webhook payload includes a cryptographic signature for verification:
const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
    
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(`sha256=${expectedSignature}`)
  );
}

// Usage in webhook handler
app.post('/webhooks', express.raw({type: 'application/json'}), (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const isValid = verifyWebhookSignature(req.body, signature, process.env.WEBHOOK_SECRET);
  
  if (!isValid) {
    return res.status(401).send('Invalid signature');
  }
  
  // Process the webhook event
  const event = JSON.parse(req.body);
  processWebhookEvent(event);
  res.status(200).send('OK');
});

Payload Encryption

For sensitive data, enable payload encryption:
const crypto = require('crypto');

function decryptWebhookPayload(encryptedPayload, key, iv) {
  const decipher = crypto.createDecipherGCM('aes-256-gcm', key);
  decipher.setIV(iv);
  
  let decrypted = decipher.update(encryptedPayload, 'base64', 'utf8');
  decrypted += decipher.final('utf8');
  
  return JSON.parse(decrypted);
}

// Usage with encrypted webhooks
app.post('/webhooks/encrypted', (req, res) => {
  const { encrypted_payload, iv, tag } = req.body;
  
  try {
    const decryptedData = decryptWebhookPayload(
      encrypted_payload, 
      process.env.ENCRYPTION_KEY, 
      iv
    );
    
    processWebhookEvent(decryptedData);
    res.status(200).send('OK');
  } catch (error) {
    console.error('Decryption failed:', error);
    res.status(400).send('Decryption failed');
  }
});

Webhook Payload Structure

All webhook events follow a consistent payload structure:
{
  "id": "evt_1234567890abcdef",
  "type": "payment.completed",
  "api_version": "2024-03-01",
  "created": "2024-03-20T15:30:00.000Z",
  "data": {
    "object": {
      "id": "pay_abcdef1234567890",
      "amount": 1000.00,
      "currency": "usdc",
      "status": "completed",
      "customer_id": "cus_1234567890",
      "created_at": "2024-03-20T15:25:00.000Z",
      "completed_at": "2024-03-20T15:30:00.000Z"
    }
  },
  "metadata": {
    "app_id": "app_your_application_id",
    "environment": "production",
    "retry_count": 0
  }
}

Payload Fields

FieldTypeDescription
idstringUnique identifier for the webhook event
typestringEvent type (e.g., “payment.completed”)
api_versionstringAPI version when event was generated
createdstringISO 8601 timestamp when event was created
dataobjectEvent-specific data containing the main object
metadataobjectAdditional context about the event

Implementation Best Practices

Endpoint Requirements

  • HTTPS only: Use HTTPS endpoints for security
  • Valid SSL certificate: Ensure proper SSL/TLS configuration
  • Fast response: Return HTTP 200 within 30 seconds
  • Idempotency: Handle duplicate events gracefully
  • Return appropriate status codes: 200 for success, 4xx/5xx for errors
  • Log webhook events: Maintain logs for debugging and auditing
  • Graceful degradation: Handle webhook failures without breaking your app
  • Retry logic: Implement your own retry logic for critical operations

Performance Optimization

1

Async Processing

Process webhook events asynchronously to respond quickly:
app.post('/webhooks', async (req, res) => {
  // Immediately acknowledge receipt
  res.status(200).send('OK');
  
  // Process asynchronously
  setImmediate(() => {
    processWebhookEvent(req.body);
  });
});
2

Queue Management

Use message queues for high-volume webhook processing:
const Queue = require('bull');
const webhookQueue = new Queue('webhook processing');

app.post('/webhooks', async (req, res) => {
  await webhookQueue.add('process-webhook', req.body);
  res.status(200).send('OK');
});
3

Database Optimization

Optimize database operations for webhook processing:
// Batch database operations
const processWebhookBatch = async (events) => {
  const updates = events.map(event => ({
    updateOne: {
      filter: { id: event.data.object.id },
      update: { $set: event.data.object },
      upsert: true
    }
  }));
  
  await db.collection('payments').bulkWrite(updates);
};

Testing and Debugging

Local Development

Use ngrok to expose local development servers:
# Install ngrok
npm install -g ngrok

# Expose local port
ngrok http 3000

# Use the HTTPS URL for webhook configuration
# https://abc123.ngrok.io/webhooks

Debugging Tools

  • Delivery logs: Track webhook delivery attempts and responses
  • Error logs: Detailed error information for failed deliveries
  • Performance metrics: Response times and success rates
  • Payload inspection: View full webhook payload for debugging
  • Event replay: Replay webhook events for testing
  • Payload validation: Validate webhook payloads against schemas
  • Signature testing: Test signature verification implementation
  • Load testing: Test webhook endpoint performance under load

Common Integration Patterns

Event-Driven Architecture

class WebhookEventProcessor {
  constructor() {
    this.handlers = new Map();
  }
  
  // Register event handlers
  on(eventType, handler) {
    if (!this.handlers.has(eventType)) {
      this.handlers.set(eventType, []);
    }
    this.handlers.get(eventType).push(handler);
  }
  
  // Process incoming webhook events
  async process(webhookEvent) {
    const { type, data } = webhookEvent;
    const handlers = this.handlers.get(type) || [];
    
    // Execute all handlers for this event type
    await Promise.all(
      handlers.map(handler => handler(data, webhookEvent))
    );
  }
}

// Usage
const processor = new WebhookEventProcessor();

processor.on('payment.completed', async (data) => {
  await updateOrderStatus(data.object.id, 'paid');
  await sendPaymentConfirmation(data.object.customer_id);
});

processor.on('transfer.completed', async (data) => {
  await updateTransferStatus(data.object.id);
  await notifyRecipient(data.object.recipient_id);
});

// In webhook endpoint
app.post('/webhooks', async (req, res) => {
  try {
    await processor.process(req.body);
    res.status(200).send('OK');
  } catch (error) {
    console.error('Webhook processing failed:', error);
    res.status(500).send('Internal Server Error');
  }
});

State Machine Updates

class PaymentStateMachine {
  constructor() {
    this.states = {
      'created': ['pending', 'failed'],
      'pending': ['completed', 'failed'],
      'completed': ['refunded'],
      'failed': ['pending'],
      'refunded': []
    };
  }
  
  async updateState(paymentId, newState, webhookData) {
    const payment = await this.getPayment(paymentId);
    const validTransitions = this.states[payment.state] || [];
    
    if (!validTransitions.includes(newState)) {
      throw new Error(`Invalid state transition from ${payment.state} to ${newState}`);
    }
    
    await this.updatePayment(paymentId, {
      state: newState,
      updated_at: webhookData.created,
      webhook_event_id: webhookData.id
    });
    
    // Trigger side effects based on state change
    await this.handleStateChange(payment, newState, webhookData);
  }
}

// Webhook handler using state machine
processor.on('payment.*', async (data, webhookEvent) => {
  const stateMachine = new PaymentStateMachine();
  const eventType = webhookEvent.type.split('.')[1]; // Extract state from event type
  
  await stateMachine.updateState(
    data.object.id, 
    eventType, 
    webhookEvent
  );
});

Getting Started

Ready to implement webhooks in your application? Follow these steps:
1

Set Up Endpoint

Create a webhook endpoint in your application that can receive HTTP POST requests
2

Create Webhook

Use the Create Webhook API to register your endpoint
3

Implement Verification

Add signature verification to ensure webhook authenticity
4

Handle Events

Process webhook events and update your application state accordingly
5

Monitor Performance

Use the Fetch Webhook API to monitor delivery statistics

API Reference

Explore the webhook management endpoints:

Next Steps