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://sandbox.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://sandbox.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://sandbox.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://sandbox.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://sandbox.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://sandbox.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