Webhooks
Webhooks allow your Brainbase agents to send real-time notifications to your systems when events occur. When a call ends or other events happen, Brainbase sends an HTTP POST request to your configured webhook endpoint with detailed information about the interaction.
Webhook Payload Schema
When a webhook is triggered, your endpoint receives a POST request with the following JSON payload:
{
extractions: object,
call_type?: string,
from_number?: string,
to_number?: string,
direction?: string,
call_id: string,
agent_id?: string,
call_status?: string,
metadata?: object,
start_timestamp?: number,
end_timestamp?: number,
disconnection_reason?: string,
transcript?: string,
transcript_object?: array,
transcript_with_tool_calls?: array,
recording_url?: string,
webhook_id: string,
log_id: string,
deployment_id: string,
raw_data: object,
log: object
}
The extractions object contains AI-extracted data based on your deployment’s extraction configuration.
extractions: {
// Dynamic fields based on your deployment's extraction config
customer_name: "John Smith",
appointment_date: "2024-01-15",
interested: true,
// ... any fields you configured
}
The fields in extractions are entirely defined by your extraction configuration. You can extract any structured data from the conversation.
Call Data
These fields contain information about the call itself, spread at the top level of the payload.
| Field | Type | Description |
|---|
call_type | string | Type of call (e.g., "web_call", "phone_call") |
from_number | string | Caller’s phone number |
to_number | string | Called phone number |
direction | string | "inbound" or "outbound" |
call_id | string | External provider’s call ID |
agent_id | string | External agent ID |
call_status | string | External provider status |
metadata | object | Custom metadata from the call |
start_timestamp | number | Unix timestamp in milliseconds |
end_timestamp | number | Unix timestamp in milliseconds |
disconnection_reason | string | Why the call ended |
recording_url | string | URL to the call recording |
opt_out_sensitive_data_storage | boolean | Whether sensitive data storage is opted out |
Transcript Fields
| Field | Type | Description |
|---|
transcript | string | Plain text transcript of the conversation |
transcript_object | array | Structured transcript with roles and timing |
transcript_with_tool_calls | array | Transcript including tool/function calls |
Transcript Object Structure:
transcript_object: [
{
role: "agent", // "agent" or "user"
content: "Hello, how can I help you today?",
words: [
{
word: "Hello",
start: 0.0, // Start time in seconds
end: 0.5 // End time in seconds
},
// ... more words
]
},
{
role: "user",
content: "I'd like to schedule an appointment.",
words: [...]
}
// ... more messages
]
| Field | Type | Description |
|---|
webhook_id | string | Your custom webhook’s ID |
log_id | string | Brainbase deployment log ID |
deployment_id | string | Brainbase deployment ID |
Raw Data
The raw_data object contains the original data from batch/outbound calls. This is your outbound_data that was passed when initiating the call.
raw_data: {
// Your original data from CSV or API
id: "row_123",
phoneNumber: "+15551234567",
firstName: "John",
lastName: "Smith",
email: "[email protected]",
customField1: "value1"
// ... any fields from your data source
}
For inbound calls, raw_data may be empty or contain minimal data. For outbound batch calls, this contains the full row data you provided.
Full Log Object
The log object contains the complete VoiceDeploymentLog from the database with all session details.
log: {
// Identifiers
id: "log_abc123...",
workerId: string,
deploymentId: string,
flowId: string,
bbEngineSessionId: string,
externalCallId: string,
call_sid: string, // Twilio call SID
// Timestamps
createdAt: "2024-01-15T10:30:00Z",
updatedAt: "2024-01-15T10:35:00Z",
startTime: "2024-01-15T10:30:00Z",
endTime: "2024-01-15T10:35:00Z",
// Call details
direction: "inbound" | "outbound",
fromNumber: string,
toNumber: string,
status: "queued" | "ongoing" | "completed" | "failed",
duration: 300, // Duration in seconds
Telephony_source: "twilio",
// Content
transcription: string, // Plain text transcript
messages: [ // Structured transcript
{ role: "agent", content: "..." },
{ role: "user", content: "..." }
],
recordingUrl: string,
// Stored data
extractionsData: object, // Stored extraction results
metadata: object,
flowSnapshot: string, // Flow code at time of call
sessionLogData: object, // Session data from engine
// Nested data object
data: {
event: "call_ended",
call_ended: object, // Full call_ended event payload
outbound_data: {
// Same as raw_data
},
extraction: {
status: "processing" | "completed",
queuedAt: "2024-01-15T10:35:00Z"
}
}
}
Log Status Values
| Status | Description |
|---|
initiated | Call has been initiated but not yet connected |
queued | Call is queued but not yet started |
ongoing | Call is currently in progress |
completed | Call has ended successfully |
failed | Call failed to complete |
voicemail | Call went to voicemail |
Example Payload
Here’s a complete example of a webhook payload:
{
"extractions": {
"customer_name": "John Smith",
"appointment_confirmed": true,
"preferred_date": "2024-01-20",
"notes": "Prefers morning appointments"
},
"call_type": "phone_call",
"from_number": "+14154650216",
"to_number": "+14158738252",
"direction": "inbound",
"call_id": "call_abc123",
"call_status": "completed",
"start_timestamp": 1705312200000,
"end_timestamp": 1705312500000,
"disconnection_reason": "customer_ended_call",
"transcript": "Agent: Hello, how can I help you today?\nUser: I'd like to schedule an appointment...",
"recording_url": "https://storage.example.com/recordings/call_abc123.mp3",
"webhook_id": "wh_xyz789",
"log_id": "log_def456",
"deployment_id": "deploy_a05e0b20-87ed-440b-9cd4-0427cc812c41",
"raw_data": {
"firstName": "John",
"lastName": "Smith",
"phoneNumber": "+14154650216",
"email": "[email protected]"
},
"log": {
"id": "log_def456",
"createdAt": "2024-01-15T10:30:00Z",
"status": "completed",
"duration": 300,
"direction": "inbound",
"fromNumber": "+14154650216",
"toNumber": "+14158738252"
}
}
Handling Webhooks
When processing webhook payloads, we recommend:
- Validate the payload - Check that required fields like
webhook_id and deployment_id are present
- Respond quickly - Return a 200 status code promptly; process data asynchronously if needed
- Handle duplicates - Use
log_id or call_id to deduplicate if your endpoint receives the same event twice
- Store raw payloads - Consider logging the full payload for debugging purposes
# Example webhook handler (Python/Flask)
@app.route('/webhook', methods=['POST'])
def handle_webhook():
payload = request.json
# Extract key fields
extractions = payload.get('extractions', {})
log_id = payload.get('log_id')
direction = payload.get('direction')
# Process the data
if extractions.get('appointment_confirmed'):
schedule_appointment(
customer=extractions.get('customer_name'),
date=extractions.get('preferred_date')
)
return {'status': 'ok'}, 200