Skip to main content

Webhooks

Receive real-time notifications when events occur in Kora Compliance — screenings complete, cases change, risk thresholds are breached, and more.

Create a Subscription

You can configure webhooks via the dashboard (Settings → Webhooks) or programmatically via the API.

Via API

Register a webhook endpoint to receive specific events:

curl -X POST https://api.korastratum.com/api/v1/webhooks/subscriptions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "X-Tenant-ID: YOUR_TENANT_ID" \
-H "Content-Type: application/json" \
-d '{
"name": "Production Webhook",
"url": "https://your-server.com/webhooks/compliance",
"events": [
"screening.completed",
"screening.match_found",
"case.created",
"case.escalated",
"risk.threshold_breached",
"batch.completed"
],
"rate_limit_per_minute": 1000
}'

Response:

{
"id": "wh_abc123",
"name": "Production Webhook",
"url": "https://your-server.com/webhooks/compliance",
"events": ["screening.completed", "screening.match_found", "..."],
"status": "ACTIVE",
"secret": "whsec_live_abc123...",
"rate_limit_per_minute": 1000,
"created_at": "2025-06-01T12:00:00Z"
}
warning

Save the secret from the response — it's used to verify webhook signatures and is only shown once.

Event Types

Screening Events

EventDescription
screening.startedScreening process initiated
screening.completedScreening finished with results
screening.failedScreening encountered an error
screening.match_foundMatch discovered in watchlists
screening.match_resolvedMatch reviewed and disposition set

Case Events

EventDescription
case.createdNew case created
case.updatedCase details updated
case.assignedCase assigned to analyst
case.escalatedCase escalated to senior reviewer
case.closedCase closed with disposition
case.reopenedClosed case reopened

Subject Events

EventDescription
subject.createdNew subject created
subject.updatedSubject data updated
subject.risk_changedSubject's risk profile changed

Risk & Decision Events

EventDescription
risk.assessedRisk assessment completed
risk.level_changedRisk level changed (e.g., LOW → HIGH)
risk.threshold_breachedConfigured risk threshold exceeded
decision.madeAutomated decision generated
decision.overriddenManual override applied

Identity Events

EventDescription
identity.verifiedIdentity verification passed
identity.failedIdentity verification failed

Reporting Events

EventDescription
report.generatedRegulatory report created
report.failedReport generation failed

System Events

EventDescription
system.alertSystem/operational alert
batch.completedBatch processing finished

Webhook Payload

Every webhook delivery has this structure:

{
"id": "del_abc123",
"event": "screening.completed",
"timestamp": "2025-06-01T12:00:00Z",
"data": {
"screening_id": "scr_abc123",
"status": "COMPLETED",
"risk_score": 750,
"risk_band": "HIGH",
"decision": {
"outcome": "REVIEW_REQUIRED",
"triggered_rules": ["SANCTIONS_MATCH"]
},
"match_summary": {
"total_matches": 1,
"sanctions_matches": 1,
"pep_matches": 0
}
}
}

Signature Verification

Every webhook includes an X-Webhook-Signature header containing an HMAC-SHA256 signature. Always verify this before processing.

const crypto = require("crypto");

function verifyWebhookSignature(payload, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(payload)
.digest("hex");

return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}

// Express middleware
app.post("/webhooks/compliance", express.raw({ type: "*/*" }), (req, res) => {
const signature = req.headers["x-webhook-signature"];
const payload = req.body.toString();

if (!verifyWebhookSignature(payload, signature, WEBHOOK_SECRET)) {
return res.status(401).send("Invalid signature");
}

const event = JSON.parse(payload);
// Process the event...

res.status(200).send("OK");
});

Retry Behavior

If your endpoint returns a non-2xx status code or times out (30 seconds), Kora Compliance retries with exponential backoff:

AttemptDelay
1Immediate
21 minute
35 minutes
430 minutes
52 hours
612 hours

After 6 failed attempts, the delivery is marked as failed. You can manually retry from the API:

curl -X POST https://api.korastratum.com/api/v1/webhooks/deliveries/del_abc123/retry \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "X-Tenant-ID: YOUR_TENANT_ID"

Test a Webhook

Send a test event to verify your endpoint is working:

curl -X POST https://api.korastratum.com/api/v1/webhooks/subscriptions/wh_abc123/test \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "X-Tenant-ID: YOUR_TENANT_ID"

Manage Subscriptions

# List all subscriptions
curl https://api.korastratum.com/api/v1/webhooks/subscriptions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "X-Tenant-ID: YOUR_TENANT_ID"

# Update a subscription
curl -X PUT https://api.korastratum.com/api/v1/webhooks/subscriptions/wh_abc123 \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "X-Tenant-ID: YOUR_TENANT_ID" \
-H "Content-Type: application/json" \
-d '{
"events": ["screening.completed", "case.created"],
"status": "ACTIVE"
}'

# Delete a subscription
curl -X DELETE https://api.korastratum.com/api/v1/webhooks/subscriptions/wh_abc123 \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "X-Tenant-ID: YOUR_TENANT_ID"

Best Practices

  • Always verify signatures — Reject unverified payloads to prevent spoofing
  • Return 200 quickly — Process events asynchronously; return 200 before doing heavy work
  • Handle duplicates — Use the delivery id for idempotency; the same event may be delivered more than once
  • Monitor delivery health — Check the deliveries endpoint for failed deliveries
  • Use specific events — Subscribe only to the events you need to reduce noise