Building with AI: the Koji API for LLMs and coding assistants
A complete, copy-paste starting point for building Koji integrations with an AI coding assistant, plus the MCP server for agentic workflows.
Building with AI: the Koji API for LLMs and coding assistants
This page is written to be handed straight to an AI coding assistant. Paste its URL (or the context block near the bottom) into Claude, Cursor, or any LLM tool, and it has everything needed to build a working Koji integration. Humans get a fast one-page overview here too, with links to the deeper guides.
Machine-readable resources
Point your assistant at these first. Each is complete and always current:
- Full docs as plain text:
https://www.koji.so/llms-full.txt(every doc article, including this whole API reference, in one file) - Docs index for LLMs:
https://www.koji.so/llms.txt(summary index plus the MCP tool list) - Docs as JSON:
https://www.koji.so/api/content(filter with?type=docs,?category=api-reference, or?slug=<slug>)
Two ways to integrate
There are two supported paths. Pick by what you are building.
| Path | Best for | Auth |
|---|---|---|
| MCP server | Natural-language and agentic workflows: let Claude, Cursor, or another MCP client run studies, read interviews, and generate reports conversationally | OAuth 2.1 (PKCE) |
| REST Headless API | Code that runs interviews inside your own product or backend | Bearer pk_live_... API key |
Path 1: the MCP server
Koji ships a Model Context Protocol server, so an AI assistant can manage your research by talking to it. Add this connector URL to your MCP client:
https://www.koji.so/api/mcp/mcp
- Transport: Streamable HTTP (SSE is a deprecated fallback)
- Auth: Auth is OAuth 2.1 with PKCE (S256). The client is public (no client secret). Discovery is automatic: clients read https://www.koji.so/.well-known/oauth-authorization-server and https://www.koji.so/.well-known/oauth-protected-resource. Dynamic Client Registration (RFC 7591) is supported, so most clients just need the connector URL and will walk you through sign-in. Tokens are Bearer (Authorization header). Access tokens last 1 hour; refresh tokens 30 days.
- Scopes: read-only (
read:studies,read:interviews,read:account).
Add the URL above as a custom MCP server and approve the sign-in. Then ask in plain language, for example "create a churn study and show me the interviews as they come in." Client-specific setup guides: Claude, Claude Code, Cursor, VS Code, Windsurf.
Available tools (15):
| Tool | What it does |
|---|---|
koji_list_studies | List your studies |
koji_get_study | Get a study's configuration and status |
koji_get_interviews | List interviews for a study |
koji_get_transcript | Get a single interview transcript |
koji_get_account | Get your account, plan, and credit balance |
koji_create_study | Create a new study from a research goal |
koji_update_brief | Iteratively edit a study's research brief |
koji_publish_study | Publish a study so it starts collecting interviews |
koji_get_study_data | Get aggregated study data and insights |
koji_generate_report | Generate an analysis report for a study |
koji_get_report | Get a study's current report |
koji_publish_report | Publish a report to a public link |
koji_configure_study | Configure branding, lead form, interaction modes, URL slug, and Open Graph in one call |
koji_export_data | Export interviews and transcripts as CSV or JSON |
koji_import_respondents | Import contacts with personalized interview URLs |
Path 2: the REST Headless API in one page
Everything below is enough to build a full text or voice interview flow.
Base URL
https://www.koji.so/api/v1
Authentication
Send a study-scoped API key as a Bearer token. You never send a project id; the key identifies the study.
Authorization: Bearer pk_live_wJalrXUtnFEMI4K7MDENGbPxRfiCYz2K
Create a key from the study's Integrate page. See API Authentication for the full model.
Endpoints
| Endpoint | Purpose |
|---|---|
POST /interviews/start | Start an interview |
POST /interviews/{interview_id}/message | Send a message |
POST /interviews/{interview_id}/complete | Complete an interview |
GET /interviews/{interview_id} | Get interview results |
Credentials per endpoint
| Endpoint | API key | Session token | Permission |
|---|---|---|---|
POST /interviews/start | Yes | No | interview:start |
POST /interviews/{interview_id}/message | Yes | Yes | interview:chat |
POST /interviews/{interview_id}/complete | Yes | Yes | interview:complete |
GET /interviews/{interview_id} | Yes | No | interview:read |
GET /embed/{project_id} | Optional | No | None |
Lifecycle
Start an interview, stream the AI's replies as the respondent answers, complete it, then read the analysis:
// Full interview lifecycle: start → message → complete → read results.
// Node 18+ (built-in fetch). Replace the key with your own.
const API_KEY = 'pk_live_wJalrXUtnFEMI4K7MDENGbPxRfiCYz2K'
const BASE = 'https://www.koji.so/api/v1'
const HEADERS = { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' }
async function main() {
// 1. Start
const started = await fetch(`${BASE}/interviews/start`, {
method: 'POST',
headers: HEADERS,
body: JSON.stringify({ respondent: { external_id: 'user_8271' }, mode: 'text' }),
}).then(r => r.json())
console.log('AI:', started.initial_message)
const session = { 'X-Session-Token': started.session_token }
// 2. One message exchange (SSE)
const res = await fetch(`${BASE}/interviews/${started.interview_id}/message`, {
method: 'POST',
headers: { ...HEADERS, ...session },
body: JSON.stringify({ content: 'I found onboarding confusing.' }),
})
let reply = ''
const reader = res.body.getReader()
const decoder = new TextDecoder()
let buffer = ''
while (true) {
const { value, done } = await reader.read()
if (done) break
buffer += decoder.decode(value, { stream: true })
const lines = buffer.split('\n')
buffer = lines.pop()
for (const line of lines) {
if (!line.startsWith('data: ')) continue
const frame = JSON.parse(line.slice(6))
if (frame.type === 'chunk') reply += frame.content
}
}
console.log('AI:', reply)
// 3. Complete
await fetch(`${BASE}/interviews/${started.interview_id}/complete`, {
method: 'POST',
headers: { ...HEADERS, ...session },
body: JSON.stringify({ reason: 'natural' }),
})
// 4. Read results (analysis lands asynchronously)
const result = await fetch(`${BASE}/interviews/${started.interview_id}`, {
headers: HEADERS,
}).then(r => r.json())
console.log('Transcript messages:', result.stats.message_count)
}
main()
The message endpoint streams Server-Sent Events. For the frame-by-frame parser and every field, see Sending Messages via API. For the embed widget instead of code, see Embed Widget Reference.
Copy-paste context block
Give this to your AI assistant as a system or context message. It is intentionally compact and complete:
You are integrating the Koji Headless API (AI-moderated research interviews).
Base URL: https://www.koji.so/api/v1
Auth: header "Authorization: Bearer pk_live_<key>" on every request. No project id in bodies; the key identifies the study.
Endpoints:
- POST /interviews/start -> { interview_id, session_token, initial_message?, mode }. Body optional: { respondent: { external_id?, display_name?, metadata? }, mode: "text"|"voice", locale }.
- POST /interviews/{id}/message -> Server-Sent Events. Headers add "X-Session-Token: <session_token>". Body { content }. Frames: {"type":"chunk","content":...} then {"type":"done","message_id":...,"interview_complete":bool}.
- POST /interviews/{id}/complete -> { status, stats, analysis, analysis_pending }. Header "X-Session-Token: <session_token>". Body { reason? }.
- GET /interviews/{id} -> transcript, stats, respondent, analysis. API key only.
Errors are JSON { "error": string } (plus retry_after / message / reason on some). No code/details field.
Rate limit: 60/min per key, headers X-RateLimit-*.
Full spec: https://www.koji.so/llms-full.txt
Where to go next
REST Headless API:
- API Authentication and API Key Permissions
- Starting Interviews via API, Sending Messages via API, Completing Interviews via API
- Rate Limits and CORS and Common Error Codes
- Embed Widget Reference
MCP server:
- MCP Integration Overview and MCP Tool Reference
- Client setup: Claude, Claude Code, Cursor, VS Code, Windsurf
- MCP Troubleshooting
FAQ
What is the single best link to give an AI assistant?
https://www.koji.so/llms-full.txt for the full text of every doc, or this page's URL for a focused API-only starting point. Both are always current.
Do I need the MCP server and the REST API?
No. Use the MCP server for conversational and agentic control of your research, or the REST API to build interviews into your own product. They are independent and you can use either alone.
Does the API need a paid plan?
The headless API is available on all plans. Usage is governed by interview credits: each interview consumes credits from the study owner's balance (text and voice at different rates), and the start endpoint rejects new interviews when the study is out of quota or the owner has no credits.
Related Articles
Airtable + Koji: Launch AI Interviews from a Base and Sync Every Insight Back to the Record
Turn any Airtable base into a customer research engine: trigger Koji AI-moderated interviews from a view or automation, then write themes, sentiment, quality scores, and a transcript link straight back onto the matching record. No native connector required — Airtable speaks Zapier, Make, and webhooks, and Koji speaks all three.
Amplitude + Koji: Trigger AI Interviews from Product Analytics and Pipe Insights Back as Events
How to close the loop between Amplitude product analytics and Koji AI interviews — fire interview links to users in specific Amplitude cohorts, and pipe interview themes, sentiment, and quality scores back into Amplitude as user properties and custom events.
API Authentication
How Koji Headless API authentication works: pk_live_ API keys, permissions, session tokens, and origin allowlists.
Attio + Koji: Launch AI Interviews from Your CRM and Sync Every Insight Back to the Record
Connect Attio to Koji to trigger AI customer interviews from CRM records and lists, then write themes, quotes, and structured scores back onto each contact and company automatically.
Calendly + Koji: Auto-Run AI Interviews After Every Demo, Call, and No-Show
Connect Calendly to Koji to trigger AI voice and text interviews from meeting events — post-demo, post-onboarding, and no-show follow-ups — and capture structured feedback automatically.
Completing Interviews via API
Finalize interviews with POST /interviews/{id}/complete, then poll the read endpoint for the asynchronous AI analysis.