Overview

Klyra webhooks allow your application to receive real-time notifications when moderation events occur. This enables you to build reactive systems that can immediately respond to moderation decisions without constantly polling the API.

Use Cases

  • Receive notification when a batch moderation job completes
  • Get alerted immediately when high-severity content is detected
  • Trigger automated workflows based on moderation results
  • Synchronize moderation decisions across multiple systems
  • Log moderation activities for compliance purposes

Setting Up Webhooks

Step 1: Create a webhook endpoint

First, create an endpoint on your server that can receive POST requests from Klyra:

const express = require('express');
const crypto = require('crypto');
const app = express();

// Parse JSON bodies
app.use(express.json());

// Your webhook endpoint
app.post('/webhooks/klyra', (req, res) => {
  // Verify the webhook signature (see security section)
  const signature = req.headers['x-klyra-signature'];
  const isValid = verifySignature(req.body, signature, 'YOUR_WEBHOOK_SECRET');
  
  if (!isValid) {
    return res.status(401).send('Invalid signature');
  }
  
  // Process the webhook event
  const event = req.body;
  
  console.log('Received webhook:', event.type);
  
  // Handle different event types
  switch(event.type) {
    case 'moderation.completed':
      handleModerationCompleted(event.data);
      break;
    case 'moderation.flagged':
      handleContentFlagged(event.data);
      break;
    // Handle other event types
  }
  
  // Acknowledge receipt of the webhook
  res.status(200).send('Webhook received');
});

function verifySignature(payload, signature, secret) {
  const hmac = crypto.createHmac('sha256', secret);
  const expectedSignature = hmac.update(JSON.stringify(payload)).digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

app.listen(3000, () => {
  console.log('Webhook server running on port 3000');
});

Step 2: Register the webhook in Klyra Dashboard

  1. Log in to the Klyra Dashboard
  2. Navigate to Project Settings > Webhooks
  3. Click Add Webhook Endpoint
  4. Enter the following details:
    • Endpoint URL: The URL of your webhook endpoint (e.g., https://your-app.com/webhooks/klyra)
    • Events to send: Select which events to receive
    • Description: A friendly name for this webhook
  5. Click Generate Secret to create a signing secret
  6. Copy the generated secret and store it securely
  7. Click Create Webhook

Webhook Events

Klyra sends the following webhook events:

Event TypeDescription
moderation.completedA moderation request has been completed
moderation.flaggedContent has been flagged as potentially violating
moderation.batch.completedA batch moderation job has finished
moderation.appeal.receivedA moderation decision appeal has been submitted
moderation.appeal.resolvedA moderation appeal has been resolved

Webhook Payload

All webhook payloads follow this format:

{
  "id": "whk_1a2b3c4d5e6f",
  "type": "moderation.completed",
  "created": 1623180660,
  "data": {
    // Event-specific data
  }
}

Example Payloads

{
  "id": "whk_1a2b3c4d5e6f",
  "type": "moderation.completed",
  "created": 1623180660,
  "data": {
    "moderation_id": "mod_9z8y7x6w5v4u",
    "status": "success",
    "results": {
      "flagged": false,
      "categories": {
        "toxic": {
          "score": 0.01,
          "flagged": false
        },
        "spam": {
          "score": 0.02,
          "flagged": false
        }
      }
    },
    "metadata": {
      "processing_time_ms": 132
    }
  }
}

Security

Verifying Signatures

To ensure webhooks are coming from Klyra and haven’t been tampered with, all webhook requests include a signature in the X-Klyra-Signature header.

The signature is an HMAC SHA-256 hash created using your webhook secret and the request body:

const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
  const hmac = crypto.createHmac('sha256', secret);
  const expectedSignature = hmac.update(JSON.stringify(payload)).digest('hex');
  
  // Use a constant-time comparison to prevent timing attacks
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

Best Practices

  • Store your webhook secret securely: Never expose your webhook secret in client-side code
  • Always verify signatures: Reject requests with invalid signatures
  • Implement idempotency: Webhook events may occasionally be delivered more than once
  • Return 2xx responses quickly: Acknowledge webhook receipt promptly (within 10 seconds)
  • Process webhooks asynchronously: Handle time-consuming tasks in background jobs

Retries and Failures

If your endpoint returns a non-2xx response or takes too long to respond, Klyra will retry the webhook with exponential backoff:

  • 1st retry: 5 minutes after initial failure
  • 2nd retry: 15 minutes after 1st retry
  • 3rd retry: 60 minutes after 2nd retry
  • 4th retry: 180 minutes after 3rd retry
  • 5th retry: 360 minutes after 4th retry

After 5 failed attempts, the webhook delivery will be marked as failed and will not be retried again.

Webhook Logs

You can view webhook delivery history in the Klyra Dashboard:

  1. Go to Project Settings > Webhooks
  2. Select a webhook endpoint
  3. View the Delivery History tab

For each delivery attempt, you can see:

  • Timestamp
  • HTTP status code
  • Response time
  • Request/response bodies
  • Error details (if any)

Testing Webhooks

You can send test webhook events from the Klyra Dashboard:

  1. Go to Project Settings > Webhooks
  2. Select a webhook endpoint
  3. Click Send Test Event
  4. Choose an event type and customize the payload if needed
  5. Click Send Test Event

For local development, we recommend using a service like ngrok to expose your local server to the internet.