Get conversation timeline
One row per turn and span name, with start, end, duration and error count, in order.
GET
/
api
/
v1
/
traces
/
conversations
/
{conversation_id}
/
timeline
Get conversation timeline
curl --request GET \
--url https://api.example.com/api/v1/traces/conversations/{conversation_id}/timeline \
--header 'X-API-KEY: <x-api-key>'import requests
url = "https://api.example.com/api/v1/traces/conversations/{conversation_id}/timeline"
headers = {"X-API-KEY": "<x-api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-KEY': '<x-api-key>'}};
fetch('https://api.example.com/api/v1/traces/conversations/{conversation_id}/timeline', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/api/v1/traces/conversations/{conversation_id}/timeline",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-KEY: <x-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/api/v1/traces/conversations/{conversation_id}/timeline"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-KEY", "<x-api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.example.com/api/v1/traces/conversations/{conversation_id}/timeline")
.header("X-API-KEY", "<x-api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/v1/traces/conversations/{conversation_id}/timeline")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-KEY"] = '<x-api-key>'
response = http.request(request)
puts response.read_body{
"conversation_id": "<string>",
"project_id": "<string>",
"total": 123,
"entries": [
{
"turn_index": 123,
"span_name": "<string>",
"start_time": {},
"end_time": {},
"duration_ns": 123,
"duration_ms": 123,
"error_count": 123
}
]
}Collapses a conversation’s spans into a chronological timeline: for each turn and span name, when the first such span started, when the last one ended, how long they ran in total, and how many failed. Lighter than fetching every span when you want a per-turn latency picture.
Request
Headers
string
required
Account API key with read access to conversations.
Path parameters
string
required
The conversation to summarise.
Query parameters
string
The agent the conversation belongs to. Optional with an account API key.
Response
string
string
integer
Number of entries.
object[]
Ordered by
turn_index, then start_time.Show properties
Show properties
integer
null for spans outside a turn.string
datetime
Earliest start among the group’s spans, UTC.
datetime
Latest end among the group’s spans, UTC.
integer
Sum of the group’s span durations. Can be less than
end_time - start_time when the spans do not run back to back.number
integer
Spans in the group with status
Error.Example
curl "https://api.us.poly.ai/api/v1/traces/conversations/CA3f2c1e9d6b7a4f8e9c0d1b2a3c4d5e6f/timeline?project_id=PROJECT-V258TF29" \
-H "X-API-KEY: YOUR_API_KEY"
{
"conversation_id": "CA3f2c1e9d6b7a4f8e9c0d1b2a3c4d5e6f",
"project_id": "PROJECT-V258TF29",
"total": 8,
"entries": [
{
"turn_index": 0,
"span_name": "polyai.turn",
"start_time": "2026-10-27T15:07:34.930309",
"end_time": "2026-10-27T15:07:34.949381",
"duration_ns": 19071851,
"duration_ms": 19.071851,
"error_count": 0
},
{
"turn_index": 0,
"span_name": "polyai.goose.llemur.call",
"start_time": "2026-10-27T15:07:34.930317",
"end_time": "2026-10-27T15:07:34.946786",
"duration_ns": 16468707,
"duration_ms": 16.468707,
"error_count": 0
}
]
}
Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid API key. |
403 | The key cannot read conversations. |
404 | The conversation has no spans, or belongs to another account. |
502 | The trace backend did not answer. |
Last modified on November 10, 2026
Was this page helpful?
⌘I
Get conversation timeline
curl --request GET \
--url https://api.example.com/api/v1/traces/conversations/{conversation_id}/timeline \
--header 'X-API-KEY: <x-api-key>'import requests
url = "https://api.example.com/api/v1/traces/conversations/{conversation_id}/timeline"
headers = {"X-API-KEY": "<x-api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-KEY': '<x-api-key>'}};
fetch('https://api.example.com/api/v1/traces/conversations/{conversation_id}/timeline', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/api/v1/traces/conversations/{conversation_id}/timeline",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-KEY: <x-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/api/v1/traces/conversations/{conversation_id}/timeline"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-KEY", "<x-api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.example.com/api/v1/traces/conversations/{conversation_id}/timeline")
.header("X-API-KEY", "<x-api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/v1/traces/conversations/{conversation_id}/timeline")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-KEY"] = '<x-api-key>'
response = http.request(request)
puts response.read_body{
"conversation_id": "<string>",
"project_id": "<string>",
"total": 123,
"entries": [
{
"turn_index": 123,
"span_name": "<string>",
"start_time": {},
"end_time": {},
"duration_ns": 123,
"duration_ms": 123,
"error_count": 123
}
]
}
