curl -X POST https://api.bota.dev/v1/summaries \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"transcription_id": "txn_abc123",
"template_id": "tmpl_sales_call",
"provider": "gemini"
}'
const response = await fetch('https://api.bota.dev/v1/summaries', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_...',
'Content-Type': 'application/json',
},
body: JSON.stringify({
transcription_id: 'txn_abc123',
template_id: 'tmpl_sales_call',
provider: 'gemini', // optional: gemini | openai | claude
}),
});
const summary = await response.json();
console.log(summary.id); // 'sum_abc123'
console.log(summary.status); // 'pending'
import requests
response = requests.post(
'https://api.bota.dev/v1/summaries',
headers={
'Authorization': 'Bearer sk_live_...',
'Content-Type': 'application/json',
},
json={
'transcription_id': 'txn_abc123',
'template_id': 'tmpl_sales_call',
'provider': 'gemini', # optional: gemini | openai | claude
},
)
summary = response.json()
print(summary['id']) # 'sum_abc123'
{
"id": "sum_abc123",
"project_id": "proj_xyz",
"transcription_id": "txn_abc123",
"status": "pending",
"template_id": "tmpl_sales_call",
"provider": "gemini",
"custom_prompt": null,
"output": null,
"error_message": null,
"started_at": null,
"completed_at": null,
"created_at": "2025-01-15T10:10:00Z",
"updated_at": "2025-01-15T10:10:00Z"
}
{
"error": {
"code": "invalid_request",
"message": "Either template_id or prompt is required, but not both"
}
}
{
"error": {
"code": "not_found",
"message": "Transcription not found"
}
}
AI Processing
Create Summary
Generate an AI-powered summary from a transcription
POST
/
summaries
curl -X POST https://api.bota.dev/v1/summaries \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"transcription_id": "txn_abc123",
"template_id": "tmpl_sales_call",
"provider": "gemini"
}'
const response = await fetch('https://api.bota.dev/v1/summaries', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_...',
'Content-Type': 'application/json',
},
body: JSON.stringify({
transcription_id: 'txn_abc123',
template_id: 'tmpl_sales_call',
provider: 'gemini', // optional: gemini | openai | claude
}),
});
const summary = await response.json();
console.log(summary.id); // 'sum_abc123'
console.log(summary.status); // 'pending'
import requests
response = requests.post(
'https://api.bota.dev/v1/summaries',
headers={
'Authorization': 'Bearer sk_live_...',
'Content-Type': 'application/json',
},
json={
'transcription_id': 'txn_abc123',
'template_id': 'tmpl_sales_call',
'provider': 'gemini', # optional: gemini | openai | claude
},
)
summary = response.json()
print(summary['id']) # 'sum_abc123'
{
"id": "sum_abc123",
"project_id": "proj_xyz",
"transcription_id": "txn_abc123",
"status": "pending",
"template_id": "tmpl_sales_call",
"provider": "gemini",
"custom_prompt": null,
"output": null,
"error_message": null,
"started_at": null,
"completed_at": null,
"created_at": "2025-01-15T10:10:00Z",
"updated_at": "2025-01-15T10:10:00Z"
}
{
"error": {
"code": "invalid_request",
"message": "Either template_id or prompt is required, but not both"
}
}
{
"error": {
"code": "not_found",
"message": "Transcription not found"
}
}
Generate a structured summary from a completed transcription. The transcription must be in
System templates can be selected by
Auto-summary works with auto-transcription for a fully automated pipeline: upload → transcribe → summarize. See the Auto-Processing Guide for full details.
completed status.
You can create multiple summaries for the same transcription using different templates.
Use webhooks to receive real-time notifications when the summary completes, or poll the Get Summary endpoint.
Re-running and recovering a summary
A new template-based POST is a request to generate a result, not a status check. For the same transcription and template, it can delete and replace an existingcompleted or failed summary. A processing summary can also be replaced when
its creation time is more than five minutes old; a pending or more recent
processing summary rejects another create request. The old summary ID may no
longer be retrievable after replacement.
Save the returned sum_... ID and use GET to continue polling it. If a create
response is lost, reconcile the existing summaries for that transcription before
attempting another POST. Do not treat a timeout as evidence that no job was
created, or switch automatically to a new idempotency key. The generic
idempotency limitations still apply.
The Node.js summary example
demonstrates durable local intent, polling the saved ID, and explicit recovery
without automatically requesting a replacement result.
Authentication
Requires an API key withsummaries:write scope.
curl -X POST https://api.bota.dev/v1/summaries \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"transcription_id": "txn_abc123",
"template_id": "tmpl_sales_call",
"provider": "gemini"
}'
const response = await fetch('https://api.bota.dev/v1/summaries', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_...',
'Content-Type': 'application/json',
},
body: JSON.stringify({
transcription_id: 'txn_abc123',
template_id: 'tmpl_sales_call',
provider: 'gemini', // optional: gemini | openai | claude
}),
});
const summary = await response.json();
console.log(summary.id); // 'sum_abc123'
console.log(summary.status); // 'pending'
import requests
response = requests.post(
'https://api.bota.dev/v1/summaries',
headers={
'Authorization': 'Bearer sk_live_...',
'Content-Type': 'application/json',
},
json={
'transcription_id': 'txn_abc123',
'template_id': 'tmpl_sales_call',
'provider': 'gemini', # optional: gemini | openai | claude
},
)
summary = response.json()
print(summary['id']) # 'sum_abc123'
Request Body
string
required
The transcription’s unique identifier (e.g.,
txn_abc123). Must be in completed status.string
System template ID to use. One of:
tmpl_general_notes, tmpl_sales_call, tmpl_clinical_soap, tmpl_legal_memo.Either template_id or prompt is required, but not both.string
Custom prompt for one-off summaries. Use this instead of
template_id for custom summarization.Must be 10-10,000 characters. Either template_id or prompt is required, but not both.string
LLM provider to use for summarization. If not specified, uses the system default.
| Provider | Description |
|---|---|
gemini | Google Gemini 2.0 Flash (default) - JSON output |
openai | OpenAI GPT-4o - JSON mode |
claude | Anthropic Claude Sonnet 4 - Structured output |
Response
Returns the newly created summary object withpending status.
{
"id": "sum_abc123",
"project_id": "proj_xyz",
"transcription_id": "txn_abc123",
"status": "pending",
"template_id": "tmpl_sales_call",
"provider": "gemini",
"custom_prompt": null,
"output": null,
"error_message": null,
"started_at": null,
"completed_at": null,
"created_at": "2025-01-15T10:10:00Z",
"updated_at": "2025-01-15T10:10:00Z"
}
{
"error": {
"code": "invalid_request",
"message": "Either template_id or prompt is required, but not both"
}
}
{
"error": {
"code": "not_found",
"message": "Transcription not found"
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
id | string | The summary’s unique identifier (e.g., sum_abc123) |
project_id | string | The project this summary belongs to |
transcription_id | string | The transcription this summary was generated from |
status | string | Current status: pending, processing, completed, or failed |
template_id | string | null | The template used, if any |
provider | string | LLM provider used (e.g., gemini, openai, claude) |
custom_prompt | string | null | The custom prompt used, if any |
output | object | null | Structured summary output (populated on completion) |
error_message | string | null | Error message if the summary failed |
started_at | string | null | ISO 8601 timestamp when processing started |
completed_at | string | null | ISO 8601 timestamp when the summary completed or failed |
created_at | string | ISO 8601 timestamp when the summary was created |
updated_at | string | ISO 8601 timestamp when the summary was last updated |
Templates
Bota provides four built-in system templates optimized for different use cases:| Template ID | Target Industry | Output Format |
|---|---|---|
tmpl_general_notes | General meetings | Key points, action items, participants, decisions, overview |
tmpl_sales_call | Sales calls | Pain points, budget, timeline, next steps, sentiment, deal probability |
tmpl_clinical_soap | Healthcare | SOAP notes (Subjective, Objective, Assessment, Plan) |
tmpl_legal_memo | Legal consultations | Facts, issues, analysis, conclusion, parties involved |
template_id; custom one-off summaries can use prompt.
Custom Prompts
For custom summarization, use theprompt parameter instead of template_id:
curl -X POST https://api.bota.dev/v1/summaries \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"transcription_id": "txn_abc123",
"prompt": "Extract all technical requirements and action items from this conversation. Format as a bulleted list."
}'
Summary Status
| Status | Description |
|---|---|
pending | Job queued, waiting to start |
processing | Summary generation in progress |
completed | Summary generated successfully |
failed | Summary generation failed (check error_message field) |
Auto-Summary
Instead of calling this endpoint manually, you can enable auto-summary to automatically generate a summary whenever a transcription completes. Configure via the hierarchical config system:curl -X PUT https://api.bota.dev/v1/config/processing \
-H "Authorization: Bearer sk_live_..." \
-d '{
"auto_summary": {
"enabled": true,
"provider": "gemini",
"template": "general_notes"
}
}'
Webhooks (Recommended)
For production use, subscribe to webhook events instead of polling:summary.started- Processing beginssummary.completed- Summary generated successfullysummary.failed- Summary generation failed
Summary generation typically takes 5-15 seconds, depending on transcript length and template complexity.
Was this page helpful?

