This page documents all webhook event types, their triggers, and payload schemas.
Event Structure
All events follow this structure:
{
"id" : "evt_abc123def456" ,
"type" : "event.type" ,
"created_at" : "2025-01-15T10:30:00Z" ,
"data" : {
// Event-specific payload
}
}
Field Type Description idstring Unique event identifier. Use for deduplication. typestring Event type (e.g., transcription.completed) created_atstring ISO 8601 timestamp of when the event occurred dataobject Event-specific payload (see below)
Recording Events
recording.created
Triggered when a new recording is created via the API.
{
"id" : "evt_abc123" ,
"type" : "recording.created" ,
"created_at" : "2025-01-15T10:00:00Z" ,
"data" : {
"id" : "rec_xyz789" ,
"end_user_id" : "eu_user123" ,
"device_id" : "dev_device456" ,
"status" : "created" ,
"consent_obtained" : true ,
"metadata" : {
"session_type" : "consultation"
},
"created_at" : "2025-01-15T10:00:00Z"
}
}
Field Type Description data.idstring Recording ID data.end_user_idstring Associated EndUser data.device_idstring Device that will capture the recording data.statusstring Always created for this event data.consent_obtainedboolean Whether consent was recorded data.metadataobject Custom metadata attached to the recording data.created_atstring When the recording was created
Common Use Cases:
Track new recordings in your system
Initialize processing pipelines
Update UI to show recording in progress
recording.uploaded
Triggered when audio upload completes successfully.
{
"id" : "evt_def456" ,
"type" : "recording.uploaded" ,
"created_at" : "2025-01-15T10:05:00Z" ,
"data" : {
"id" : "rec_xyz789" ,
"end_user_id" : "eu_user123" ,
"device_id" : "dev_device456" ,
"status" : "uploaded" ,
"duration_seconds" : 1847.5 ,
"file_size_bytes" : 44328000 ,
"format" : "wav" ,
"started_at" : "2025-01-15T09:30:00Z" ,
"ended_at" : "2025-01-15T10:00:47Z" ,
"uploaded_at" : "2025-01-15T10:05:00Z"
}
}
Field Type Description data.idstring Recording ID data.statusstring Always uploaded for this event data.duration_secondsnumber Audio duration in seconds data.file_size_bytesinteger File size in bytes data.formatstring Audio format (wav, mp3, m4a, flac) data.started_atstring When recording started (device time) data.ended_atstring When recording ended (device time) data.uploaded_atstring When upload completed
Common Use Cases:
Trigger transcription automatically
Update recording status in your UI
Calculate storage usage
recording.deleted
Triggered when a recording is deleted via the API.
{
"id" : "evt_rst345" ,
"type" : "recording.deleted" ,
"created_at" : "2025-01-15T11:00:00Z" ,
"data" : {
"id" : "rec_xyz789" ,
"deleted_at" : "2025-01-15T11:00:00Z"
}
}
Field Type Description data.idstring Recording ID that was deleted data.deleted_atstring When the recording was deleted
When a recording is deleted, all associated transcriptions and summaries are also deleted (cascade delete).
Common Use Cases:
Clean up local cached data
Update UI to remove deleted recordings
Audit logging for compliance
Transcription Events
transcription.started
Triggered when transcription processing begins.
{
"id" : "evt_uvw678" ,
"type" : "transcription.started" ,
"created_at" : "2025-01-15T10:05:30Z" ,
"data" : {
"id" : "txn_abc123" ,
"recording_id" : "rec_xyz789" ,
"status" : "processing" ,
"language" : "en" ,
"created_at" : "2025-01-15T10:05:20Z" ,
"started_at" : "2025-01-15T10:05:30Z"
}
}
Field Type Description data.idstring Transcription ID data.recording_idstring Associated recording data.statusstring Always processing for this event data.languagestring Language code (specified or auto-detected) data.started_atstring When processing started
Common Use Cases:
Show “processing” status in UI
Track processing time metrics
Trigger dependent workflows
transcription.completed
Triggered when transcription processing completes successfully.
{
"id" : "evt_ghi789" ,
"type" : "transcription.completed" ,
"created_at" : "2025-01-15T10:07:00Z" ,
"data" : {
"id" : "txn_abc123" ,
"recording_id" : "rec_xyz789" ,
"status" : "completed" ,
"text" : "Hello, thank you for coming in today. How can I help you?" ,
"duration_seconds" : 1847.5 ,
"segments" : [
{
"start" : 0.0 ,
"end" : 2.5 ,
"text" : "Hello, thank you for coming in today." ,
"speaker" : "SPEAKER_00" ,
"confidence" : 0.95
},
{
"start" : 2.8 ,
"end" : 4.2 ,
"text" : "How can I help you?" ,
"speaker" : "SPEAKER_00" ,
"confidence" : 0.97
}
],
"speakers" : [
{
"id" : "SPEAKER_00" ,
"label" : "Speaker 1"
},
{
"id" : "SPEAKER_01" ,
"label" : "Speaker 2"
}
],
"language" : "en" ,
"created_at" : "2025-01-15T10:05:30Z" ,
"completed_at" : "2025-01-15T10:07:00Z"
}
}
Field Type Description data.idstring Transcription ID data.recording_idstring Associated recording data.statusstring Always completed for this event data.textstring Full transcript text data.duration_secondsnumber Audio duration processed data.segmentsarray Timestamped segments with speaker labels data.segments[].startnumber Segment start time (seconds) data.segments[].endnumber Segment end time (seconds) data.segments[].textstring Segment text data.segments[].speakerstring Speaker identifier data.segments[].confidencenumber Confidence score (0-1) data.speakersarray List of detected speakers data.languagestring Detected language code data.completed_atstring When transcription finished
Common Use Cases:
Display transcript to users
Trigger summarization
Index for search
Extract action items or entities
transcription.failed
Triggered when transcription processing fails.
{
"id" : "evt_jkl012" ,
"type" : "transcription.failed" ,
"created_at" : "2025-01-15T10:07:00Z" ,
"data" : {
"id" : "txn_abc123" ,
"recording_id" : "rec_xyz789" ,
"status" : "failed" ,
"error" : {
"code" : "audio_quality_insufficient" ,
"message" : "Audio quality is too low for accurate transcription"
},
"created_at" : "2025-01-15T10:05:30Z" ,
"failed_at" : "2025-01-15T10:07:00Z"
}
}
Field Type Description data.idstring Transcription ID data.recording_idstring Associated recording data.statusstring Always failed for this event data.error.codestring Error code data.error.messagestring Human-readable error message data.failed_atstring When transcription failed
Error Codes:
Code Description audio_quality_insufficientAudio too noisy or unclear audio_too_shortRecording less than 1 second audio_format_unsupportedInvalid audio format processing_errorInternal processing error timeoutProcessing exceeded time limit
Common Use Cases:
Alert users to recording issues
Retry with different settings
Log for quality monitoring
Summary Events
summary.started
Triggered when summary generation begins.
{
"id" : "evt_xyz012" ,
"type" : "summary.started" ,
"created_at" : "2025-01-15T10:07:30Z" ,
"data" : {
"id" : "sum_def456" ,
"transcription_id" : "txn_abc123" ,
"recording_id" : "rec_xyz789" ,
"status" : "processing" ,
"template" : "clinical" ,
"created_at" : "2025-01-15T10:07:20Z" ,
"started_at" : "2025-01-15T10:07:30Z"
}
}
Field Type Description data.idstring Summary ID data.transcription_idstring Source transcription data.recording_idstring Original recording data.statusstring Always processing for this event data.templatestring Template used (general, sales, clinical, legal) data.started_atstring When processing started
Common Use Cases:
Show “generating summary” status in UI
Track processing time metrics
Update workflow progress indicators
summary.completed
Triggered when summary generation completes successfully.
{
"id" : "evt_mno345" ,
"type" : "summary.completed" ,
"created_at" : "2025-01-15T10:08:00Z" ,
"data" : {
"id" : "sum_def456" ,
"transcription_id" : "txn_abc123" ,
"recording_id" : "rec_xyz789" ,
"status" : "completed" ,
"text" : "The patient presented with symptoms of seasonal allergies. Dr. Smith recommended over-the-counter antihistamines and a follow-up in two weeks if symptoms persist." ,
"template" : "medical_note" ,
"created_at" : "2025-01-15T10:07:30Z" ,
"completed_at" : "2025-01-15T10:08:00Z"
}
}
Field Type Description data.idstring Summary ID data.transcription_idstring Source transcription data.recording_idstring Original recording data.statusstring Always completed for this event data.textstring Generated summary text data.templatestring Template used (if specified) data.completed_atstring When summary finished
Common Use Cases:
Display summary to users
Send notification that processing is complete
Update clinical notes or CRM records
summary.failed
Triggered when summary generation fails.
{
"id" : "evt_pqr678" ,
"type" : "summary.failed" ,
"created_at" : "2025-01-15T10:08:00Z" ,
"data" : {
"id" : "sum_def456" ,
"transcription_id" : "txn_abc123" ,
"recording_id" : "rec_xyz789" ,
"status" : "failed" ,
"error" : {
"code" : "content_policy_violation" ,
"message" : "Content could not be summarized due to policy restrictions"
},
"failed_at" : "2025-01-15T10:08:00Z"
}
}
Field Type Description data.error.codestring Error code data.error.messagestring Human-readable error message
Device Events (Optional)
These events are available for enterprise customers who enable device monitoring.
device.low_battery
Triggered when device battery falls below 20%.
{
"id" : "evt_stu901" ,
"type" : "device.low_battery" ,
"created_at" : "2025-01-15T14:00:00Z" ,
"data" : {
"id" : "dev_device456" ,
"end_user_id" : "eu_user123" ,
"battery_percent" : 15 ,
"last_sync_at" : "2025-01-15T13:55:00Z"
}
}
device.offline
Triggered when device hasn’t synced for 24+ hours.
{
"id" : "evt_vwx234" ,
"type" : "device.offline" ,
"created_at" : "2025-01-16T10:00:00Z" ,
"data" : {
"id" : "dev_device456" ,
"end_user_id" : "eu_user123" ,
"last_sync_at" : "2025-01-15T10:00:00Z" ,
"hours_offline" : 24
}
}
Device events require enterprise plan and explicit opt-in during webhook registration.
Subscribing to Events
When creating a webhook, specify which events to receive:
curl -X POST https://api.bota.dev/v1/webhooks \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/bota",
"events": [
"recording.created",
"recording.uploaded",
"recording.deleted",
"transcription.started",
"transcription.completed",
"transcription.failed",
"summary.started",
"summary.completed",
"summary.failed"
]
}'
Event Wildcards
Use * to subscribe to all events:
{
"url" : "https://your-app.com/webhooks/bota" ,
"events" : [ "*" ]
}
Or subscribe to all events in a category:
{
"url" : "https://your-app.com/webhooks/bota" ,
"events" : [ "recording.*" , "transcription.*" ]
}
Event Delivery Order
Events are delivered in the order they occur, but network conditions may cause out-of-order arrival. Design your handlers to be order-independent.
Example Timeline:
recording.created — Recording entry created
recording.uploaded — Audio upload completed (may be minutes/hours later)
transcription.started — Transcription processing begins
transcription.completed — Transcription finished
summary.started — Summary generation begins
summary.completed — Summary generated
Each event is independent. You may receive transcription.completed before your handler has finished processing recording.uploaded.
Handling Tips
Async Processing
Process events asynchronously to avoid timeouts:
app . post ( '/webhooks/bota' , async ( req , res ) => {
// Respond immediately
res . status ( 200 ). send ( 'OK' );
// Queue for async processing
await eventQueue . add ( 'process-webhook' , req . body );
});
Type-Safe Handlers
Use TypeScript or schema validation:
type BotaEvent =
| { type : 'recording.created' ; data : RecordingCreatedData }
| { type : 'transcription.completed' ; data : TranscriptionCompletedData }
| { type : 'summary.completed' ; data : SummaryCompletedData };
function handleEvent ( event : BotaEvent ) {
switch ( event . type ) {
case 'recording.created' :
// event.data is typed as RecordingCreatedData
break ;
case 'transcription.completed' :
// event.data is typed as TranscriptionCompletedData
break ;
}
}
Webhooks Overview Setup, verification, and best practices
Create Webhook API endpoint reference