Create Webhook

The Create Webhook endpoint enables you to register webhook endpoints for receiving real-time event notifications from your Devdraft application. Webhooks allow your application to receive automated notifications when specific events occur, enabling real-time integration and workflow automation.

Endpoint DetailsCopied!

  • URL: /api/v0/webhooks

  • Method: POST

  • Authentication: Required (API Key Authentication with Scopes)

  • Content-Type: application/json

  • Required Scope: webhook:create

AuthenticationCopied!

This endpoint requires API key authentication with specific scopes:

Required Headers

x-client-key: your-client-key
x-client-secret: your-client-secret

Required Scope

Your API key must have the webhook:create scope to access this endpoint.

Request BodyCopied!

Required Fields

Field

Type

Description

Validation

name

string

Webhook name for identification

3-100 characters

url

string

Endpoint URL where events will be sent

Valid URL format

Optional Fields

Field

Type

Description

Default

Validation

isActive

boolean

Whether webhook is active

true

Boolean

signing_secret

string

Secret for payload signature verification

Auto-generated

Min 32 chars, alphanumeric + _-

encrypted

boolean

Whether payloads should be encrypted

false

Boolean

Request Schema

{
  "name": "string",
  "url": "string",
  "isActive": "boolean",
  "signing_secret": "string",
  "encrypted": "boolean"
}

ResponseCopied!

Success Response (201 Created)

{
  "id": "wh_123456789",
  "name": "Payment Notifications",
  "url": "https://api.example.com/webhooks/payments",
  "isActive": true,
  "encrypted": false,
  "created_at": "2024-03-20T12:00:00.000Z",
  "updated_at": "2024-03-20T12:00:00.000Z",
  "delivery_stats": {
    "total_events": 0,
    "successful_deliveries": 0,
    "failed_deliveries": 0,
    "last_delivery": null
  }
}

Error Responses

400 Bad Request - Invalid Input
{
  "statusCode": 400,
  "message": "Invalid webhook URL format",
  "error": "Bad Request",
  "details": "URL must be a valid HTTPS endpoint"
}
400 Bad Request - Validation Errors
{
  "statusCode": 400,
  "message": [
    "Name must be at least 3 characters long",
    "URL must be a valid URL",
    "Signing secret must be at least 32 characters and contain only letters, numbers, underscores, and hyphens"
  ],
  "error": "Bad Request"
}
401 Unauthorized - Missing Credentials
{
  "statusCode": 401,
  "message": "Client key or secret missing",
  "error": "Unauthorized",
  "details": "Please provide both x-client-key and x-client-secret headers"
}
403 Forbidden - Missing Scope
{
  "statusCode": 403,
  "message": "Missing required scope",
  "error": "Forbidden",
  "details": "API key does not have the required webhook:create scope"
}

Field Validation RulesCopied!

Name Validation

  • Required: Yes

  • Type: String

  • Length: 3-100 characters

  • Description: Human-readable name for webhook identification

URL Validation

  • Required: Yes

  • Type: String (URL format)

  • Protocol: Must be a valid URL (HTTPS recommended for production)

  • Description: Endpoint where webhook events will be sent

Signing Secret Validation

  • Required: No (auto-generated if not provided)

  • Type: String

  • Pattern: ^[a-zA-Z0-9_\-]{32,}$

  • Length: Minimum 32 characters

  • Characters: Letters, numbers, underscores, and hyphens only

Active Status

  • Required: No

  • Type: Boolean

  • Default: true

  • Description: Whether webhook will receive events

Encryption

  • Required: No

  • Type: Boolean

  • Default: false

  • Description: Whether webhook payloads should be encrypted

Example RequestsCopied!

Basic Webhook Creation

curl -X POST https://api.devdraft.com/api/v0/webhooks \
  -H "Content-Type: application/json" \
  -H "x-client-key: your-client-key" \
  -H "x-client-secret: your-client-secret" \
  -d '{
    "name": "Payment Notifications",
    "url": "https://api.example.com/webhooks/payments"
  }'

Webhook with Custom Configuration

curl -X POST https://api.devdraft.com/api/v0/webhooks \
  -H "Content-Type: application/json" \
  -H "x-client-key: your-client-key" \
  -H "x-client-secret: your-client-secret" \
  -d '{
    "name": "Order Updates",
    "url": "https://api.example.com/webhooks/orders",
    "isActive": true,
    "signing_secret": "whsec_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
    "encrypted": true
  }'

Inactive Webhook for Testing

curl -X POST https://api.devdraft.com/api/v0/webhooks \
  -H "Content-Type: application/json" \
  -H "x-client-key: your-client-key" \
  -H "x-client-secret: your-client-secret" \
  -d '{
    "name": "Test Webhook",
    "url": "https://webhook.site/unique-url",
    "isActive": false
  }'

Use CasesCopied!

1. Payment Event Notifications

Receive real-time updates about payment status changes:

{
  "name": "Payment Status Updates",
  "url": "https://api.yourapp.com/webhooks/payments",
  "isActive": true
}

2. Invoice Lifecycle Tracking

Monitor invoice creation, updates, and payments:

{
  "name": "Invoice Lifecycle",
  "url": "https://api.yourapp.com/webhooks/invoices",
  "isActive": true,
  "encrypted": true
}

3. Customer Activity Monitoring

Track customer registration and profile updates:

{
  "name": "Customer Activity",
  "url": "https://api.yourapp.com/webhooks/customers",
  "isActive": true,
  "signing_secret": "whsec_secure_secret_key_here_32_chars_min"
}

4. Transaction Processing

Monitor transaction status and settlement events:

{
  "name": "Transaction Processing",
  "url": "https://api.yourapp.com/webhooks/transactions",
  "isActive": true,
  "encrypted": true
}

Response Fields ExplanationCopied!

Field

Type

Description

id

string

Unique webhook identifier (starts with wh_)

name

string

Webhook name as provided

url

string

Webhook endpoint URL

isActive

boolean

Current active status

encrypted

boolean

Whether payloads are encrypted

created_at

string

ISO 8601 timestamp of creation

updated_at

string

ISO 8601 timestamp of last update

delivery_stats

object

Webhook delivery statistics

Delivery Statistics Object

Field

Type

Description

total_events

number

Total number of events sent to this webhook

successful_deliveries

number

Number of successful deliveries (2xx response)

failed_deliveries

number

Number of failed deliveries (non-2xx response)

last_delivery

string | null

ISO 8601 timestamp of most recent delivery

Security FeaturesCopied!

Signature Verification

  • Each webhook payload includes a signature header

  • Use the signing_secret to verify payload authenticity

  • Prevents replay attacks and ensures data integrity

Encryption Support

  • Optional payload encryption for sensitive data

  • End-to-end encryption between Devdraft and your endpoint

  • Additional security layer for compliance requirements

Access Control

  • Scoped API key access prevents unauthorized webhook creation

  • Webhooks are isolated per application

  • Only authenticated applications can create webhooks

Integration ExamplesCopied!

Node.js/Express

const express = require('express');
const crypto = require('crypto');

async function createWebhook() {
  const webhookData = {
    name: 'Payment Notifications',
    url: 'https://api.example.com/webhooks/payments',
    isActive: true,
    signing_secret: 'whsec_' + crypto.randomBytes(32).toString('hex')
  };

  try {
    const response = await fetch('https://api.devdraft.com/api/v0/webhooks', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-client-key': process.env.DEVDRAFT_CLIENT_KEY,
        'x-client-secret': process.env.DEVDRAFT_CLIENT_SECRET
      },
      body: JSON.stringify(webhookData)
    });

    if (!response.ok) {
      throw new Error(`Webhook creation failed: ${response.statusText}`);
    }

    const webhook = await response.json();
    console.log('Webhook created:', webhook.id);
    
    return webhook;
  } catch (error) {
    console.error('Error creating webhook:', error);
    throw error;
  }
}

// Webhook endpoint to receive events
app.post('/webhooks/payments', express.raw({type: 'application/json'}), (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const payload = req.body;
  
  // Verify signature (implement signature verification)
  if (verifySignature(payload, signature)) {
    const event = JSON.parse(payload);
    console.log('Received webhook event:', event.type);
    
    // Process the event
    handlePaymentEvent(event);
    
    res.status(200).send('OK');
  } else {
    res.status(401).send('Invalid signature');
  }
});

Python

import requests
import hmac
import hashlib
import json
from flask import Flask, request

class WebhookManager:
    def __init__(self, client_key, client_secret, base_url):
        self.client_key = client_key
        self.client_secret = client_secret
        self.base_url = base_url
        
    def create_webhook(self, name, url, active=True, encrypted=False):
        headers = {
            'Content-Type': 'application/json',
            'x-client-key': self.client_key,
            'x-client-secret': self.client_secret
        }
        
        data = {
            'name': name,
            'url': url,
            'isActive': active,
            'encrypted': encrypted
        }
        
        response = requests.post(
            f"{self.base_url}/api/v0/webhooks",
            headers=headers,
            json=data
        )
        
        response.raise_for_status()
        return response.json()
    
    def verify_signature(self, payload, signature, secret):
        """Verify webhook signature"""
        expected_signature = hmac.new(
            secret.encode('utf-8'),
            payload,
            hashlib.sha256
        ).hexdigest()
        
        return hmac.compare_digest(signature, f"sha256={expected_signature}")

# Usage
webhook_manager = WebhookManager(
    client_key='your-client-key',
    client_secret='your-client-secret',
    base_url='https://api.devdraft.com'
)

# Create webhook
webhook = webhook_manager.create_webhook(
    name='Payment Events',
    url='https://api.example.com/webhooks/payments',
    active=True,
    encrypted=False
)

print(f"Created webhook: {webhook['id']}")

# Flask endpoint for receiving webhooks
app = Flask(__name__)

@app.route('/webhooks/payments', methods=['POST'])
def handle_payment_webhook():
    signature = request.headers.get('x-webhook-signature')
    payload = request.get_data()
    
    # Verify signature
    if webhook_manager.verify_signature(payload, signature, 'your-signing-secret'):
        event = request.get_json()
        print(f"Received event: {event['type']}")
        
        # Process the event
        process_payment_event(event)
        
        return 'OK', 200
    else:
        return 'Invalid signature', 401

React Component

import React, { useState } from 'react';

function WebhookCreator({ onWebhookCreated }) {
  const [formData, setFormData] = useState({
    name: '',
    url: '',
    isActive: true,
    encrypted: false
  });
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);

  const handleSubmit = async (e) => {
    e.preventDefault();
    setIsLoading(true);
    setError(null);

    try {
      const response = await fetch('/api/v0/webhooks', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'x-client-key': process.env.REACT_APP_CLIENT_KEY,
          'x-client-secret': process.env.REACT_APP_CLIENT_SECRET
        },
        body: JSON.stringify(formData)
      });

      if (!response.ok) {
        const errorData = await response.json();
        throw new Error(errorData.message || 'Failed to create webhook');
      }

      const webhook = await response.json();
      onWebhookCreated(webhook);
      
      // Reset form
      setFormData({
        name: '',
        url: '',
        isActive: true,
        encrypted: false
      });
    } catch (err) {
      setError(err.message);
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <form onSubmit={handleSubmit} className="webhook-creator">
      <div>
        <label>Webhook Name:</label>
        <input
          type="text"
          value={formData.name}
          onChange={(e) => setFormData({...formData, name: e.target.value})}
          required
          minLength={3}
          maxLength={100}
          disabled={isLoading}
        />
      </div>

      <div>
        <label>Webhook URL:</label>
        <input
          type="url"
          value={formData.url}
          onChange={(e) => setFormData({...formData, url: e.target.value})}
          required
          disabled={isLoading}
        />
      </div>

      <div>
        <label>
          <input
            type="checkbox"
            checked={formData.isActive}
            onChange={(e) => setFormData({...formData, isActive: e.target.checked})}
            disabled={isLoading}
          />
          Active
        </label>
      </div>

      <div>
        <label>
          <input
            type="checkbox"
            checked={formData.encrypted}
            onChange={(e) => setFormData({...formData, encrypted: e.target.checked})}
            disabled={isLoading}
          />
          Encrypted
        </label>
      </div>

      {error && <div className="error">{error}</div>}

      <button type="submit" disabled={isLoading}>
        {isLoading ? 'Creating...' : 'Create Webhook'}
      </button>
    </form>
  );
}

Best PracticesCopied!

1. URL Security

  • Use HTTPS endpoints in production

  • Implement proper SSL/TLS certificate validation

  • Consider using webhook-specific subdomains

2. Signature Verification

  • Always verify webhook signatures in production

  • Store signing secrets securely (environment variables)

  • Implement signature verification before processing events

3. Error Handling

  • Return appropriate HTTP status codes (200 for success)

  • Implement retry logic for failed deliveries

  • Log webhook events for debugging and monitoring

4. Performance

  • Process webhooks asynchronously when possible

  • Respond quickly to webhook requests (< 30 seconds)

  • Implement proper queuing for high-volume events

5. Security

  • Validate webhook payloads before processing

  • Implement rate limiting on webhook endpoints

  • Use encrypted webhooks for sensitive data

Rate LimitingCopied!

This endpoint is subject to the standard API rate limits:

  • Production: 1000 requests per hour per API key

  • Development: 100 requests per hour per API key

Webhook EventsCopied!

Common event types that webhooks receive include:

  • payment.completed

  • payment.failed

  • invoice.created

  • invoice.paid

  • customer.created

  • transfer.completed