curl -X POST https://api.bota.dev/v1/ask/sessions/as_abc123/messages \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "content": "And what about the next sprint?" }'
const response = await fetch('https://api.bota.dev/v1/ask/sessions/as_abc123/messages', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_...',
'Content-Type': 'application/json',
},
body: JSON.stringify({ content: 'And what about the next sprint?' }),
});
const { session_id, message, sources } = await response.json();
import requests
response = requests.post(
'https://api.bota.dev/v1/ask/sessions/as_abc123/messages',
headers={
'Authorization': 'Bearer sk_live_...',
'Content-Type': 'application/json',
},
json={'content': 'And what about the next sprint?'},
)
result = response.json()
{
"session_id": "as_abc123",
"message": {
"id": "msg_def456",
"role": "assistant",
"content": "You agreed to send the budget draft by Friday.",
"parts": [
{ "type": "text", "text": "You agreed to send the budget draft by Friday." },
{ "type": "citation", "recording_id": "rec_ghi789", "start_ms": 754000 }
],
"tokens": { "input": 1240, "output": 32, "cached": 0 },
"model": "gemini-2.0-flash",
"provider": "gemini",
"finish_reason": "stop",
"created_at": "2026-05-20T10:23:45Z"
},
"sources": [
{
"chunk_id": "chk_jkl012",
"recording_id": "rec_ghi789",
"transcription_id": "txn_mno345",
"chunk_text": "I'll send the budget draft by Friday.",
"speaker": "SPEAKER_1",
"start_ms": 754000,
"end_ms": 759000,
"recorded_at": "2026-05-16T09:12:00Z",
"score": 0.0312
}
]
}
AI Ask
Send Message
Append a message to a session and get the assistant’s answer
POST
/
ask
/
sessions
/
{id}
/
messages
curl -X POST https://api.bota.dev/v1/ask/sessions/as_abc123/messages \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "content": "And what about the next sprint?" }'
const response = await fetch('https://api.bota.dev/v1/ask/sessions/as_abc123/messages', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_...',
'Content-Type': 'application/json',
},
body: JSON.stringify({ content: 'And what about the next sprint?' }),
});
const { session_id, message, sources } = await response.json();
import requests
response = requests.post(
'https://api.bota.dev/v1/ask/sessions/as_abc123/messages',
headers={
'Authorization': 'Bearer sk_live_...',
'Content-Type': 'application/json',
},
json={'content': 'And what about the next sprint?'},
)
result = response.json()
{
"session_id": "as_abc123",
"message": {
"id": "msg_def456",
"role": "assistant",
"content": "You agreed to send the budget draft by Friday.",
"parts": [
{ "type": "text", "text": "You agreed to send the budget draft by Friday." },
{ "type": "citation", "recording_id": "rec_ghi789", "start_ms": 754000 }
],
"tokens": { "input": 1240, "output": 32, "cached": 0 },
"model": "gemini-2.0-flash",
"provider": "gemini",
"finish_reason": "stop",
"created_at": "2026-05-20T10:23:45Z"
},
"sources": [
{
"chunk_id": "chk_jkl012",
"recording_id": "rec_ghi789",
"transcription_id": "txn_mno345",
"chunk_text": "I'll send the budget draft by Friday.",
"speaker": "SPEAKER_1",
"start_ms": 754000,
"end_ms": 759000,
"recorded_at": "2026-05-16T09:12:00Z",
"score": 0.0312
}
]
}
Append a user message to an existing session and receive the assistant’s answer. This is the multi-turn continuation of a conversation; the scope is taken from the session, so you never resend it. Answers cite their sources: each citation in
message.parts deep-links to a recording_id + start_ms.
The request body is the same message shape used for initial_message when creating a session, so a client can use one composer for both.
Authentication
Requires an API key. The session is looked up within the key’s project; an unknown session returns404. An end-user-scoped key can only post to its own sessions.
curl -X POST https://api.bota.dev/v1/ask/sessions/as_abc123/messages \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "content": "And what about the next sprint?" }'
const response = await fetch('https://api.bota.dev/v1/ask/sessions/as_abc123/messages', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_...',
'Content-Type': 'application/json',
},
body: JSON.stringify({ content: 'And what about the next sprint?' }),
});
const { session_id, message, sources } = await response.json();
import requests
response = requests.post(
'https://api.bota.dev/v1/ask/sessions/as_abc123/messages',
headers={
'Authorization': 'Bearer sk_live_...',
'Content-Type': 'application/json',
},
json={'content': 'And what about the next sprint?'},
)
result = response.json()
Path Parameters
string
required
Session identifier (
as_*).Request Body
string
required
The user’s message (1–10000 characters).
string
LLM provider to use for this turn (
gemini, openai, or claude). Defaults to the project/system default.array
@mentioned recordings to attach to this turn:
[{ "type": "recording", "id": "rec_..." }] (max 20). Reserved for upcoming features; persisted today.Response
Returns the ask result — the assistant message and the session it belongs to.{
"session_id": "as_abc123",
"message": {
"id": "msg_def456",
"role": "assistant",
"content": "You agreed to send the budget draft by Friday.",
"parts": [
{ "type": "text", "text": "You agreed to send the budget draft by Friday." },
{ "type": "citation", "recording_id": "rec_ghi789", "start_ms": 754000 }
],
"tokens": { "input": 1240, "output": 32, "cached": 0 },
"model": "gemini-2.0-flash",
"provider": "gemini",
"finish_reason": "stop",
"created_at": "2026-05-20T10:23:45Z"
},
"sources": [
{
"chunk_id": "chk_jkl012",
"recording_id": "rec_ghi789",
"transcription_id": "txn_mno345",
"chunk_text": "I'll send the budget draft by Friday.",
"speaker": "SPEAKER_1",
"start_ms": 754000,
"end_ms": 759000,
"recorded_at": "2026-05-16T09:12:00Z",
"score": 0.0312
}
]
}
Response Fields
| Field | Type | Description |
|---|---|---|
session_id | string | The conversation session (as_*) |
message | object | The assistant message |
message.parts | array | Rich content: text segments and citation parts ({ type, recording_id, start_ms }) |
message.tokens | object | Token usage { input, output, cached } |
sources | array | Retrieved chunks fed into the prompt (cross-recording scopes only; empty for recording) — same shape as Search Recordings |
The user message is persisted before the model is called, so on an LLM failure (
502) you can safely retry with the returned session_id. A recording-scoped session whose transcription isn’t ready returns 409; an oversized single-recording transcript returns 413 (use a cross-recording scope instead).Was this page helpful?

