> ## Documentation Index
> Fetch the complete documentation index at: https://blackbox.dasha.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Test Webhook Endpoints Before Going Live

> Test webhook endpoints locally with ngrok, validate payloads, and verify security before production deployment.

Verify your webhook integration works before going live. Test endpoints locally, simulate events, and validate payloads.

**What you'll learn:** Local testing with ngrok, API test endpoint, payload validation, and debugging techniques.

## Testing Methods

| Method             | Best For                                   |
| ------------------ | ------------------------------------------ |
| **Dashboard Test** | Quick validation                           |
| **webhook.site**   | Inspecting payloads without server         |
| **ngrok**          | Full integration testing with local server |

***

<Accordion title="API Test Endpoint">
  Send test webhooks programmatically:

  ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  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/webhook',
        headers: { 'Authorization': 'Bearer your-secret' }
      },
      webhookType: 'CompletedWebHookPayload',
      callAdditionalData: { userId: 'test-123' }
    })
  });

  const result = await response.json();
  console.log('Success:', result.success);
  console.log('HTTP Status:', result.httpStatus);
  console.log('Time:', result.timeTaken, 'ms');
  ```
</Accordion>

<Accordion title="Example: Test webhook response">
  ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
  {
    "success": true,
    "httpStatus": 200,
    "responseData": { "received": true },
    "timeTaken": 245
  }
  ```
</Accordion>

***

## Testing with webhook.site

1. Visit [webhook.site](https://webhook.site)
2. Copy your unique URL
3. Use as webhook URL in test API
4. Inspect full request details

***

## Local Testing with ngrok

<Accordion title="Setup">
  ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
  # Install ngrok
  brew install ngrok  # macOS
  # or download from ngrok.com

  # Authenticate
  ngrok config add-authtoken YOUR_TOKEN

  # Start tunnel
  ngrok http 3000
  # Output: https://abc123.ngrok.io -> localhost:3000
  ```
</Accordion>

<Accordion title="Local Webhook Server">
  ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const express = require('express');

  const app = express();
  app.use(express.json());

  app.post('/webhook', (req, res) => {
    console.log('Webhook received:', req.body.type);

    // Handle by type
    switch (req.body.type) {
      case 'StartWebHookPayload':
        console.log('Call started:', req.body.callId);
        break;
      case 'CompletedWebHookPayload':
        console.log('Call completed:', req.body.callId);
        break;
      case 'FailedWebHookPayload':
        console.error('Call failed:', req.body.errorMessage);
        break;
    }

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

  app.listen(3000, () => console.log('Server on port 3000'));
  ```
</Accordion>

<Accordion title="Testing Workflow">
  ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
  # Terminal 1: Start server
  node webhook-server.js

  # Terminal 2: Start ngrok
  ngrok http 3000

  # Terminal 3: Test
  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"
    }'
  ```
</Accordion>

Access ngrok web interface at `http://127.0.0.1:4040` to inspect and replay requests.

***

## Testing Event Types

<Accordion title="StartWebHookPayload">
  ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  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/webhook' },
      webhookType: 'StartWebHookPayload',
      agentAdditionalData: { companyName: 'Acme Corp' },
      callAdditionalData: { customerId: 'cust_123' }
    })
  });
  ```
</Accordion>

<Accordion title="ToolWebHookPayload">
  ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  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/webhook' },
      webhookType: 'ToolWebHookPayload',
      toolName: 'check_availability',
      toolArguments: { date: '2025-01-20', time: '14:00' }
    })
  });
  ```
</Accordion>

***

<Accordion title="Testing Retry Behavior">
  Simulate failures to test retry handling:

  ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  let attemptCount = 0;

  app.post('/webhook', (req, res) => {
    attemptCount++;
    console.log(`Attempt ${attemptCount}`);

    // Fail first 2 attempts
    if (attemptCount <= 2) {
      return res.status(500).json({ error: 'Temporary error' });
    }

    res.status(200).json({ received: true });
  });
  ```
</Accordion>

***

<Accordion title="Testing Idempotency">
  Handle duplicate webhooks:

  ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const processed = new Set();

  app.post('/webhook', (req, res) => {
    const id = `${req.body.callId}_${req.body.timestamp}`;

    if (processed.has(id)) {
      console.log('Duplicate webhook, skipping');
      return res.status(200).json({ duplicate: true });
    }

    processed.add(id);
    processWebhook(req.body);

    res.status(200).json({ received: true });
  });
  ```
</Accordion>

***

## Debugging

### Common Issues

| Issue              | Solution                                 |
| ------------------ | ---------------------------------------- |
| Connection refused | Verify URL is publicly accessible        |
| Timeout            | Respond within 30s, use async processing |
| 401 Unauthorized   | Check authentication headers             |
| 500 errors         | Check server logs, add error handling    |

### Response Time Requirements

| Event Type          | Max Response Time |
| ------------------- | ----------------- |
| StartWebHookPayload | 5 seconds         |
| ToolWebHookPayload  | 10 seconds        |
| Other webhooks      | 30 seconds        |

<Accordion title="Quick Response Pattern">
  ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  app.post('/webhook', (req, res) => {
    // Respond immediately
    res.status(200).json({ received: true });

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

***

## Pre-Production Checklist

* [ ] Webhook URL is publicly accessible
* [ ] Response time under required limit
* [ ] Idempotency handling for duplicates
* [ ] Error handling for all scenarios
* [ ] Logging enabled for debugging
* [ ] Tested all event types

***

## Next Steps

* [Configuring Webhooks](/docs/webhooks-and-events/configuring-webhooks) — Set up webhook endpoints
* [Webhook Events](/docs/webhooks-and-events/webhook-events) — Event types and payloads
