Skip to main content

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
}

Extraction Results

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.
FieldTypeDescription
call_typestringType of call (e.g., "web_call", "phone_call")
from_numberstringCaller’s phone number
to_numberstringCalled phone number
directionstring"inbound" or "outbound"
call_idstringExternal provider’s call ID
agent_idstringExternal agent ID
call_statusstringExternal provider status
metadataobjectCustom metadata from the call
start_timestampnumberUnix timestamp in milliseconds
end_timestampnumberUnix timestamp in milliseconds
disconnection_reasonstringWhy the call ended
recording_urlstringURL to the call recording
opt_out_sensitive_data_storagebooleanWhether sensitive data storage is opted out

Transcript Fields

FieldTypeDescription
transcriptstringPlain text transcript of the conversation
transcript_objectarrayStructured transcript with roles and timing
transcript_with_tool_callsarrayTranscript 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
]

Metadata Fields

FieldTypeDescription
webhook_idstringYour custom webhook’s ID
log_idstringBrainbase deployment log ID
deployment_idstringBrainbase 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

StatusDescription
initiatedCall has been initiated but not yet connected
queuedCall is queued but not yet started
ongoingCall is currently in progress
completedCall has ended successfully
failedCall failed to complete
voicemailCall 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:
  1. Validate the payload - Check that required fields like webhook_id and deployment_id are present
  2. Respond quickly - Return a 200 status code promptly; process data asynchronously if needed
  3. Handle duplicates - Use log_id or call_id to deduplicate if your endpoint receives the same event twice
  4. 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