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 |
---|---|---|---|
|
|
Webhook name for identification |
3-100 characters |
|
|
Endpoint URL where events will be sent |
Valid URL format |
Optional Fields
Field |
Type |
Description |
Default |
Validation |
---|---|---|---|---|
|
|
Whether webhook is active |
|
Boolean |
|
|
Secret for payload signature verification |
Auto-generated |
Min 32 chars, alphanumeric + |
|
|
Whether payloads should be encrypted |
|
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 |
---|---|---|
|
|
Unique webhook identifier (starts with |
|
|
Webhook name as provided |
|
|
Webhook endpoint URL |
|
|
Current active status |
|
|
Whether payloads are encrypted |
|
|
ISO 8601 timestamp of creation |
|
|
ISO 8601 timestamp of last update |
|
|
Webhook delivery statistics |
Delivery Statistics Object
Field |
Type |
Description |
---|---|---|
|
|
Total number of events sent to this webhook |
|
|
Number of successful deliveries (2xx response) |
|
|
Number of failed deliveries (non-2xx response) |
|
|
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