# Getting the most from AI tests Source: https://docs.getversive.com/ai-tests/best-practices Features worth turning on, and how experienced teams run their tests ## Set up personas like a qual study * **Build personas from real research data.** Upload interview transcripts, survey exports, or research docs and let Versive [distill them](/ai-tests/personas) — a persona grounded in real quotes and numbers behaves far more specifically than one written from imagination. * **Treat personas like human qualitative research.** You can learn from a sample size of one — a single run will surface real issues. But aim for **3–5 executions per persona** so the aggregated summary can group findings and show you which ones are stable versus one-off. * **Test with more than one persona.** Results are attributed per persona, so running your skeptical novice alongside your power user shows you where their experiences diverge. ## Scope the test tightly * **Test small flows and tasks, not open-ended tours.** "Sign up and invite a teammate" produces attributable findings; "explore the app" produces noise. Run several small tests instead of one big one. * **Keep Figma files clean.** Import only the frames you actually want tested, in the order you want them seen — stray exploration screens and dead-end frames read as usability failures. * **Have placeholder content? Turn on the content-accuracy flag.** The [*ignore content accuracy*](/ai-tests/figma-and-image-tests#test-configuration) setting tells the AI to disregard lorem ipsum and dummy data and focus on structure and flow — without it, placeholder content gets flagged as confusing. ## Pick the right mode * **Conversational tests simulate real user interviews.** Use them when you want reactions, expectations, and the *why* behind problems — and add a per-screen interview script for the screens you're most worried about. * **Expert audits give design-review-style feedback.** A systematic pass against Nielsen's heuristics (or your own design-system rules as [custom heuristics](/ai-tests/test-modes#expert-audit-heuristic-evaluation)) — great before design reviews. * **Use SUS to compare across concepts.** Enable the [SUS questionnaire](/ai-tests/test-modes#sus-questionnaires) on a fixed test setup and re-run it per concept or design iteration — the 0–100 score gives you a consistent yardstick. Read it relatively (A vs. B), not as an absolute benchmark. ## Iterate inside the project * **Add more test runs anytime.** A project isn't one-and-done — after reading the first results, add runs with new personas or more executions to the same project and regenerate the summary. * **Test iterations in the same project.** When the design changes, run a new round of tests in the same project with the same personas — comparing rounds shows you whether the fixes actually landed. ## Know what AI tests are best at AI tests excel at uncovering **usability, product, and design improvements** — confusing flows, unclear copy, missing affordances, heuristic violations — in minutes instead of weeks. Treat findings as hypotheses ranked by likelihood: for higher-risk decisions, or research into real-world behavior, attitudes, and willingness to pay, validate with real participants in a [study](/studies/overview). # Figma prototype & image tests Source: https://docs.getversive.com/ai-tests/figma-and-image-tests Test interactive prototypes and static designs with AI users Prototype and image tests share the same engine: AI personas review a sequence of **screens** and respond to each according to the [test mode](/ai-tests/test-modes) you choose. ## Figma prototype tests Import a prototype in one of two ways: * **Paste a Figma URL** — Versive reads the file, detects the prototype's defined interactions, and imports your frames as screens. The file needs link sharing enabled ("Anyone with the link can view"). * **The Figma plugin** — *Versive: Instant Usability Tests* in the Figma Community. Select pages and frames inside Figma, authenticate with your Versive account (OAuth — reconnect anytime), and create a test without leaving the design file. After import, you choose which frames to include and their order, so you can test a single flow out of a larger file. ## Image tests Upload static screenshots or mockups (multiple images per test) and arrange them in the order the AI should see them. Ideal for early concepts, landing pages, emails, and ad creative — anything where you want reactions to a design that isn't clickable yet. ## Test configuration | Setting | Description | | - | - | | **Goal** | The context and objective for the test — what the design is, who it's for, and what you want to learn. | | **Test mode** | Conversational interview or expert heuristic audit — see [Test modes](/ai-tests/test-modes). | | **Test sections** | The dimensions each screen is evaluated on. Defaults: *Initial Impressions, User Actions & Behavior, Usability Issues,* and *Recommendations* — fully editable. | | **Per-screen notes & scripts** | Add notes to individual screens, and (in conversational mode) custom interview questions per screen. | | **Personas** | One or more [personas](/ai-tests/personas), each with its own execution count. | | **SUS questionnaire** | Optionally have each persona fill out a System Usability Scale questionnaire — see [Test modes](/ai-tests/test-modes#sus-questionnaires). | | **Ignore content accuracy** | Tell the AI to disregard placeholder content (lorem ipsum, dummy data) and focus on structure and flow, with optional notes about what to ignore. | ## Tips * **Test one flow at a time.** Ten focused screens beat forty mixed ones — findings stay attributable, and runs are cheaper to repeat as the design iterates. * **Write the goal like a research brief**: "First-time user setting up a workspace; we want to know if the invite step is discoverable" beats "test my app." * **Test iterations in the same project** — when the design changes, run a new round with the same personas and compare rounds to see whether the fixes landed. # AI tests overview Source: https://docs.getversive.com/ai-tests/overview Instant usability testing with AI personas — no recruiting required AI tests let you test designs and websites with **AI personas** instead of recruited participants. Import a Figma prototype, paste a website URL, or upload design images, and get a detailed usability report — transcripts, screenshots, findings, and prioritized recommendations — in minutes. ## Test types Import an interactive prototype by URL or via the Figma plugin. AI users move through your selected frames and react screen by screen. Upload static screenshots or mockups and get feedback on visual design, layout, and information hierarchy. An AI user operates a real browser on your live site, working toward a task you define — with a step-by-step action log, screenshots, and a full session recording. Reusable, richly detailed AI participants — hand-written or distilled from your own research data. ## How a test comes together 1. **Create a project** from a Figma prototype, image upload, or website URL. Projects organize all the tests you run against one design. 2. **Configure the test** — the goal or task, the [test mode](/ai-tests/test-modes) (conversational, expert audit), the questions each screen is evaluated on, and optional extras like SUS questionnaires. 3. **Pick personas** — one or many, each with its own run count, from your [persona library](/ai-tests/personas) or written inline. 4. **Run it.** Each persona execution is one test run, and a single launch can include up to 50 runs across all selected personas. Runs complete in minutes; website tests can be watched live. 5. **Read the results** — per-run transcripts and screenshots, plus an aggregated summary with key takeaways and prioritized recommendations. See [Results & reports](/ai-tests/results). ## Projects & lifecycle Projects live in folders alongside your studies and move through **Draft → Active → Completed / Archived** (a draft becomes active on its first run). You can duplicate a project to iterate on a new version of a design, and every run keeps a snapshot of the exact configuration and screens it tested — so old results stay meaningful as the design evolves. Test runs themselves are **running → completed** (or *failed* — retryable once, free unless the retry succeeds; prototype runs can be *partially successful* if only some screens complete). ## Credits | Run type | Credits | | - | - | | Figma prototype / image test run (per persona execution) | 1 | | Website test run (up to 50 browser steps) | 1 | | Website test run with extended limit (up to 100 steps) | up to 2 | Credits are only charged for runs that **succeed** (including partially successful prototype runs) and come from the same allowance as study completions. # AI personas Source: https://docs.getversive.com/ai-tests/personas Build reusable AI participants from scratch or from your own research data Personas are the AI participants in your tests. They live in an organization-wide **persona library**, organized into folders, and are reusable across every test and [study simulation](/studies/launch-and-sharing#simulate-ai-test-participants). ## Creating personas There are three ways to create a persona: Describe the persona in free text — up to 500,000 characters, so you can be as detailed as you like. Attach real research files — interview transcripts, survey exports, research reports — as PDF, DOCX, TXT, or Markdown (up to 10 MB per file, 50 MB per persona). Versive's AI distills your text and files into a structured persona, preserving specific details, numbers, and quotes from the source data. You can also write a quick **custom persona inline** while configuring a test, without saving it to the library. ## What's in a distilled persona | Field | What it captures | | - | - | | **Summary** | A 20–120 word portrait of who this is. | | **Identity** | Demographics and background — age, location, education, income, family, role, lifestyle. | | **Context** | Why they're looking for a solution right now. | | **Goals & outcomes** | What success looks like for them, including concrete KPIs. | | **Friction points** | Known pain points and obstacles. | | **Behavioral patterns** | Habits and typical workflows. | | **Interaction style** | Communication style, technology comfort level, and decision-making process. | | **Psychometric profile** | Big Five traits — openness, conscientiousness, extraversion, agreeableness, neuroticism. | | **Unique factors** | Distinctive details, real quotes, and behavioral instructions. | Everything is editable after distillation. ## Using personas in tests * Add any number of personas to a test; each has its own **execution count** (how many independent runs it performs). * Each persona execution is a separate test run and consumes one credit (website runs with the extended step limit can cost up to two). * Results are attributed to their persona, so you can compare how different user types experience the same design. ## Best practices * **Source personas from real research.** A persona distilled from ten actual interview transcripts behaves far more specifically than one written from imagination. The distiller keeps real quotes and numbers — feed it real data. * **One persona, one segment.** Don't average two audiences into one persona ("busy parents and enterprise admins") — make two, and run both. * **Use execution counts for consistency.** Running the same persona 3–5 times shows which findings are stable and which were one-off. * **Maintain the library like a team asset.** Name personas by segment, keep them in folders, and update them as new research comes in — your plan includes a persona limit, so prune stale ones. # Results & reports Source: https://docs.getversive.com/ai-tests/results What AI test runs produce and how to read them ## Per-run results Every persona execution is a **test run** with its own detailed record: * **Conversational tests** — a full interview transcript per screen (moderator and persona turns), alongside the screen image. * **Expert audits** — heuristic-by-heuristic ratings (*Good / Fair / Poor / Not Applicable*) with the specific issues found. * **Website tests** — the step-by-step action log with screenshots and reasoning, task completion status with a confidence score, abandonment reason if the persona gave up, and the session video replay. * **SUS score** (if enabled) — the persona's questionnaire answers and computed 0–100 score. * **Run summary** — key findings plus recommendations prioritized as **P0 (critical), P1 (important), P2 (nice to have)**. * **Accessibility analysis** (website tests) — WCAG-based compliance check with an impact breakdown. Runs progress from *running* to *completed* (or *failed* — a failed run can be retried once, free unless the retry succeeds; prototype runs may be *partially successful* if only some screens complete). ## Aggregated test summary Above individual runs, each test gets an **aggregated summary** across all personas and executions: * **Test overview** and an overall **results rating** — *Excellent, Good, Fair, Poor,* or *Critical* — with an explanation. * **Key takeaways**, each tagged with sentiment (positive / negative / neutral). * **Prioritized recommendations**, linked to the pages or screens they concern and to the supporting runs and quotes — so every recommendation has receipts. Summaries generate on demand and can be regenerated after you add more runs. ## Sharing & feedback * **Public result links** — share a read-only view of a test with anyone, no Versive account needed; revocable at any time. * **Word & Markdown export** — formatted reports for stakeholders. * **Rate the run** — leave a 1–5 star rating and comment on any run; this feedback goes straight to the Versive team. ## Reading AI test results well * **Treat findings as hypotheses ranked by likelihood, not verdicts.** AI tests are exceptional at surfacing *where* flows confuse and *what* to look at; confirm the highest-stakes findings with a small real-user [study](/studies/overview). * **Look for repetition across personas and executions.** An issue that appears in four of five runs is signal; a one-off is a maybe. * **Treat priorities as guidelines.** The P0/P1/P2 rankings are the AI's read on severity — read each recommendation and decide whether it matches your own understanding before acting on it. * **Read the abandonment reasons.** Where and why the AI gave up on a task is often the single most actionable data point in a website test. # Test modes Source: https://docs.getversive.com/ai-tests/test-modes Conversational interviews, expert heuristic audits, and SUS questionnaires Prototype and image tests run in one of two modes, and either can add a SUS questionnaire on top. ## Conversational test (dynamic interview) The default mode. An AI moderator interviews the AI persona about each screen, producing a natural back-and-forth transcript — first impressions, expectations, confusion, and what they'd do next. * The interview covers your **test sections** (e.g. *Initial Impressions, User Actions & Behavior, Usability Issues, Recommendations*). * You can add a **custom interview script per screen** to make sure specific questions get asked. * Every persona execution produces its own transcript, so five personas give you five distinct perspectives on the same flow. **Use it when** you want qualitative reactions and the *why* behind usability problems — the closest thing to a moderated usability session, minutes instead of weeks. ## Expert audit (heuristic evaluation) A single AI expert reviews the entire flow against usability heuristics — by default **Nielsen's 10 usability heuristics**: 1. Visibility of system status 2. Match between system and the real world 3. User control and freedom 4. Consistency and standards 5. Error prevention 6. Recognition rather than recall 7. Flexibility and efficiency of use 8. Aesthetic and minimalist design 9. Help users recognize, diagnose, and recover from errors 10. Help and documentation You can replace or extend these with **custom heuristics** — each is just a name and a definition, so you can audit against your own design system rules or accessibility criteria. Results rate each heuristic (**Good / Fair / Poor / Not Applicable**), list the specific issues found, and produce per-screen recommendations. **Use it when** you want a fast, systematic design QA pass rather than simulated user reactions — great before design reviews or as a pre-launch checklist. ## SUS questionnaires Optionally, every persona fills in a **System Usability Scale** questionnaire after its run: * Starts from the 10 standard SUS statements (alternating positive/negative), each answered on a 1–5 scale. * Statements are editable, and you can use 1–20 of them — polarity is tracked per statement so scoring stays correct. * Produces the standard **0–100 SUS score** per run, comparable across design iterations. SUS scores from AI personas are best used **relatively** — comparing design A to design B, or v1 to v2 — rather than as absolute benchmarks against human-normed scales. ## Choosing a mode | You want… | Mode | | - | - | | User reactions, confusion points, and quotes | Conversational | | A systematic design-quality audit | Expert audit | | A trackable usability metric across iterations | Either + SUS | | Both perspectives | Run one test in each mode — same project, same screens | # Website tests Source: https://docs.getversive.com/ai-tests/website-tests AI users operate a real browser on your live site In a website test, an AI persona drives a **real browser** on your live, publicly accessible website, working toward a task you define. You get a step-by-step action log with a screenshot and reasoning for every step, plus a full session recording. ## Configuration | Setting | Description | | - | - | | **Website URL** | The page where the AI user starts. The site must be publicly reachable. | | **Task** | What the user should accomplish — e.g. "Find a two-bedroom apartment in Austin under \$2,000 and start an application." | | **Viewport** | Desktop sizes 1920×1080, 1536×864, 1366×768 (default), 1280×720, 1024×768 — or 500×1080 to simulate mobile. | | **Test sections** | The dimensions the run is evaluated on. Defaults: *Initial Impressions, User Action & Behavior, Recommendations.* | | **Personas** | One or more [personas](/ai-tests/personas), each with an execution count. | | **Extended limit** | Raises the per-run cap from 50 to 100 browser steps for longer journeys (may cost up to 2 credits). | ## While it runs * **Live view** — watch the AI user navigate in real time. * Each step logs the action (navigate, click, type, scroll), the element involved, a screenshot, and the AI's reasoning for taking it. ## What you get * **Task completion status** with a confidence score — and if the AI gave up, the abandonment reason. * **Step-by-step replay**: the full click path with screenshots, plus a session video recording. * **Findings per test section**, and an aggregated summary with key takeaways and recommendations linked back to the runs that produced them. * Optional **accessibility analysis** — WCAG-based checks with an impact breakdown and recommendations. ## Tips * **Write tasks with a verifiable end state.** "Add the cheapest annual plan to the cart" gives a clean success/failure signal; "explore the pricing page" doesn't. * **Start narrow.** Test the critical path (sign-up, checkout, key search) before broad "look around" tests. * **Match the viewport to your traffic.** If most visitors are on phones, run the mobile viewport — layouts fail differently at 500px. * **Staging environments** work as long as they're publicly reachable (no VPN or login walls the AI can't pass). # Create folder Source: https://docs.getversive.com/api-reference/folders/create-folder POST /folders Create a folder for organizing studies Creates a folder. Returns `201`. The folder name. `FULL_ACCESS`, `CAN_EDIT`, `CAN_VIEW`, `INVITE_ONLY`, or `CAN_EDIT_SURVEY_ONLY`. Days to keep interview transcripts in this folder's studies, from 1 to 36500, counted from each interview's last message. After that the transcript and the study memory learned from it are deleted. `null` keeps transcripts indefinitely. Over an MCP connection, only the organization owner can set it. See [Transcript retention](/platform/folders-and-permissions#transcript-retention). ### Response ```bash cURL theme={null} curl -X POST https://api.getversive.com/api/v1/folders \ -H "Authorization: Bearer $VERSIVE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Q3 churn research", "retention_policy_days": 30 }' ``` # List folders Source: https://docs.getversive.com/api-reference/folders/list-folders GET /folders List your organization's folders Returns all folders in your organization. ### Response An array of `{ id, name, created_at, retention_policy_days }`. `retention_policy_days` is `null` when the folder has no [retention policy](/platform/folders-and-permissions#transcript-retention). ```bash cURL theme={null} curl https://api.getversive.com/api/v1/folders \ -H "Authorization: Bearer $VERSIVE_API_KEY" ``` # Update folder Source: https://docs.getversive.com/api-reference/folders/update-folder PATCH /folders/{id} Rename a folder or set its transcript retention policy Updates only the fields you send. The folder ID. New folder name. Days to keep interview transcripts in this folder's studies, from 1 to 36500, counted from each interview's last message. Send `null` to turn retention off. Setting it on a folder with existing studies deletes their transcripts older than the window at the next hourly check. See [Transcript retention](/platform/folders-and-permissions#transcript-retention) for what is deleted and kept. Organization API keys can change this field. Over an MCP connection, only the organization owner can. ### Response ```bash cURL theme={null} curl -X PATCH https://api.getversive.com/api/v1/folders/5c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f \ -H "Authorization: Bearer $VERSIVE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "retention_policy_days": 30 }' ``` # Get interview insights Source: https://docs.getversive.com/api-reference/insights/get-insights GET /insights Fetch the AI-generated summary for an interview Returns the AI-generated transcript summary insight(s) for a completed interview. The interview ID. ### Response An array of insight objects: Currently `TRANSCRIPT_SUMMARY`. The structured summary content. ```bash cURL theme={null} curl "https://api.getversive.com/api/v1/insights?interview_id=5c8e2f1a-7d4b-4e9c-a1f3-6b2d8c4e0a9f" \ -H "Authorization: Bearer $VERSIVE_API_KEY" ``` # Create interview Source: https://docs.getversive.com/api-reference/interviews/create-interview POST /interviews Create an interview and get a personal participant link Creates an interview for a study and returns a unique **participant link**. This is the main integration point for inviting participants from your own systems — each interview gets its own `vid` token, so you can track exactly who responded. The study to create the interview in. Arbitrary key/value data stored with the interview (e.g. your internal user ID, cohort, source). Available in results, filters, and exports. A label for the interview (e.g. the participant's reference). Currently only `English` is accepted. ### Response The interview ID. The personal participant URL — send this to your participant. The study. Starts as `open`. ```bash cURL theme={null} curl -X POST https://api.getversive.com/api/v1/interviews \ -H "Authorization: Bearer $VERSIVE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "study_id": "9b2f7c1e-4a4b-4f6e-9a1d-1c2d3e4f5a6b", "title": "Participant #1042", "metadata": { "userId": "u_1042", "cohort": "churned-q2" } }' ``` ```json 200 theme={null} { "id": "5c8e2f1a-7d4b-4e9c-a1f3-6b2d8c4e0a9f", "title": "Participant #1042", "study_id": "9b2f7c1e-4a4b-4f6e-9a1d-1c2d3e4f5a6b", "metadata": { "userId": "u_1042", "cohort": "churned-q2" }, "link": "https://getversive.com/s/9b2f7c1e-4a4b-4f6e-9a1d-1c2d3e4f5a6b?vid=Xy3...", "status": "open", "created_at": "2026-07-13T10:30:00Z" } ``` # Get interview Source: https://docs.getversive.com/api-reference/interviews/get-interview GET /interviews/{id} Fetch an interview, including transcript and status Fetches an interview created via the API. The interview ID. ### Response `open`, `in_progress`, `paused`, `processing`, `closed` (complete), `screened_out`, or `canceled`. The participant link (empty if none). The participant link token. Your metadata from creation. The interview transcript. The conversation as `{ role, content }` messages. Structured per-question responses. Completion progress. Timestamp of the first message. Timestamp of the last message. Active participation time. Always `VERSIVE` for API-accessible interviews. Whether this is a simulated interview. ```bash cURL theme={null} curl https://api.getversive.com/api/v1/interviews/5c8e2f1a-7d4b-4e9c-a1f3-6b2d8c4e0a9f \ -H "Authorization: Bearer $VERSIVE_API_KEY" ``` # Get interview by link token Source: https://docs.getversive.com/api-reference/interviews/get-interview-by-vid GET /interviews Look up an interview by its participant link token (vid) Fetches an interview by the `vid` token from its participant link — useful when your system knows the link but not the interview ID (e.g. handling a redirect back from the study). The participant link token. ### Response The same interview object as [Get interview](/api-reference/interviews/get-interview). ```bash cURL theme={null} curl "https://api.getversive.com/api/v1/interviews?vid=Xy3AbC..." \ -H "Authorization: Bearer $VERSIVE_API_KEY" ``` # Get interview media Source: https://docs.getversive.com/api-reference/interviews/get-interview-media GET /interviews/{id}/media List a participant's recordings and uploaded files, each with a time-limited access link Lists the media captured during an interview: participant audio, screen recordings, camera video, and files uploaded in media-upload questions. Each item carries a link you can open or download from. Links point back at the Versive API (`/api/v1/media/{token}`) rather than at storage. Opening one re-checks that the key that requested it is still active and still has access to the study, then redirects to a short-lived download URL. Each link expires after 24 hours, stops working after about 500 opens, and dies as soon as the key is deactivated. Links carry no readable information, so they are safe to pass to other tools, but treat them like any other credential and do not post them publicly. Organization API keys can call this endpoint with no extra setup. Apps connected over [MCP](/mcp/overview) cannot use it yet: it requires the `media:read` scope, which the MCP server does not issue today. The interview ID. Comma-separated subset of `audio`, `screen`, `video`, `uploaded`. Defaults to all. ### Response Item counts keyed by `media_type`. The media ID. `audio`, `screen`, `video`, `uploaded_image`, or `uploaded_video`. The question the media was captured for. 1-based position of that question in the study. Short label derived from the question text. The transcript message it belongs to, when linked. Seconds. Only set for audio recordings. Only set for uploaded files. Only set for uploaded files. Bytes. Only set for uploaded files. Whether streaming playback has finished processing. The link works either way. Time-limited access link. Answers with a redirect to the file. When the link stops working. ```bash cURL theme={null} curl "https://api.getversive.com/api/v1/interviews/5c8e2f1a-7d4b-4e9c-a1f3-6b2d8c4e0a9f/media?types=audio,uploaded" \ -H "Authorization: Bearer $VERSIVE_API_KEY" ``` ```json Response theme={null} { "interview_id": "5c8e2f1a-7d4b-4e9c-a1f3-6b2d8c4e0a9f", "study_id": "0f1e2d3c-4b5a-4c6d-8e7f-9a0b1c2d3e4f", "counts": { "audio": 2, "uploaded_image": 1 }, "items": [ { "id": "8d2a1c0e-3f4b-4a5c-9d6e-7f8a9b0c1d2e", "media_type": "audio", "question_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d", "question_index": 1, "question_title": "How did you first hear about the product?", "message_id": "b2c3d4e5-f6a7-4b8c-9d0e-1f2a3b4c5d6e", "duration": 42.7, "mime_type": null, "file_name": null, "file_size": null, "ready": true, "created_at": "2026-09-10T14:03:11.402Z", "url": "https://api.getversive.com/api/v1/media/Zk3f...", "expires_at": "2026-09-11T14:05:00.118Z" } ] } ``` # Update interview Source: https://docs.getversive.com/api-reference/interviews/update-interview PUT /interviews/{id} Update an interview's status Updates an interview's status — for example, to cancel a link you no longer want used. The interview ID. One of `open`, `in_progress`, `paused`, `processing`, `closed`, `screened_out`, `canceled`. Omitting it makes the request a no-op. ### Response ```json theme={null} { "message": "Interview updated successfully" } ``` ```bash cURL theme={null} curl -X PUT https://api.getversive.com/api/v1/interviews/5c8e2f1a-7d4b-4e9c-a1f3-6b2d8c4e0a9f \ -H "Authorization: Bearer $VERSIVE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "status": "canceled" }' ``` # API introduction Source: https://docs.getversive.com/api-reference/introduction Authentication, conventions, and errors for the Versive public API The Versive public API (v1) lets you manage studies, questions, logic, interviews, translations, and insights programmatically. Typical uses: creating interviews with tracked links from your own app, syncing study content from your systems, building studies with the AI agent, and pulling interview transcripts and summaries into your data warehouse. ## Base URL ``` https://api.getversive.com/api/v1 ``` The machine-readable OpenAPI document is available at: ``` https://api.getversive.com/api/v1/openapi.json ``` Use the OpenAPI document for code generation and agent tool discovery. The pages in this reference add examples, authorization context, and product guidance that are not represented fully in the schema. ## Authentication Public REST integrations use an organization **API key** passed as a Bearer token: ```bash theme={null} curl https://api.getversive.com/api/v1/studies \ -H "Authorization: Bearer $VERSIVE_API_KEY" ``` API keys are created in your organization settings (**Organization → API keys**) by an owner or admin. Each key is scoped to one organization and grants full API access to that organization's data — there are no per-key scopes, so treat keys like passwords: store them in a secrets manager, never in client-side code, and deactivate keys you no longer use. A missing or invalid bearer credential returns `401` with `{"detail": "Invalid authentication credentials"}`. The same public API routes also accept short-lived, scoped JWTs issued for authenticated [Versive MCP server](/mcp/overview) sessions. Each MCP connection is granted `studies:read`, `interviews:read`, and `studies:write` at consent time (or a narrower set if the client requests one). Those scopes are an upper bound: organization roles and study access policies are still checked on every request. MCP clients manage these credentials automatically; do not copy MCP access tokens into direct REST API integrations. ## Conventions * **JSON everywhere** — request bodies are JSON (`Content-Type: application/json`); one endpoint ([Update question](/api-reference/questions/update-question)) also accepts `multipart/form-data` for file uploads. * **IDs are UUID strings.** * **Organization scoping is automatic** — the key determines the organization; requesting a resource that belongs to another organization returns `403`. * **Partial updates** — `PUT` endpoints only change the fields you send. On studies, the `config` object is *merged* into the existing config rather than replaced. * **Pagination is endpoint-specific** — list studies currently returns all matching records, while `GET /interviews?study_id=...` supports `page` and `page_size`. Check each endpoint's parameters before assuming either behavior. ## Rate limits and retries Versive does not currently publish numeric request-rate limits for the public API. Clients should keep concurrency bounded and retry transient `5xx` responses with exponential backoff and jitter. If the API edge returns `429`, treat it as transient and honor `Retry-After` when present. Do not retry validation, authentication, or authorization failures without changing the request. See [Versioning and compatibility](/api-reference/versioning) for the public API lifecycle and deprecation signals. ## Errors Errors use conventional HTTP status codes with a JSON body: ```json theme={null} { "detail": "Study not found" } ``` | Status | Meaning | | - | - | | `400` | Invalid request — missing/invalid parameters or values. | | `401` | Missing or invalid bearer credential. | | `403` | The resource belongs to a different organization. | | `404` | Resource not found. | | `429` | The API edge rejected excess traffic — retry with backoff and honor `Retry-After` when present. | | `422` | Validation failed — e.g. invalid `{{Q:...}}` question references; the body includes an `errors` array. | | `500` | Internal server error. | ## Resources Create, list, update, translate, and AI-edit studies; read response metrics. Read, batch-create/update, and delete a study's questions. Manage conditional branching rules. Create tracked participant links and read interview transcripts and status. Fetch AI-generated interview summaries. Trigger and manage study translations. Create and list folders for organizing studies. Receive an event after an interview is completed. Understand compatibility guarantees and deprecation signals. # Create question logic Source: https://docs.getversive.com/api-reference/question-logic/create-question-logic POST /question-logic Add a branching rule to a question Creates a logic rule. Rules on a question are evaluated top to bottom; the first match wins. Returns `201`. The study. The question the rule attaches to (must belong to the study). `==`, `!=`, `<`, `<=`, `>`, `>=`, `COUNT_LT`, `INCLUDES`, `NOT_INCLUDES`, `ALWAYS`, or `SMART_CONDITION`. (`INCLUDE_RESPONSE_IN_NEXT_QUESTION` is accepted for backwards compatibility but is legacy — use question mentions instead.) `string`, `int`, or `smart_condition`. `next_question_id`, `move_to_question_group`, `end_interview`, `redirect_url`, or `screen_out`. The comparison value — or, for `SMART_CONDITION`, the natural-language condition (e.g. "the participant mentions pricing"). Required for `next_question_id` actions; must be a question in the same study. Cannot be the rule's own question, or a question inside a randomized group (directly or nested) — target the group with `move_to_question_group` instead. Required for `move_to_question_group` actions; the interview enters at the group's first question (respecting per-participant randomization). Question groups must be enabled for the study. Must be a group in the same study that contains at least one question. Cannot be the question's own group or an ancestor of it, or a group nested inside a randomized group. Required for `redirect_url` actions. Set for `end_interview` actions. The language this rule applies to. ### Response The created logic rule — same shape as [List question logic](/api-reference/question-logic/list-question-logic). ```bash cURL theme={null} curl -X POST https://api.getversive.com/api/v1/question-logic \ -H "Authorization: Bearer $VERSIVE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "study_id": "9b2f7c1e-4a4b-4f6e-9a1d-1c2d3e4f5a6b", "question_id": "q-123", "operation": "<", "comparison_value": "3", "comparison_value_type": "int", "action_type": "screen_out" }' ``` # Delete question logic Source: https://docs.getversive.com/api-reference/question-logic/delete-question-logic DELETE /question-logic/{logic_id} Remove a branching rule Deletes a logic rule (soft delete). Returns `204 No Content`. The rule ID. ```bash cURL theme={null} curl -X DELETE https://api.getversive.com/api/v1/question-logic/lr-42 \ -H "Authorization: Bearer $VERSIVE_API_KEY" ``` # List question logic Source: https://docs.getversive.com/api-reference/question-logic/list-question-logic GET /question-logic List logic rules for a question or study Lists logic rules. Provide at least one of `question_id` or `study_id`. All rules in a study. Rules attached to one question. Filter by language. ### Response An array of logic rules: Rule ID. The study. The question the rule belongs to. Condition operator: `==`, `!=`, `<`, `<=`, `>`, `>=`, `COUNT_LT`, `INCLUDES`, `NOT_INCLUDES`, `ALWAYS`, or `SMART_CONDITION` (AI-evaluated natural-language rule). `INCLUDE_RESPONSE_IN_NEXT_QUESTION` is a legacy operator that may appear on older studies — use question mentions instead. The value to compare against — or the natural-language condition for `SMART_CONDITION`. `string`, `int`, or `smart_condition`. `next_question_id`, `move_to_question_group`, `end_interview`, `redirect_url`, or `screen_out`. Jump target for `next_question_id` actions. Jump target for `move_to_question_group` actions; the interview enters at the group's first question. Target URL for `redirect_url` actions. Whether the rule ends the interview. The language the rule applies to. ```bash cURL theme={null} curl "https://api.getversive.com/api/v1/question-logic?study_id=9b2f7c1e-4a4b-4f6e-9a1d-1c2d3e4f5a6b" \ -H "Authorization: Bearer $VERSIVE_API_KEY" ``` # Update question logic Source: https://docs.getversive.com/api-reference/question-logic/update-question-logic PUT /question-logic/{logic_id} Modify a branching rule Updates a logic rule; only the fields you send change. Returns `204 No Content`. The rule ID. Body fields (all optional): `operation`, `comparison_value`, `comparison_value_type`, `next_question_id`, `next_question_group_id`, `redirect_url`, `end_interview`, `action_type`, `language` — same semantics and target validation as [Create question logic](/api-reference/question-logic/create-question-logic). ```bash cURL theme={null} curl -X PUT https://api.getversive.com/api/v1/question-logic/lr-42 \ -H "Authorization: Bearer $VERSIVE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "comparison_value": "4" }' ``` # Batch create/update questions Source: https://docs.getversive.com/api-reference/questions/batch-questions POST /questions/batch Create and update questions in one call Creates and/or updates questions in a single study in one request. Items **with** an `id` are updated; items **without** an `id` are created (appended after the existing questions in the order given). Returns `201`. The questions to create or update. Every item must include the same `study_id`. Recognized fields per item: * `id` — include to update an existing question; omit to create. * `study_id` — **required** on every item. * `content` — question text; may include `{{Q:...}}` references. * `type` — question type (see [List questions](/api-reference/questions/list-questions) for values). * `props` — type-specific settings object. On updates it is merged with the existing props, with the same handling of multiple-choice `exclusiveOptions` as [Update question](/api-reference/questions/update-question#editing-multiple-choice-options) and the same validation of `earlierAnswerChecks` ([checks against earlier answers](/api-reference/questions/update-question#checks-against-earlier-answers)). * `interviewer_notes` — private AI guidance. * `assets` — media assets array. * `display_order` — position (new questions are auto-ordered if omitted). ### Question references (mentions) `content` can reference an earlier answer with either: * `{{Q:}}` — the complete answer. * A type-specific property token — one option response from a structured answer, such as: * `{{Q:.ratingForItem[0]}}` * `{{Q:.rankOfOption[0]}}` * `{{Q:.optionAtRank[0]}}` * `{{Q:.allocationForItem[0]}}` Property indices are zero-based. Do not construct property tokens with a generic `.option[index]` selector; it is not supported. Call [List available references](/api-reference/studies/available-references) for the destination question's position and copy the returned `template` verbatim. References are validated on write, and invalid property names, indices, missing questions, or forward references fail with `422` and an `errors` array. ### Response IDs of newly created questions, in input order. IDs of updated questions. The example below creates one new question and updates an existing one (`8d3b6a2f-1c4e-4f7a-b5d9-2e6c8a0f4b1d`), piping that existing question's answer into the new question's text. References must point at questions that already exist in the study — use [List available references](/api-reference/studies/available-references) to discover valid templates. ```bash cURL theme={null} curl -X POST https://api.getversive.com/api/v1/questions/batch \ -H "Authorization: Bearer $VERSIVE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "questions": [ { "id": "8d3b6a2f-1c4e-4f7a-b5d9-2e6c8a0f4b1d", "study_id": "9b2f7c1e-4a4b-4f6e-9a1d-1c2d3e4f5a6b", "content": "Which plan are you currently on?" }, { "study_id": "9b2f7c1e-4a4b-4f6e-9a1d-1c2d3e4f5a6b", "type": "question", "content": "Why did you choose the {{Q:8d3b6a2f-1c4e-4f7a-b5d9-2e6c8a0f4b1d}} plan?", "props": { "required": true, "maxFollowupQuestions": 3 } } ] }' ``` ```json 201 theme={null} { "created_question_ids": ["4f9c1e7a-6b2d-4a8e-9c3f-1d5b7e9a2c4f"], "updated_question_ids": ["8d3b6a2f-1c4e-4f7a-b5d9-2e6c8a0f4b1d"] } ``` # Delete question Source: https://docs.getversive.com/api-reference/questions/delete-question DELETE /questions/{question_id} Remove a question from its study Deletes a question (soft delete) and recalculates the study's estimated length. Returns `204 No Content`. The question ID. ```bash cURL theme={null} curl -X DELETE https://api.getversive.com/api/v1/questions/q-456 \ -H "Authorization: Bearer $VERSIVE_API_KEY" ``` # List questions Source: https://docs.getversive.com/api-reference/questions/list-questions GET /questions List a study's questions with logic and mentions Returns all questions in a study, ordered by `display_order`, each with its logic rules and resolved mentions. The study whose questions to list. ### Response An array of question objects: Question ID. The question text (may include `{{Q:...}}` reference placeholders). Question type — e.g. `question` (AI Question), `textInput`, `shortText`, `message`, `email`, `multipleChoice`, `ratingScale`, `matrixRatingScale`, `starRating`, `nps`, `number`, `ranking`, `rankingWithMatrix`, `cardSort`, `allocation`, `allocationWithMatrix`, `conjoint`, `treeTest`, `prototypeTask`, `websiteTest`, `externalLink`, `calendar`, `mediaUpload`, `exploratory`. Write endpoints accept `type` as a free-form string; these are the types the Versive app uses. Private notes guiding the AI interviewer. Position in the study. Type-specific settings (options, scales, limits, and so on). Attached media assets. Each asset keeps its stable `url` identifier and includes `download_url` for viewing or downloading it. Private storage links last one hour; `download_url_expires_at` is their UTC expiry time. Request this endpoint again for a fresh link. External URLs are passed through and have no expiry time. If a private file cannot be signed, both download fields are `null`; the rest of the response remains available. Use `download_url` to fetch the file. When updating a question, retain the asset's `url` identifier and omit the read-only `download_url` and `download_url_expires_at` fields. A private asset's identifier may contain `/object/public/`; it identifies the stored file but cannot be used as a public download link. The question's logic rules — same shape as [question logic](/api-reference/question-logic/list-question-logic). Resolved `{{Q:...}}` references in the content: `placeholder`, `referenced_question_id`, `label`, `type` (`question` | `propertyAnswer`), `property_name`, `property_index`, `valid`, `error`. ```bash cURL theme={null} curl "https://api.getversive.com/api/v1/questions?study_id=9b2f7c1e-4a4b-4f6e-9a1d-1c2d3e4f5a6b" \ -H "Authorization: Bearer $VERSIVE_API_KEY" ``` # Update question Source: https://docs.getversive.com/api-reference/questions/update-question PUT /questions/{question_id} Update a single question Updates a question. Only the fields you send change, and `props` is **merged** with the existing props. Returns `204 No Content`. The question ID. New question text. `{{Q:...}}` references are validated (`422` on invalid references). Private AI guidance. New position. Settings to merge into the existing props. See [Editing multiple-choice options](#editing-multiple-choice-options) for how exclusive options are kept in sync, and [Checks against earlier answers](#checks-against-earlier-answers) for `number` and `allocation` validation against an earlier answer. Replaces the media assets array. Keep each asset's stable `url` from [List questions](/api-reference/questions/list-questions). `download_url` and `download_url_expires_at` are read-only and are discarded if sent back. ### Adding an earlier answer Mentions are stored directly in `content`. Use `{{Q:}}` for the complete earlier answer. For one response from a matrix, ranking, allocation, or card-sort question, first call [List available references](/api-reference/studies/available-references) with `before_question_id` set to this question, then copy the returned property `template` verbatim. For example, this inserts the rating for the first matrix item: ```json theme={null} { "content": "You rated speed {{Q:matrix-q-123.ratingForItem[0]}}. What influenced that rating?" } ``` Property indices are zero-based. Invalid property names or indices return `422`. ### Editing multiple-choice options Multi-select `multipleChoice` questions can mark options such as "None of the above" as **exclusive** in `props.exclusiveOptions`. Entries are the option *text* and must exactly match an entry in `props.options` (case-sensitive), otherwise the request is rejected with `400`. You don't need to resend `exclusiveOptions` when you edit `options`. If you omit it, or send it unchanged, the API keeps it in sync for you: * Renaming one option keeps its exclusive marker (the marker follows the new text). * Removing an option drops its marker. * Setting `isMultiSelect` to `false` clears all markers, since exclusivity only applies to multi-select. To change which options are exclusive, send the new `exclusiveOptions` list explicitly, matching the final `options`. ```json theme={null} { "props": { "options": ["Red", "Blue", "None of the above"], "exclusiveOptions": ["None of the above"] } } ``` ### Checks against earlier answers `number` and `allocation` questions can carry checks of the answer against an earlier answer in `props.earlierAnswerChecks`. Each check has an `operation` (`<`, `<=`, `==`, `>=`, or `>`) and a `source`: the earlier question's `questionId`, plus `option` (the exact option text) when the earlier question is an `allocation`. * A `number` question holds a list of checks. * An `allocation` question holds either `{"target": "total", "checks": [...]}` — the total is compared, and the fixed limit (`hasLimit`) no longer applies — or `{"target": "options", "checks": {"