Threads
A suggestion's refinement history, read as one conversation from its first turn to its latest.
List threads
Lists your tenant's threads, newest first. A thread is a suggestion's refinement history read as one conversation. Every filter is optional and filters combine with AND.
Results are paged with a cursor. Take meta.next_cursor from a response and pass it back as cursor for the next page; it is null on the last page. The order is always newest first, and there is no total count.
What you can see depends on how you authenticate. A signed-in user sees the threads they created, plus every thread with no creator. An access-token caller sees every thread in the tenant, and can narrow to one user with created_by. Anything you cannot see is simply absent from the page — you never get a 403, and asking for another user's threads gives an empty page. An unknown query parameter is rejected with 422.
query Parameters
segment_idReturn only sets for this segment.
A UUID, lower-case and hyphenated. Identifiers minted by this API are UUIDv7, so sorting them as strings happens to order them by creation time — the listings rely on that, which is why they need no sort parameter. Do not depend on it yourself, and do not read a timestamp out of an id: ids from other systems may be a different version, and the guarantee is not part of this contract.
use_case_idReturn only sets for this use-case.
A UUID, lower-case and hyphenated. Identifiers minted by this API are UUIDv7, so sorting them as strings happens to order them by creation time — the listings rely on that, which is why they need no sort parameter. Do not depend on it yourself, and do not read a timestamp out of an id: ids from other systems may be a different version, and the guarantee is not part of this contract.
created_byReturn only items created by this user. Naming a user whose items you cannot see gives an empty page.
A UUID, lower-case and hyphenated. Identifiers minted by this API are UUIDv7, so sorting them as strings happens to order them by creation time — the listings rely on that, which is why they need no sort parameter. Do not depend on it yourself, and do not read a timestamp out of an id: ids from other systems may be a different version, and the guarantee is not part of this contract.
cursorThe meta.next_cursor value from a previous response. Treat it as an opaque string: pass it back unchanged, and never build one yourself.
limitHow many items to return per page. Omit it for 20. A value above 100 is rejected with 422 rather than quietly reduced to it, so read the maximum from this parameter rather than probing for it.
Treat it as an upper bound, not a promise: a short page does not mean the listing has ended. Keep paging until meta.next_cursor is null.
List threads › Responses
The matching page of threads.
Pagination metadata. There is no total count and no page number — a listing is walked forwards with the cursor until next_cursor is null, and cannot be jumped into part-way.
Fetch a thread by id
Adds turns to the thread, oldest first. threadId is the stored thread id, stable across refinements — a link to a thread keeps resolving after a further refinement.
A signed-in user can fetch a thread they created, or any thread with no creator. An access-token caller can fetch any thread in the tenant. A thread you cannot see returns 404, not 403.
path Parameters
threadIdA UUID, lower-case and hyphenated. Identifiers minted by this API are UUIDv7, so sorting them as strings happens to order them by creation time — the listings rely on that, which is why they need no sort parameter. Do not depend on it yourself, and do not read a timestamp out of an id: ids from other systems may be a different version, and the guarantee is not part of this contract.
Fetch a thread by id › Responses
The thread, with its turns.
idA UUID, lower-case and hyphenated. Identifiers minted by this API are UUIDv7, so sorting them as strings happens to order them by creation time — the listings rely on that, which is why they need no sort parameter. Do not depend on it yourself, and do not read a timestamp out of an id: ids from other systems may be a different version, and the guarantee is not part of this contract.
nameA generated name for the thread; null until one has been generated for it.
Always set today; reserved to be null for future content that is not tied to a use-case.
locale^[a-z]{2,3}(-[A-Z]{2… · requiredA BCP 47 language tag. Content is generated and stored in one of two locales today, written as a bare language code with no region subtag: en or de. The pattern also admits a region subtag (en-GB) so that regional content can be added without a breaking change, but no such locale exists yet: a request naming one matches nothing, and no response carries one. Which locale your content is generated in comes from your tenant's settings; you do not choose it per request.
The user who started the thread. Null only for ready-made (precompute) content, which no individual user requested.
The thread's current newest turn.
root_originWhere the thread started: precompute for ready-made content, steered for a generation from a brief, or user_draft for content you wrote yourself. A thread's root is never a refinement.
turn_countHow many turns the thread has, always at least one — a thread and its first turn are written together. It is also the version of the newest turn, so a thread whose turn_count has grown since you last read it has been refined.
created_atWhen the thread's first turn was generated or saved.
updated_atWhen the thread last changed. Two unrelated things move it: a refinement appending a turn, and a rename. It is therefore not a reliable "new content" signal on its own — compare turn_count or head_suggestion_id for that.
The thread's turns, oldest first. Present only on GET /v1/threads/{threadId}.
Rename a thread
Sets the thread's name, overwriting any name it already has — generated or user-given.
Signed-in users only, since a rename is attributed to the person who asked for it, and a machine-to-machine access token identifies an integration rather than a user.
A thread you cannot see returns 404, not 403. The name is checked before it is saved, and a rejection comes back as 422 with a thread_name_empty, thread_name_too_long or thread_name_not_plain_text code — this operation's own vocabulary, not the input_* codes a rejected brief uses. Whitespace is trimmed and collapsed before the name is stored, and an 8-word limit applies on top of the 60-character one, so read the thread back rather than assuming the name you sent is the name that was saved.
path Parameters
threadIdA UUID, lower-case and hyphenated. Identifiers minted by this API are UUIDv7, so sorting them as strings happens to order them by creation time — the listings rely on that, which is why they need no sort parameter. Do not depend on it yourself, and do not read a timestamp out of an id: ids from other systems may be a different version, and the guarantee is not part of this contract.
Rename a thread › Request Body
nameThe thread's new name. Leading and trailing whitespace is trimmed and any run of whitespace is collapsed to a single space before the name is stored, so the name you read back may differ from the one you sent.
Two further limits are checked after schema validation and are reported as 422 rather than 400: the trimmed name must be at most 60 characters and at most 8 words, both as thread_name_too_long. A short name can therefore still be rejected for having too many words. Line breaks and other control characters are refused as thread_name_not_plain_text, and a name that is empty once trimmed as thread_name_empty.
Rename a thread › Responses
The thread, renamed.
idA UUID, lower-case and hyphenated. Identifiers minted by this API are UUIDv7, so sorting them as strings happens to order them by creation time — the listings rely on that, which is why they need no sort parameter. Do not depend on it yourself, and do not read a timestamp out of an id: ids from other systems may be a different version, and the guarantee is not part of this contract.
nameA generated name for the thread; null until one has been generated for it.
Always set today; reserved to be null for future content that is not tied to a use-case.
locale^[a-z]{2,3}(-[A-Z]{2… · requiredA BCP 47 language tag. Content is generated and stored in one of two locales today, written as a bare language code with no region subtag: en or de. The pattern also admits a region subtag (en-GB) so that regional content can be added without a breaking change, but no such locale exists yet: a request naming one matches nothing, and no response carries one. Which locale your content is generated in comes from your tenant's settings; you do not choose it per request.
The user who started the thread. Null only for ready-made (precompute) content, which no individual user requested.
The thread's current newest turn.
root_originWhere the thread started: precompute for ready-made content, steered for a generation from a brief, or user_draft for content you wrote yourself. A thread's root is never a refinement.
turn_countHow many turns the thread has, always at least one — a thread and its first turn are written together. It is also the version of the newest turn, so a thread whose turn_count has grown since you last read it has been refined.
created_atWhen the thread's first turn was generated or saved.
updated_atWhen the thread last changed. Two unrelated things move it: a refinement appending a turn, and a rename. It is therefore not a reliable "new content" signal on its own — compare turn_count or head_suggestion_id for that.
The thread's turns, oldest first. Present only on GET /v1/threads/{threadId}.