Skip to main content

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

PropertyValue
MethodPOST
Content-Typeapplication/json
Signature headerX-Zenoo-Signature (HMAC-SHA256)
Retry schedule1 min, 5 min, 30 min, 2 hr, 24 hr
IdempotencyEach event has a unique event_id
Timeout30 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

EventTrigger
case.createdNew case created
case.status_changedCase status transition
case.closedCase closed with resolution
case.escalatedCase escalated to a manager

Alert events

EventTrigger
alert.createdNew alert generated from check result
alert.resolvedAlert resolved by analyst or auto-disposition
alert.escalatedAlert escalated to manager
alert.ai_research_completedAI research completed for alert

Check events

EventTrigger
check.completedCheck execution completed with result
check.failedCheck execution failed

Risk events

EventTrigger
risk_assessment.completedRisk assessment scoring completed
risk_assessment.approvedRisk assessment approved by reviewer

SLA events

EventTrigger
sla.warningCase approaching SLA deadline (warning threshold)
sla.breachedCase 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
  }
}
FieldTypeDescription
event_idstringUnique event identifier for idempotency
event_typestringEvent type string
created_atstringISO 8601 timestamp of event creation
dataobjectEvent-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