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

# Webhook Integration

> Integrate ElevenLabs AI voice agent with access911 platform

## Webhook Overview

access911 integrates with ElevenLabs AI voice agents to process real emergency calls. The webhook system captures call transcripts, extracts emergency metadata, and stores the information in AWS services for real-time dashboard updates.

## ElevenLabs Configuration

### Voice Agent Setup

1. **Create ElevenLabs Account**: Sign up at [ElevenLabs](https://elevenlabs.io)
2. **Create AI Voice Agent**: Set up a voice agent for emergency call handling
3. **Configure Data Collection**: Set up fields to collect emergency metadata
4. **Set Webhook URL**: Point webhook to DispatchAI endpoint

### Data Collection Fields

Configure your ElevenLabs agent to collect these fields during calls:

```json theme={null}
{
  "emergency_type": {
    "type": "text",
    "description": "Type of emergency (fire, medical, etc.)",
    "required": true
  },
  "location": {
    "type": "text", 
    "description": "Location or address of emergency",
    "required": true
  },
  "latitude": {
    "type": "number",
    "description": "Latitude coordinate",
    "required": false
  },
  "longitude": {
    "type": "number",
    "description": "Longitude coordinate", 
    "required": false
  },
  "severity": {
    "type": "text",
    "description": "Emergency severity level",
    "required": true
  }
}
```

## Webhook Endpoint

### Endpoint URL

```
https://your-api-gateway-url/elevenlabs-webhook
```

### Webhook Configuration

Set up your ElevenLabs agent webhook with these settings:

* **Event Type**: `post_call_transcription`
* **Method**: POST
* **Content-Type**: application/json
* **Secret**: Optional webhook secret for verification

## Webhook Payload

### Incoming Webhook Structure

```json theme={null}
{
  "type": "post_call_transcription",
  "event_timestamp": 1703123456,
  "data": {
    "conversation_id": "conv_123456789",
    "agent_id": "agent_emergency_911",
    "status": "completed",
    "transcript": [
      {
        "speaker": "caller",
        "text": "Hello, I need help. There's a fire at my house.",
        "timestamp": 1703123400
      },
      {
        "speaker": "agent",
        "text": "I understand you have an emergency. Can you tell me your location?",
        "timestamp": 1703123405
      }
    ],
    "analysis": {
      "transcript_summary": "Caller reported house fire and provided location details.",
      "call_successful": true,
      "data_collection_results": {
        "emergency_type": {
          "value": "structure_fire",
          "rationale": "Caller explicitly mentioned house fire"
        },
        "location": {
          "value": "1234 Main Street, Anytown",
          "rationale": "Caller provided specific address"
        },
        "latitude": {
          "value": 34.0522,
          "rationale": "Geocoded from provided address"
        },
        "longitude": {
          "value": -118.2437,
          "rationale": "Geocoded from provided address"
        },
        "severity": {
          "value": "critical",
          "rationale": "Structure fire is always critical priority"
        }
      }
    },
    "metadata": {
      "call_duration_secs": 180,
      "language": "en-US"
    }
  }
}
```

### Webhook Processing

The webhook handler processes incoming calls:

```python theme={null}
@app.post("/elevenlabs-webhook")
async def webhook(request: Request):
    # 1. Verify webhook signature (optional)
    signature_header = request.headers.get("elevenlabs-signature")
    if signature_header and WEBHOOK_SECRET:
        # Verify signature for security
        pass
    
    # 2. Parse incoming data
    data = await request.json()
    
    # 3. Extract emergency metadata
    analysis = data.get("data", {}).get("analysis", {})
    metadata = extract_metadata_from_elevenlabs(analysis)
    
    # 4. Store in DynamoDB
    save_to_dynamodb(conversation_id, timestamp, call_data, analysis, metadata)
    
    # 5. Store full payload in S3
    save_to_s3(conversation_id, data)
    
    return {"status": "success", "message": "Webhook received"}
```

## Data Storage

### DynamoDB Storage

Emergency calls are stored in DynamoDB with this structure:

```json theme={null}
{
  "conversation_id": "conv_123456789",
  "timestamp": 1703123456,
  "agent_id": "agent_emergency_911",
  "summary": "Caller reported house fire and provided location details.",
  "call_successful": true,
  "duration_secs": 180,
  "transcript_length": 15,
  "created_at": "2023-12-21T10:30:56.789Z",
  "emergency_type": "structure_fire",
  "location": "1234 Main Street, Anytown",
  "latitude": 34.0522,
  "longitude": -118.2437,
  "severity": "critical"
}
```

### S3 Storage

Full webhook payloads are stored in S3 for audit and analysis:

```
s3://your-bucket/calls/conv_123456789/conv_123456789_20231221_103056.json
```

## Security

### Webhook Signature Verification

Optional webhook signature verification for security:

```python theme={null}
def verify_webhook_signature(signature_header, body, secret):
    if not signature_header or not secret:
        return True  # Skip verification if not configured
    
    # Parse signature header
    headers_parts = signature_header.split(",")
    timestamp = None
    signature = None
    
    for part in headers_parts:
        if part.startswith("t="):
            timestamp = part[2:]
        elif part.startswith("v0="):
            signature = part
    
    # Verify timestamp (within 30 minutes)
    if timestamp:
        req_timestamp = int(timestamp) * 1000
        tolerance = int(time.time() * 1000) - (30 * 60 * 1000)
        if req_timestamp <= tolerance:
            return False
    
    # Verify signature
    if timestamp and signature:
        message = f"{timestamp}.{body.decode('utf-8')}"
        expected_digest = 'v0=' + hmac.new(
            key=secret.encode("utf-8"),
            msg=message.encode("utf-8"),
            digestmod=sha256
        ).hexdigest()
        return hmac.compare_digest(signature, expected_digest)
    
    return False
```

### Environment Variables

Configure these environment variables:

```bash theme={null}
# Webhook security
ELEVENLABS_WEBHOOK_SECRET=your_webhook_secret_here

# AWS configuration
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=your_access_key
AWS_SECRET_ACCESS_KEY=your_secret_key
DYNAMODB_TABLE_NAME=emergency-calls
S3_BUCKET_NAME=emergency-call-storage
```

## Error Handling

### Webhook Error Responses

The webhook handler returns appropriate HTTP status codes:

* **200 OK**: Webhook processed successfully
* **400 Bad Request**: Invalid webhook payload
* **401 Unauthorized**: Invalid webhook signature
* **500 Internal Server Error**: Processing error

### Error Logging

Comprehensive error logging for debugging:

```python theme={null}
try:
    # Process webhook
    result = process_webhook(data)
    return {"status": "success", "message": "Webhook received"}
except Exception as e:
    print(f"❌ EXCEPTION OCCURRED:")
    print(f"   Type: {type(e).__name__}")
    print(f"   Message: {str(e)}")
    import traceback
    traceback.print_exc()
    return {"status": "error", "message": str(e)}
```

## Testing

### Local Testing

Test webhook integration locally:

```bash theme={null}
# Start local webhook server
python webhook_server.py

# Test webhook endpoint
curl -X POST http://localhost:8000/elevenlabs-webhook \
  -H "Content-Type: application/json" \
  -d '{
    "type": "post_call_transcription",
    "event_timestamp": 1703123456,
    "data": {
      "conversation_id": "test_conv_123",
      "agent_id": "test_agent",
      "status": "completed",
      "transcript": [],
      "analysis": {
        "transcript_summary": "Test emergency call",
        "call_successful": true,
        "data_collection_results": {
          "emergency_type": {"value": "test"},
          "location": {"value": "Test Location"},
          "severity": {"value": "moderate"}
        }
      }
    }
  }'
```

### Webhook Validation

Validate webhook configuration:

```python theme={null}
def test_webhook_endpoint():
    # Test webhook signature verification
    # Test data extraction
    # Test DynamoDB storage
    # Test S3 storage
    pass
```

## Monitoring

### Webhook Metrics

Monitor webhook performance:

* **Incoming Requests**: Number of webhook requests received
* **Processing Time**: Time to process each webhook
* **Success Rate**: Percentage of successfully processed webhooks
* **Error Rate**: Number of failed webhook processing attempts

### Dashboard Updates

Webhook processing triggers real-time dashboard updates:

1. **Call Appears**: New emergency call appears on map
2. **Status Updates**: Call status updates in real-time
3. **Queue Updates**: Call queue refreshes automatically
4. **History Updates**: Call history updates immediately

## Best Practices

<AccordionGroup>
  <Accordion icon="shield" title="Security">
    Always use webhook signature verification in production environments.
  </Accordion>

  <Accordion icon="clock" title="Performance">
    Process webhooks quickly to ensure real-time dashboard updates.
  </Accordion>

  <Accordion icon="database" title="Data Integrity">
    Store both summarized and full payload data for audit trails.
  </Accordion>

  <Accordion icon="monitor" title="Monitoring">
    Monitor webhook performance and error rates continuously.
  </Accordion>
</AccordionGroup>

## Troubleshooting

### Common Issues

<AccordionGroup>
  <Accordion icon="wifi" title="Webhook Not Receiving">
    Check ElevenLabs webhook configuration and endpoint URL.
  </Accordion>

  <Accordion icon="database" title="Storage Issues">
    Verify AWS credentials and DynamoDB/S3 permissions.
  </Accordion>

  <Accordion icon="clock" title="Slow Processing">
    Check Lambda function timeout and memory configuration.
  </Accordion>

  <Accordion icon="shield" title="Signature Errors">
    Verify webhook secret configuration and signature format.
  </Accordion>
</AccordionGroup>

<Note>
  **Production Use**: Ensure proper security configuration and monitoring before deploying to production emergency response systems.
</Note>
