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
Create ElevenLabs Account : Sign up at ElevenLabs
Create AI Voice Agent : Set up a voice agent for emergency call handling
Configure Data Collection : Set up fields to collect emergency metadata
Set Webhook URL : Point webhook to DispatchAI endpoint
Data Collection Fields
Configure your ElevenLabs agent to collect these fields during calls:
{
"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
{
"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:
@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:
{
"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:
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:
# 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:
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:
# 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:
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:
Call Appears : New emergency call appears on map
Status Updates : Call status updates in real-time
Queue Updates : Call queue refreshes automatically
History Updates : Call history updates immediately
Best Practices
Always use webhook signature verification in production environments.
Process webhooks quickly to ensure real-time dashboard updates.
Store both summarized and full payload data for audit trails.
Monitor webhook performance and error rates continuously.
Troubleshooting
Common Issues
Check ElevenLabs webhook configuration and endpoint URL.
Verify AWS credentials and DynamoDB/S3 permissions.
Check Lambda function timeout and memory configuration.
Verify webhook secret configuration and signature format.
Production Use : Ensure proper security configuration and monitoring before deploying to production emergency response systems.