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

# Webhooks Guide

> Detailed webhook setup and event handling for real-time call notifications. Webhooks enable real-time communication between CallIntel and your application. Receive instant notifications when important events occur, such as call completion, status changes, and transcripts.

## Table of Contents

1. [What are Webhooks?](#what-are-webhooks)
2. [Getting Started](#getting-started)
3. [Webhook Events](#webhook-events)
4. [Setup & Configuration](#setup--configuration)
5. [Event Payloads](#event-payloads)
6. [Best Practices](#best-practices)
7. [Testing & Debugging](#testing--debugging)
8. [Troubleshooting](#troubleshooting)

***

## What are Webhooks?

Webhooks are HTTP callbacks that allow CallIntel to send real-time notifications to your application when specific events occur. Instead of constantly polling our API for updates, webhooks push data to your system instantly.

### Key Benefits

* **Real-time Updates**: Receive instant notifications about call events
* **Reduced Latency**: No need for polling intervals
* **Efficient**: Only receive data when events occur
* **Scalable**: Handle high volumes of events asynchronously
* **Reliable**: Automatic retry mechanism for failed deliveries

### How Webhooks Work

```
1. Event occurs in CallIntel (call completed, transcript ready, etc.)
   ↓
2. System triggers webhook event
   ↓
3. HTTP POST request sent to your configured webhook URL
   ↓
4. Your application receives and processes the data
   ↓
5. Your application sends HTTP 200 response
   ↓
6. Webhook delivery marked as successful
```

***

## Getting Started

### Prerequisites

* CallIntel account with organization
* Public HTTPS URL for receiving webhooks
* Basic understanding of HTTP and JSON

### Quick Setup

1. **Navigate to Webhooks Settings**
   * Go to Organization Dashboard → Settings → Webhooks

2. **Add Webhook URL**
   * Enter your HTTPS endpoint URL
   * Example: `https://your-domain.com/webhooks/callintel`

3. **Select Events**
   * Choose which events to subscribe to
   * Save configuration

4. **Test Connection**
   * Click "Send Test Webhook"
   * Verify receipt and logging

5. **Start Receiving Events**
   * Your system is now ready to receive real-time events

***

## Webhook Events

CallIntel supports the following webhook event types:

### Call Events

<CardGroup cols={2}>
  <Card title="call.initiated" icon="phone">
    A new call has been initiated (outbound only)
  </Card>

  <Card title="call.connected" icon="link">
    Call has been successfully connected
  </Card>

  <Card title="call.in_progress" icon="hourglass">
    Call is currently in progress
  </Card>

  <Card title="call.completed" icon="check-circle">
    Call has been completed successfully
  </Card>

  <Card title="call.failed" icon="phone-xmark">
    Call failed to connect or was dropped
  </Card>

  <Card title="call.missed" icon="phone-missed">
    Inbound call was not answered
  </Card>
</CardGroup>

### Data Events

<CardGroup cols={2}>
  <Card title="call.transcript_ready" icon="message">
    Call transcript has been generated
  </Card>

  <Card title="call.recording_ready" icon="headphones">
    Call recording is available for download
  </Card>

  <Card title="call.summary_ready" icon="list">
    AI-generated call summary is ready
  </Card>

  <Card title="call.analysis_complete" icon="brain">
    Call analysis (sentiment, intent, etc.) is complete
  </Card>
</CardGroup>

### Batch Events

<CardGroup cols={2}>
  <Card title="batch.initiated" icon="phone">
    Batch call campaign has been initiated
  </Card>

  <Card title="batch.in_progress" icon="hourglass">
    Batch calls are currently being processed
  </Card>

  <Card title="batch.completed" icon="check">
    All batch calls have been completed
  </Card>

  <Card title="batch.failed" icon="close">
    Batch call campaign encountered errors
  </Card>
</CardGroup>

***

## Setup & Configuration

### Configure Webhook Endpoint

Your webhook endpoint must:

* ✅ Be publicly accessible over HTTPS
* ✅ Accept POST requests
* ✅ Return HTTP 200 status code
* ✅ Respond within 10 seconds
* ✅ Handle duplicate events

### Add Webhook URL

#### Via Dashboard

1. Go to **Organization Settings** → **Webhooks**
2. Click **"Add Webhook"**
3. Enter webhook URL: `https://your-domain.com/webhooks/callintel`
4. Select event types to subscribe
5. Click **"Save"**

#### Via API

```bash theme={null}
curl -X POST https://py.callai.rejoicehub.com/v1/webhooks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-domain.com/webhooks/callintel",
    "events": [
      "call.completed",
      "call.transcript_ready",
      "batch.completed"
    ],
    "active": true
  }'
```

### Webhook Settings

| Setting     | Description               | Default  |
| ----------- | ------------------------- | -------- |
| **URL**     | Your webhook endpoint     | Required |
| **Events**  | Event types to receive    | All      |
| **Active**  | Enable/disable webhook    | Enabled  |
| **Retry**   | Automatic retry attempts  | 3        |
| **Timeout** | Request timeout (seconds) | 10       |

***

## Event Payloads

### Call Status Changed Event

```json theme={null}
{
  "event_type": "call.completed",
  "timestamp": "2024-12-16T10:30:45Z",
  "webhook_id": "wh_1a2b3c4d5e",
  "data": {
    "id": "call_123456789",
    "call_from": "+1234567890",
    "call_to": "+0987654321",
    "agent_id": "agent_abc123",
    "agent_name": "Support Agent",
    "status": "completed",
    "direction": "outbound",
    "call_type": "voice",
    "start_time": "2024-12-16T10:25:00Z",
    "end_time": "2024-12-16T10:30:45Z",
    "duration_seconds": 345,
    "recording_url": "https://storage.callintel.com/recordings/call_123.mp3",
    "transcript_url": "https://storage.callintel.com/transcripts/call_123.txt",
    "custom_metadata": {
      "campaign_id": "camp_001",
      "customer_id": "cust_789"
    }
  }
}
```

### Call Transcript Event

```json theme={null}
{
  "event_type": "call.transcript_ready",
  "timestamp": "2024-12-16T10:31:00Z",
  "webhook_id": "wh_1a2b3c4d5e",
  "data": {
    "id": "call_123456789",
    "call_id": "call_123456789",
    "transcript": "Agent: Hello, how can I help you today? Customer: I'd like to check my order status...",
    "summary": "Customer inquired about order #12345. Agent confirmed order is in transit and will arrive by Dec 20.",
    "sentiment": "positive",
    "intent": "order_tracking",
    "actionable_items": [
      "Send customer tracking link",
      "Follow up if not delivered by Dec 20"
    ],
    "keywords": ["order", "tracking", "delivery"],
    "confidence_score": 0.95
  }
}
```

### Batch Call Event

```json theme={null}
{
  "event_type": "batch.completed",
  "timestamp": "2024-12-16T11:45:00Z",
  "webhook_id": "wh_1a2b3c4d5e",
  "data": {
    "id": "batch_987654321",
    "batch_name": "Q4 Customer Survey",
    "agent_id": "agent_abc123",
    "agent_name": "Survey Agent",
    "status": "completed",
    "total_numbers": 1000,
    "successfully_called": 856,
    "failed_calls": 144,
    "avg_duration_seconds": 287,
    "start_time": "2024-12-16T10:00:00Z",
    "end_time": "2024-12-16T11:45:00Z",
    "success_rate": 0.856,
    "cost_usd": 45.20,
    "custom_metadata": {
      "campaign_type": "survey",
      "department": "customer_success"
    }
  }
}
```

***

## Best Practices

### 1. Verify Webhook Authenticity

Always verify that webhooks are legitimate CallIntel requests:

```python theme={null}
import hmac
import hashlib
from flask import Flask, request

app = Flask(__name__)
WEBHOOK_SECRET = "your_webhook_secret"

@app.route('/webhooks/callintel', methods=['POST'])
def handle_webhook():
    # Get signature from headers
    signature = request.headers.get('X-Callintel-Signature')
    
    # Calculate expected signature
    payload = request.get_data(as_text=True)
    expected_signature = hmac.new(
        WEBHOOK_SECRET.encode(),
        payload.encode(),
        hashlib.sha256
    ).hexdigest()
    
    # Verify signature
    if not hmac.compare_digest(signature, expected_signature):
        return {'error': 'Invalid signature'}, 401
    
    # Process webhook
    data = request.get_json()
    process_event(data)
    
    return {'status': 'success'}, 200
```

### 2. Handle Duplicate Events

Events may be delivered multiple times. Use idempotency keys:

```python theme={null}
def process_event(event):
    webhook_id = event.get('webhook_id')
    
    # Check if already processed
    if WebhookLog.query.filter_by(webhook_id=webhook_id).exists():
        return  # Already processed
    
    # Process event
    event_data = event.get('data')
    # ... your logic here ...
    
    # Log webhook
    log = WebhookLog(webhook_id=webhook_id, processed_at=datetime.now())
    db.session.add(log)
    db.session.commit()
```

### 3. Implement Retry Logic

Handle temporary failures gracefully:

```python theme={null}
def handle_webhook(event):
    try:
        # Process event
        result = process_event(event)
        return {'status': 'success'}, 200
    except TemporaryError as e:
        # Return 5xx for CallIntel to retry
        return {'error': 'Temporary error'}, 503
    except PermanentError as e:
        # Log error and return 200 to prevent retries
        logger.error(f"Permanent error: {e}")
        return {'status': 'error', 'logged': True}, 200
```

### 4. Respond Quickly

Your endpoint should respond as quickly as possible:

```python theme={null}
@app.route('/webhooks/callintel', methods=['POST'])
def handle_webhook():
    event = request.get_json()
    
    # Acknowledge immediately
    result = {'status': 'received'}
    
    # Process asynchronously
    process_event_async.delay(event)
    
    return result, 202  # Accepted
```

### 5. Log All Webhooks

Maintain a log of all webhook deliveries:

```python theme={null}
def log_webhook(event, status, response):
    log = WebhookLog(
        webhook_id=event.get('webhook_id'),
        event_type=event.get('event_type'),
        status=status,
        response=response,
        received_at=datetime.now()
    )
    db.session.add(log)
    db.session.commit()
```

***

## Testing & Debugging

### Test Webhook from Dashboard

1. Navigate to **Organization Settings** → **Webhooks**
2. Select your webhook
3. Click **"Send Test Event"**
4. Choose event type to test
5. View response status and logs

### Manual Testing with curl

```bash theme={null}
# Send test webhook
curl -X POST https://your-domain.com/webhooks/callintel \
  -H "Content-Type: application/json" \
  -H "X-Callintel-Signature: test_signature" \
  -d '{
    "event_type": "call.completed",
    "timestamp": "2024-12-16T10:30:45Z",
    "webhook_id": "wh_test_123",
    "data": {
      "id": "call_test_123",
      "status": "completed",
      "duration_seconds": 300
    }
  }'
```

### Monitor Webhook Logs

#### Via Dashboard

1. Go to **Organization Settings** → **Webhooks**
2. Click **"View Logs"**
3. Filter by:
   * Date range
   * Event type
   * Status (Success/Failed/Pending)
   * Response code

#### Via API

```bash theme={null}
curl -X GET "https://py.callai.rejoicehub.com/v1/webhooks/logs?limit=50" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Debug Webhook Issues

Use these tools to debug webhook problems:

* **[Webhook.site](https://webhook.site)** - Inspect webhook requests
* **[RequestBin](https://requestbin.com)** - Test webhook delivery
* **[ngrok](https://ngrok.com)** - Expose local server for testing
* **[Postman](https://postman.com)** - Simulate webhook requests

***

## Troubleshooting

### Common Issues

#### Webhook Not Being Delivered

**Check:**

* ✅ Webhook URL is publicly accessible
* ✅ URL uses HTTPS (HTTP will be rejected)
* ✅ Endpoint accepts POST requests
* ✅ Firewall allows incoming connections
* ✅ Webhook is enabled in settings

```bash theme={null}
# Test URL accessibility
curl -X POST https://your-domain.com/webhooks/callintel \
  -H "Content-Type: application/json" \
  -d '{"test": true}'
```

#### Webhook Timeout

**Issue**: Webhook endpoint takes too long to respond

**Solution:**

* Process events asynchronously
* Respond with 202 Accepted
* Use background job queue

```python theme={null}
# ✗ WRONG - Will timeout
@app.route('/webhooks/callintel', methods=['POST'])
def handle_webhook():
    event = request.get_json()
    process_long_task(event)  # Takes 30 seconds
    return {'status': 'success'}, 200

# ✓ CORRECT - Responds quickly
@app.route('/webhooks/callintel', methods=['POST'])
def handle_webhook():
    event = request.get_json()
    queue.enqueue(process_long_task, event)
    return {'status': 'accepted'}, 202
```

#### Duplicate Event Processing

**Issue**: Same event processed multiple times

**Solution**: Implement idempotency

```python theme={null}
def process_event(event):
    webhook_id = event['webhook_id']
    
    # Use atomic operation to prevent duplicates
    created = WebhookLog.create_if_not_exists(webhook_id)
    
    if not created:
        return  # Already processed
    
    # Process event...
```

#### Invalid Signature

**Issue**: Webhook signature verification fails

**Check:**

* ✅ Using correct webhook secret
* ✅ Signature header present
* ✅ Not modifying request body
* ✅ Using correct hash algorithm (SHA-256)

### Error Response Codes

| Code    | Meaning      | Action                      |
| ------- | ------------ | --------------------------- |
| 200     | Success      | Event processed             |
| 201     | Created      | Resource created            |
| 202     | Accepted     | Will process asynchronously |
| 400     | Bad Request  | Invalid payload format      |
| 401     | Unauthorized | Invalid signature           |
| 403     | Forbidden    | Access denied               |
| 404     | Not Found    | Endpoint doesn't exist      |
| 500-599 | Server Error | Will retry automatically    |

### Get Support

If you're experiencing webhook issues:

1. **Check Logs** - Review webhook delivery logs in dashboard
2. **Test Webhook** - Send test event to verify endpoint
3. **Monitor Status** - Check Organization Health page
4. **Contact Support** - Email: [callintel01@gmail.com](mailto:callintel01@gmail.com)

***

## Advanced Configuration

### Webhook Filters

Filter events to reduce noise:

```bash theme={null}
curl -X POST https://py.callai.rejoicehub.com/v1/webhooks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-domain.com/webhooks",
    "events": ["call.completed"],
    "filters": {
      "direction": "outbound",
      "status": "completed",
      "min_duration": 60
    }
  }'
```

### Multiple Webhooks

Register multiple endpoints for different purposes:

```bash theme={null}
# Production webhook
curl -X POST https://py.callai.rejoicehub.com/v1/webhooks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "url": "https://py.callai.rejoicehub.com/webhooks",
    "events": ["call.completed", "batch.completed"]
  }'

# Analytics webhook
curl -X POST https://py.callai.rejoicehub.com/v1/webhooks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "url": "https://analytics.example.com/webhooks",
    "events": ["call.completed"]
  }'

# Backup webhook
curl -X POST https://py.callai.rejoicehub.com/v1/webhooks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "url": "https://backup.example.com/webhooks",
    "events": ["call.completed", "call.transcript_ready"]
  }'
```

### Webhook Retry Policy

Configure retry behavior:

```bash theme={null}
curl -X PUT https://py.callai.rejoicehub.com/v1/webhooks/wh_123 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "retry_policy": {
      "max_attempts": 5,
      "backoff_multiplier": 2,
      "initial_delay_seconds": 60,
      "max_delay_seconds": 3600
    }
  }'
```

***

## FAQ

<Accordion title="How long are webhooks retried?">
  Webhooks are retried up to 3 times with exponential backoff. First retry at 60 seconds, then 300 seconds, then 900 seconds.
</Accordion>

<Accordion title="Can I receive webhooks on HTTP (not HTTPS)?">
  No, webhooks must use HTTPS for security. HTTP endpoints will be rejected.
</Accordion>

<Accordion title="What if my webhook endpoint is temporarily unavailable?">
  CallIntel will retry the webhook delivery multiple times. Once all retries are exhausted, the webhook delivery is marked as failed and logged.
</Accordion>

<Accordion title="How do I verify webhook authenticity?">
  Each webhook includes an `X-Callintel-Signature` header containing an HMAC-SHA256 signature. Verify this against your webhook secret.
</Accordion>

<Accordion title="Can I filter which events I receive?">
  Yes, when registering a webhook, you can select specific event types or use filters for more granular control.
</Accordion>

<Accordion title="What's the maximum payload size?">
  Webhook payloads are limited to 10 MB. Larger payloads will be truncated or rejected.
</Accordion>

<Accordion title="How do I test webhooks locally?">
  Use ngrok to expose your local server: `ngrok http 8000`, then use the generated URL as your webhook endpoint.
</Accordion>

<Accordion title="Can I disable a webhook temporarily?">
  Yes, toggle the "Active" switch in webhook settings to disable without deleting it.
</Accordion>

***

## See Also

* [API Reference](/api-reference/introduction) - Complete API documentation
* [Call Management](/guides/core-concepts/calling) - Learn about call events
* [Organization Settings](/guides/organization/org-admin-dashboard) - Configure webhooks
* [Troubleshooting Guide](/guides/getting-started/configuration) - Common issues and solutions

***

**Happy Building! 🚀**

For support or questions about webhooks, contact us at **[callintel01@gmail.com](mailto:callintel01@gmail.com)**
