Documentation Index
Fetch the complete documentation index at: https://docs.zenoo.com/llms.txt
Use this file to discover all available pages before exploring further.
Webhook Events
Zenoo sends webhook events to your configured endpoint when significant actions occur in the CLM platform. Use webhooks to build real-time integrations, trigger workflows, and keep external systems in sync.
Event delivery
| Property | Value |
|---|
| Method | POST |
| Content-Type | application/json |
| Signature header | X-Zenoo-Signature (HMAC-SHA256) |
| Retry schedule | 1 min, 5 min, 30 min, 2 hr, 24 hr |
| Idempotency | Each event has a unique event_id |
| Timeout | 30 seconds (your endpoint must respond) |
Always verify the X-Zenoo-Signature header before processing webhook payloads. See the signature verification section below.
Event types
Case events
| Event | Trigger |
|---|
case.created | New case created |
case.status_changed | Case status transition |
case.closed | Case closed with resolution |
case.escalated | Case escalated to a manager |
Alert events
| Event | Trigger |
|---|
alert.created | New alert generated from check result |
alert.resolved | Alert resolved by analyst or auto-disposition |
alert.escalated | Alert escalated to manager |
alert.ai_research_completed | AI research completed for alert |
Check events
| Event | Trigger |
|---|
check.completed | Check execution completed with result |
check.failed | Check execution failed |
Risk events
| Event | Trigger |
|---|
risk_assessment.completed | Risk assessment scoring completed |
risk_assessment.approved | Risk assessment approved by reviewer |
SLA events
| Event | Trigger |
|---|
sla.warning | Case approaching SLA deadline (warning threshold) |
sla.breached | Case has passed its SLA deadline |
Common envelope
Every webhook event uses this envelope structure:
{
"event_id": "evt_abc123xyz",
"event_type": "case.created",
"created_at": "2026-02-16T10:01:00Z",
"data": {
// Event-specific payload
}
}
| Field | Type | Description |
|---|
event_id | string | Unique event identifier for idempotency |
event_type | string | Event type string |
created_at | string | ISO 8601 timestamp of event creation |
data | object | Event-specific payload (varies by type) |
Event payloads
case.created
{
"event_id": "evt_001",
"event_type": "case.created",
"created_at": "2026-02-16T10:01:00Z",
"data": {
"case_token": "cas_xyz789",
"type": "Onboarding",
"status": "New",
"priority": "Medium",
"entity_token": "ent_abc123",
"entity_name": "Acme Holdings Ltd",
"due_date": "2026-03-02T10:00:00Z"
}
}
case.status_changed
{
"event_id": "evt_002",
"event_type": "case.status_changed",
"created_at": "2026-02-16T10:30:00Z",
"data": {
"case_token": "cas_xyz789",
"old_status": "New",
"new_status": "In Progress",
"changed_by": { "id": "user_analyst01", "name": "Sarah Johnson" }
}
}
case.closed
{
"event_id": "evt_003",
"event_type": "case.closed",
"created_at": "2026-02-16T11:35:00Z",
"data": {
"case_token": "cas_xyz789",
"risk_tier": "Medium",
"risk_score": 45,
"resolution_notes": "All checks passed. PEP match reviewed and cleared.",
"closed_by": { "id": "user_analyst01", "name": "Sarah Johnson" }
}
}
case.escalated
{
"event_id": "evt_004",
"event_type": "case.escalated",
"created_at": "2026-02-16T12:00:00Z",
"data": {
"case_token": "cas_xyz789",
"escalated_by": { "id": "user_analyst01", "name": "Sarah Johnson" },
"escalated_to": { "id": "user_manager01", "name": "Mike Chen" },
"reason": "Complex corporate structure requires senior review."
}
}
alert.created
{
"event_id": "evt_005",
"event_type": "alert.created",
"created_at": "2026-02-16T10:15:00Z",
"data": {
"alert_token": "alt_001",
"case_token": "cas_xyz789",
"type": "Screening",
"category": "PEP Match",
"title": "PEP Match: John Doe",
"priority": "High",
"priority_score": 78,
"entity_name": "John Doe"
}
}
alert.resolved
{
"event_id": "evt_006",
"event_type": "alert.resolved",
"created_at": "2026-02-16T11:30:00Z",
"data": {
"alert_token": "alt_001",
"case_token": "cas_xyz789",
"status": "Resolved",
"resolution_action": "Approve",
"resolution_notes": "Former local councillor. Low risk.",
"resolved_by": { "id": "user_analyst01", "name": "Sarah Johnson" }
}
}
alert.escalated
{
"event_id": "evt_007",
"event_type": "alert.escalated",
"created_at": "2026-02-16T12:00:00Z",
"data": {
"alert_token": "alt_002",
"case_token": "cas_xyz789",
"escalated_by": { "id": "user_analyst01", "name": "Sarah Johnson" },
"escalated_to": { "id": "user_manager01", "name": "Mike Chen" },
"reason": "Potential sanctions match requires senior review."
}
}
alert.ai_research_completed
{
"event_id": "evt_008",
"event_type": "alert.ai_research_completed",
"created_at": "2026-02-16T10:05:30Z",
"data": {
"alert_token": "alt_001",
"confidence": 85,
"false_positive_probability": 82,
"recommended_action": "Approve"
}
}
check.completed
{
"event_id": "evt_009",
"event_type": "check.completed",
"created_at": "2026-02-16T10:10:12Z",
"data": {
"check_token": "chk_001",
"case_token": "cas_xyz789",
"type": "PEP Screening",
"category": "Screening",
"result": "Refer",
"provider": "WorldCheck",
"entity_name": "John Doe",
"alert_generated": true,
"alert_token": "alt_001"
}
}
check.failed
{
"event_id": "evt_010",
"event_type": "check.failed",
"created_at": "2026-02-16T10:12:00Z",
"data": {
"check_token": "chk_003",
"case_token": "cas_xyz789",
"type": "Company Registry",
"category": "Company",
"error": "Provider timeout after 30 seconds",
"retry_scheduled": true,
"retry_count": 1
}
}
risk_assessment.completed
{
"event_id": "evt_011",
"event_type": "risk_assessment.completed",
"created_at": "2026-02-16T11:00:00Z",
"data": {
"assessment_token": "rsk_001",
"case_token": "cas_xyz789",
"overall_tier": "Medium",
"overall_score": 45,
"customer_risk": { "score": 40, "tier": "Medium" },
"geographic_risk": { "score": 30, "tier": "Low" },
"product_risk": { "score": 55, "tier": "Medium" },
"channel_risk": { "score": 25, "tier": "Low" },
"edd_required": false
}
}
risk_assessment.approved
{
"event_id": "evt_012",
"event_type": "risk_assessment.approved",
"created_at": "2026-02-16T11:15:00Z",
"data": {
"assessment_token": "rsk_001",
"case_token": "cas_xyz789",
"approved_by": { "id": "user_manager01", "name": "Mike Chen" },
"overall_tier": "Medium"
}
}
sla.warning
{
"event_id": "evt_013",
"event_type": "sla.warning",
"created_at": "2026-02-28T01:00:00Z",
"data": {
"case_token": "cas_xyz789",
"due_date": "2026-03-02T10:00:00Z",
"days_remaining": 2,
"assigned_to": { "id": "user_analyst01", "name": "Sarah Johnson" }
}
}
sla.breached
{
"event_id": "evt_014",
"event_type": "sla.breached",
"created_at": "2026-03-03T01:00:00Z",
"data": {
"case_token": "cas_xyz789",
"due_date": "2026-03-02T10:00:00Z",
"days_overdue": 1,
"auto_escalated": true,
"escalated_to": { "id": "user_manager01", "name": "Mike Chen" }
}
}
Signature verification
Verify the webhook signature to ensure the payload is authentic:
import hmac
import hashlib
def verify_signature(payload_bytes, signature, secret):
expected = hmac.new(
secret.encode("utf-8"),
payload_bytes,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)
# In your webhook handler:
signature = request.headers.get("X-Zenoo-Signature")
is_valid = verify_signature(request.body, signature, WEBHOOK_SECRET)
Next steps