New

Now in Claude, ChatGPT, Cursor & more with our MCP server

Back to docs
API Reference

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:start permission. See API Authentication for how to create one.
  • A project with at least one published interview guide.
  • A Scale plan, which includes headless API access.

Endpoint

POST /api/v1/interviews/start

Headers

HeaderValueRequired
AuthorizationBearer your_api_keyYes
Content-Typeapplication/jsonYes

Request Body

Send a JSON object with the following fields:

FieldTypeRequiredDescription
project_idstring (UUID)YesThe ID of the project to run the interview in
guide_idstring (UUID)NoSpecific interview guide to use. If omitted, uses the project's default guide
respondent_namestringNoDisplay name for the respondent
respondent_emailstringNoEmail address for the respondent
metadataobjectNoArbitrary key-value pairs attached to the interview for your own tracking purposes
languagestringNoLanguage code (e.g., en, es, fr). Defaults to the project setting
modestringNoInterview mode: text or voice. Defaults to the project setting

Example Request

curl -X POST https://app.getkoji.com/api/v1/interviews/start \
  -H "Authorization: Bearer koji_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "project_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "respondent_name": "Jane Doe",
    "respondent_email": "[email protected]",
    "metadata": {
      "segment": "power_users",
      "source": "onboarding_flow"
    }
  }'

Response

A successful request returns a 201 Created response with a JSON body:

{
  "interview_id": "f8e7d6c5-b4a3-2109-8765-432109876543",
  "respondent_id": "r_abc123def456",
  "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...",
  "voice_credentials": {
    "token": "voice_tok_xxxxxxxxxx",
    "server_url": "wss://voice.getkoji.com/session/f8e7d6c5"
  }
}

Response Fields

FieldTypeDescription
interview_idstringUnique identifier for this interview. Use this for all subsequent API calls.
respondent_idstringIdentifier for the respondent record created for this interview
session_tokenstringToken required for session-scoped operations like completing the interview. Pass it as X-Session-Token header.
initial_messagestringThe first message from the interviewer. Display this to the respondent.
voice_credentialsobject or nullPresent only when mode is voice. Contains a token and WebSocket URL for establishing the voice connection.

Store the interview_id and session_token — you need both for subsequent operations.


Understanding the Response

interview_id

This is your primary reference for the interview. Use it to retrieve the interview, 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 complete endpoint.

initial_message

This is the greeting generated for the respondent based on your interview guide, project settings, and any respondent information you provided. Display this message in your interface as the start of the conversation.

voice_credentials

If the interview is configured for voice mode, this object contains everything needed to establish a real-time voice connection. The token authenticates the voice session, and the server_url is the WebSocket endpoint to connect to. If the interview uses text mode, this field is null.


Handling Errors

Status CodeErrorMeaning
400invalid_requestMissing required fields or invalid field values
401unauthorizedInvalid or missing API key
403forbiddenKey lacks interview:start permission or plan does not include API access
404not_foundThe specified project or guide does not exist
422unprocessableThe project has no published guide, or configuration prevents starting
429rate_limitedToo many requests. Check Rate Limits and CORS

All error responses include a JSON body with error and message fields:

{
  "error": "invalid_request",
  "message": "The field project_id is required."
}

Metadata

The metadata field accepts any flat JSON object. Use it to attach your own tracking data to the interview. 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