Juno

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.

14 topics8 min read

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.

Everything slow is a job Authoring, simulations, and exports never block the request. They return a job you poll. Treat the job handle as the source of truth for progress, not a fixed wait.

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 the durable invite link after setting mode to live. The user shares it with participants. The REST path retains the technical name /interview-link.

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.

The transcript lives in the export Neither call returns the transcript or the answers. Start an export for the full interview data.

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.

Full endpoint reference

Browse the full API reference Every endpoint, request, and response — rendered live from the OpenAPI spec, with copy-paste examples in your language.
Machine-readable spec Point your codegen at the raw OpenAPI document at /v1/api/openapi.json to generate a typed client.