GET /v1/chats/:id/messages
List visible messages for a chat in chronological order (oldest first).
Unlike /v1/chats and /v1/releases — which return newest-first — messages are ordered ascending so you can read a transcript top-to-bottom without reversing the list.
Request
Bearer token. See Authentication.
Chat ID (UUID).
Number of messages to return. Default
20, max 100.Cursor for pagination. Pass the
id of the last message from the previous page.404 if the chat doesn’t exist, doesn’t belong to your project, or is excluded from the public chats API (internal, eval, or release-generated).
Returns 400 with Invalid parameters when pagination inputs are malformed — for example, limit outside 1..100 or a non-UUID starting_after. The response body includes a details array with the Zod issue for each offending field.
Returns 400 with No such message: <id> if starting_after parses as a UUID but is not a visible message in this chat.
Message object
Message ID (UUID).
"message""user", "assistant", or "system". system is rare in public output.Ordered content blocks. See Part types.
Citations referenced by an assistant message.
null when there are none."positive", "negative", or null. User thumbs-up/down from the UI.Token and cost metrics for assistant messages.
null on user/system messages or when metrics were not recorded.ISO 8601 timestamp — when the message was recorded.
ISO 8601 timestamp — when streaming finished.
null while still streaming.Part types
text
thinking
Internal reasoning shown to the user in a collapsible section.
redacted_thinking
Marker for reasoning that was redacted. No content.
file
User-uploaded file attached to a message.
filename is null if none was provided.
tool_use
A tool call made by the assistant. All tool transports (server tools, MCP tools) normalize to this single shape.
One of
input_available, output_available, output_error, output_denied. Transient internal lifecycle states (e.g. streaming input, approval requests) are mapped to input_available.tool_result
A tool result for a previous tool_use. All result transports (web search, code execution, MCP) normalize to this shape.
Tool payload stability
The shapes insidetool_use.input and tool_result.content are tool-specific and may evolve as tools change. Don’t hard-code field paths — read them defensively. Everything else in the response is stable and versioned.
Truncation
Large payloads are capped to keep response sizes predictable. When atool_use.input, tool_result.content, or sources[].query exceeds 32 KB of JSON-encoded UTF-8:
truncated === true rather than hardcoding the size — the threshold may change.
Truncated sources surface the same way — query becomes null with matching truncated/truncation_reason fields:
Pagination
has_more is true, pass starting_after with the last message’s id to get the next page. Results are ordered oldest first, so walking pages with starting_after traverses the transcript forward in time.