Webhooks Guide

Complete guide to UncleBTech webhooks including supported events, payload structures, and secure webhook processing.

Last updated: 21 January 2025
Tags:
webhookseventsautomationintegrationreal-time

Webhooks Guide

UncleBTech webhooks provide real-time notifications about important events in your account, allowing you to automate workflows and integrate with external systems. This guide covers webhook setup, event types, and secure processing.

Webhook Overview

What Are Webhooks?

Webhook Basics:

  • Real-Time Notifications: Immediate notification when events occur
  • HTTP POST Requests: Events sent as HTTP POST requests to your endpoint
  • JSON Payload: Event data sent in JSON format
  • Secure Delivery: Signed requests for verification and security
  • Retry Logic: Automatic retries for failed deliveries

Webhook vs Polling:

# Traditional polling (inefficient)
while (true) {
  check_for_new_invoices();
  sleep(60); // Check every minute
}

# Webhook approach (efficient)
webhook_endpoint('/invoices/created', function(event) {
  process_new_invoice(event.data);
});

Webhook Architecture

Event Flow:

UncleBTech System → Event Trigger → Webhook Queue → 
HTTP POST → Your Endpoint → Response Verification → 
Retry Logic (if needed)

Delivery Guarantees:

  • At-Least-Once Delivery: Events delivered at least once, possibly more
  • Retry Logic: Failed deliveries retried with exponential backoff
  • Timeout Handling: 30-second timeout for webhook responses
  • Dead Letter Queue: Failed events stored for manual review

Supported Webhook Events

Service Events

Service Lifecycle Events:

# Service created
service.created
{
  "id": "svc_wp_123456",
  "type": "wordpress_hosting",
  "plan": "advanced",
  "domain": "example.com",
  "status": "provisioning",
  "created_at": "2025-01-21T10:00:00Z"
}

# Service activated
service.activated
{
  "id": "svc_wp_123456",
  "status": "active",
  "server_ip": "192.168.1.100",
  "control_panel_url": "https://cp.unclebtech.com/...",
  "activated_at": "2025-01-21T10:30:00Z"
}

# Service suspended
service.suspended
{
  "id": "svc_wp_123456",
  "status": "suspended",
  "reason": "payment_overdue",
  "suspended_at": "2025-01-21T10:00:00Z",
  "grace_period_ends": "2025-01-31T23:59:59Z"
}

# Service cancelled
service.cancelled
{
  "id": "svc_wp_123456",
  "status": "cancelled",
  "reason": "customer_request",
  "cancelled_at": "2025-01-21T10:00:00Z",
  "data_retention_until": "2025-02-21T10:00:00Z"
}

Domain Events

Domain Lifecycle Events:

# Domain registered
domain.registered
{
  "domain": "newdomain.com",
  "registrar": "unclebtech",
  "expires_at": "2026-01-21T10:00:00Z",
  "nameservers": ["ns1.unclebtech.com", "ns2.unclebtech.com"],
  "registered_at": "2025-01-21T10:00:00Z"
}

# Domain transferred
domain.transferred
{
  "domain": "example.com",
  "transfer_status": "completed",
  "previous_registrar": "other-registrar",
  "transferred_at": "2025-01-21T10:00:00Z",
  "expires_at": "2026-01-21T10:00:00Z"
}

# Domain expiring soon
domain.expiring
{
  "domain": "example.com",
  "expires_at": "2025-02-21T10:00:00Z",
  "days_until_expiry": 30,
  "auto_renew_enabled": false,
  "renewal_price": "14.99"
}

# Domain expired
domain.expired
{
  "domain": "example.com",
  "expired_at": "2025-01-21T10:00:00Z",
  "grace_period_ends": "2025-02-21T10:00:00Z",
  "redemption_fee": "75.00"
}

Billing Events

Payment and Invoice Events:

# Invoice created
invoice.created
{
  "id": "inv_123456",
  "number": "UBT-2025-001234",
  "amount": "17.99",
  "currency": "GBP",
  "due_date": "2025-01-28T23:59:59Z",
  "services": ["svc_wp_123456"],
  "created_at": "2025-01-21T10:00:00Z"
}

# Payment succeeded
payment.succeeded
{
  "id": "pay_123456",
  "invoice_id": "inv_123456",
  "amount": "17.99",
  "currency": "GBP",
  "payment_method": {
    "type": "card",
    "last4": "4242"
  },
  "processed_at": "2025-01-21T10:30:00Z"
}

# Payment failed
payment.failed
{
  "id": "pay_123457",
  "invoice_id": "inv_123456",
  "amount": "17.99",
  "currency": "GBP",
  "failure_reason": "insufficient_funds",
  "retry_at": "2025-01-24T10:00:00Z",
  "failed_at": "2025-01-21T10:00:00Z"
}

# Subscription renewed
subscription.renewed
{
  "service_id": "svc_wp_123456",
  "previous_expires_at": "2025-01-21T10:00:00Z",
  "new_expires_at": "2025-02-21T10:00:00Z",
  "amount_charged": "14.99",
  "renewed_at": "2025-01-21T10:00:00Z"
}

Support Events

Support Ticket Events:

# Ticket created
ticket.created
{
  "id": "tkt_123456",
  "number": "UBT-2025-001234",
  "subject": "WordPress site loading slowly",
  "department": "technical",
  "priority": "normal",
  "customer": {
    "id": "acc_123456",
    "email": "customer@example.com"
  },
  "created_at": "2025-01-21T10:00:00Z"
}

# Ticket updated
ticket.updated
{
  "id": "tkt_123456",
  "status": "in_progress",
  "assigned_to": "Technical Support Team",
  "last_reply": {
    "from": "support",
    "message": "We're investigating the performance issue...",
    "created_at": "2025-01-21T11:00:00Z"
  },
  "updated_at": "2025-01-21T11:00:00Z"
}

# Ticket resolved
ticket.resolved
{
  "id": "tkt_123456",
  "status": "resolved",
  "resolution": "Performance issue resolved by enabling advanced caching",
  "resolved_by": "Technical Support Team",
  "resolved_at": "2025-01-21T12:00:00Z"
}

Webhook Configuration

Setting Up Webhooks

Create Webhook Endpoint:

POST /api/v1/webhooks
{
  "url": "https://your-app.com/webhooks/unclebtech",
  "events": [
    "service.created",
    "service.suspended",
    "payment.failed",
    "ticket.created"
  ],
  "secret": "your-webhook-secret-key",
  "active": true,
  "description": "Production webhook for service monitoring"
}

# Response
{
  "success": true,
  "data": {
    "id": "wh_123456",
    "url": "https://your-app.com/webhooks/unclebtech",
    "events": ["service.created", "service.suspended", "payment.failed", "ticket.created"],
    "secret": "wh_secret_abc123",
    "active": true,
    "created_at": "2025-01-21T10:00:00Z"
  }
}

List Configured Webhooks:

GET /api/v1/webhooks

# Response
{
  "success": true,
  "data": [
    {
      "id": "wh_123456",
      "url": "https://your-app.com/webhooks/unclebtech",
      "events": ["service.created", "payment.failed"],
      "active": true,
      "last_delivery": "2025-01-21T09:30:00Z",
      "delivery_success_rate": "99.5%"
    }
  ]
}

Update Webhook Configuration:

PUT /api/v1/webhooks/wh_123456
{
  "events": [
    "service.created",
    "service.suspended", 
    "service.cancelled",
    "payment.failed",
    "invoice.created"
  ],
  "active": true
}

Webhook Security

Signature Verification:

import hmac
import hashlib

def verify_webhook_signature(payload, signature, secret):
    """Verify webhook signature for security"""
    expected_signature = hmac.new(
        secret.encode('utf-8'),
        payload.encode('utf-8'),
        hashlib.sha256
    ).hexdigest()
    
    return hmac.compare_digest(signature, expected_signature)

# Usage in webhook handler
def handle_webhook(request):
    payload = request.body
    signature = request.headers.get('X-UncleBTech-Signature')
    
    if not verify_webhook_signature(payload, signature, webhook_secret):
        return HttpResponse(status=401)
    
    event = json.loads(payload)
    process_webhook_event(event)
    return HttpResponse(status=200)

Security Headers:

# Webhook request headers
X-UncleBTech-Signature: sha256=abc123...
X-UncleBTech-Event: payment.failed
X-UncleBTech-Delivery: wh_delivery_123456
User-Agent: UncleBTech-Webhooks/1.0

Webhook Event Processing

Event Handler Examples

Node.js/Express Webhook Handler:

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

app.use(express.raw({ type: 'application/json' }));

app.post('/webhooks/unclebtech', (req, res) => {
  const signature = req.headers['x-unclebtech-signature'];
  const payload = req.body;
  
  // Verify signature
  const expectedSignature = crypto
    .createHmac('sha256', process.env.WEBHOOK_SECRET)
    .update(payload)
    .digest('hex');
  
  if (signature !== `sha256=${expectedSignature}`) {
    return res.status(401).send('Invalid signature');
  }
  
  const event = JSON.parse(payload);
  
  // Process event
  switch (event.type) {
    case 'payment.failed':
      handlePaymentFailed(event.data);
      break;
    case 'service.suspended':
      handleServiceSuspended(event.data);
      break;
    case 'ticket.created':
      handleTicketCreated(event.data);
      break;
    default:
      console.log(`Unhandled event type: ${event.type}`);
  }
  
  res.status(200).send('OK');
});

function handlePaymentFailed(data) {
  // Send notification to customer
  // Update internal billing system
  // Trigger account review process
}

PHP Webhook Handler:

<?php
function handleUncleBTechWebhook() {
    $payload = file_get_contents('php://input');
    $signature = $_SERVER['HTTP_X_UNCLEBTECH_SIGNATURE'] ?? '';
    
    // Verify signature
    $expectedSignature = 'sha256=' . hash_hmac('sha256', $payload, $webhookSecret);
    if (!hash_equals($signature, $expectedSignature)) {
        http_response_code(401);
        exit('Invalid signature');
    }
    
    $event = json_decode($payload, true);
    
    switch ($event['type']) {
        case 'service.created':
            // Send welcome email
            // Update CRM system
            // Provision additional services
            break;
            
        case 'invoice.created':
            // Sync with accounting system
            // Send custom invoice notification
            // Update payment tracking
            break;
            
        case 'ticket.created':
            // Notify support team
            // Update helpdesk system
            // Trigger auto-responses
            break;
    }
    
    http_response_code(200);
    echo 'OK';
}

Event Processing Patterns

Idempotent Processing:

# Ensure idempotent webhook processing
def process_webhook_event(event):
    event_id = event['id']
    
    # Check if event already processed
    if EventLog.objects.filter(event_id=event_id).exists():
        return  # Already processed
    
    # Process the event
    try:
        handle_event(event)
        
        # Log successful processing
        EventLog.objects.create(
            event_id=event_id,
            event_type=event['type'],
            status='processed',
            processed_at=timezone.now()
        )
    except Exception as e:
        # Log failed processing
        EventLog.objects.create(
            event_id=event_id,
            event_type=event['type'],
            status='failed',
            error_message=str(e),
            processed_at=timezone.now()
        )
        raise

Webhook Event Details

Service Event Payloads

Complete Service Created Event:

{
  "id": "evt_123456",
  "type": "service.created",
  "created_at": "2025-01-21T10:00:00Z",
  "data": {
    "service": {
      "id": "svc_wp_123456",
      "type": "wordpress_hosting",
      "plan": "advanced",
      "domain": "example.com",
      "status": "provisioning",
      "server_ip": "192.168.1.100",
      "resource_limits": {
        "storage": "10 GB",
        "bandwidth": "100 GB",
        "php_memory": "512 MB"
      },
      "expires_at": "2025-02-21T10:00:00Z"
    },
    "customer": {
      "id": "acc_123456",
      "email": "customer@example.com",
      "name": "John Smith"
    }
  }
}

Service Suspended Event:

{
  "id": "evt_123457",
  "type": "service.suspended",
  "created_at": "2025-01-21T10:00:00Z",
  "data": {
    "service": {
      "id": "svc_wp_123456",
      "domain": "example.com",
      "status": "suspended",
      "suspension_reason": "payment_overdue",
      "suspended_at": "2025-01-21T10:00:00Z",
      "grace_period_ends": "2025-01-31T23:59:59Z"
    },
    "invoice": {
      "id": "inv_123456",
      "amount": "17.99",
      "due_date": "2025-01-14T23:59:59Z",
      "days_overdue": 7
    }
  }
}

Payment Event Payloads

Payment Failed Event:

{
  "id": "evt_123458",
  "type": "payment.failed",
  "created_at": "2025-01-21T10:00:00Z",
  "data": {
    "payment": {
      "id": "pay_123456",
      "invoice_id": "inv_123456",
      "amount": "17.99",
      "currency": "GBP",
      "failure_code": "card_declined",
      "failure_message": "Your card was declined",
      "payment_method": {
        "type": "card",
        "last4": "4242",
        "brand": "visa",
        "exp_month": 12,
        "exp_year": 2024
      }
    },
    "retry_schedule": {
      "next_retry": "2025-01-24T10:00:00Z",
      "max_retries": 3,
      "current_attempt": 1
    },
    "customer": {
      "id": "acc_123456",
      "email": "customer@example.com"
    }
  }
}

Payment Succeeded Event:

{
  "id": "evt_123459",
  "type": "payment.succeeded",
  "created_at": "2025-01-21T10:30:00Z",
  "data": {
    "payment": {
      "id": "pay_123457",
      "invoice_id": "inv_123456",
      "amount": "17.99",
      "currency": "GBP",
      "payment_method": {
        "type": "card",
        "last4": "4242",
        "brand": "visa"
      },
      "processed_at": "2025-01-21T10:30:00Z"
    },
    "services_affected": [
      {
        "id": "svc_wp_123456",
        "action": "renewed",
        "new_expiry": "2025-02-21T10:30:00Z"
      }
    ]
  }
}

Support Event Payloads

Ticket Created Event:

{
  "id": "evt_123460",
  "type": "ticket.created",
  "created_at": "2025-01-21T10:00:00Z",
  "data": {
    "ticket": {
      "id": "tkt_123456",
      "number": "UBT-2025-001234",
      "subject": "WordPress site loading slowly",
      "department": "technical",
      "priority": "normal",
      "status": "open",
      "service_id": "svc_wp_123456",
      "created_at": "2025-01-21T10:00:00Z"
    },
    "customer": {
      "id": "acc_123456",
      "email": "customer@example.com",
      "name": "John Smith"
    },
    "initial_message": {
      "message": "My WordPress site has been loading very slowly...",
      "attachments": ["screenshot.png"]
    }
  }
}

Webhook Endpoint Implementation

Basic Webhook Endpoint

Flask (Python) Example:

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

app = Flask(__name__)

@app.route('/webhooks/unclebtech', methods=['POST'])
def handle_webhook():
    # Get payload and signature
    payload = request.get_data()
    signature = request.headers.get('X-UncleBTech-Signature', '')
    
    # Verify signature
    if not verify_signature(payload, signature):
        return jsonify({'error': 'Invalid signature'}), 401
    
    # Parse event
    try:
        event = json.loads(payload)
    except json.JSONDecodeError:
        return jsonify({'error': 'Invalid JSON'}), 400
    
    # Process event
    try:
        process_event(event)
        return jsonify({'status': 'success'}), 200
    except Exception as e:
        # Log error but return 200 to prevent retries for application errors
        log_error(f"Webhook processing error: {str(e)}")
        return jsonify({'status': 'error', 'message': str(e)}), 500

def verify_signature(payload, signature):
    expected = hmac.new(
        WEBHOOK_SECRET.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, f'sha256={expected}')

def process_event(event):
    event_type = event['type']
    event_data = event['data']
    
    if event_type == 'payment.failed':
        handle_payment_failed(event_data)
    elif event_type == 'service.suspended':
        handle_service_suspended(event_data)
    elif event_type == 'ticket.created':
        handle_ticket_created(event_data)
    else:
        log_info(f"Unhandled event type: {event_type}")

Advanced Webhook Processing

Async Processing with Queue:

import asyncio
from celery import Celery

# Celery configuration for async processing
celery_app = Celery('webhook_processor')

@app.route('/webhooks/unclebtech', methods=['POST'])
def handle_webhook():
    # Verify signature (same as above)
    
    # Queue event for async processing
    event = json.loads(request.get_data())
    process_webhook_async.delay(event)
    
    # Return immediately
    return jsonify({'status': 'queued'}), 200

@celery_app.task
def process_webhook_async(event):
    """Process webhook event asynchronously"""
    try:
        # Process the event
        process_event(event)
        
        # Update processing status
        update_event_status(event['id'], 'processed')
        
    except Exception as e:
        # Handle errors and retry logic
        update_event_status(event['id'], 'failed', str(e))
        raise

Webhook Testing and Debugging

Testing Webhook Endpoints

Webhook Testing Tool:

# Test webhook endpoint manually
curl -X POST https://your-app.com/webhooks/unclebtech \
  -H "Content-Type: application/json" \
  -H "X-UncleBTech-Signature: sha256=test-signature" \
  -H "X-UncleBTech-Event: payment.failed" \
  -d '{
    "id": "evt_test_123",
    "type": "payment.failed",
    "created_at": "2025-01-21T10:00:00Z",
    "data": {
      "payment": {
        "id": "pay_test_123",
        "invoice_id": "inv_test_123",
        "failure_reason": "card_declined"
      }
    }
  }'

Webhook Validation:

# Validate webhook configuration
POST /api/v1/webhooks/wh_123456/test
{
  "event_type": "payment.failed"
}

# Response
{
  "success": true,
  "data": {
    "test_delivery_id": "del_test_123456",
    "status": "delivered",
    "response_code": 200,
    "response_time": "245ms",
    "delivered_at": "2025-01-21T10:00:00Z"
  }
}

Webhook Delivery Monitoring

Check Delivery Status:

GET /api/v1/webhooks/wh_123456/deliveries?limit=10

# Response
{
  "success": true,
  "data": [
    {
      "id": "del_123456",
      "event_id": "evt_123456",
      "event_type": "payment.failed",
      "status": "delivered",
      "response_code": 200,
      "response_time": "245ms",
      "attempts": 1,
      "delivered_at": "2025-01-21T10:00:00Z"
    },
    {
      "id": "del_123457",
      "event_id": "evt_123457",
      "event_type": "service.suspended",
      "status": "failed",
      "response_code": 500,
      "attempts": 3,
      "last_attempt": "2025-01-21T09:45:00Z",
      "next_retry": "2025-01-21T11:00:00Z"
    }
  ]
}

Retry Failed Deliveries:

POST /api/v1/webhooks/wh_123456/deliveries/del_123457/retry

# Response
{
  "success": true,
  "data": {
    "delivery_id": "del_123457",
    "status": "retrying",
    "scheduled_at": "2025-01-21T10:05:00Z"
  }
}

Integration Examples

Customer Onboarding Automation

Automated Onboarding Workflow:

// Handle service creation webhook
function handleServiceCreated(event) {
  const service = event.data.service;
  const customer = event.data.customer;
  
  // 1. Send welcome email
  sendWelcomeEmail(customer.email, {
    serviceName: service.type,
    domain: service.domain,
    controlPanelUrl: service.control_panel_url
  });
  
  // 2. Create onboarding tasks
  createOnboardingTasks(customer.id, service.id);
  
  // 3. Schedule follow-up
  scheduleFollowUp(customer.id, '7 days');
  
  // 4. Update CRM
  updateCRM(customer.id, {
    status: 'active_customer',
    services: [service.id]
  });
}

Billing System Integration

Sync with Accounting System:

def handle_invoice_created(event):
    invoice_data = event['data']['invoice']
    
    # Create invoice in accounting system
    accounting_invoice = {
        'external_id': invoice_data['id'],
        'customer_id': invoice_data['customer']['id'],
        'amount': invoice_data['amount'],
        'currency': invoice_data['currency'],
        'due_date': invoice_data['due_date'],
        'line_items': [
            {
                'description': item['description'],
                'amount': item['amount'],
                'service_id': item['service_id']
            }
            for item in invoice_data['line_items']
        ]
    }
    
    # Sync with accounting system
    accounting_system.create_invoice(accounting_invoice)

def handle_payment_succeeded(event):
    payment_data = event['data']['payment']
    
    # Mark invoice as paid in accounting system
    accounting_system.mark_invoice_paid(
        external_id=payment_data['invoice_id'],
        payment_date=payment_data['processed_at'],
        payment_method=payment_data['payment_method']['type']
    )

Support System Integration

Helpdesk Integration:

function handleTicketCreated(event) {
  const ticket = event.data.ticket;
  const customer = event.data.customer;
  
  // Create ticket in external helpdesk
  const helpdeskTicket = {
    external_id: ticket.id,
    subject: ticket.subject,
    customer_email: customer.email,
    priority: mapPriority(ticket.priority),
    department: ticket.department,
    initial_message: event.data.initial_message.message,
    service_context: {
      service_id: ticket.service_id,
      service_type: getServiceType(ticket.service_id)
    }
  };
  
  helpdesk.createTicket(helpdeskTicket);
  
  // Set up bidirectional sync
  setupTicketSync(ticket.id, helpdeskTicket.id);
}

function handleTicketUpdated(event) {
  const ticket = event.data.ticket;
  
  // Sync updates to external helpdesk
  helpdesk.updateTicket(ticket.id, {
    status: ticket.status,
    last_reply: ticket.last_reply,
    assigned_to: ticket.assigned_to
  });
}

Webhook Best Practices

Endpoint Design

Webhook Endpoint Best Practices:

  1. Return Quickly: Process webhooks asynchronously, return 200 immediately
  2. Idempotent Processing: Handle duplicate events gracefully
  3. Proper Error Handling: Return appropriate HTTP status codes
  4. Signature Verification: Always verify webhook signatures
  5. Logging: Log all webhook events for debugging and audit

Response Codes:

# Appropriate response codes
200 OK: Event processed successfully
400 Bad Request: Invalid payload format
401 Unauthorized: Invalid signature
500 Internal Server Error: Processing error (will trigger retry)

Security Considerations

Webhook Security Checklist:

  1. HTTPS Only: Only accept webhooks over HTTPS
  2. Signature Verification: Always verify webhook signatures
  3. IP Whitelisting: Optionally whitelist UncleBTech IP addresses
  4. Rate Limiting: Implement rate limiting on webhook endpoints
  5. Input Validation: Validate all webhook payload data

IP Whitelist (Optional):

# UncleBTech webhook source IPs
185.199.108.0/24
185.199.109.0/24
185.199.110.0/24
185.199.111.0/24

Error Handling and Retries

Retry Logic:

# Webhook retry schedule
Attempt 1: Immediate
Attempt 2: 1 minute later
Attempt 3: 5 minutes later
Attempt 4: 15 minutes later
Attempt 5: 1 hour later
Attempt 6: 6 hours later
Final: 24 hours later (then marked as failed)

Handling Retry Logic:

def handle_webhook_with_retry(event):
    max_retries = 3
    retry_count = 0
    
    while retry_count < max_retries:
        try:
            process_event(event)
            return True
        except TemporaryError as e:
            retry_count += 1
            if retry_count >= max_retries:
                log_permanent_failure(event, e)
                return False
            
            # Exponential backoff
            sleep_time = 2 ** retry_count
            time.sleep(sleep_time)
        except PermanentError as e:
            log_permanent_failure(event, e)
            return False

Webhook Reliability Tip: Design your webhook endpoints to be idempotent and handle duplicate events gracefully. UncleBTech may send the same event multiple times to ensure delivery.

Webhook Management

Managing Webhook Subscriptions

Update Event Subscriptions:

PUT /api/v1/webhooks/wh_123456
{
  "events": [
    "service.created",
    "service.suspended",
    "service.cancelled",
    "payment.failed",
    "payment.succeeded",
    "invoice.created",
    "ticket.created",
    "ticket.resolved"
  ],
  "active": true
}

Disable Webhook Temporarily:

PUT /api/v1/webhooks/wh_123456
{
  "active": false,
  "reason": "maintenance"
}

Delete Webhook:

DELETE /api/v1/webhooks/wh_123456

# Response
{
  "success": true,
  "message": "Webhook deleted successfully"
}

Webhook Analytics

Delivery Statistics:

GET /api/v1/webhooks/wh_123456/analytics?period=30d

# Response
{
  "success": true,
  "data": {
    "total_deliveries": 1250,
    "successful_deliveries": 1238,
    "failed_deliveries": 12,
    "success_rate": "99.04%",
    "average_response_time": "245ms",
    "event_breakdown": {
      "payment.failed": 45,
      "service.created": 23,
      "ticket.created": 156,
      "invoice.created": 89
    }
  }
}

Troubleshooting Webhooks

Common Issues

Webhook Not Receiving Events:

  1. Check Endpoint URL: Ensure URL is accessible and returns 200
  2. Verify HTTPS: Webhook endpoints must use HTTPS
  3. Check Firewall: Ensure firewall allows incoming connections
  4. Validate Response: Endpoint must return 200 status code
  5. Check Event Filters: Verify you're subscribed to the correct events

Signature Verification Failing:

  1. Check Secret: Ensure webhook secret matches configuration
  2. Verify Algorithm: Use SHA-256 HMAC for signature verification
  3. Check Encoding: Ensure proper encoding of payload and secret
  4. Debug Signatures: Log expected vs received signatures for debugging

Debugging Tools

Webhook Testing Service:

# Use webhook testing service for development
POST /api/v1/webhooks
{
  "url": "https://webhook.site/unique-url",
  "events": ["payment.failed"],
  "active": true
}

Local Development with ngrok:

# Expose local development server
ngrok http 3000

# Use ngrok URL for webhook testing
POST /api/v1/webhooks
{
  "url": "https://abc123.ngrok.io/webhooks/unclebtech",
  "events": ["service.created"],
  "active": true
}

Getting Webhook Support

Webhook Support Resources

Support Channels:

  • Email: webhooks@unclebtech.com for webhook-specific issues
  • API Documentation: Comprehensive webhook documentation and examples
  • Developer Forum: Community support for webhook integration
  • GitHub Examples: Sample webhook implementations in multiple languages

Common Support Requests:

  • Signature Verification Issues: Help with implementing signature verification
  • Event Processing: Guidance on processing specific event types
  • Delivery Issues: Troubleshooting webhook delivery problems
  • Integration Patterns: Best practices for webhook integrations

Information for Webhook Support

When Contacting Webhook Support:

  • Webhook ID: Include webhook ID from your configuration
  • Event Type: Specific event types experiencing issues
  • Delivery ID: Include delivery ID for failed webhook deliveries
  • Error Messages: Complete error messages from your endpoint
  • Request/Response: Full request and response details
  • Timeline: When the issue started and frequency

Ready to implement webhooks? Start by setting up a simple webhook endpoint and subscribing to basic events like service.created. Use our testing tools to verify your implementation before going live.

Was this documentation helpful?

Still need help? Contact our technical team or visit our Help Centre.