Skip to main content

Configuring Webhooks

Webhooks enable your application to receive real-time notifications when events occur in Dasha BlackBox. This guide covers everything from initial setup through advanced configuration, troubleshooting, and best practices for production deployments.

What Are Webhooks?

Webhooks are HTTP callbacks that Dasha BlackBox sends to your server when specific events occur. Instead of polling the API repeatedly to check for updates, your server receives instant notifications about:
  • Call Events: Call starts, completions, failures
  • Agent Updates: Configuration changes, status updates
  • Tool Invocations: When agents call your custom functions
  • Transfer Events: Call transfers to human operators
Real-Time Integration: Webhooks deliver events within 1-2 seconds of occurrence, enabling immediate responses to customer interactions.

Configuration Methods

Configure webhooks through the dashboard or programmatically via API.
Best For: Initial setup, testing, and non-technical users
  • Visual configuration interface
  • Test webhook button
  • Live delivery monitoring
  • No coding required

Dashboard Configuration

Set up webhooks visually through the Dasha BlackBox dashboard.

Step 1: Navigate to Agent Settings

  1. Open Dashboard: Log in to Dasha BlackBox Dashboard
  2. Select Agent: Navigate to Agents and choose your agent
  3. Access Webhooks: Click Settings tab, then Webhooks section

Step 2: Configure Webhook URL

Enter Webhook Endpoint:
  1. Webhook URL Field: Enter your HTTPS endpoint
    • Example: https://api.yourcompany.com/webhooks/blackbox
    • Must be publicly accessible
    • HTTPS required (HTTP rejected)
  2. Validation: Dashboard validates URL format
    • Checks for HTTPS protocol
    • Verifies URL structure
    • Tests DNS resolution
URL Requirements:
  • Must use HTTPS (not HTTP)
  • Must be publicly accessible (not localhost)
  • Must respond with 2xx status code
  • Should complete under 10 seconds
Localhost URLs Not Supported: Use ngrok or similar tunneling service for local development. See Testing Webhooks for development setup.

Step 3: Configure Authentication

Add authentication headers to secure your webhook endpoint. Custom Headers:
  1. Click Add Header button
  2. Enter header name and value
  3. Common patterns:
    • Bearer tokens: Authorization: Bearer your-secret-token
    • API keys: X-API-Key: your-api-key
    • Custom auth: X-Webhook-Secret: your-webhook-secret
Example Configurations: Bearer Token Authentication:
Header Name: Authorization
Header Value: Bearer sk_live_abc123def456ghi789
API Key Authentication:
Header Name: X-API-Key
Header Value: your-api-key-here
Custom Webhook Secret:
Header Name: X-Webhook-Secret
Header Value: whsec_abc123def456

Step 4: Select Event Types

Choose which events trigger webhook notifications. Available Webhook Payload Types:
  • StartWebHookPayload: Pre-call webhook when call is initiated
  • CompletedWebHookPayload: Call completed successfully with full transcript
  • FailedWebHookPayload: Call encountered error
  • CallDeadLineWebHookPayload: Call canceled due to deadline expiration
Selection Strategy:
  • All Events: Maximum observability, higher volume
  • Critical Only: CompletedWebHookPayload, FailedWebHookPayload, ToolWebHookPayload
  • Custom Selection: Choose specific payload types for your workflow
Event Filtering: Dasha BlackBox sends all events to your webhook URL. Filter unwanted events in your webhook handler rather than relying on server-side filtering.

Step 5: Configure Timeout Settings

Set maximum wait time for webhook responses. Timeout Configuration:
  • Default: 10 seconds (recommended)
  • Minimum: 5 seconds
  • Maximum: 30 seconds
Choosing Timeout:
  • 5 seconds: For fast, async processing (recommended)
  • 10 seconds: Standard configuration
  • 30 seconds: For synchronous processing (use cautiously)
Best Practice: Keep timeouts under 10 seconds. Use async processing with message queues for heavy operations. Respond immediately, process later.

Step 6: Test Webhook

Verify your configuration before enabling.
  1. Click Test Button: Sends sample event to your endpoint
  2. Review Response:
    • Success: Green checkmark, response displayed
    • Failure: Error message with details
  3. Check Server Logs: Verify webhook received and processed
Test Payload Example:
{
  "eventType": "call.completed",
  "eventId": "evt_test_abc123",
  "timestamp": "2025-01-15T14:30:00Z",
  "callId": "call_test_123",
  "agentId": "agent_456",
  "status": "completed",
  "duration": 180
}

Step 7: Save Configuration

  1. Click Save: Commits webhook configuration
  2. Confirmation: Dashboard shows success message
  3. Activation: Webhook active immediately for new events
Configuration Summary:
  • Webhook URL: https://api.yourcompany.com/webhooks/blackbox
  • Authentication: Bearer token configured
  • Payload Types: StartWebHookPayload, CompletedWebHookPayload, FailedWebHookPayload
  • Timeout: 10 seconds
  • Status: Active

API Configuration

Configure webhooks programmatically for automated deployments.

Creating Agent with Webhook

Complete Configuration:
const createAgentWithWebhook = async () => {
  const response = await fetch('https://blackbox.dasha.ai/api/v1/agents', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      name: "Customer Support Agent",
      description: "Handles customer support inquiries",
      config: {
        primaryLanguage: "en-US",
        llmConfig: {
          vendor: "openai",
          model: "gpt-4.1-mini",
          prompt: "You are a helpful customer support agent.",
          options: {
            temperature: 0.7,
            maxTokens: 800
          }
        },
        ttsConfig: {
          vendor: "elevenlabs",
          voiceId: "21m00Tcm4TlvDq8ikWAM",
          model: "eleven_turbo_v2_5"
        },
        sttConfig: {
          vendor: "deepgram",
          model: "nova-2",
          language: "en-US"
        },
        webhookUrl: "https://api.yourcompany.com/webhooks/blackbox",
        webhookHeaders: {
          "Authorization": "Bearer sk_live_abc123",
          "X-Custom-Header": "your-value"
        },
        webhookTimeout: 10
      }
    })
  });

  const agent = await response.json();
  console.log('Agent created with webhook:', agent.id);
  console.log('Webhook URL:', agent.config.webhookUrl);

  return agent;
};

createAgentWithWebhook();

Webhook Configuration Fields

webhookUrl (string, optional)
  • Full HTTPS URL to your webhook endpoint
  • Must be publicly accessible
  • Format: https://api.example.com/webhooks/blackbox
  • Validation: Must use HTTPS, valid URL format
  • Example: https://api.yourcompany.com/webhooks/blackbox
webhookHeaders (object, optional)
  • Custom HTTP headers sent with each webhook
  • Used for authentication and routing
  • Key-value pairs (string: string)
  • Common uses: Bearer tokens, API keys, tenant IDs
  • Example: { "Authorization": "Bearer sk_live_abc123" }
webhookTimeout (integer, optional)
  • Maximum seconds to wait for webhook response
  • Default: 10 seconds
  • Minimum: 5 seconds
  • Maximum: 30 seconds
  • Recommended: 10 seconds or below
Optional Configuration: All webhook fields are optional. Omit webhookUrl to create an agent without webhooks. Add it later via PUT request.

Webhook URL Requirements

Your webhook endpoint must meet specific requirements for reliable delivery.

HTTPS Only

Requirement: All webhook URLs must use HTTPS. Why HTTPS Required:
  • Protects webhook payloads in transit
  • Prevents man-in-the-middle attacks
  • Industry standard for webhook security
  • Ensures payload integrity
Valid Examples:
✓ https://api.yourcompany.com/webhooks/blackbox
✓ https://webhooks.yourapp.com/blackbox/events
✓ https://your-domain.com:8443/webhooks
Invalid Examples:
✗ http://api.yourcompany.com/webhooks (HTTP not allowed)
✗ localhost:3000/webhook (Localhost not accessible)
✗ 192.168.1.100/webhook (Private IP not accessible)

Public Accessibility

Requirement: Webhook URL must be publicly accessible from internet. Accessibility Checklist:
  • Domain has valid DNS record
  • Server accepts connections on port 443
  • Firewall allows inbound HTTPS traffic
  • No VPN or authentication required for connection
  • SSL certificate is valid and trusted
Testing Public Accessibility:
# Test from external server or service
curl -I https://api.yourcompany.com/webhooks/blackbox

# Expected response (not 404)
HTTP/2 200
Content-Type: application/json
Development Environments: For local development, use ngrok, localtunnel, or similar to create public URLs. See Testing Webhooks for setup instructions.

Response Requirements

HTTP Status Codes: Your webhook endpoint must respond with appropriate status codes: Success (2xx):
  • 200 OK: Webhook received and processed successfully
  • 201 Created: Webhook received, resource created
  • 202 Accepted: Webhook received, will process asynchronously
Client Errors (4xx) - No Retry:
  • 400 Bad Request: Invalid payload format
  • 401 Unauthorized: Authentication failed
  • 404 Not Found: Endpoint not found
Server Errors (5xx) - Triggers Retry:
  • 500 Internal Server Error: Processing failed, retry
  • 502 Bad Gateway: Upstream error, retry
  • 503 Service Unavailable: Temporary issue, retry
Retry Behavior: Dasha BlackBox automatically retries webhooks that fail with 5xx errors or timeouts:
AttemptDelayWhen
1stImmediateInitial delivery
2nd1 minuteAfter first failure
3rd5 minutesAfter second failure
Idempotency Required: Your webhook handler must be idempotent since retries may cause duplicate delivery. Use event IDs to detect and skip duplicates.

SSL Certificate Validation

Certificate Requirements:
  • Issued by trusted Certificate Authority (CA)
  • Not expired
  • Domain matches webhook URL
  • Complete certificate chain provided
Common SSL Issues: Self-Signed Certificates - Not Accepted:
✗ Self-signed certificate
✗ Expired certificate
✗ Domain mismatch
✗ Incomplete certificate chain
Solutions:
  • Use Let’s Encrypt for free trusted certificates
  • Purchase certificate from trusted CA
  • Use cloud provider managed certificates (AWS ACM, Cloudflare)
Testing SSL Certificate:
# Check certificate validity
openssl s_client -connect api.yourcompany.com:443 -servername api.yourcompany.com

# Or use online tools
# https://www.ssllabs.com/ssltest/

Authentication Setup

Secure your webhook endpoint with authentication headers.

Bearer Token Authentication

Most Common Pattern: Use Bearer tokens in Authorization header. Configuration:
  1. Navigate to webhook configuration
  2. Click Add Header
  3. Header Name: Authorization
  4. Header Value: Bearer sk_live_your_secret_token
  5. Click Save
Server-Side Verification:
// Express.js example
app.post('/webhooks/blackbox', (req, res) => {
  const authHeader = req.headers['authorization'];
  const expectedToken = 'Bearer ' + process.env.WEBHOOK_TOKEN;

  if (authHeader !== expectedToken) {
    console.error('Invalid authorization token');
    return res.status(401).json({ error: 'Unauthorized' });
  }

  // Process webhook
  console.log('Authenticated webhook:', req.body);
  res.status(200).json({ received: true });
});

API Key Authentication

Alternative Pattern: Custom API key header. Configuration:
// API configuration
{
  webhookUrl: "https://api.yourcompany.com/webhooks/blackbox",
  webhookHeaders: {
    "X-API-Key": "apk_live_abc123def456"
  }
}
Server-Side Verification:
app.post('/webhooks/blackbox', (req, res) => {
  const apiKey = req.headers['x-api-key'];
  const expectedKey = process.env.WEBHOOK_API_KEY;

  if (apiKey !== expectedKey) {
    return res.status(401).json({ error: 'Invalid API key' });
  }

  // Process webhook
  res.status(200).json({ received: true });
});

HMAC Signature Verification

Most Secure: Verify payload hasn’t been tampered with. How It Works:
  1. Dasha BlackBox computes HMAC-SHA256 of payload using shared secret
  2. Signature sent in X-Dasha BlackBox-Signature header
  3. Your server recomputes signature and compares
  4. Reject if signatures don’t match
Configuration:
// Store webhook secret securely
const webhookSecret = process.env.BLACKBOX_WEBHOOK_SECRET;

// Dasha BlackBox automatically includes signature header
// No configuration needed
Server-Side Verification:
const crypto = require('crypto');

function verifyWebhookSignature(req, secret) {
  const signature = req.headers['x-blackbox-signature'];

  if (!signature) {
    throw new Error('Missing signature');
  }

  // Extract hash from "sha256=..." format
  const receivedHash = signature.replace('sha256=', '');

  // Compute expected signature
  const payload = JSON.stringify(req.body);
  const hmac = crypto.createHmac('sha256', secret);
  hmac.update(payload);
  const expectedHash = hmac.digest('hex');

  // Timing-safe comparison
  const isValid = crypto.timingSafeEqual(
    Buffer.from(receivedHash, 'hex'),
    Buffer.from(expectedHash, 'hex')
  );

  if (!isValid) {
    throw new Error('Invalid signature');
  }

  return true;
}

// Usage
app.post('/webhooks/blackbox', (req, res) => {
  try {
    verifyWebhookSignature(req, process.env.WEBHOOK_SECRET);

    // Process webhook
    console.log('Valid webhook:', req.body);
    res.status(200).json({ received: true });

  } catch (error) {
    console.error('Signature verification failed:', error);
    res.status(401).json({ error: 'Unauthorized' });
  }
});
Security Best Practice: Use HMAC signature verification in addition to Bearer tokens for maximum security. This prevents replay attacks and payload tampering.

Custom Headers

Add custom headers for routing, authentication, or metadata.

Common Use Cases

Multi-Tenant Routing:
{
  webhookUrl: "https://api.yourcompany.com/webhooks/blackbox",
  webhookHeaders: {
    "X-Tenant-ID": "tenant_12345",
    "X-Organization-ID": "org_abc"
  }
}
Environment Routing:
{
  webhookUrl: "https://webhooks.yourcompany.com/blackbox",
  webhookHeaders: {
    "X-Environment": "production",
    "X-Region": "us-east-1"
  }
}
Correlation IDs:
{
  webhookUrl: "https://api.yourcompany.com/webhooks",
  webhookHeaders: {
    "X-Correlation-ID": "agent_550e8400",
    "X-Service-Name": "blackbox-webhooks"
  }
}

Server-Side Header Access

Express.js Example:
app.post('/webhooks/blackbox', (req, res) => {
  // Access custom headers
  const tenantId = req.headers['x-tenant-id'];
  const orgId = req.headers['x-organization-id'];
  const environment = req.headers['x-environment'];

  console.log('Webhook for tenant:', tenantId);
  console.log('Organization:', orgId);
  console.log('Environment:', environment);

  // Route to appropriate handler
  const handler = getHandlerForTenant(tenantId);
  handler.processWebhook(req.body);

  res.status(200).json({ received: true });
});
Flask Example:
@app.route('/webhooks/blackbox', methods=['POST'])
def webhook():
    # Access custom headers
    tenant_id = request.headers.get('X-Tenant-ID')
    org_id = request.headers.get('X-Organization-ID')
    environment = request.headers.get('X-Environment')

    print(f"Webhook for tenant: {tenant_id}")
    print(f"Organization: {org_id}")
    print(f"Environment: {environment}")

    # Route to appropriate handler
    handler = get_handler_for_tenant(tenant_id)
    handler.process_webhook(request.get_json())

    return jsonify({'received': True}), 200

Header Limitations

Character Limits:
  • Header name: Maximum 100 characters
  • Header value: Maximum 1000 characters
  • Total headers: Maximum 10 custom headers
Allowed Characters:
  • Header names: Alphanumeric, hyphens, underscores
  • Header values: Any UTF-8 characters
Reserved Headers (Cannot Override):
  • Content-Type: Always application/json
  • User-Agent: Always Dasha BlackBox-Webhook/1.0
  • Content-Length: Auto-calculated
  • X-Dasha BlackBox-Signature: Auto-generated
Sensitive Data: Avoid including sensitive information in header values unless using HTTPS (required). Store secrets in environment variables, not configuration.

Timeout Settings

Configure how long Dasha BlackBox waits for your webhook to respond.

Default Timeout

Default: 10 seconds for all webhook events Applies To:
  • Call lifecycle events (started, ended, completed, failed)
  • Agent update events
  • Tool invocation events
  • Transfer events

Configuring Timeout

  1. Navigate to agent webhook settings
  2. Locate Timeout field
  3. Enter timeout in seconds (5-30)
  4. Click Save
  5. Applies to all future webhooks

Choosing the Right Timeout

5 seconds - Recommended:
  • Quick acknowledgment pattern
  • Async processing with queues
  • Fastest retry on failure
  • Best for high-volume systems
10 seconds - Default:
  • Balanced approach
  • Light synchronous processing
  • Standard for most use cases
30 seconds - Maximum:
  • Heavy synchronous processing
  • Complex validation logic
  • Use only when necessary
  • Risk of call delays
Response Time Best Practices:
// GOOD: Quick response, async processing
app.post('/webhook', (req, res) => {
  // Respond immediately
  res.status(200).json({ received: true });

  // Process asynchronously
  setImmediate(() => {
    processWebhook(req.body);
  });
});

// BAD: Slow synchronous processing
app.post('/webhook', async (req, res) => {
  // Don't do this - might timeout
  await updateDatabase(req.body);
  await sendEmail(req.body);
  await callExternalAPI(req.body);

  res.status(200).json({ received: true });
});
Production Pattern: Use 5-10 second timeout with async processing. Add webhook to message queue, respond immediately, process later. This ensures fast responses and prevents timeouts.

Retry Configuration

Dasha BlackBox automatically retries failed webhook deliveries with exponential backoff.

Retry Behavior

Automatic Retries: Enabled for all webhooks by default. Retry Triggers:
  • HTTP 5xx status codes (500, 502, 503, 504)
  • Connection timeouts (over configured timeout)
  • Network errors (DNS failure, connection refused)
  • SSL/TLS errors
No Retry:
  • HTTP 2xx status codes (success)
  • HTTP 4xx status codes (client errors)
  • Valid response received

Retry Schedule

Exponential Backoff Strategy:
AttemptDelay After FailureTotal Elapsed Time
1stImmediate0 seconds
2nd1 minute1 minute
3rd5 minutes6 minutes
After 3 Attempts:
  • Webhook marked as failed
  • No further retry attempts
  • Logged in delivery history
  • Alert sent to account administrators
Maximum Retries: Dasha BlackBox retries up to 3 times total. Ensure your webhook handler is idempotent to handle potential duplicate deliveries.

Implementing Idempotency

Use Event IDs: Every webhook includes a unique eventId. Use it to detect duplicates:
// In-memory deduplication (simple)
const processedEvents = new Set();

app.post('/webhook', (req, res) => {
  const eventId = req.body.eventId;

  // Check if already processed
  if (processedEvents.has(eventId)) {
    console.log('Duplicate event, skipping:', eventId);
    return res.status(200).json({
      received: true,
      duplicate: true
    });
  }

  // Process webhook
  processedEvents.add(eventId);
  processWebhook(req.body);

  res.status(200).json({ received: true });
});
Database-Backed Deduplication:
// Production-ready with persistence
app.post('/webhook', async (req, res) => {
  const eventId = req.body.eventId;

  // Atomic check-and-insert
  const inserted = await db.query(`
    INSERT INTO processed_webhooks (event_id, received_at)
    VALUES ($1, NOW())
    ON CONFLICT (event_id) DO NOTHING
    RETURNING event_id
  `, [eventId]);

  if (inserted.rows.length === 0) {
    console.log('Duplicate event:', eventId);
    return res.status(200).json({
      received: true,
      duplicate: true
    });
  }

  // Process webhook (guaranteed first time)
  await processWebhook(req.body);

  res.status(200).json({ received: true });
});

Retry Optimization

Fast Failure for 4xx Errors:
app.post('/webhook', (req, res) => {
  // Validate payload quickly
  if (!req.body.eventType || !req.body.eventId) {
    // Return 400 to prevent retries
    return res.status(400).json({
      error: 'Invalid payload'
    });
  }

  // Authentication failure
  if (!isValidAuth(req.headers)) {
    // Return 401 to prevent retries
    return res.status(401).json({
      error: 'Unauthorized'
    });
  }

  // Process webhook
  processWebhook(req.body);
  res.status(200).json({ received: true });
});
Temporary Failures with 5xx:
app.post('/webhook', async (req, res) => {
  try {
    await processWebhook(req.body);
    res.status(200).json({ received: true });

  } catch (error) {
    console.error('Processing failed:', error);

    // Return 500 to trigger retry
    res.status(500).json({
      error: 'Temporary processing error',
      message: error.message
    });
  }
});

Multiple Webhooks

Dasha BlackBox supports one webhook URL per agent. For multiple destinations, use a webhook proxy.

Single Webhook Limitation

Current Behavior:
  • One webhookUrl per agent
  • Cannot configure multiple endpoints directly
  • All events go to single URL
Workaround: Implement webhook proxy/router.

Webhook Proxy Pattern

Architecture:
Dasha BlackBox → Your Proxy Server → Multiple Endpoints
                └→ CRM System
                └→ Analytics Platform
                └→ Notification Service
Implementation:
const express = require('express');
const app = express();
app.use(express.json());

// Webhook destinations
const destinations = [
  'https://crm.yourcompany.com/webhooks/blackbox',
  'https://analytics.yourcompany.com/webhooks',
  'https://notifications.yourcompany.com/hooks'
];

app.post('/webhook-proxy', async (req, res) => {
  const webhook = req.body;

  // Respond immediately to Dasha BlackBox
  res.status(200).json({ received: true });

  // Fan out to all destinations asynchronously
  const promises = destinations.map(url =>
    fetch(url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(webhook)
    }).catch(err => {
      console.error(`Failed to forward to ${url}:`, err);
    })
  );

  await Promise.allSettled(promises);
});

app.listen(3000);

Conditional Routing

Route by Event Type:
app.post('/webhook-conditional', async (req, res) => {
  const payload = req.body;
  const { type } = payload;

  // Respond to Dasha BlackBox
  res.status(200).json({ received: true });

  // Conditional routing based on payload type
  if (type === 'CompletedWebHookPayload') {
    await sendToCRM(payload);
    await sendToAnalytics(payload);
  }

  if (type === 'FailedWebHookPayload') {
    await sendToAlerts(payload);
  }

  if (type === 'ToolWebHookPayload') {
    await sendToFunctionLogger(payload);
  }

  // Route based on call data
  if (payload.durationSeconds > 300) {  // over 5 minutes
    await sendToQualityAssurance(payload);
  }
});

Testing Configuration

Verify your webhook configuration before production deployment.

Testing with webhook.site

Quick Validation:
  1. Get Test URL: Visit https://webhook.site
  2. Configure in Dasha BlackBox: Use provided URL as webhook endpoint
  3. Trigger Events: Make test calls or use webhook test API
  4. Inspect Requests: View full HTTP request details

Testing with Dasha BlackBox Test API

Send Test Webhook:
const testWebhook = async () => {
  const response = await fetch('https://blackbox.dasha.ai/api/v1/webhooks/test', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      webHook: {
        url: 'https://your-server.com/webhooks/blackbox',
        headers: {
          'Authorization': 'Bearer your-webhook-secret'
        }
      },
      webhookType: 'CompletedWebHookPayload',
      agentAdditionalData: {
        companyName: 'Test Company'
      },
      callAdditionalData: {
        userId: 'test-user-123'
      }
    })
  });

  const result = await response.json();

  console.log('Test successful:', result.success);
  console.log('HTTP status:', result.httpStatus);
  console.log('Response:', result.responseData);
  console.log('Time taken:', result.timeTaken, 'ms');

  if (!result.success) {
    console.error('Error:', result.error);
  }
};

testWebhook();

Testing with ngrok

Local Development Testing:
# Terminal 1: Start your webhook server
node webhook-server.js

# Terminal 2: Start ngrok tunnel
ngrok http 3000

# Output: https://abc123.ngrok.io -> http://localhost:3000

# Terminal 3: Test with Dasha BlackBox
curl -X POST https://blackbox.dasha.ai/api/v1/webhooks/test \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "webHook": {
      "url": "https://abc123.ngrok.io/webhook"
    },
    "webhookType": "CompletedWebHookPayload"
  }'
See Testing Webhooks for complete ngrok setup guide.

Updating Webhooks

Modify webhook configuration for existing agents.

Updating via Dashboard

  1. Navigate to Agent: Open agent settings
  2. Edit Webhooks: Click Webhooks section
  3. Modify Configuration: Update URL, headers, or timeout
  4. Save Changes: Click Save button
  5. Verify: Test updated configuration

Updating via API

Update Webhook URL:
const updateWebhook = async (agentId) => {
  const response = await fetch(`https://blackbox.dasha.ai/api/v1/agents/${agentId}`, {
    method: 'PUT',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      config: {
        webhookUrl: "https://api.yourcompany.com/webhooks/blackbox-v2",
        webhookHeaders: {
          "Authorization": "Bearer new_token_abc123"
        },
        webhookTimeout: 10
      }
    })
  });

  const agent = await response.json();
  console.log('Webhook updated:', agent.config.webhookUrl);
};

updateWebhook('550e8400-e29b-41d4-a716-446655440000');
Update Headers Only:
const updateHeaders = async (agentId) => {
  const response = await fetch(`https://blackbox.dasha.ai/api/v1/agents/${agentId}`, {
    method: 'PUT',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      config: {
        webhookHeaders: {
          "Authorization": "Bearer updated_token_xyz789",
          "X-Tenant-ID": "tenant_new_456"
        }
      }
    })
  });

  const agent = await response.json();
  console.log('Headers updated');
};

Update Timing

Immediate Effect:
  • Changes apply to new events immediately
  • Active calls continue with old configuration
  • No restart or downtime required
Migration Pattern:
// Safe migration to new webhook endpoint
const migrateWebhook = async (agentId) => {
  // Step 1: Deploy new webhook endpoint
  // Step 2: Verify new endpoint works (test)

  await testWebhook('https://api.yourcompany.com/webhooks/v2');

  // Step 3: Update agent configuration
  await updateWebhook(agentId, {
    webhookUrl: 'https://api.yourcompany.com/webhooks/v2'
  });

  // Step 4: Monitor new endpoint
  // Step 5: Decommission old endpoint after 24h
};

Disabling Webhooks

Temporarily or permanently disable webhook notifications.

Temporary Disable

Dashboard Method:
  1. Navigate to agent webhook settings
  2. Toggle Enabled switch to OFF
  3. Click Save
  4. Webhooks paused, configuration preserved
API Method:
// Disable by setting URL to null
const disableWebhook = async (agentId) => {
  const response = await fetch(`https://blackbox.dasha.ai/api/v1/agents/${agentId}`, {
    method: 'PUT',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      config: {
        webhookUrl: null
      }
    })
  });

  const agent = await response.json();
  console.log('Webhook disabled');
};

disableWebhook('550e8400-e29b-41d4-a716-446655440000');

Permanent Removal

Remove Configuration:
const removeWebhook = async (agentId) => {
  const response = await fetch(`https://blackbox.dasha.ai/api/v1/agents/${agentId}`, {
    method: 'PUT',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      config: {
        webhookUrl: null,
        webhookHeaders: null,
        webhookTimeout: null
      }
    })
  });

  const agent = await response.json();
  console.log('Webhook configuration removed');
};

Re-Enabling Webhooks

Restore Configuration:
const enableWebhook = async (agentId) => {
  const response = await fetch(`https://blackbox.dasha.ai/api/v1/agents/${agentId}`, {
    method: 'PUT',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      config: {
        webhookUrl: "https://api.yourcompany.com/webhooks/blackbox",
        webhookHeaders: {
          "Authorization": "Bearer sk_live_abc123"
        },
        webhookTimeout: 10
      }
    })
  });

  const agent = await response.json();
  console.log('Webhook re-enabled:', agent.config.webhookUrl);
};

Troubleshooting

Common webhook configuration issues and solutions.

Webhook Not Receiving Events

Symptoms:
  • No webhooks arriving at endpoint
  • Zero delivery attempts in logs
  • Events occurring but no notifications
Troubleshooting Steps:
  1. Verify Configuration:
// Get current agent configuration
const agent = await fetch(`https://blackbox.dasha.ai/api/v1/agents/${agentId}`, {
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
}).then(r => r.json());

console.log('Webhook URL:', agent.config.webhookUrl);
console.log('Headers:', agent.config.webhookHeaders);
console.log('Timeout:', agent.config.webhookTimeout);
  1. Test Endpoint Accessibility:
# Test from external server
curl -X POST https://your-webhook-url.com/webhooks \
  -H "Content-Type: application/json" \
  -d '{"test": true}'

# Should return 200 OK
  1. Check Firewall Rules:
  • Verify port 443 (HTTPS) is open
  • Whitelist Dasha BlackBox IP ranges (if applicable)
  • Check security group rules
  1. Test with webhook.site:
  • Replace URL with webhook.site URL
  • Trigger events
  • Verify webhooks arrive at webhook.site

Webhooks Timing Out

Symptoms:
  • Delivery marked as failed with timeout error
  • Retries exhausted
  • Server logs show request started but no response
Solutions: Optimize Response Time:
// BAD: Slow synchronous processing
app.post('/webhook', async (req, res) => {
  await heavyProcessing(req.body);  // Takes 15 seconds
  res.status(200).json({ received: true });
});

// GOOD: Quick response, async processing
app.post('/webhook', (req, res) => {
  res.status(200).json({ received: true });  // Immediate

  setImmediate(() => {
    heavyProcessing(req.body);  // Happens after response
  });
});
Use Message Queue:
const queue = require('bull');
const webhookQueue = new queue('webhooks');

app.post('/webhook', async (req, res) => {
  await webhookQueue.add(req.body);  // Fast queue add
  res.status(200).json({ received: true });
});

webhookQueue.process(async (job) => {
  await heavyProcessing(job.data);  // No time limit
});
Reduce Timeout Setting:
// Force quick responses
{
  webhookUrl: "https://api.yourcompany.com/webhooks",
  webhookTimeout: 5  // 5 seconds maximum
}

Authentication Failures

Symptoms:
  • 401 Unauthorized responses
  • Signature verification failures
  • Header missing errors
Troubleshooting: Verify Headers Sent:
app.post('/webhook', (req, res) => {
  console.log('All headers:', req.headers);
  console.log('Authorization:', req.headers['authorization']);
  console.log('X-API-Key:', req.headers['x-api-key']);

  res.status(200).json({ received: true });
});
Check Header Case:
// Headers are lowercase in Node.js
const authHeader = req.headers['authorization'];  // Correct
const authHeader = req.headers['Authorization'];  // Wrong (undefined)
Verify Signature Computation:
// Debug signature verification
const receivedSig = req.headers['x-blackbox-signature'];
const payload = JSON.stringify(req.body);
const expectedSig = 'sha256=' + crypto
  .createHmac('sha256', process.env.WEBHOOK_SECRET)
  .update(payload)
  .digest('hex');

console.log('Received:', receivedSig);
console.log('Expected:', expectedSig);
console.log('Match:', receivedSig === expectedSig);

SSL Certificate Errors

Symptoms:
  • SSL handshake failures
  • Certificate verification errors
  • “Invalid certificate” in logs
Solutions: Check Certificate Validity:
# Test SSL certificate
openssl s_client -connect your-domain.com:443 -servername your-domain.com

# Check expiration
echo | openssl s_client -connect your-domain.com:443 2>/dev/null | \
  openssl x509 -noout -dates
Use Trusted Certificate:
  • Obtain certificate from trusted CA (Let’s Encrypt, DigiCert)
  • Avoid self-signed certificates
  • Ensure complete certificate chain
Verify Domain Match:
# Certificate should match webhook domain
echo | openssl s_client -connect your-domain.com:443 2>/dev/null | \
  openssl x509 -noout -text | grep DNS

High Retry Rate

Symptoms:
  • Many retry attempts in logs
  • Same webhooks delivered multiple times
  • 500 errors in server logs
Solutions: Improve Error Handling:
app.post('/webhook', async (req, res) => {
  try {
    await processWebhook(req.body);
    res.status(200).json({ received: true });

  } catch (error) {
    console.error('Processing error:', error);

    // Distinguish temporary vs permanent errors
    if (error.code === 'ECONNREFUSED') {
      // Temporary - trigger retry
      res.status(503).json({ error: 'Service unavailable' });
    } else {
      // Permanent - don't retry
      res.status(400).json({ error: 'Invalid payload' });
    }
  }
});
Add Circuit Breaker:
const circuitBreaker = require('opossum');

const processWebhookSafe = circuitBreaker(processWebhook, {
  timeout: 5000,        // 5 second timeout
  errorThresholdPercentage: 50,  // Open after 50% errors
  resetTimeout: 30000   // Try again after 30 seconds
});

app.post('/webhook', async (req, res) => {
  try {
    await processWebhookSafe(req.body);
    res.status(200).json({ received: true });
  } catch (error) {
    res.status(503).json({ error: 'Service temporarily unavailable' });
  }
});

Validation Checklist

Before going to production, verify your webhook configuration: Endpoint Requirements:
  • URL uses HTTPS (not HTTP)
  • URL is publicly accessible (not localhost)
  • Endpoint responds with 200 status code
  • Response time under 10 seconds
  • SSL certificate valid and trusted
Security:
  • Authentication headers configured
  • Signature verification implemented
  • Webhook secret stored securely (env var)
  • Input validation on all fields
  • No sensitive data in URLs
Reliability:
  • Idempotency implemented (event ID tracking)
  • Error handling covers all scenarios
  • Async processing for heavy operations
  • Message queue for reliability
  • Monitoring and alerting configured
Testing:
  • Tested with webhook.site
  • Tested with ngrok locally
  • Tested all event types
  • Tested retry behavior
  • Load tested with expected volume
Operations:
  • Logging enabled for debugging
  • Delivery logs monitored
  • Alerts configured for failures
  • Runbook documented
  • Rollback procedure defined

Next Steps

Now that you’ve configured webhooks:

API Cross-References