Access and limits
Create an API key assigned to a support agent in Settings → API. Send it in thecx-api-key header. Both read-only endpoints require analytics:read and organization-wide dashboard access; they do not fall back to a personal or team-only export.
Filtering to your own agent ID does not waive these permissions. Both endpoints use the analytics rate tier of 10 requests/minute. They return JSON, not CSV/Excel, and do not change tickets, send surveys, or modify sessions. For aggregate scores, response rates, and online time, use Reports and metrics.
Export CSAT surveys
Choose one date population: surveys submitted in a period, or surveys sent in a period, including those still unanswered. Only surveys attached to existing, non-deleted, non-side, non-imported tickets in the workspace are eligible.
Supply exactly one complete date pair as ISO 8601 instants with
Z or an explicit offset. The lower bound is inclusive and the upper bound exclusive: [from, before). The upper bound must be later and no more than 90 × 24 hours after the lower bound. Unlike report-query UNTIL, before is not an inclusive calendar date. Unknown query parameters are rejected.
Start with a small sent-date export without comments:
agent_example with your workspace’s agent ID. Request comments only if your integration needs customer-entered text and the key has the additional scope:
Read survey results
The following invented example shows the default response without comments. Results are ordered ascending by your selected date field, then survey ID.score and submitted_at may be null; ticket_number, credited_agent_id, and credited_agent_name are also nullable.
credited_agent_id is the survey’s stored agent_id, not a read-time guess from the ticket’s resolver or assignee. Missing credit stays null with attribution_source: "unattributed". A credited name may be unavailable even when an ID is stored. Legacy survey credit is not rewritten, so historical credit is not proof of who resolved the ticket.
For newly created surveys without explicitly supplied credit, default attribution snapshots the ticket’s recorded solved_by only when its current status is resolved and that resolver is eligible in the same workspace. There is no fallback to an assignee or message author. The legacy AI marker and AI agents excluded from analytics accounting do not receive default credit, including after an excluded agent is deleted. Reopening or reassigning the ticket later does not recompute that snapshot. This default can credit an eligible AI resolver; it is not a human-only guarantee.
With include_comments=true, each item additionally has comment as a string or null, and meta.comments_included is true. Without it, the field is omitted entirely. Comments may contain personal data: restrict downstream access and avoid copying them into logs. The export does not return customer contact details, survey tokens or links, or ticket bodies.
Export agent sessions
Use recorded login intervals to inspect session starts, ends, and last activity. These are the existing mutable login-session records, not a new presence-event store. There is no stored break or event history in this export.session_start < before and either session_end > from or session_end is null. A session ending exactly at from or starting exactly at before is excluded. A session starting before the period can be returned. Original timestamps are retained without clipping, and overlapping records are not merged.
This invented response includes a stale open record deliberately:
session_end is not proof of current availability. Inspect last_activity separately; this export never infers an end from it. Returned session rows contain only id, agent_id, session_start, session_end, last_activity, and updated_at, never IP addresses, browser details, or user agents. To obtain deduplicated, period-clipped online seconds with time-bucket allocation, query agent_online_time through Reports and metrics, rather than summing raw durations.
Continue an export
Whenpagination.has_more is true, use pagination.next_cursor as the next request’s cursor. Stop when has_more is false. Preserve the key, workspace, assigned agent, scopes, and every filter, including limit and comment inclusion. Changing them invalidates the cursor. Treat timestamps and cursors as opaque strings; rebuilding a cursor from a timestamp can lose precision.
For the low-score query above, set NEXT_CURSOR to the returned token and repeat the same parameters:
session_start, then id, ascending. Neither export is a frozen snapshot: replica reads are eventually consistent, survey responses can arrive later, and session ends or activity timestamps can change during pagination. For ongoing imports, reread bounded overlapping windows and update downstream rows by id; this is not a change-event feed. For adjacent date windows, reuse the previous before as the next from.
Troubleshooting
If a small valid request still fails, contact support with the response
request_id, endpoint, and redacted filters. Never share API keys or customer comments in diagnostic logs.