- Developers
- Call Data API
- Endpoints
- List calls and transcripts
List calls and transcripts
Return recent matching session rows and optional transcript columns. Maximum 1,000 rows.
POST https://rpt-2.trellus.ai/session-list-v6
Send start and select in a JSON body. Results are positional row arrays, newest first, with a default limit of 50 and a maximum of 1,000.
Authentication: send Authorization: Bearer $TRELLUS_API_KEY. The key inherits the user’s existing permissions. See Authentication.
curl https://rpt-2.trellus.ai/session-list-v6 \
-H "Authorization: Bearer $TRELLUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"start": 1790812800000000,
"end": 1791417600000000,
"cnf": [[{ "column_name": "conversation_type", "operator": "EQ", "value_safe": 1 }]],
"limit": 50,
"select": ["session_id", "started_at", "customer_data.name", "duration"]
}'const response = await fetch("https://rpt-2.trellus.ai/session-list-v6", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.TRELLUS_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"start": 1790812800000000,
"end": 1791417600000000,
"cnf": [[{ "column_name": "conversation_type", "operator": "EQ", "value_safe": 1 }]],
"limit": 50,
"select": ["session_id", "started_at", "customer_data.name", "duration"]
}),
});
console.log(await response.text());import os
import requests
response = requests.post(
"https://rpt-2.trellus.ai/session-list-v6",
headers={
"Authorization": f"Bearer {os.environ['TRELLUS_API_KEY']}",
"Content-Type": "application/json",
},
json={
"start": 1790812800000000,
"end": 1791417600000000,
"cnf": [[{ "column_name": "conversation_type", "operator": "EQ", "value_safe": 1 }]],
"limit": 50,
"select": ["session_id", "started_at", "customer_data.name", "duration"]
},
)
print(response.text)
[["EXAMPLE_SESSION_ID", 1790812800, "Example contact", 120]]
Headers
| Header | Description |
|---|---|
Authorization Required |
Bearer $TRELLUS_API_KEYThe API key belonging to your Trellus user. |
Content-Type Required |
application/jsonParameters go in the POST body as JSON. |
Body parameters
Send a JSON object. Requests and filters explains date units, filter groups and operators; the field reference lists every column path.
| Parameter | Description |
|---|---|
start integer, required | Inclusive UTC range start in Unix microseconds. Use Date.parse(ISO_WITH_TIMEZONE) * 1000 in JavaScript. |
end integer, optional | Exclusive UTC range end in Unix microseconds. Defaults to now. |
team_id string, optional | One permitted team per request; defaults to the key owner’s team. This does not expand access. |
cnf Filter[][], optional | AND of OR filter groups. Defaults to []. Do not use an empty inner group. |
select string[], required | Exact reporting column paths. Response cell i corresponds to select[i]. |
limit integer, optional | Default 50; minimum 1 and maximum 1000. A row cap, not a page size with a continuation token. |
Response
| Status | What you receive |
|---|---|
200 application/json |
JSON arrays in select order; started_at is Unix seconds. |
Any other status text/plain |
Read the HTTP status and response text; on 429 honor Retry-After seconds. |
- List responses are JSON arrays of positional rows. Each cell follows the request’s select order. [] is a successful query with no matching readable rows.
- Top-level request start and end use Unix microseconds. List started_at and started_at filter values use Unix seconds. Durations and transcript offsets are seconds.
- Combine turn_data.texts, turn_data.is_customers and turn_data.starts by index. true identifies customer speech; false identifies agent speech.
- Unset proto values can appear as 0, false, empty strings or empty arrays. They do not prove an event was measured. Detection flags are signals, not verified outcomes.
More on rows, units and transcripts: Responses and transcripts.
Add transcript columns
Select turn_data.texts, turn_data.is_customers and turn_data.starts to return transcript turns with each row. The example below requests October 1–7, 2026 in UTC.
curl https://rpt-2.trellus.ai/session-list-v6 \
-H "Authorization: Bearer $TRELLUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"start": 1790812800000000,
"end": 1791417600000000,
"cnf": [[{ "column_name": "conversation_type", "operator": "EQ", "value_safe": 1 }]],
"limit": 50,
"select": [
"session_id",
"started_at",
"customer_address",
"customer_data.name",
"customer_data.title",
"customer_data.company_name",
"turn_data.texts",
"turn_data.is_customers",
"turn_data.starts"
]
}'const response = await fetch("https://rpt-2.trellus.ai/session-list-v6", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.TRELLUS_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"start": 1790812800000000,
"end": 1791417600000000,
"cnf": [[{ "column_name": "conversation_type", "operator": "EQ", "value_safe": 1 }]],
"limit": 50,
"select": [
"session_id",
"started_at",
"customer_address",
"customer_data.name",
"customer_data.title",
"customer_data.company_name",
"turn_data.texts",
"turn_data.is_customers",
"turn_data.starts"
]
}),
});
console.log(await response.text());import os
import requests
response = requests.post(
"https://rpt-2.trellus.ai/session-list-v6",
headers={
"Authorization": f"Bearer {os.environ['TRELLUS_API_KEY']}",
"Content-Type": "application/json",
},
json={
"start": 1790812800000000,
"end": 1791417600000000,
"cnf": [[{ "column_name": "conversation_type", "operator": "EQ", "value_safe": 1 }]],
"limit": 50,
"select": [
"session_id",
"started_at",
"customer_address",
"customer_data.name",
"customer_data.title",
"customer_data.company_name",
"turn_data.texts",
"turn_data.is_customers",
"turn_data.starts"
]
},
)
print(response.text)
Rows beyond the limit
- Session-list returns the newest matching rows, sorted by started_at descending. There is no cursor or offset.
- Use a maximum limit of 1000. If a time window reaches the cap, divide it into smaller [start, end) windows and deduplicate by session_id. Dense windows may also require rep filters. Do not label a capped or sampled response as a complete export.
Rate limit
2 requests per 4 seconds per user by default. Shared by v5 and v6. Pace calls at least 2.5 seconds apart. See Rate limits and exports.
Errors
Error bodies can be plain text. Read the status and the response text.
400 or rejected phone, company, email or transcript field
Use the exact paths in the field guide. start and select are required for lists; metrics use selects. POST parameters belong in JSON, with Content-Type: application/json. Error responses can be plain text.
200 with [] or missing contact/transcript values
Confirm the UTC date window, readable reps and filters. Remove the live-duration filter to include short calls. Contact data depends on captured CRM enrichment; transcripts depend on recording/transcription settings. A 200 empty result is a successful query with no matching readable rows.
401 “not permissioned” or “not authorized”
The user behind the key cannot read that session or team. Check /visible and ask your team admin to review reporting access. A team_id parameter does not grant access. “inactive user” can also mean the key is invalid or the account is inactive.
429 Too Many Requests
Wait the Retry-After number of seconds, then retry with a bounded retry policy. Coordinate workers using the same user key. Default backend limits are per user, not per IP. If only your shared cloud host is blocked despite pacing, give support the UTC time, endpoint and response headers so upstream limits can be investigated.
I need every call, not just the newest 50
Set limit to at most 1000. There is no cursor or offset pagination. If a window fills the limit, split it into smaller [start, end) windows and deduplicate by session_id. A full 1000-row response does not prove the export is complete; very dense windows may also need rep filters.
Every documented case is on Errors and troubleshooting.