Webhooks
Real-time event notifications for your applications
Webhooks allow your application to receive real-time notifications when events occur in VPN Enterprise. Secure, reliable, and with automatic retry logic for failed deliveries.
Event Types
User, VPN, Database, Billing eventsSecurity
HMAC signature verificationReliability
Automatic retries and monitoringQuick Setup
Set up an HTTPS endpoint to receive webhook events from VPN Enterprise.
POST /webhooksImplement HMAC-SHA256 signature verification for security.
X-VPN-SignatureProcess webhook events and return 2xx status codes for successful handling.
200 OKAvailable Event Types
user.createdEventNew user registered or invited
user.updatedEventUser profile or permissions updated
user.deletedEventUser removed from organization
user.loginEventUser successfully authenticated
vpn.connectedEventVPN connection established
vpn.disconnectedEventVPN connection terminated
vpn.server.createdEventNew VPN server provisioned
vpn.server.deletedEventVPN server decommissioned
database.createdEventDatabase instance created
database.updatedEventDatabase configuration changed
database.deletedEventDatabase instance deleted
database.backup.completedEventDatabase backup finished
billing.invoice.createdEventNew invoice generated
billing.invoice.paidEventInvoice payment successful
billing.invoice.failedEventInvoice payment failed
billing.subscription.updatedEventSubscription plan changed
Security Implementation
Node.js Example
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');
const providedSignature = signature.replace('sha256=', '');
return crypto.timingSafeEqual(
Buffer.from(expectedSignature, 'hex'),
Buffer.from(providedSignature, 'hex')
);
}
// Express.js middleware
app.use('/webhooks', express.raw({type: 'application/json'}));
app.post('/webhooks/vpn-enterprise', (req, res) => {
const signature = req.get('X-VPN-Signature');
const payload = req.body;
if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Unauthorized');
}
const event = JSON.parse(payload);
console.log('Received event:', event.type);
res.status(200).send('OK');
});Python Example
import hmac
import hashlib
from flask import Flask, request, abort
app = Flask(__name__)
def verify_webhook_signature(payload, signature, secret):
expected_signature = hmac.new(
secret.encode('utf-8'),
payload,
hashlib.sha256
).hexdigest()
provided_signature = signature.replace('sha256=', '')
return hmac.compare_digest(expected_signature, provided_signature)
@app.route('/webhooks/vpn-enterprise', methods=['POST'])
def handle_webhook():
signature = request.headers.get('X-VPN-Signature')
payload = request.get_data()
if not verify_webhook_signature(payload, signature, 'your-webhook-secret'):
abort(401)
event = request.get_json()
print(f"Received event: {event['type']}")
return 'OK', 200API Endpoints
/webhooksResponse
{
"success": true,
"webhooks": [
{
"id": "wh_123",
"url": "https://api.myapp.com/webhooks/vpn-enterprise",
"events": ["user.created", "vpn.connected", "billing.invoice.paid"],
"status": "active",
"secret": "whsec_***masked***",
"created_at": "2024-01-15T10:30:00Z",
"last_delivery": "2024-12-02T14:20:00Z",
"delivery_stats": {
"successful": 1249,
"failed": 3,
"last_30_days": 87
}
}
],
"total": 2
}/webhooksRequest Body
{
"url": "https://api.myapp.com/webhooks/vpn-enterprise",
"events": ["user.created", "vpn.connected", "billing.invoice.paid"],
"description": "Production webhook for user and billing events",
"active": true
}/webhooks/:idResponse
{
"success": true,
"webhook": {
"id": "wh_123",
"url": "https://api.myapp.com/webhooks/vpn-enterprise",
"events": ["user.created", "vpn.connected", "billing.invoice.paid"],
"status": "active",
"secret": "whsec_***masked***",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-11-15T09:20:00Z",
"description": "Production webhook for user and billing events",
"delivery_stats": {
"total_deliveries": 1252,
"successful_deliveries": 1249,
"failed_deliveries": 3,
"last_successful_delivery": "2024-12-02T14:20:00Z",
"last_failed_delivery": "2024-11-28T11:15:00Z",
"average_response_time_ms": 145
}
}
}/webhooks/:idRequest Body
{
"url": "https://api.myapp.com/webhooks/vpn-enterprise-v2",
"events": ["user.created", "user.deleted", "vpn.connected", "vpn.disconnected", "billing.invoice.paid"],
"description": "Updated webhook with additional events",
"active": true
}/webhooks/:idResponse
{
"success": true,
"message": "Webhook deleted successfully",
"webhook_id": "wh_123"
}/webhooks/:id/deliveriesResponse
{
"success": true,
"deliveries": [
{
"id": "del_789",
"webhook_id": "wh_123",
"event_type": "user.created",
"delivered_at": "2024-12-02T14:20:00Z",
"status": "success",
"response_status": 200,
"response_time_ms": 142,
"attempts": 1,
"event_data": {
"user_id": "usr_456",
"email": "newuser@example.com",
"created_at": "2024-12-02T14:19:45Z"
}
}
],
"total": 1252,
"has_more": true
}/webhooks/:id/testRequest Body
{
"event_type": "webhook.test",
"custom_data": {
"test": true,
"timestamp": "2024-12-02T15:30:00Z"
}
}Webhook Best Practices
Idempotent Processing
Design your webhook handlers to be idempotent. The same event may be delivered multiple times due to retries.
Fast Response Times
Respond within 10 seconds and return 2xx status codes. For heavy processing, acknowledge receipt first and process asynchronously.
Error Handling & Monitoring
Implement proper error handling and monitoring. Failed deliveries will be retried with exponential backoff for up to 3 days.