New

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

Back to docs
API Reference

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:

  1. Open your project in Koji.
  2. Navigate to Settings > Integrations > Webhooks.
  3. Click Add Webhook Endpoint.
  4. Enter your endpoint URL. This must be an HTTPS URL that accepts POST requests.
  5. Select the events you want to receive.
  6. 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

EventTriggerDescription
interview.completedInterview is marked completeFires when the complete endpoint is called or the interview ends naturally
interview.analysis_readyAnalysis finishes processingFires when the automatic analysis pipeline finishes and results are available
interview.quality_scoredQuality score is assignedFires 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:

  1. Retrieve the raw request body as a string (before any JSON parsing).
  2. Compute an HMAC-SHA256 of the body using your webhook secret as the key.
  3. Compare the computed hash with the value in the X-Koji-Signature header.
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_id and 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