GET /v1/studies
List all active studies for your project.
Returns studies with their current usage, whether they’re accepting new responses, and a summary of each study’s Study Manager state (ledger_summary) so you can tell at a glance which study has moved.
Request
string
required
Bearer token. See Authentication.
string
active (default), paused, concluded, or all. Filters on the stored status; a stale or limit-reached study is active.integer
Number of studies to return. Default
20, max 100.string
Cursor for pagination. Pass the
id of the last study from the previous page.ledger_summary is null for a study whose Study Manager has not saved yet. See Ledger summary for the fields. If a summary query fails on our side, the affected studies come back with ledger_summary: null and the list still succeeds.
GET /v1/studies/:id
Retrieve a single study with full details: what it set out to learn, who is interviewed, what the product is, the questions with their interviewer notes, and the interview count. Add expand=ledger to embed the study’s ledger in the same response.
Request
string
required
Bearer token. See Authentication.
string
required
Study ID (UUID).
string
ledger embeds the study’s current ledger as ledger: the same object GET /v1/studies/:id/ledger returns, active items only, or null before the Study Manager’s first save (not a 404). Without expand, the response has no ledger key. Any other value returns 400.404 if the study doesn’t exist or doesn’t belong to your project. Returns 400 with code "invalid_parameter" and param "expand" when expand is anything but ledger.
Study object
string
Study ID (UUID).
string
"study"string
Display name.
string
"active", "paused", or "concluded": the stored lifecycle, the one a person drives. A study is created active. Pausing and concluding stop the interview link admitting respondents; interviews already in progress finish, and the Study Manager still reviews them. Every move is a status_changed event on the study’s timeline with who made it.string
Public URL for respondents. Append
?reference_id=your_user_id to track who completes the interview.boolean
true exactly when state.value is "active" or "stale": the study is active and no limit has been reached. A paused or concluded study is never accepting, even within its limits.object
The one displayed state: the stored
status folded with the two things that stop or quiet a study without anyone touching it, a limit reached and silence. Computed on read.string[]
Language codes the study supports (e.g.
["en", "es"]).object
string
ISO 8601 timestamp.
object
How the study’s completed interviews were graded. Every completed, non-test, non-deleted interview is scored once it is processed (or by hand on the Conversations page) and counts in exactly one of the four counts. A low
ratio says the study’s setup is not getting usable conversations (questions, audience, length), not that respondents think anything.Ledger summary (list only)
Each item ofGET /v1/studies carries ledger_summary: the study’s Study Manager state at a glance. The Study Manager is the agent that reads every quality interview and keeps the study’s ledger. The summary is null until the agent has saved its first version, so a study with no ledger is visibly a study with no ledger, never a quiet one. This is a summary, not the ledger: phase is the value alone, and the full object is only on the detail with expand=ledger.
object | null
Detail-only fields
These fields are only included inGET /v1/studies/:id responses:
string | null
What the person who concluded the study wrote: what it settled and what is left open.
null when the study was concluded without notes, and when it was never concluded. Written only by the conclude move (uj studies conclude <id> --notes "…", or notes on studies_set_status with to: "concluded"), where a blank note clears it; a reopened study keeps its last notes until it is concluded again. The same text is on the status_changed event as detail.notes.string | null
The research objective for this study.
string | null
The product being researched.
string | null
What the product is and does, as the interviewer and the Study Manager read it.
string | null
"existing_user" or "discovery".string | null
Who is being interviewed, in the study owner’s words.
object[]
The interview questions.
integer
Total number of completed interviews for this study.
object | null
Interactive prototype the participant uses during the interview, or
null when the study has none. See Interactive prototype.object | null
Present only with
expand=ledger. The study’s current ledger, the same study ledger object as GET /v1/studies/:id/ledger with active items only, or null before the Study Manager’s first save. Unlike the ledger endpoint, a missing ledger is not a 404 here: the study detail is still returned.Interactive prototype
A study can embed a live web prototype in the interview instead of static screenshots. The switch is per study:prototype_config is null (off) or an object, set through the studies_config_update MCP tool or uj studies config set <id> --file config.json.
baseUrlmust be https (http is allowed only for localhost). The prototype publishes its valid{ screen, scenario }pairs atGET {baseUrl}/api/states.description(max 240 characters) is what the interviewer agent reads about the start state.prototypeis the prototype’s id: every message the prototype posts carries it assource, and the participant page accepts no other. Copy it fromGET {baseUrl}/api/states.screens(optional, up to 12 of{ id, description }) tells the agent what each screen of the prototype is and what the participant can do there, so it understands its live context notes. Copy thescreensarray fromGET {baseUrl}/api/states.flows(optional, up to 8 of{ task, steps }) tells the agent how common tasks are done, so it can guide a stuck participant. Copy it fromGET {baseUrl}/api/states.events(optional, up to 64 of{ token, meaning, use }) tells the agent what each of the prototype’s context notes means and how to act on it. Copy it fromGET {baseUrl}/api/states.- The agent receives exactly two stimulus ids for the prototype:
PROTOTYPE_STARTshows it,PROTOTYPE_ENDhides it. Question notes must say when to call them, for example “Call PROTOTYPE_START now and keep it visible until the last question.” - While the prototype is visible, the participant’s actions are summarised to the agent as short context notes and recorded in the interview’s session replay. The prototype writes those notes itself; see Prototype messages.
Prototype messages
The prototype posts one message per interaction towindow.parent:
sourcemust equalprototype_config.prototype;typeis the prototype’s own event name;ts,seqandsessionIdidentify the message.note(max 280 characters) is what the agent reads.eventsin the study config explains every note.delivery:now(default) sends the note;activitysends nothing and only shows the participant is busy, so the agent is not told they are idle. Anowmessage without a note reaches the agent asevent=<type>.merge: a key; a newer note with the same key replaces the pending one, e.g. typing sendstyped=12thentyped=40and the agent receivestyped=40.state: values that open every note,on=<screen>first (null removes a key).- Notes are batched (1.5 s), repeats collapse to
x<n>, and the agent receives at most 12 updates a minute. After 20 seconds without any message the agent is toldidle=<s>.