Webhook Setup
Receive real-time notifications when interviews complete and analysis finishes using webhooks.
Webhook Setup
Webhooks let you receive real-time notifications from Koji when key events happen in your project — most importantly, when an interview completes and its analysis is ready. Instead of polling the API, you provide a URL and Koji sends the data to you.
Why Use Webhooks
Polling the API to check if an interview's analysis is done works, but it has drawbacks: unnecessary requests, delayed detection, and wasted resources. Webhooks solve all of these by pushing data to your server the moment it is available.
Common use cases for webhooks include:
- Syncing results to your database as soon as analysis completes
- Triggering downstream workflows like sending a thank-you email to respondents
- Updating dashboards in real time as new interviews come in
- Alerting your team when a high-priority interview finishes
Configuring a Webhook
Set up webhooks from your project settings:
- Open your project in Koji.
- Navigate to Settings > Integrations > Webhooks.
- Click Add Webhook Endpoint.
- Enter your endpoint URL. This must be an HTTPS URL that accepts POST requests.
- Select the events you want to receive.
- Click Save.
Koji sends a verification request to your endpoint when you save it. Your server must respond with a 200 status code to confirm it is ready to receive events.
Supported Events
| Event | Trigger | Description |
|---|---|---|
interview.completed | Interview is marked complete | Fires when the complete endpoint is called or the interview ends naturally |
interview.analysis_ready | Analysis finishes processing | Fires when the automatic analysis pipeline finishes and results are available |
interview.quality_scored | Quality score is assigned | Fires when the quality gate has evaluated the interview |
You can subscribe to one or more events per webhook endpoint. Most integrations subscribe to interview.analysis_ready since that is when actionable data is available.
Webhook Payload
Koji sends a POST request to your endpoint with a JSON body:
{
"event": "interview.analysis_ready",
"timestamp": "2025-01-15T10:26:15Z",
"project_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"data": {
"interview_id": "f8e7d6c5-b4a3-2109-8765-432109876543",
"status": "completed",
"analysis_status": "completed",
"quality_score": 4.2,
"respondent": {
"id": "r_abc123def456",
"name": "Jane Doe"
},
"stats": {
"duration_seconds": 1530,
"total_messages": 37
},
"metadata": {
"segment": "power_users",
"source": "onboarding_flow"
}
}
}
The payload includes enough information to identify the interview and decide if you need to fetch full results. To retrieve the complete transcript and analysis, call GET /api/v1/interviews/:interview_id using your API key.
Verifying Webhook Signatures
Every webhook request includes a signature header that lets you verify the request genuinely came from Koji:
X-Koji-Signature: sha256=abc123...
To verify the signature:
- Retrieve the raw request body as a string (before any JSON parsing).
- Compute an HMAC-SHA256 of the body using your webhook secret as the key.
- Compare the computed hash with the value in the
X-Koji-Signatureheader.
const crypto = require('crypto');
function verifyWebhookSignature(rawBody, signature, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
Your webhook secret is displayed once when you create the webhook endpoint. Store it securely.
Always verify signatures before processing webhook data. Without verification, an attacker could send fake events to your endpoint.
Responding to Webhooks
Your endpoint must return a 2xx status code within 10 seconds to acknowledge receipt. If Koji does not receive a successful response, it retries the delivery.
Retry Policy
- Immediate retry after the first failure.
- Exponential backoff for subsequent retries: 1 minute, 5 minutes, 30 minutes, 2 hours.
- Maximum retries: 5 attempts over approximately 2.5 hours.
- After all retries are exhausted, the event is marked as failed. You can see failed deliveries in the webhook logs on your Integrations page.
Best Practices for Handling Webhooks
- Return 200 immediately. Do your heavy processing asynchronously after acknowledging receipt. If your processing takes more than 10 seconds, the webhook times out.
- Be idempotent. Koji may send the same event more than once (for example, if your server returned 200 but the connection dropped before Koji received the response). Use the
interview_idand event type to deduplicate. - Log everything. Store raw webhook payloads so you can debug issues later.
- Monitor failures. Check the webhook logs in your Integrations page regularly.
Testing Webhooks
The Integrations page includes a Send Test Event button for each webhook endpoint. This sends a sample payload to your URL so you can verify your handler works correctly before real interviews generate events.
During development, tools like ngrok or similar tunneling services let you expose a local server to receive webhook deliveries.
Troubleshooting
If your webhook is not receiving events:
- Check the endpoint URL is correct and accessible from the internet.
- Verify HTTPS. Koji only delivers webhooks to HTTPS URLs.
- Check your firewall allows incoming requests from Koji's IP ranges.
- Review the delivery logs in Settings > Integrations > Webhooks for error details.
- Confirm event subscription. Make sure you are subscribed to the events you expect.
Next Steps
Related Articles
API Authentication
Learn how to authenticate with the Koji API using API keys and Bearer tokens.
Completing Interviews via API
Use the POST /complete endpoint to finish an interview session and trigger automatic analysis.
Starting Interviews via API
Use the POST /start endpoint to programmatically launch interviews from your application.
Sending Messages via API
Understand how messages flow between your application and Koji during an API-started interview.
Embed Widget Reference
Technical reference for the Koji embed widget including iframe parameters and PostMessage API.
Rate Limits and CORS
Understand how Koji's API rate limiting works and how to configure CORS origins for your integration.