Search spans
Find spans across conversations by name, status, duration and time window.
POST
/
api
/
v1
/
traces
/
spans
/
search
Search spans
curl --request POST \
--url https://api.example.com/api/v1/traces/spans/search \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <x-api-key>' \
--data '
{
"project_id": "<string>",
"span_name": "<string>",
"conversation_id": "<string>",
"status_code": "<string>",
"min_duration_ms": 123,
"from": {},
"to": {},
"limit": 123,
"offset": 123
}
'import requests
url = "https://api.example.com/api/v1/traces/spans/search"
payload = {
"project_id": "<string>",
"span_name": "<string>",
"conversation_id": "<string>",
"status_code": "<string>",
"min_duration_ms": 123,
"from": {},
"to": {},
"limit": 123,
"offset": 123
}
headers = {
"X-API-KEY": "<x-api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-KEY': '<x-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
project_id: '<string>',
span_name: '<string>',
conversation_id: '<string>',
status_code: '<string>',
min_duration_ms: 123,
from: {},
to: {},
limit: 123,
offset: 123
})
};
fetch('https://api.example.com/api/v1/traces/spans/search', 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/spans/search",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'project_id' => '<string>',
'span_name' => '<string>',
'conversation_id' => '<string>',
'status_code' => '<string>',
'min_duration_ms' => 123,
'from' => [
],
'to' => [
],
'limit' => 123,
'offset' => 123
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"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"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/api/v1/traces/spans/search"
payload := strings.NewReader("{\n \"project_id\": \"<string>\",\n \"span_name\": \"<string>\",\n \"conversation_id\": \"<string>\",\n \"status_code\": \"<string>\",\n \"min_duration_ms\": 123,\n \"from\": {},\n \"to\": {},\n \"limit\": 123,\n \"offset\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-KEY", "<x-api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/api/v1/traces/spans/search")
.header("X-API-KEY", "<x-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"project_id\": \"<string>\",\n \"span_name\": \"<string>\",\n \"conversation_id\": \"<string>\",\n \"status_code\": \"<string>\",\n \"min_duration_ms\": 123,\n \"from\": {},\n \"to\": {},\n \"limit\": 123,\n \"offset\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/v1/traces/spans/search")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-KEY"] = '<x-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"project_id\": \"<string>\",\n \"span_name\": \"<string>\",\n \"conversation_id\": \"<string>\",\n \"status_code\": \"<string>\",\n \"min_duration_ms\": 123,\n \"from\": {},\n \"to\": {},\n \"limit\": 123,\n \"offset\": 123\n}"
response = http.request(request)
puts response.read_body{
"spans": [
{}
],
"limit": 123,
"offset": 123,
"has_more": true
}Searches spans across all conversations of the account or one agent. Use it to find the slowest or failing operations of a given kind, then open the conversation they belong to. For counts and percentiles use aggregate spans instead.
Request
Headers
string
required
Account API key with read access to conversations.
Body
string
Restrict to one agent. Omit to search the whole account.
string
Exact span name, for example
polyai.llm_gateway.provider_call.string
Restrict to one conversation.
string
Ok, Error or Unset.integer
Only spans at least this long, 0–86,400,000.
datetime
Inclusive lower bound on span start.
datetime
Exclusive upper bound on span start.
integer
default:"20"
Spans per page, 1–100.
integer
default:"0"
Spans to skip, 0–1000.
Response
object[]
Same fields as in get conversation spans, newest first.
integer
integer
boolean
Example
Failed LLM calls slower than one second
curl -X POST https://api.us.poly.ai/api/v1/traces/spans/search \
-H "X-API-KEY: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"project_id": "PROJECT-V258TF29",
"span_name": "polyai.llm_gateway.provider_call",
"status_code": "Error",
"min_duration_ms": 1000,
"from": "2026-10-26T00:00:00Z",
"to": "2026-10-28T00:00:00Z",
"limit": 2
}'
{
"spans": [
{
"timestamp": "2026-10-27T08:02:07.129899",
"trace_id": "a9ef4a96c0582a560b74f8c7eafb29dd",
"span_id": "dcceb1840a7d4ec3",
"parent_span_id": "47bcc81194662cda",
"span_name": "polyai.llm_gateway.provider_call",
"span_kind": "Client",
"duration_ns": 5010374548,
"duration_ms": 5010.374548,
"status_code": "Error",
"conversation_id": "CA3f2c1e9d6b7a4f8e9c0d1b2a3c4d5e6f",
"project_id": "PROJECT-V258TF29",
"turn_index": 1,
"function_name": null,
"function_execution_id": null,
"function_originating_turn_index": null,
"function_attempt": null,
"prompt_tokens": null,
"cached_tokens": null,
"prefix_cache_hit_ratio": null
}
],
"limit": 2,
"offset": 0,
"has_more": true
}
Errors
| Status | Meaning |
|---|---|
400 | from is not before to. |
401 | Missing or invalid API key. |
403 | The key cannot read conversations. |
422 | A value is outside its range. |
502 | The trace backend did not answer. |
Last modified on November 10, 2026
Was this page helpful?
⌘I
Search spans
curl --request POST \
--url https://api.example.com/api/v1/traces/spans/search \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <x-api-key>' \
--data '
{
"project_id": "<string>",
"span_name": "<string>",
"conversation_id": "<string>",
"status_code": "<string>",
"min_duration_ms": 123,
"from": {},
"to": {},
"limit": 123,
"offset": 123
}
'import requests
url = "https://api.example.com/api/v1/traces/spans/search"
payload = {
"project_id": "<string>",
"span_name": "<string>",
"conversation_id": "<string>",
"status_code": "<string>",
"min_duration_ms": 123,
"from": {},
"to": {},
"limit": 123,
"offset": 123
}
headers = {
"X-API-KEY": "<x-api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-KEY': '<x-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
project_id: '<string>',
span_name: '<string>',
conversation_id: '<string>',
status_code: '<string>',
min_duration_ms: 123,
from: {},
to: {},
limit: 123,
offset: 123
})
};
fetch('https://api.example.com/api/v1/traces/spans/search', 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/spans/search",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'project_id' => '<string>',
'span_name' => '<string>',
'conversation_id' => '<string>',
'status_code' => '<string>',
'min_duration_ms' => 123,
'from' => [
],
'to' => [
],
'limit' => 123,
'offset' => 123
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"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"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/api/v1/traces/spans/search"
payload := strings.NewReader("{\n \"project_id\": \"<string>\",\n \"span_name\": \"<string>\",\n \"conversation_id\": \"<string>\",\n \"status_code\": \"<string>\",\n \"min_duration_ms\": 123,\n \"from\": {},\n \"to\": {},\n \"limit\": 123,\n \"offset\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-KEY", "<x-api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/api/v1/traces/spans/search")
.header("X-API-KEY", "<x-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"project_id\": \"<string>\",\n \"span_name\": \"<string>\",\n \"conversation_id\": \"<string>\",\n \"status_code\": \"<string>\",\n \"min_duration_ms\": 123,\n \"from\": {},\n \"to\": {},\n \"limit\": 123,\n \"offset\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/v1/traces/spans/search")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-KEY"] = '<x-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"project_id\": \"<string>\",\n \"span_name\": \"<string>\",\n \"conversation_id\": \"<string>\",\n \"status_code\": \"<string>\",\n \"min_duration_ms\": 123,\n \"from\": {},\n \"to\": {},\n \"limit\": 123,\n \"offset\": 123\n}"
response = http.request(request)
puts response.read_body{
"spans": [
{}
],
"limit": 123,
"offset": 123,
"has_more": true
}
