Cross-ticket responses query API
This article and the rest of the API documentation in this section are written for a technical audience — integrators and developers connecting external systems to Tickiti. Familiarity with HTTP, REST, JSON and bearer-token authentication is assumed.
This endpoint returns responses drawn from across every ticket the token can see — the bulk counterpart to List responses, which works one ticket at a time. Filter by a created-at window, queue, the internal/staff flags or a set of ticket numbers, and page through the matches with a keyset cursor. Use it to pull all activity in a date range without walking tickets one by one: to feed an external analytics store, build a digest, or reconcile an audit log.
Endpoint
POST /api/v1/tickets/responses/queryHeaders
Authorization: Bearer YOUR_TOKEN— required. Token must have thetickets:readability. Atickets:writetoken also works (write implies read).Content-Type: application/json— required. NoIdempotency-Keyis needed (this is a read).
Body
Every field is optional. With an empty body the endpoint returns the first page of responses across all tickets you can see, oldest first.
created_from— lower bound on a response’s creation time. A bareYYYY-MM-DDmeans that day from00:00:00; a fullYYYY-MM-DD HH:MM:SSis used as given. Compared againstcreated_atas stored (UTC wall-clock).created_to— upper bound. A bareYYYY-MM-DDmeans that day to23:59:59.is_internal—truefor internal staff notes only,falsefor public responses only. Omit to include both.staff_response—truefor staff-authored responses only,falsefor customer responses only. Omit for either.queue— array of queue names; restrict to responses on tickets in those queues.queue_id— array of queue ids; the same restriction by id.ticket_number— array of 6-digit ticket numbers; restrict to responses on those tickets.include_deleted—trueto include soft-deleted responses. Defaults tofalse.fields— array selecting which heavy fields to return, any ofhtml,plain_text,attachments. Omit a field to skip it server-side; the default returns all three. The metadata fields are always returned. For a cheap metadata-only pull, pass"fields": [].limit— page size. Defaults to200, maximum1000.cursor— a{ "created_at": ..., "id": ... }object copied verbatim from a previous page’snext_cursor. Omit it for the first page. See Paging below.
What you can see
Results obey the same visibility rule as the staff interface: a response is included only if its ticket sits in a queue the acting user can view, or that user is a participant on the ticket. A non-staff token owner is refused with 403. The queue, queue_id and ticket_number filters narrow within that visible set — they can never widen it, so a token cannot read responses its owner could not read on screen.
Example
Pull the metadata for every response created in the Sales queue over a two-day window, dropping the bodies:
curl -X POST https://support.sole-provider.example/api/v1/tickets/responses/query \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"created_from": "2026-05-01",
"created_to": "2026-05-02",
"queue": ["Sales"],
"fields": ["attachments"],
"limit": 200
}'Successful response
A responses array, ordered oldest to newest by created_at (ties broken by id), plus the next_cursor to fetch the following page and the count on this page. Each row carries the ticket it belongs to, so you can group responses back onto their tickets.
{
"ok": true,
"data": {
"responses": [
{
"response_id": "41",
"ticket_number": "220009",
"is_internal": true,
"is_pinned": false,
"staff_response": true,
"created_by_email": "priya.sharma@sole-provider.example",
"created_at": "2026-05-02T10:05:11+00:00",
"updated_at": "2026-05-02T10:05:11+00:00",
"is_email_sourced": false,
"html": "<p>Internal note: replacement authorised.</p>",
"plain_text": "Internal note: replacement authorised.",
"attachments": []
}
],
"next_cursor": { "created_at": "2026-05-02 10:05:11", "id": 41 },
"count": 1
}
}When fields omits a heavy field, that key is absent from each row rather than null. The metadata keys above are always present.
Paging
Paging is keyset-based, not offset-based, so it stays correct even as new responses arrive mid-walk. To read the whole result set: call the endpoint, process data.responses, then if data.next_cursor is not null call again with that object as cursor. Stop when next_cursor comes back null. Keep the other filters identical across pages.
Error responses
422 validation_failed— a field has the wrong type,fieldscontains a value other thanhtml/plain_text/attachments,limitis out of range, or a suppliedcursoris missing itscreated_atorid.401 unauthenticated— bad or missing token.403 forbidden— token lacks thetickets:read(ortickets:write) ability, or the token owner is not a staff account.
Where to go next
- List responses API — the single-ticket version, when you already know the ticket.
- Download attachment API — fetch the bytes of an attachment listed on a response.
- MCP server — reach this endpoint from an AI assistant via the
query_responsesandexport_responsestools.