curl --request GET \
--url https://{host}/api/v1/conversations \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://{host}/api/v1/conversations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://{host}/api/v1/conversations"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text){
"items": [
{
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"agent_kind": "human",
"ai_billing_mode": "byo",
"ai_cost_amount": "<string>",
"ai_sell_amount": "<string>",
"audio_split_known": true,
"call_uuid": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"contact_e164": "<string>",
"contact_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"direction": "inbound",
"ended_at": "2023-11-07T05:31:56Z",
"flags": [
{
"detail": "<string>",
"kind": "competitor",
"seq": 123
}
],
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"model": "<string>",
"organisation_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"provider": "<string>",
"started_at": "2023-11-07T05:31:56Z",
"summary": "<string>",
"tokens_audio": 123,
"tokens_input": 123,
"tokens_output": 123,
"turn_count": 123,
"virtual_agent_profile_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"virtual_agent_profile_name": "<string>"
}
],
"limit": 123,
"offset": 123,
"total": 123
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}List conversations
One per call, whoever handled it: provider and model are null for a human-handled call, which is what keeps this from being an AI log with a general-sounding name. Read-only — a conversation is a record of what happened, and an editable transcript is not one. assembled_context is omitted here and returned only for a single conversation, because it can run to kilobytes per row. Requires conversations:read, separate from recordings:listen: searchable text of every word and a person’s recorded voice are different disclosures.
curl --request GET \
--url https://{host}/api/v1/conversations \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://{host}/api/v1/conversations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://{host}/api/v1/conversations"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text){
"items": [
{
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"agent_kind": "human",
"ai_billing_mode": "byo",
"ai_cost_amount": "<string>",
"ai_sell_amount": "<string>",
"audio_split_known": true,
"call_uuid": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"contact_e164": "<string>",
"contact_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"direction": "inbound",
"ended_at": "2023-11-07T05:31:56Z",
"flags": [
{
"detail": "<string>",
"kind": "competitor",
"seq": 123
}
],
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"model": "<string>",
"organisation_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"provider": "<string>",
"started_at": "2023-11-07T05:31:56Z",
"summary": "<string>",
"tokens_audio": 123,
"tokens_input": 123,
"tokens_output": 123,
"turn_count": 123,
"virtual_agent_profile_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"virtual_agent_profile_name": "<string>"
}
],
"limit": 123,
"offset": 123,
"total": 123
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}Authorizations
Every request sends Authorization: Bearer <token>. The token is either a panel session (a JWT from /auth/login, 12 hours) or an API key ft_<id>_<secret>. An API key is accepted only from an address on its IP allowlist (403 ip_not_allowed otherwise; 403 ip_allowlist_required for an old key that has none), is limited to its rate per minute (429 rate_limited with Retry-After; X-RateLimit-Limit/Remaining/Reset on every response), and at most 60 call placements a minute.
Query Parameters
x <= 500Sort key. Each list accepts its own allow-list of keys, given in that endpoint's description; anything else is a 400. ORDER BY cannot be parameterised, so the key is looked up rather than interpolated. Every sort carries a tiebreak on the primary key, so paging stays disjoint when the sort column has duplicates.
Sort direction. Defaults to ascending, except the call log, which reads newest first.
asc, desc Free-text search across the list's searchable columns (case-insensitive substring). % and _ in the term match themselves.
true: only conversations the post-call review flagged; false: only those it did not.