A valid request URL is required to generate request examples{
"thread": {
"id": "<string>",
"title": "<string>",
"createdAt": "2023-11-07T05:31:56Z",
"updatedAt": "2023-11-07T05:31:56Z",
"lastMessageAt": "2023-11-07T05:31:56Z",
"messageCount": 1
},
"mode": "auto",
"messages": [
{
"id": "<string>",
"role": "user",
"parts": [
{}
],
"metadata": {
"createdAt": "2023-11-07T05:31:56Z",
"finishReason": "<string>",
"stopReason": "completed"
}
}
],
"omittedFiles": 1,
"nextBefore": "<string>"
}{
"error": {
"code": "backend_resolution_failed",
"message": "<string>",
"retryable": true
}
}{
"error": {
"code": "unauthorized",
"reason": "missing_credentials",
"hint": "<string>"
}
}{
"error": {
"code": "backend_resolution_failed",
"message": "<string>",
"retryable": true
}
}{
"error": {
"code": "not_found",
"message": "<string>"
}
}{
"error": {
"code": "rate_limited",
"message": "<string>"
}
}One thread, with a page of its messages
The thread and its newest messages, oldest first, as UI messages a chat client renders without translation. A tool part in state approval-requested on the last message is a question still waiting: answer it on POST /v1/copilot.
PAGED, NEWEST FIRST. The response carries the newest limit messages; nextBefore names the oldest of them when older ones exist, and sending it back as before returns the page before that. A thread is heavy in a way a listing is not: every tool result carries its full text and every screenshot its bytes.
Inline screenshots (file parts with a data: URL) are carried within a budget of 4194304 DECODED bytes per response (about 1.33 times that on the wire, as base64 inside JSON). The fit is greedy, newest first: each screenshot is kept if it fits what is left, so a large one that does not fit is left out while a smaller older one may still be carried. files=none leaves every one out. omittedFiles counts what was left out, and the frameId on the tool output beside each one still names the picture for the frames API.
A thread that is not yours, one that was deleted, and one that never existed all answer 404 alike.
Hosted deployments only. A local checkout does not mount this route, so calling it there is a 404.
A valid request URL is required to generate request examples{
"thread": {
"id": "<string>",
"title": "<string>",
"createdAt": "2023-11-07T05:31:56Z",
"updatedAt": "2023-11-07T05:31:56Z",
"lastMessageAt": "2023-11-07T05:31:56Z",
"messageCount": 1
},
"mode": "auto",
"messages": [
{
"id": "<string>",
"role": "user",
"parts": [
{}
],
"metadata": {
"createdAt": "2023-11-07T05:31:56Z",
"finishReason": "<string>",
"stopReason": "completed"
}
}
],
"omittedFiles": 1,
"nextBefore": "<string>"
}{
"error": {
"code": "backend_resolution_failed",
"message": "<string>",
"retryable": true
}
}{
"error": {
"code": "unauthorized",
"reason": "missing_credentials",
"hint": "<string>"
}
}{
"error": {
"code": "backend_resolution_failed",
"message": "<string>",
"retryable": true
}
}{
"error": {
"code": "not_found",
"message": "<string>"
}
}{
"error": {
"code": "rate_limited",
"message": "<string>"
}
}Authorizations
The control surface credential. Send Authorization: Bearer <token>.
Two kinds of token are accepted and they are told apart by shape, not by a separate header. A token beginning pbk_ is an org scoped API key, whose public half and secret half are generated together and of which only a hash of the secret is ever stored; anything else is treated as an OAuth 2.1 access token and verified against the authorization server's keys.
Both resolve to the same context: an org, a principal and a set of scopes. Nothing downstream branches on which channel you used, with one deliberate exception, key management, which requires a signed-in person so that a key can never mint another key.
Scopes are enforced when MCP tools are REGISTERED rather than when they are called, so a tool your credential cannot use is absent from tools/list rather than refused mid gesture.
Path Parameters
The thread id.
Query Parameters
How many messages, 1 to 200. Defaults to 50. Above the maximum is refused, never quietly reduced.
1 <= x <= 200A message id from a previous page's nextBefore: the page before that message. Omit it for the newest page.
inline (the default) carries screenshots as data: URLs within the byte budget; none leaves every one out.
inline, none Response
The thread and one page of its messages.
Show child attributes
Show child attributes
This thread's saved automation mode, or null when none was chosen. Read it when reopening the chat on another browser.
auto, ask, manual, null Oldest first, newest last.
Show child attributes
Show child attributes
Inline screenshots left out of this page, by files=none or the byte budget.
x >= 0The oldest message id on this page, to send as before for the page before it. Absent when this page reached the start.