Skip to main content

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
  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:
{
  "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:
  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

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.