Starting Interviews via API
Use the POST /start endpoint to programmatically launch interviews from your application.
Starting Interviews via API
The POST /api/v1/interviews/start endpoint lets you programmatically launch an interview session from your own application. This is the entry point for any headless integration with Koji.
Before You Begin
Make sure you have:
- An API key with the
interview:startpermission. See API Authentication for how to create one. - A project with a published research brief.
- API access is available on all Koji plans, including the free tier.
Endpoint
POST https://koji.so/api/v1/interviews/start
Headers
| Header | Value | Required |
|---|---|---|
Authorization | Bearer your_api_key | Yes |
Content-Type | application/json | Yes |
Request Body
Send a JSON object with the following fields:
| Field | Type | Required | Description |
|---|---|---|---|
respondent | object | No | Respondent information (see below) |
mode | string | No | Interview mode: text or voice. Defaults to the project setting |
locale | string | No | Language/locale code (e.g., en, es, fr). Defaults to the project setting |
Respondent Object
The respondent field accepts an object with these properties:
| Field | Type | Required | Description |
|---|---|---|---|
external_id | string | No | Your own identifier for this respondent, useful for linking back to your system |
display_name | string | No | Display name for the respondent |
metadata | object | No | Arbitrary key-value pairs attached to the respondent for your own tracking purposes |
Note that metadata is nested under the respondent object, not at the top level of the request body.
Example Request
curl -X POST https://koji.so/api/v1/interviews/start \
-H "Authorization: Bearer pk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{'
"respondent": {
"external_id": "user_12345",
"display_name": "Jane Doe",
"metadata": {
"segment": "power_users",
"source": "onboarding_flow"
}
},
"mode": "text",
"locale": "en"
}'
Response
A successful request returns a 201 Created response with a JSON body:
{
"interview_id": "f8e7d6c5-b4a3-2109-8765-432109876543",
"session_token": "st_live_xxxxxxxxxxxxxxxxxxxx",
"initial_message": "Hi Jane! Thanks for taking the time to chat with us today. I'd love to learn about your experience..."
}
Response Fields
| Field | Type | Description |
|---|---|---|
interview_id | string | Unique identifier for this interview. Use this for all subsequent API calls. |
session_token | string | Token required for session-scoped operations like sending messages and completing the interview. Pass it as X-Session-Token header. |
initial_message | string | The first message from the interviewer. Display this to the respondent. |
Store the interview_id and session_token — you need both for subsequent operations.
Important: The response field is interview_id, not conversation_id. Use interview_id consistently across all API calls.
Structured Questions
If your research brief includes structured questions (scale ratings, multiple choice, ranking, yes/no), the interview will present interactive widgets to the respondent during the conversation. When the interview completes and analysis runs, structured answers are returned alongside qualitative insights.
Each structured answer in the analysis includes:
questionIdandquestionText— identifies which question was answeredquestionType— the type of question (scale, single_choice, multiple_choice, ranking, yes_no)structuredValue— the typed response (number for scale, string for single choice, string array for multiple choice or ranking, boolean for yes/no)qualitativeAnswer— any additional context the respondent providedconfidence— how confident the analysis is in the extracted answerfollowUpInsights— insights from follow-up probing
This enables programmatic aggregation of quantitative data alongside qualitative insights.
Understanding the Response
interview_id
This is your primary reference for the interview. Use it to send messages, complete it, and look it up in your project dashboard.
session_token
The session token acts as a secondary authentication layer scoped to this specific interview. It proves that the caller is the same entity that started the interview. You must include it when calling the message endpoint and the complete endpoint.
initial_message
This is the greeting generated for the respondent based on your research brief, project settings, and any respondent information you provided. Display this message in your interface as the start of the conversation.
Handling Errors
| Status Code | Error | Meaning |
|---|---|---|
| 400 | invalid_request | Missing required fields or invalid field values |
| 401 | unauthorized | Invalid or missing API key |
| 403 | forbidden | Key lacks interview:start permission |
| 404 | not_found | The specified project does not exist |
| 422 | unprocessable | The project has no published brief, or configuration prevents starting |
| 429 | rate_limited | Too many requests. Check Rate Limits and CORS |
All error responses include a JSON body with error and message fields:
{
"error": "invalid_request",
"message": "The project has no published research brief."
}
Respondent Metadata
The metadata field inside the respondent object accepts any flat JSON object. Use it to attach your own tracking data to the respondent. Common use cases include:
- User segmentation:
{"plan": "enterprise", "tenure_months": 24} - Source tracking:
{"source": "post_purchase_email", "campaign_id": "camp_123"} - A/B testing:
{"variant": "B", "experiment": "onboarding_v2"}
Metadata is returned when you retrieve the interview and is available in exports and webhooks. It does not affect the interview itself.
Integration Patterns
Server-to-Server
The most common pattern is calling the start endpoint from your backend when a user triggers an action (for example, clicking a "Give Feedback" button). Your backend starts the interview, receives the response, and passes the interview_id and initial_message to your frontend.
Batch Invitations
For research projects, you might start interviews in batch — for example, iterating through a list of participants and starting an interview for each one. Store the returned interview_id and session_token for each participant so you can track and complete them later.
Embedded Experience
Combine the API with the embed widget for a hybrid approach: start the interview server-side for tracking purposes, then hand off the interview_id to the embed widget for the conversational UI.
Next Steps
- Send and receive messages during the interview
- Complete the interview and trigger analysis
- Learn about structured questions
- Explore the headless API overview
Further reading on the blog
- AI-Moderated vs Human-Moderated Interviews: Which Should You Choose? — AI-moderated and human-moderated interviews each have a time and a place. Here is the honest comparison to help you choose the right approac
- Can I Paste User Interviews into ChatGPT? A Guide to GDPR and LLMs — Every product manager wants to ask an LLM about their user feedback. But pasting customer transcripts into public models is a GDPR nightmare
- The Continuous Discovery Handbook: How Product Teams Run Weekly Customer Interviews (2026) — 64% of software features are rarely or never used. Continuous discovery — weekly customer interviews baked into your product workflow — is t
Related Articles
API Authentication
Learn how to authenticate with the Koji API using API keys and Bearer tokens.
User Research API: Embed AI Interviews into Any Product or Workflow
How to use Koji's User Research API to run AI-moderated interviews from your own backend. Covers REST endpoints, the embed widget, webhooks, authentication, rate limits, and headless interview patterns.
Sending Messages via API
Understand how messages flow between your application and Koji during an API-started interview.
Headless API Overview
Manage interviews programmatically with the Koji REST API — start, message, and complete interviews from your own code.
Structured Questions in AI Interviews
Mix quantitative data collection — scales, ratings, multiple choice, ranking — with AI-powered conversational follow-up in a single interview.
Send Research Insights to Slack: Real-Time Customer Interview Notifications via Webhooks
Pipe customer interview insights from Koji into your Slack workspace in real time. Use Koji webhooks to notify a #research channel the moment an interview completes, post quote highlights to #product-feedback, or alert #cs-alerts when a churn signal is detected. Step-by-step setup with a working Slack incoming webhook recipe.