curl --request GET \
--url https://{host}/api/v1/cdrs/{uuid}/conversation \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://{host}/api/v1/cdrs/{uuid}/conversation', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://{host}/api/v1/cdrs/{uuid}/conversation"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text){
"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>",
"assembled_context": "<string>",
"turns": [
{
"at": "2023-11-07T05:31:56Z",
"role": "caller",
"seq": 123,
"text": "<string>",
"tool_args": {},
"tool_name": "<string>",
"tool_result": {}
}
]
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}The conversation for a call
Keyed on the call rather than the conversation, for the call-detail screen. Scoped through the CDR.
curl --request GET \
--url https://{host}/api/v1/cdrs/{uuid}/conversation \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://{host}/api/v1/cdrs/{uuid}/conversation', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://{host}/api/v1/cdrs/{uuid}/conversation"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text){
"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>",
"assembled_context": "<string>",
"turns": [
{
"at": "2023-11-07T05:31:56Z",
"role": "caller",
"seq": 123,
"text": "<string>",
"tool_args": {},
"tool_name": "<string>",
"tool_result": {}
}
]
}{
"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.
Response
OK
human, virtual byo means the tenant's own credential paid, so they were billed by the provider directly and no amount appears here.
byo, rated What the operator paid the provider. Absent without margin:read, and absent whenever the tenant's own key paid.
What the AI on this call cost, as an exact decimal string. ABSENT, never zero, in three situations that must not be confused: the caller lacks billing:read, no price row matched the model, or the tenant's own credential paid the provider so there is nothing for us to charge.
False when the provider itemised no audio tokens at all. It changes how every figure here should be read: tokens_audio is then "not reported" rather than "none", and the audio was priced at the TEXT rate because there is no other number to price it at. Reported so an approximate amount is not read as an exact one. Gemini reports no split.
inbound, outbound The post-call review of an AI agent's conversation. competitor: an agent turn named one of the profile's competitor_names (seq is the turn). never_searched: the knowledge base was too large to give the agent whole and it answered without searching it. Empty when the review found nothing, or did not run (a human agent).
Show child attributes
Show child attributes
Null for a human-handled call.
The audio PORTION of tokens_input, not a third total. Adding it to input charges the audio twice. Counts as the provider reported them, not money: prices change, and an amount computed from a hardcoded price is silently wrong later.
The profile that handled this call, as it was at the time. Not a live reference to the agent's current profile.
The profile's name as recorded when the call ran, so a later rename does not restate history.
Exactly what the agent was told before it spoke.
Show child attributes
Show child attributes