REST API concepts
Understand what each REST action does, from uploading a briefing file through to exporting the finished interviews. Use the reference for exact payloads and responses.
Upload files
Upload a document with POST /v1/api/files as multipart form data. Juno accepts .pdf, .docx, .xlsx, .csv, .pptx, .txt and .md. Text files may be up to 10 MB and everything else up to 50 MB. The response returns a file_id.
A file has no effect on its own. Pass its file_id in file_ids when you create or update a study.
Create study
Send the user's brief as guidance. If documents are part of the brief, upload them first and include their file_ids. Uploading a file by itself does not create or change a study.
Update study
Give Juno further guidance to change an existing study. Include file_ids when new documents are part of the update. The REST path :refine and MCP tool refine_study retain their wire names.
Check study job
Create and update requests return a job_id. Poll that job until status is ready, then use the returned study_id.
View studies
List the organisation's studies, newest first, or read one study together with its current brief and status.
Simulate interview
Test mode is a safe preview. Juno plays both sides: the interviewer runs the study's real interview and a synthetic participant answers it. A simulation uses no credits, produces no analysis and no exports, and is not real participant research. The API enforces this. Simulating a study whose collection is live returns 409, on REST and on MCP alike. At most three simulations run at once per organisation; a fourth returns 429.
Set study mode
Set an explicit target; the endpoint never toggles blindly. 'test' selects Test mode. 'live' selects Live mode and performs Go live the first time. 'paused' and 'closed' are technical collection states. Setting 'live' requires studies:golive; other changes require studies:write.
The established mode field also accepts 'paused' and 'closed'. These are technical collection states, not additional study modes. Test mode and Live mode remain the only product modes.
Get invite link
Get the durable invite link after setting mode to live. The user shares it with participants. The REST path retains the technical name /interview-link.
Links that carry context
POST /v1/api/studies/{study_id}/participant-links mints an invite link carrying what you already know about the people who will open it. Put facts in context, as key and value pairs such as company and role: Juno briefs the interviewer with them so it does not ask for what you supplied, and they come back on the interview record. Put free-text direction in note: it steers the interview, is never shown to the participant, and never becomes interview data.
By default the link is for a group, so you can send one link to everyone in a segment. Set audience to 'person' when the context identifies one individual and you want the finished interview matched back to their record. That link then belongs to whoever opens it first.
See the interviews
GET /v1/api/interviews lists participant interviews, filtered by study_id and by status, which is in_progress, completed, or failed. GET /v1/api/interviews/{id} returns one. Each record carries the status, whether it finished, whether it was a test, the modality, when it started and completed, how long it took, the context attached to the invite link, and a permalink into the Juno app. Both need export:read.
Export interviews
In Live mode, export participant interviews as CSV. Exports run in the background. A test-environment key cannot export, and Test-mode simulations have no exports.
Start the export with POST /v1/api/exports, then poll GET /v1/api/exports/{job_id} until status is completed. Status is queued, running, completed, or failed. Then call GET /v1/api/exports/{job_id}/download, which returns either a download_url that expires after five minutes or the CSV itself. Asking to download before the job is finished returns 409.
Paging through lists
List studies and list interviews are paged. Both take limit, up to 200, and default to 50. When there is another page, REST returns the cursor in an X-Next-Cursor response header; pass it back as the cursor query parameter. A response with no header is the last page. Cursors are keyset based, so rows arriving while you page never shift or duplicate what you are walking.
Repeat-safe requests
Three endpoints accept an Idempotency-Key header: POST /v1/api/studies, POST /v1/api/studies/{study_id}/participant-links, and POST /v1/api/studies/{study_id}:refine. Send the same key with the same body and Juno replays the first answer instead of doing the work twice. Juno remembers a key for seven days. Reusing it with a different body returns 409, and so does reusing it while the first request is still running. The key may be up to 255 characters. MCP has no equivalent, because JSON-RPC carries no headers.
