{"site":{"name":"Koji","description":"AI-native customer research platform that helps teams conduct, analyze, and synthesize customer interviews at scale.","url":"https://www.koji.so","contentTypes":["blog","documentation"],"lastUpdated":"2026-05-18T12:54:55.763Z"},"content":[{"type":"documentation","id":"d7494458-b3b1-4768-a3fa-69798a1c25a9","slug":"api-authentication","title":"API Authentication","url":"https://www.koji.so/docs/api-authentication","summary":"Koji API authentication uses project-scoped API keys (pk_live_ prefix) passed as Bearer tokens. Keys carry four granular permissions (interview:start, interview:chat, interview:complete, interview:read) and have a default rate limit of 60 requests per minute. API access is available on all plans. Session tokens provide additional per-interview authentication.","content":"# API Authentication\n\nEvery request to the Koji API must include a valid API key passed as a Bearer token. Without proper authentication, the API returns a 401 Unauthorized response.\n\n---\n\n## How Authentication Works\n\nKoji uses API keys to authenticate requests to its REST API. Each key is scoped to a specific project and carries a set of permissions that control what operations it can perform. When you make a request, include your API key in the `Authorization` header:\n\n```\nAuthorization: Bearer your_api_key_here\n```\n\nThe API validates your key on every request, checks that the key has the required permissions for the endpoint you are calling, and verifies that the key has not been revoked. If any of these checks fail, you receive an error response with details about what went wrong.\n\n---\n\n## Creating an API Key\n\nAPI keys are created from the **Integrations** page within your project settings. Here is how to generate one:\n\n1. Open the project you want to integrate with.\n2. Navigate to **Settings > Integrations**.\n3. Click **Create API Key**.\n4. Give the key a descriptive name (for example, \"Production Backend\" or \"Staging Test Key\").\n5. Select the permissions the key needs (see the Permissions section below).\n6. Click **Generate**.\n7. Copy the key immediately. For security, Koji only displays the full key once at creation time.\n\nAPI keys use the `pk_live_` prefix followed by 32 cryptographically random characters. The key is stored as a SHA-256 hash, so it cannot be retrieved after creation.\n\nStore your API key securely. Treat it like a password. Never commit it to source control, embed it in client-side code, or share it in plain text. For more on key lifecycle management, see [Managing API Keys](/docs/managing-api-keys).\n\n---\n\n## Permissions\n\nEach API key can be granted one or more permissions. This follows the principle of least privilege — only grant the permissions your integration actually needs.\n\n| Permission | What It Allows |\n|---|---|\n| `interview:start` | Start new interviews via the API |\n| `interview:chat` | Send and receive messages during an interview |\n| `interview:complete` | Mark interviews as complete and trigger analysis |\n| `interview:read` | Retrieve interview data, transcripts, and analysis |\n\nBy default, new API keys are created with all four permissions. For a typical integration that starts interviews, exchanges messages, and then retrieves results, all four permissions are appropriate. For a read-only dashboard that simply displays completed interview data, `interview:read` alone is sufficient.\n\nYou can update permissions on an existing key at any time from the Integrations page without regenerating the key itself.\n\n---\n\n## Session Tokens\n\nSome endpoints use a secondary authentication mechanism called a **session token**. When you [start an interview via the API](/docs/starting-interviews-via-api), the response includes a `session_token`. This token is tied to that specific interview session and is required when calling certain endpoints like [sending messages](/docs/sending-messages-via-api) and the [complete endpoint](/docs/completing-interviews-via-api).\n\n<figure class=\"koji-figure\">\n  <img\n    src=\"https://sybpuenocntpoywqhgkf.supabase.co/storage/v1/object/public/blog-images/api-authentication/inline-tokens-comparison.webp\"\n    alt=\"API key versus session token comparison for the Koji headless API across scope, lifetime, header and creation steps.\"\n    title=\"API key vs session token\"\n    width=\"800\"\n    height=\"401\"\n    loading=\"lazy\"\n  />\n  <figcaption>\n    <span class=\"caption-text\">How API keys and session tokens differ across scope, lifetime, header and the way each is created.</span>\n    <span class=\"caption-source\">Koji headless API documentation</span>\n  </figcaption>\n</figure>\n\nSession tokens differ from API keys in important ways:\n\n- **Scope**: A session token is valid only for the single interview it was created for.\n- **Lifetime**: Session tokens expire when the interview is completed or after a period of inactivity.\n- **Header**: Pass the session token using the `X-Session-Token` header, not the `Authorization` header.\n\nA typical request using both authentication methods looks like this:\n\n```\nPOST https://koji.so/api/v1/interviews/:id/message\nAuthorization: Bearer your_api_key_here\nX-Session-Token: session_token_from_start_response\n```\n\n---\n\n## Plan Requirements\n\nAPI access is available on all Koji plans, including the free tier. The API is gated behind the `headless_api` entitlement, which is enabled for every plan. You can start building your integration immediately after creating a project.\n\n---\n\n## Rate Limiting\n\nEach API key has a default rate limit of 60 requests per minute. Every response includes rate limit headers so you can monitor your usage:\n\n| Header | Description |\n|---|---|\n| `X-RateLimit-Limit` | Maximum requests allowed in the current window |\n| `X-RateLimit-Remaining` | Requests remaining in the current window |\n| `X-RateLimit-Reset` | Unix timestamp when the current window resets |\n\nWhen you exceed the limit, the API returns a `429 Too Many Requests` response. For detailed guidance on handling rate limits, see [Rate Limits and CORS](/docs/rate-limits-and-cors).\n\n---\n\n## Revoking Keys\n\nIf you suspect a key has been compromised, revoke it immediately:\n\n1. Go to **Settings > Integrations** in your project.\n2. Find the key in the list.\n3. Click the **Revoke** button.\n4. Confirm the action.\n\nRevocation is instant. Any in-flight requests using that key will fail. There is no undo — if you need API access again, create a new key.\n\nYou can also deactivate a key temporarily by setting its `is_active` field to false, which lets you re-enable it later without regenerating. It is good practice to rotate your API keys periodically, even if you do not suspect compromise.\n\n---\n\n## Error Responses\n\nAuthentication errors return standard HTTP status codes:\n\n| Status Code | Meaning | Common Cause |\n|---|---|---|\n| 401 Unauthorized | Missing or invalid API key | Key not provided, malformed, or revoked |\n| 403 Forbidden | Key lacks required permission | Key does not have the permission needed for this endpoint |\n\nThe response body includes a JSON object with an `error` field and a human-readable `message` field to help you diagnose the issue.\n\n```json\n{\n  \"error\": \"unauthorized\",\n  \"message\": \"The provided API key is invalid or has been revoked.\"\n}\n```\n\n---\n\n## Security Best Practices\n\nFollowing these practices protects your integration and your respondents' data:\n\n- **Never expose keys client-side.** API keys belong on your server. If you need browser-based access, proxy requests through your backend.\n- **Use environment variables.** Store keys in environment variables or a secrets manager, not in your codebase.\n- **Scope permissions tightly.** Grant only the permissions each key actually needs.\n- **Rotate regularly.** Set a calendar reminder to rotate keys every 90 days.\n- **Monitor usage.** Review your API usage in the project dashboard to spot unusual patterns.\n- **Revoke unused keys.** If a key is no longer needed, revoke it. Orphaned keys are a security risk.\n\nFor more on securing your API integration, see [Rate Limits and CORS](/docs/rate-limits-and-cors).\n\n---\n\n## Next Steps\n\n- [Start your first interview via the API](/docs/starting-interviews-via-api)\n- [Understand rate limits and CORS configuration](/docs/rate-limits-and-cors)\n- [Learn about managing API keys](/docs/managing-api-keys)\n- [Explore the headless API overview](/docs/headless-api-overview)","category":"API Reference","lastModified":"2026-05-18T06:21:56.631829+00:00","metaTitle":"API Authentication — Koji Docs","metaDescription":"Learn how to authenticate with the Koji API using Bearer tokens, manage API key permissions, and follow security best practices.","keywords":["api authentication","api key","bearer token","permissions","session token","koji api"],"aiSummary":"Koji API authentication uses project-scoped API keys (pk_live_ prefix) passed as Bearer tokens. Keys carry four granular permissions (interview:start, interview:chat, interview:complete, interview:read) and have a default rate limit of 60 requests per minute. API access is available on all plans. Session tokens provide additional per-interview authentication.","aiPrerequisites":["creating-your-account"],"aiLearningOutcomes":["Create and manage API keys","Understand the permissions model","Use session tokens for interview-scoped auth","Follow security best practices for key management"],"aiDifficulty":"beginner","aiEstimatedTime":"6 min read"}],"pagination":{"total":1,"returned":1,"offset":0}}