Webhooks

Set up webhooks to get notified when debates complete. Includes signature verification examples in Node.js and Python.

1 min read
Share

Webhooks send HTTP POST requests to your server when events occur, like a debate completing.

Setup

  1. Go to Developer Portal → Webhooks
  2. Click Create Webhook
  3. Enter your endpoint URL (must be HTTPS)
  4. Select events to subscribe to
  5. Copy the signing secret for verification

Events

EventDescription
debate.completedA debate has finished with a verdict
debate.failedA debate encountered an error
credits.lowCredit balance below threshold
key.createdNew API key was created
key.revokedAn API key was revoked

Payload Format

json
{
  "id": "evt_abc123",
  "type": "debate.completed",
  "timestamp": "2026-02-20T10:30:00Z",
  "data": {
    "debateId": "dbt_xyz789",
    "question": "Should we adopt Kubernetes?",
    "verdict": {
      "recommendation": "Proceed with caution",
      "confidence": 65
    }
  }
}

Signature Verification

Every webhook request includes a signature header for verification:

plaintext
X-AskVerdict-Signature: sha256=abc123...

Node.js

typescript
import crypto from "crypto";
 
function verifyWebhookSignature(
  payload: string,
  signature: string,
  secret: string
): boolean {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(payload)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(`sha256=${expected}`)
  );
}
 
// In your handler
app.post("/webhooks/askverdict", (req, res) => {
  const signature = req.headers["x-askverdict-signature"];
  const isValid = verifyWebhookSignature(
    JSON.stringify(req.body),
    signature,
    process.env.WEBHOOK_SECRET
  );
 
  if (!isValid) {
    return res.status(401).send("Invalid signature");
  }
 
  // Process the event
  const { type, data } = req.body;
  console.log(`Received ${type}:`, data);
  res.status(200).send("OK");
});

Python

python
import hmac
import hashlib
 
def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, f"sha256={expected}")

Retry Policy

If your endpoint returns a non-2xx status code, we retry:

AttemptDelay
1st retry1 minute
2nd retry5 minutes
3rd retry30 minutes
4th retry2 hours
Final retry24 hours

After 5 failed attempts, the webhook is disabled and you'll receive an email notification.

Always return a 200 status code quickly. Process webhook data asynchronously to avoid timeouts.

Testing

Use the Test Webhook button in the Developer Portal to send a sample event to your endpoint.

Was this page helpful?