Confirm the key and readable scope
Call /visible first. It returns the readable directory for one team, including user and group IDs. The team field appears only with whole-team read access.
Public documentation
Read call records, transcripts and outcomes. Build reports with counts, duration totals and breakdowns, then retrieve the details or audio for a selected call.
Use the API key belonging to your Trellus user. In Trellus, open Settings → Integrations → API (the Call Data API page) to copy your own key. Keep it in a server-side environment variable named TRELLUS_API_KEY.
The key inherits the user’s existing permissions. It is not a separately restricted read-only credential. Verify the readable users with /visible; team_id never grants access.
Do not place API keys in browser code, query strings, analytics, logs, public repositories or prompts. Contact support to replace an exposed key.
| API host | Headers |
|---|---|
ext.trellus.ai | api_key: $TRELLUS_API_KEY |
rpt-2.trellus.ai | Authorization: Bearer $TRELLUS_API_KEY |
api.trellus.ai/get-audio-links | api_key: $TRELLUS_API_KEY and session_id: SESSION_ID |
curl https://ext.trellus.ai/visible \
-H "api_key: $TRELLUS_API_KEY"
The directory includes readable users, a user ID to email mapping, groups and memberships. team appears only when the user can read the whole team. Its absence does not mean authentication failed.
{
"team": { "team_id": "...", "team": "..." },
"users": [{ "user_id": "...", "user_name": "..." }],
"user_id_to_email": { "...": "rep@example.com" },
"groups": [],
"memberships": []
}
Start with a bounded date window and a short list of columns. The example below requests October 1–7, 2026 in UTC. Use the request builder to choose your own dates. Examples on this page never send requests or ask you to enter a key.
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"]
}'
Use the directory to resolve people, reporting endpoints to answer questions, and detail endpoints for one selected call.
https://ext.trellus.ai/visible
Start here. Returns the team, users, emails, groups, and memberships this key can see.
Authentication: api_key header
Optionally send a team_id header to select a team you are permitted to read. Match users[].user_id to resource_id in call rows. Memberships connect user_group_id and member_id; member_is_group identifies group members.
curl https://ext.trellus.ai/visible \
-H "api_key: $TRELLUS_API_KEY"
https://ext.trellus.ai/bootstrap
Load the complete account context and exact disposition, sentiment, and purpose values.
Authentication: api_key header
This returns the key owner’s account configuration and filter vocabulary. It is not a call list. Use it for exact configured disposition, sentiment and purpose strings instead of guessing labels.
curl https://ext.trellus.ai/bootstrap \
-H "api_key: $TRELLUS_API_KEY"
https://rpt-2.trellus.ai/session-list-v6
Return recent matching session rows and optional transcript columns. Maximum 1,000 rows.
Authentication: Bearer token
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.
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"]
}'
https://rpt-2.trellus.ai/metric-details-v7
Calculate counts and numeric sums, optionally filtered or grouped by a reporting column.
Authentication: Bearer token
Send start and selects in a JSON body. Each select returns a count or sum. A group_by value becomes the first cell in each row.
curl https://rpt-2.trellus.ai/metric-details-v7 \
-H "Authorization: Bearer $TRELLUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"start": 1790812800000000,
"end": 1791417600000000,
"selects": [
{ "cnf": [] },
{ "column_name": "duration" },
{ "cnf": [[{ "column_name": "dial_metric.live_duration", "operator": "GE", "value_safe": 30 }]] }
],
"cnf": [[{ "column_name": "conversation_type", "operator": "EQ", "value_safe": 1 }]],
"group_by": { "column_name": "user_log.disposition" }
}'
https://rpt-2.trellus.ai/session
Fetch one complete session after session-list returns the session_id you want to inspect.
Authentication: Bearer token + x-session-id
Send the exact list-row ID in the x-session-id header. A query parameter or JSON body is not used. Add x-proto-as-json: true for camelCase JSON; otherwise the response is binary protobuf. JSON omits wordData.
curl https://rpt-2.trellus.ai/session \
-H "Authorization: Bearer $TRELLUS_API_KEY" \
-H "x-session-id: SESSION_ID" \
-H "x-proto-as-json: true"
https://api.trellus.ai/get-audio-links
Return temporary download URLs for one readable call. Generate them only when needed.
Authentication: api_key + session_id headers
The response is { session, audio, audio_links }: one session object and two arrays aligned by index. URLs expire after one hour. Beyond recording retention, audio arrays may be empty. Within retention, a non-call session returns 400.
curl https://api.trellus.ai/get-audio-links \
-H "api_key: $TRELLUS_API_KEY" \
-H "session_id: SESSION_ID"
List and metrics requests use Content-Type: application/json. Put parameters in the POST body.
| Parameter | Type / requirement | Meaning |
|---|---|---|
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 for lists | Exact reporting column paths. Response cell i corresponds to select[i]. |
limit | integer Optional for lists | Default 50; minimum 1 and maximum 1000. A row cap, not a page size with a continuation token. |
selects | Aggregate[] Required for metrics | Ordered count or sum definitions. Each select can include cnf, column_name, or both. Empty {} is invalid. |
group_by | object Optional for metrics | Reporting column_name. Prepends the group value to each result row. |
start and end are Unix microseconds. Returned started_at and values in a started_at filter are Unix seconds. Duration and transcript offsets are also seconds. The date range includes its start and excludes its end.const start = Date.parse("2026-10-01T00:00:00Z") * 1000;
const end = Date.parse("2026-10-08T00:00:00Z") * 1000;
// A returned list started_at value uses seconds:
const startedAt = new Date(started_at * 1000);
cnf is an AND list of OR groups: every outer group must match, and at least one condition inside each group must match. An empty outer list adds no extra filter. Avoid empty inner groups.
Each condition needs column_name, operator and value_safe. Use actual booleans, numbers or strings. IN and NIN take arrays. Recognized enum fields accept their names or numeric values; byte values use base64. user_log.source is a numeric field for list results and filters: use the documented numeric codes, not their explanatory labels.
{
"cnf": [
[
{
"column_name": "conversation_type",
"operator": "EQ",
"value_safe": 1
}
],
[
{
"column_name": "resource_id",
"operator": "IN",
"value_safe": [
"REP_ID_ONE",
"REP_ID_TWO"
]
}
],
[
{
"column_name": "user_log.disposition",
"operator": "EQ",
"value_safe": "YOUR_INTERESTED_OPTION"
},
{
"column_name": "dial_metric.live_duration",
"operator": "GE",
"value_safe": 30
}
]
]
}
| Operator | Meaning |
|---|---|
EQ | Equal to the typed value. |
NEQ | Not equal to the typed value. |
GT | Greater than. |
GE | Greater than or equal to. |
LT | Less than. |
LE | Less than or equal to. |
IN | One of the values in the value_safe array. |
NIN | Not in the value_safe array. |
REGEX | Search a string with the backend regular-expression engine; look-around and backreferences are not supported. |
Select an array as a whole, use a concrete path such as agents.[0].agent_id, or project members with agents.[*].agent_id. A filter containing [*] requires reducer: "ANY" or reducer: "ALL". Do not add a reducer to a filter without [*]; select projections do not use reducers.
customer_data.custom_fields is JSON text in list results. Parse it before reading keys. Captured keys vary by account and source; there is no guaranteed standard contact email column.
Replace sample rep IDs and outcome labels with the values returned by /visible and /bootstrap. agent_joined: false alone is not a universal definition of a missed call: combine it with call type and inbound filters for that analysis.
[{ "column_name": "dial_metric.is_inbound", "operator": "EQ", "value_safe": true }]
[{ "column_name": "duration", "operator": "GE", "value_safe": 300 }]
[{ "column_name": "dial_metric.live_duration", "operator": "GE", "value_safe": 30 }]
[{ "column_name": "agent_joined", "operator": "EQ", "value_safe": false }]
[{ "column_name": "resource_id", "operator": "EQ", "value_safe": "USER_ID" }]
[{ "column_name": "resource_id", "operator": "EQ", "value_safe": "USER_ID_FROM_BOOTSTRAP" }]
[{ "column_name": "user_log.disposition", "operator": "IN", "value_safe": ["Interested", "Demo booked"] }]
[{ "column_name": "user_log.purpose", "operator": "EQ", "value_safe": "Follow up" }]
// Example only: select = ["session_id", "started_at", "customer_data.name"]
// Response: [["CALL_ID", 1791849600, "Example contact"]]
const calls = rows.map(row => Object.fromEntries(
select.map((column, index) => [column, row[index]])
));
const startedAt = calls[0] ? new Date(calls[0].started_at * 1000) : null;
// Transcript columns are aligned arrays:
const turns = texts.map((text, index) => ({
text,
speaker: isCustomers[index] ? "customer" : "agent",
startSeconds: starts[index]
}));
// /session with x-proto-as-json: true uses different JSON spelling:
// { "sessionId": "CALL_ID", "customerData": { "name": "Example contact" },
// "turnData": { "texts": ["Hello"], "isCustomers": [true], "starts": [0] } }
// Default-valued proto fields may be omitted. wordData is omitted.
// Grouped metrics: selects = [{"cnf": []}, {"column_name": "duration"}]
// Example response: [["Interested", 12, 840]]
// Read as: disposition, count, summed duration in seconds.
| What you need | Column | How to use it |
|---|---|---|
| Call ID | session_id | Copy the exact string into the x-session-id header for /session. |
| Call time | started_at | Unix seconds in list rows. Convert with new Date(value * 1000). |
| Customer phone/address | customer_address | For phone calls, the customer address; phone is not a column name. |
| Rep ID | resource_id | Match to users[].user_id from /visible. |
| Contact name | customer_data.name | Use this instead of prospect_name or name. |
| Contact title | customer_data.title | Use this instead of title. |
| Company | customer_data.company_name | Use this instead of company. |
| Company website | customer_data.company_url | May be empty when not enriched. |
| Contact email / custom data | customer_data.custom_fields | No standard email column. Custom fields are JSON text; inspect available keys rather than assuming email exists. |
| Transcript text | turn_data.texts | Array of utterances, not one transcript string. |
| Transcript speaker | turn_data.is_customers | Aligned with texts: true = customer, false = agent. |
| Transcript timing | turn_data.starts | Aligned with texts; seconds from the start of the session. |
| Call duration | duration | Seconds. dial_metric.live_duration measures the live portion. |
| Saved outcome | user_log.disposition | Use /bootstrap for your exact configured option strings. |
Use metric-details-v7 for totals across a date range. This avoids treating the limited rows from a list request as a total.
curl https://rpt-2.trellus.ai/metric-details-v7 \
-H "Authorization: Bearer $TRELLUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"start": 1790812800000000,
"end": 1791417600000000,
"selects": [
{ "cnf": [] },
{ "column_name": "duration" },
{ "cnf": [[{ "column_name": "dial_metric.live_duration", "operator": "GE", "value_safe": 30 }]] }
],
"cnf": [[{ "column_name": "conversation_type", "operator": "EQ", "value_safe": 1 }]],
"group_by": { "column_name": "user_log.disposition" }
}'
metric-details-v7 uses the reporting column paths from session-list-v6.
Each item in selects produces one numeric result cell:
- { "cnf": [] } counts every session in the time window.
- { "cnf": [[filter]] } counts sessions matching that filter.
- { "column_name": "duration" } sums a numeric or boolean column.
- A select may contain both column_name and cnf to sum only matching sessions.
group_by adds a group value as the first cell in every row:
- { "column_name": "resource_id" } gives one row per rep/resource.
- { "column_name": "user_log.disposition" } gives one row per disposition.
- { "column_name": "dial_metric.is_inbound" } separates inbound and non-inbound calls.
The remaining cells stay in the same order as selects. Use /visible to map resource_id values to user names. Use /bootstrap to discover exact disposition strings.
Each aggregation’s filters are additional to the top-level cnf. A sum can use a numeric or boolean column; summing a boolean counts true values. An empty aggregation object is invalid.
Call /visible first. It returns the readable directory for one team, including user and group IDs. The team field appears only with whole-team read access.
Use session-list-v6 with conversation_type = 1 and dial_metric.live_duration >= 30. Do not require SIP 200 by default, because processed calls can come from non-Trellus telephony. Include transcript columns when snippets are enough.
Use metric-details-v7 for counts, numeric sums, and categorical breakdowns. It accepts the same reporting column paths used by session-list-v6. Only fetch session rows when the user asks which calls caused the metric or wants transcript evidence.
Use /visible to resolve user names to resource_id values. Use /bootstrap when you also need exact user_log.disposition, user_log.sentiment, or user_log.purpose strings.
Pass limit in the session-list-v6 JSON body. Use limit: 1000 for bulk pulls, then narrow by rep, disposition, date, call type, or duration. For broader history, split windows that reach the limit and merge rows by session_id; a capped response is not a complete export.
Choose a readable call from session-list, then call /get-audio-links with its session_id header. The returned links expire after one hour; request them only when you are ready to play or download the audio.
150 selectable fields and 17 documented array members, with types, definitions and enum values. These are reporting paths, not arbitrary CRM property names. List paths use snake_case; single-session JSON uses camelCase.
Member paths written with .[]. explain the contents of an object array. They are not literal query paths: select the parent array or use .[0]. / .[*].. Recognized enum columns and projections return names; values inside whole object arrays may remain numeric. user_log.source returns a numeric code and requires numeric filter values.
167 documented fields and members
| Field / type | Definition and values |
|---|---|
session_idstring |
Unique session identifier. Use the exact returned string in the x-session-id header for detail or session_id header for audio. |
team_idstring |
Team owning this session; selecting a team does not grant permission to read it. |
started_atuint32 |
Session start as Unix seconds. List/metric request start and end instead use Unix microseconds. |
conversation_typeenum |
Kind of conversation; CONVERSATION_TYPE_CALL (1) identifies calls.
|
customer_addressstring |
Customer address; a phone number for phone calls. There is no phone alias. |
agent_addressstring |
Agent-side address associated with the session; not a user identifier. |
address_typeenum |
Address category, such as phone, email or web.
|
resource_idstring |
Resource/user associated with this session. For rep reports, resolve against /visible users[].user_id. |
provisioning_team_idstring |
Provisioning/partner team identifier, when present; not the team_id to assume for report access. |
is_provisionalbool |
True while the stored session snapshot is provisional rather than finalized. |
customer_joinedbool |
Whether the customer channel joined. This can include automated answering; it does not prove a human conversation. |
customer_joined_atfloat |
Customer join offset in seconds from session start; zero can be unset. |
agent_joinedbool |
Whether an agent connection joined, including a user, voice bot or bridged number. Not a human-only answer flag. |
agent_joined_atfloat |
Legacy aggregate agent join offset in seconds; may remain unset. Prefer agents[].joined_at for participant timing. |
durationfloat |
Total session duration in seconds, including ringing/queue time. Use dial_metric.live_duration for the live portion. |
customer_wordsint32 |
Backend customer word-count statistic for eligible turns; approximate, not an exact transcript token count. |
agent_wordsint32 |
Backend agent word-count statistic for eligible turns; approximate, not an exact transcript token count. |
end_reasonenum |
Recorded reason the session ended; unknown can mean it was not populated.
|
customer_turn_durationfloat |
Sum of eligible customer transcript-turn durations in seconds. Outbound dial turns before the live portion are excluded. |
agent_turn_durationfloat |
Sum of eligible agent transcript-turn durations in seconds. Outbound dial turns before the live portion are excluded. |
| Field / type | Definition and values |
|---|---|
agentsobject[] |
Joined agent connections; may include users, bots and numbers. See member definitions below. |
agents.[].agent_idstring |
Identifier of this connected participant; interpret together with agent_type rather than assuming every ID is a rep user ID. |
agents.[].agent_typeenum |
Participant kind (user, voice bot or number, among the schema enum values).
|
agents.[].joined_atfloat |
Participant join offset in seconds from session start. |
agents.[].left_atfloat |
Participant leave offset in seconds from session start; session end is used if no earlier leave time is recorded. |
| Field / type | Definition and values |
|---|---|
privacy.customer_recordedbool |
Customer audio recording policy flag; does not guarantee a retained file is currently downloadable. |
privacy.agent_recordedbool |
Agent audio recording policy flag; does not guarantee a retained file is currently downloadable. |
privacy.customer_transcript_persistedbool |
Whether customer transcript persistence is permitted. |
privacy.agent_transcript_persistedbool |
Whether agent transcript persistence is permitted. |
privacy.customer_transcribedbool |
Whether customer streaming transcription is enabled. |
privacy.agent_transcribedbool |
Whether agent streaming transcription is enabled. |
privacy.is_zdrbool |
Zero data retention mode; persisted transcript content is suppressed and cost data may remain. |
privacy.transcribe_may_logbool |
Whether transcription logging is permitted by the account policy. Does not indicate recording availability. |
audio_filesobject[] |
Stored recording-file metadata, not playable URLs. Request temporary download links from /get-audio-links. |
audio_files.[].uploaded_keystring |
Recording reference, not a download URL. Use /get-audio-links to request temporary audio download URLs. |
audio_files.[].audio_file_typeenum |
Recording channel/file category.
|
audio_files.[].startfloat |
Recording start offset in seconds from session start. |
| Field / type | Definition and values |
|---|---|
word_data.startsfloat[] |
Word start offsets in seconds from session start; aligned with ends, words and is_customers. |
word_data.endsfloat[] |
Word end offsets in seconds from session start; aligned with starts, words and is_customers. |
word_data.wordsstring[] |
Individual recognized words. /session JSON intentionally clears wordData; use turn_data for a transcript. |
word_data.is_customersbool[] |
Word speakers: true = customer, false = agent; aligned with words. |
word_data.known_atsfloat[] |
Offsets in seconds from session origin when words became known to the live processor; diagnostic latency data, not wall-clock timestamps. |
sound_data.tone_startsfloat[] |
Detected tone start offsets in seconds from session start; pair with tone_ends by index. |
sound_data.tone_endsfloat[] |
Detected tone end offsets in seconds from session start; pair with tone_starts by index. |
sound_data.music_startsfloat[] |
Detected music start offsets in seconds from session start; pair with music_ends by index. |
sound_data.music_endsfloat[] |
Detected music end offsets in seconds from session start; pair with music_starts by index. |
turn_data.startsfloat[] |
Utterance start offsets in seconds from session start; aligned by index with ends, texts and is_customers. |
turn_data.endsfloat[] |
Utterance end offsets in seconds from session start; aligned by index with starts, texts and is_customers. |
turn_data.textsstring[] |
Array of utterance strings, not one transcript string. Content may be empty or redacted by transcription/retention settings. |
turn_data.is_customersbool[] |
Utterance speakers: true = customer, false = agent; aligned by index with texts, starts and ends. |
| Field / type | Definition and values |
|---|---|
stateJSON text |
Session evaluation/context state as JSON text in list rows. Keys vary; inspect rather than inventing a fixed schema. |
platformenum |
Integration/platform where the session originated.
|
base_pathstring |
Opaque call context metadata. Do not construct API URLs from this value. |
client_versionstring |
Originating client/extension version when captured. |
phone_typestring |
Phone-type metadata supplied by the originating client. No fixed vocabulary is defined here. |
telephony_customer_call_idstring |
Telephony provider identifier for the customer call leg; distinct from session_id. |
alternate_addressstring |
Alternate customer address supplied on dial creation, when available. |
predicted_pickupfloat |
Optional model pickup probability, clipped to (0, 1] when supplied. Zero/default means no populated prediction, not a measured pickup outcome. |
custom_metricsJSON text |
Deprecated custom metrics as JSON text. Prefer supported named metrics; do not assume stable custom keys. |
| Field / type | Definition and values |
|---|---|
dial_metric.sip_codeint32 |
Telephony SIP response/status code, when recorded. Zero can mean no code was captured. |
dial_metric.is_connectedbool |
Whether the customer channel connected; automated voicemail/menu connections can also satisfy this. |
dial_metric.is_dialbool |
Whether the session was created through the dial flow; use is_inbound separately for direction. |
dial_metric.ringing_atfloat |
Ringing start offset in seconds from session start; zero can be unset. |
dial_metric.telephonyenum |
Telephony category recorded for the session, represented by the listed enum values.
|
dial_metric.connected_durationfloat |
Customer connected-channel duration in seconds; does not by itself measure human talk time. |
dial_metric.is_livebool |
Whether outbound-call analysis identified a live portion. Inbound processing may populate live_duration without this flag. |
dial_metric.live_durationfloat |
Live portion duration in seconds, measured from detected live start for analyzed outbound calls; inbound calls use customer-channel duration. |
dial_metric.live_open_ended_atfloat |
Offset in seconds where the detected opening live utterance ended; diagnostic bridge timing. |
dial_metric.live_open_known_atfloat |
Offset in seconds when the processor first recognized the live opening; diagnostic detection timing. |
dial_metric.live_open_is_bridgedbool |
Whether an agent bridge time was found for the detected live opening. |
dial_metric.live_open_delay_to_bridgefloat |
Non-negative seconds between detected live-opening end and agent bridge; meaningful with live_open_is_bridged. |
dial_metric.live_stated_atfloat |
Detected live-opening start offset in seconds from session start; zero can be unset. |
dial_metric.has_voicemailbool |
Whether call analysis detected voicemail, including a full mailbox. |
dial_metric.has_screenbool |
Whether call analysis detected a call-screening prompt. |
dial_metric.has_menubool |
Whether call analysis detected an automated menu. |
dial_metric.left_voicemailbool |
Backend inference/known-provider signal that voicemail was left; not proof of a retained recording. |
dial_metric.left_screenbool |
Backend inference that screening was passed or agent speech was provided after the screening prompt. |
dial_metric.is_inboundbool |
True for inbound calls; false for outbound/default. Combine with conversation_type for call reports. |
dial_metric.is_trellus_telephonybool |
Whether the call uses Trellus telephony rather than an external/copilot bridge. |
dial_metric.is_autodialbool |
Single-line autodial indicator; current creation path sets true when configured parallel_lines is 1. |
dial_metric.parallel_linesint32 |
Configured simultaneous dial-line count; a configuration value, not the number of connected participants. |
dial_metric.is_bridge_user_firstbool |
Stored user-first bridge-strategy flag. Do not infer actual participant order from this flag; use connection timing. |
dial_metric.is_timeoutbool |
Whether the dial ended through a no-answer timeout. |
| Field / type | Definition and values |
|---|---|
quality_metric.said_do_not_callbool |
Detected do-not-call expression. A signal, not an independently verified legal/compliance determination. |
quality_metric.said_not_audiblebool |
Customer speech matched a cannot-hear/not-audible expression. |
quality_metric.said_angrybool |
Customer or agent speech matched profanity/anger expressions. |
quality_metric.said_spambool |
Detected statement that the phone number shows as spam. |
quality_metric.said_scambool |
Customer speech matched an accusation of a scam/fraud. |
quality_metric.said_risky_numbersbool |
Speech mentioned sensitive financial/identity numbers, such as SSN or credit card numbers. |
quality_metric.said_risky_credentialsbool |
Speech matched sharing/requesting credentials or account/password information. |
quality_metric.said_risky_paymentbool |
Speech matched offering/requesting a money transfer/payment. |
quality_metric.said_representativebool |
Customer speech requested a representative, agent or operator. |
| Field / type | Definition and values |
|---|---|
sales_metric.has_prospectbool |
Detected prospect participation. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_gatekeeperbool |
Detected gatekeeper participation. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_obj_denybool |
Detected denial/rejection objection. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_obj_wrong_personbool |
Detected wrong-person objection. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_obj_not_decision_makerbool |
Detected lack-of-decision-authority objection. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_obj_not_relevantbool |
Detected not-relevant objection. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_obj_not_nowbool |
Detected bad-time/not-now objection. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_obj_no_callbool |
Detected objection to calls. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_obj_no_emailbool |
Detected objection to email. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_obj_no_meetingbool |
Detected objection to a meeting. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_obj_no_needbool |
Detected no-need objection. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_obj_no_budgetbool |
Detected no-budget objection. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_obj_using_competitorsbool |
Detected existing use of competitors. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_ask_referralbool |
Detected request for a referral. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_ask_businessbool |
Detected question about the prospect business. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_ask_responsibilitiesbool |
Detected question about responsibilities. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_offer_meetingbool |
Detected offer of a meeting. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_offer_callbool |
Detected offer of a follow-up call. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_offer_emailbool |
Detected offer of a follow-up email. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_meeting_confirmbool |
Detected confirmation of a meeting; not a calendar booking ID. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_call_confirmbool |
Detected confirmation of a follow-up call. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_email_confirmbool |
Detected confirmation of follow-up email. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_referral_providedbool |
Detected provision of a referral. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.has_product_interestbool |
Detected product interest. Evaluation signal; false/default is not proof the event could not occur. |
sales_metric.stagestring |
Deprecated sales-stage string. Prefer current user_log outcomes. |
sales_metric.trellus_dispositionstring |
Deprecated Trellus disposition string. Prefer user_log.disposition. |
| Field / type | Definition and values |
|---|---|
cost.twilio_costfloat |
Recorded usage estimate in USD, when populated. This is not the customer invoice or a guaranteed complete billing total. |
cost.bandwidth_costfloat |
Recorded usage estimate in USD, when populated. This is not the customer invoice or a guaranteed complete billing total. |
cost.assembly_costfloat |
Recorded usage estimate in USD, when populated. This is not the customer invoice or a guaranteed complete billing total. |
cost.deepgram_costfloat |
Recorded usage estimate in USD, when populated. This is not the customer invoice or a guaranteed complete billing total. |
cost.cartesia_costfloat |
Recorded usage estimate in USD, when populated. This is not the customer invoice or a guaranteed complete billing total. |
cost.eleven_costfloat |
Recorded usage estimate in USD, when populated. This is not the customer invoice or a guaranteed complete billing total. |
cost.openai_costfloat |
Recorded usage estimate in USD, when populated. This is not the customer invoice or a guaranteed complete billing total. |
cost.google_costfloat |
Recorded usage estimate in USD, when populated. This is not the customer invoice or a guaranteed complete billing total. |
cost.anthropic_costfloat |
Recorded usage estimate in USD, when populated. This is not the customer invoice or a guaranteed complete billing total. |
| Field / type | Definition and values |
|---|---|
prior_activity.num_sessionsint32 |
Prior team sessions for the same customer address, excluding the current session when the snapshot was initialized. |
prior_activity.days_since_firstint32 |
Rounded days between this session start and the first prior team session for this customer address. |
prior_activity.num_out_dialsint32 |
Prior outbound dials for this customer address within the team. |
| Field / type | Definition and values |
|---|---|
call_metric.customer_talk_durationfloat |
Eligible customer transcript-turn duration in seconds; turns before detected live start are excluded. |
call_metric.agent_talk_durationfloat |
Eligible agent transcript-turn duration in seconds; turns before detected live start are excluded. |
call_metric.customer_tempofloat |
Customer words per second over eligible utterances containing at least three words; multiply by 60 for words per minute. |
call_metric.agent_tempofloat |
Agent words per second over eligible utterances containing at least three words; multiply by 60 for words per minute. |
call_metric.customer_dropped_durationfloat |
Customer audio loss/overwrite duration estimate in seconds; not a dropped-call count. |
call_metric.agent_dropped_durationfloat |
Agent audio loss/overwrite duration estimate in seconds; not a dropped-call count. |
| Field / type | Definition and values |
|---|---|
customer_data.namestring |
Captured/enriched contact name; may be empty. Use instead of prospect_name. |
customer_data.titlestring |
Captured/enriched contact job title; may be empty. |
customer_data.occupationstring |
Captured/enriched contact occupation; vocabulary depends on the source. |
customer_data.senioritystring |
Captured/enriched contact seniority; vocabulary depends on the source. |
customer_data.company_namestring |
Captured/enriched company name; may be empty. Use instead of company. |
customer_data.company_urlstring |
Captured/enriched company website URL; may be empty. |
customer_data.company_industrystring[] |
Captured/enriched industry labels as an array of strings. |
customer_data.person_xrefsobject[] |
External person/contact identifiers and URLs, associated with their source platform. |
customer_data.person_xrefs.[].platformenum |
Source integration platform.
|
customer_data.person_xrefs.[].person_idstring |
External contact/person record ID. |
customer_data.person_xrefs.[].person_urlstring |
External contact/person record URL. |
customer_data.person_xrefs.[].company_idstring |
External company record ID associated with this person. |
customer_data.company_xrefsobject[] |
External company identifiers and URLs, associated with their source platform. |
customer_data.company_xrefs.[].platformenum |
Source integration platform.
|
customer_data.company_xrefs.[].company_idstring |
External company record ID. |
customer_data.company_xrefs.[].company_urlstring |
External company record URL. |
customer_data.cadence_xrefsobject[] |
External cadence/sequence references; source-specific type and value. |
customer_data.cadence_xrefs.[].platformenum |
Source integration platform.
|
customer_data.cadence_xrefs.[].cadence_typestring |
Source-specific cadence/sequence category. |
customer_data.cadence_xrefs.[].valuestring |
Source-specific cadence/sequence reference value. |
customer_data.custom_fieldsJSON text |
Account/source-specific custom data as JSON text in list rows. Parse it before reading keys; no standard contact email field is guaranteed. |
customer_data.vcc_campaign_idbytes |
VCC campaign identifier encoded as base64 bytes in list output, not a hex/UUID string. |
customer_data.vcc_contact_idbytes |
VCC contact identifier encoded as base64 bytes in list output, not a hex/UUID string. |
| Field / type | Definition and values |
|---|---|
user_log.dispositionstring |
Recorded call outcome string. Use /bootstrap account options rather than invented labels; may be set by a user, rule, telephony or AI. |
user_log.sentimentstring |
Recorded sentiment string. Use /bootstrap account vocabulary; may be automatically populated. |
user_log.purposestring |
Recorded call-purpose string. Use /bootstrap account vocabulary. |
user_log.notesstring |
Recorded notes/summary text; may be user-entered or generated, not the full transcript. |
user_log.retry_atuint32 |
Suggested/scheduled retry or callback time as Unix seconds; zero means no populated retry time. |
user_log.sourceint32 |
Source that populated the disposition/outcome (for example user, AI or telephony), not a user ID. Returned as a numeric code in list results; filter with the numeric values below. The labels explain those codes and are not accepted filter strings for this field.
|
user_log.vcc_disposition_idbytes |
VCC disposition identifier encoded as base64 bytes in list output. |
user_log.vcc_agent_idbytes |
VCC agent responsible for disposition, encoded as base64 bytes in list output; can be empty. |
| Endpoint | Limit | Shared budget |
|---|---|---|
| Session list | 2 requests per 4 seconds | Shared by v5 and v6. Pace calls at least 2.5 seconds apart. |
| Metric details | 4 requests per 4 seconds | Shared by v6 and v7. |
| Session detail | 1 request per second | |
| Visible directory | 2 requests per 4 seconds | |
| Bootstrap | 2 requests per 4 seconds |
Error bodies can be plain text. Keep the status, endpoint, UTC time and response text when asking support for help. Exclude credentials and customer personal data from logs.
Send the exact session_id from a list row in the x-session-id header, with the same Bearer key. A session_id query parameter or JSON body is ignored. “not found” means the session could not be located, not that you need a transcript scope. If correct headers still fail, contact support with the session ID, endpoint, status, response text and UTC time; never include your API key.
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.
The backend found the session record but could not load its stored detail. Report the session ID and response text to support. You can still use transcript columns from the list when available.
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.
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.
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.
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.
A Trellus API key belongs to a user and inherits their permissions; using it for reporting does not make it a separately restricted credential. Each user can copy their own key in Settings → Integrations → API. Use an appropriately permissioned account for team reporting, verify /visible, and contact support for key replacement if it was exposed.
A request body that exceeds the accepted size can return 413. Reduce the request size and query scope. For transient 5xx responses, use bounded backoff; do not retry indefinitely.
Download the OpenAPI 3.1 starter for the six documented endpoints. It covers request parameters and authentication; account-specific response objects are described rather than exhaustively modeled.
Add the report or integration you want to build, then paste these instructions into your coding assistant. The prompt contains no API key. Set the key privately in your server environment before making live requests.
Implement a server-side client for the Trellus Call Data API.
Follow my existing project's language and framework. Implement the integration and give
me setup steps plus a small test. Use these reporting endpoints to read data; do not use
them to manage dialer settings or CRM mappings.
Read TRELLUS_API_KEY from the server environment. Never ask me to paste a key into chat.
If it is missing, implement the code and explain how to set it privately before live requests.
Do not expose it in browser code, URLs, logs, output, or prompts. This prompt has no credential.
Ask about the timezone or team only when my requested report depends on that choice.
Authentication and endpoint map:
- GET https://ext.trellus.ai/visible — api_key header; optional team_id header.
- GET https://ext.trellus.ai/bootstrap — api_key header; key owner's account configuration.
- POST https://rpt-2.trellus.ai/session-list-v6 — Authorization: Bearer <API_KEY>; JSON body.
- POST https://rpt-2.trellus.ai/metric-details-v7 — Authorization: Bearer <API_KEY>; JSON body.
- GET https://rpt-2.trellus.ai/session — Authorization: Bearer <API_KEY>, x-session-id, x-proto-as-json: true.
- GET https://api.trellus.ai/get-audio-links — api_key and session_id headers.
Call /visible first to verify identity and read permissions. A key belongs to a user;
team_id selects a permitted team and does not expand access. Do not assume a separate read-only key.
Use /bootstrap for exact disposition, sentiment and purpose strings.
List requests require start (Unix microseconds) and select (array of column paths).
end is exclusive and defaults to now. cnf defaults to []; limit defaults to 50, maximum 1000.
For calls, cnf = [[{ "column_name": "conversation_type", "operator": "EQ", "value_safe": 1 }]].
Fields include session_id, started_at, resource_id, customer_address, customer_data.name,
customer_data.title, customer_data.company_name, duration, turn_data.texts,
turn_data.is_customers and turn_data.starts. There is no standard customer email column.
Return rows are arrays in select order; started_at is seconds, not microseconds.
cnf is AND of OR groups. Filter values for started_at use seconds. Turn offsets and duration use seconds.
For counts/sums, use metric-details-v7 with selects: [{ "cnf": [] }, { "column_name": "duration" }].
If grouped, the group value precedes numeric cells. Both column_name and cnf can appear in a select.
Request parameter definitions:
- start: inclusive range start, Unix microseconds; required for list and metrics.
- end: exclusive range end, Unix microseconds; optional, defaults to now.
- team_id: optional report-body team selector; defaults to the key owner's team. One team per request.
- select: required list of exact column paths for session-list-v6; response cell i corresponds to select[i].
- limit: session-list row cap, default 50, maximum 1000; not a page size with a continuation token.
- cnf: optional AND of OR filter groups. [] imposes no extra filter; avoid empty inner groups.
- column_name: exact column path to filter, sum or group; not an alias or display label.
- operator: EQ equals; NEQ not equal; GT greater; GE greater or equal; LT less;
LE less or equal; IN is one of the value_safe array; NIN is not in that array;
REGEX searches a string using the backend regex engine (no look-around/backreferences).
- value_safe: typed comparison value, not a stringified JSON value. Booleans use true/false,
numerics use numbers, IN/NIN use arrays, bytes use base64, recognized enum columns accept names or numeric values. user_log.source is a numeric
field for list results and filters; use its numeric codes, not the explanatory labels.
- reducer: required only when a filter path contains [*]; ANY = at least one item matches,
ALL = every item matches. Do not attach reducer to a path without [*].
- selects: required metric-details-v7 aggregation array. { "cnf": [] } counts matching rows;
{ "column_name": "duration" } sums seconds; specifying both gives a filtered sum.
Boolean sums count true values. Each aggregation's cnf is additional to the top-level cnf.
Empty {} is invalid. Numeric response cells follow selects order.
- group_by: optional metrics object with column_name; its value is the first cell in each row.
String/boolean/enum grouping uses exact values; float/time grouping requires step_size_safe
and step_start_safe. Integer grouping can use exact values or steps.
- step_size_safe: bin width; step_start_safe: bin origin; step_modulus_safe: optional repeat period.
Steps use the grouped column's units (started_at uses seconds). A step requires an origin;
do not supply step parameters for strings, booleans or enums. Group cells with steps are bin
indices: floor(((value - origin) modulo period, if supplied) / width), not timestamps.
Compatibility note: when grouping started_at, the current endpoint scales that bin index by
1,000,000. Divide the returned group cell by 1,000,000 before reconstructing a time bin.
Response definitions and defaults:
- /visible users: readable user records, including user_id for resource_id matching.
user_id_to_email maps known user IDs to email addresses; not every user must have an entry.
team is included only for whole-team readers; absence does not mean the key failed.
groups are readable group records; memberships link user_group_id to member_id;
member_is_group distinguishes a group member from a user member.
- /bootstrap: the key owner's account configuration and option vocabulary, not a call list.
- session-list-v6: JSON array of positional row arrays; [] means no matching readable sessions.
Each cell's type/meaning is defined in the catalogue below. Results are newest started_at first.
- metric-details-v7: JSON row arrays; with grouping, [groupValue, ...aggregationValues].
Without grouping, cells follow selects order. Counts and sums are numeric, not session objects.
- /session: SessionData object in protobuf JSON, with camelCase property names, enum names
and base64 bytes. Default scalar/empty fields may be omitted; missing is not permission evidence.
Catalogue paths are snake_case list-query paths, not property names to copy into detail JSON.
- /get-audio-links: session is one session metadata object; audio is a recording metadata array;
audio_links[i] is the temporary URL for audio[i]. Empty audio/audio_links arrays may mean
recording retention expired. Do not treat session as an array.
- Unset proto values can appear as 0, false, empty string or empty arrays in list cells.
A default value is not proof an event was measured or a prediction/evaluation ran.
Sales/quality flags are detection signals, not guaranteed ground truth.
Use the exact session_id from a row as x-session-id for /session, not a URL query or JSON body.
/session JSON is camelCase (sessionId, customerData, turnData) and omits wordData.
Inspect 401 text: not found differs from not permissioned and not on db.
Audio returns { session, audio, audio_links }; links expire after one hour.
Pace list requests at least 2.5 seconds apart. The default application limit is 2 requests
per 4 seconds per user, shared with session-list-v5. Metrics: 4 per 4 seconds; detail: 1 per second.
Honor Retry-After on 429, use bounded backoff for transient 5xx, and read error bodies as text.
There is no cursor/offset paging. If a window returns limit rows, split it into smaller date
windows and deduplicate by session_id; never claim a capped response is a full export.
Never log credentials or include them in prompts. Report missing enrichment/transcripts honestly.
Minimal call-list body (compute the dates; do not copy old sample timestamps):
{
"start": START_UNIX_MICROSECONDS,
"end": END_UNIX_MICROSECONDS,
"limit": 50,
"cnf": [[{ "column_name": "conversation_type", "operator": "EQ", "value_safe": 1 }]],
"select": ["session_id", "started_at", "resource_id", "customer_address", "customer_data.name",
"customer_data.title", "customer_data.company_name", "user_log.disposition", "turn_data.texts",
"turn_data.is_customers", "turn_data.starts"]
}
Use Date.parse(ISO_WITH_TIMEZONE) * 1000 to build start/end in JavaScript.
Use new Date(started_at * 1000) for returned list timestamps. Handle empty results before
indexing a row. Combine the aligned transcript arrays into speaker/text/offset objects.
For errors, preserve the HTTP status and response text but redact credentials and customer
personal data in logs. If correct /session headers still produce not found or not on db,
report that as an unresolved backend detail lookup; do not fabricate a transcript.
Return accurate totals and label capped or sampled results clearly.
Complete field names, types, enum values and definitions:
https://www.trellus.ai/developers/api#fields
OpenAPI starter:
https://www.trellus.ai/developers/openapi.json
Read the field reference before choosing columns. Do not invent aliases.
Member paths containing .[]. are documentation notation. Select the parent array, or use .[0]. or .[*]. projections. Filters through [*] require ANY/ALL; select projections do not use a reducer.