Skip to main content

Working with Webhooks

This guide explains how to register webhooks, handle incoming webhook events, and understand the custom headers and payloads provided by the Diligent AI API.

1. Registering and managing webhooks

You can register multiple webhooks (up to 10), each with its own URL, secret, and event filter — for example a production endpoint, a staging endpoint, and a data-warehouse ingester. When an event occurs, Diligent delivers it to every active webhook whose filter includes that event type. Webhooks are managed with a standard CRUD API:
Method & pathPurpose
POST /webhooksCreate a webhook
GET /webhooksList all your webhooks
GET /webhooks/{webhook_id}Get a single webhook
PATCH /webhooks/{webhook_id}Update a webhook
DELETE /webhooks/{webhook_id}Delete a webhook (delivery stops at once)
POST /webhooks always creates a new webhook. To change an existing one, use PATCH /webhooks/{webhook_id} — re-posting will not update it.
Create a webhook — subscribe an endpoint to a subset of events:
// POST /webhooks
{
  "webhook_url": "https://your-server.com/webhooks",
  "is_active": true,
  "secret": "your-secret",
  "events": ["cdd_state_changed", "alert_remediated"]
}
The response includes the new webhook’s id and a has_secret flag (the secret itself is never returned):
{
  "id": "df89eb16-4c6a-439f-b668-7cca0cd786fa",
  "webhook_url": "https://your-server.com/webhooks",
  "is_active": true,
  "has_secret": true,
  "status": "active",
  "last_delivery_at": null,
  "last_delivery_status": null,
  "events": ["cdd_state_changed", "alert_remediated"]
}
Update a webhook — change only the fields you send. Omit secret to keep it, send "" to remove it, or send a new value to replace it:
// PATCH /webhooks/df89eb16-4c6a-439f-b668-7cca0cd786fa
{
  "events": ["cdd_state_changed", "alert_remediated", "search_completed"],
  "is_active": false
}
Delete a webhookDELETE /webhooks/{webhook_id} returns 204 and delivery to that endpoint stops immediately. Per-webhook event filtering: each webhook only receives the event types listed in its events array, so different endpoints can subscribe to different events. The supported types are:
  • cdd_state_changed: Triggered when the state of a CDD changes to inconclusive or complete.
  • monitoring_alert_fired: Triggered when a monitoring alert is fired on failure.
  • cdd_document_fetched: Triggered when a new document is successfully added to a CDD case.
  • search_completed: Triggered when a name screening search completes and results are available.
  • alert_remediated: Triggered when a name screening alert has been remediated (all hits resolved).
  • flow_run_completed: Triggered when a flow run finishes successfully (COMPLETED).
  • flow_run_failed: Triggered when a flow run fails (FAILED).
See the Register Webhook API Reference for full details.

2. Receiving Webhooks

When an event occurs, Diligent AI sends an HTTPS POST request to your registered endpoint.

Custom Headers

Each webhook request includes custom headers to help you identify and verify the event:
HeaderDescription
Content-TypeAlways application/json
User-AgentSender identifier (e.g., DiligentAI/1.0)
X-Webhook-IdUnique ID of your webhook
X-Event-IdUnique ID of this delivery event
X-Customer-IdYour customer ID
X-Target-typeEntity type (CDD, MONITORING_ALERT, NAME_SCREENING_SEARCH, NAME_SCREENING_ALERT, or FLOW_RUN)
X-Event-NameName of the triggered event (CDD_STATE_CHANGED, MONITORING_ALERT_FIRED, SEARCH_COMPLETED, CDD_DOCUMENT_FETCHED, ALERT_REMEDIATED, FLOW_RUN_COMPLETED, FLOW_RUN_FAILED)
X-SignatureHMAC signature for authenticity

Example Payloads

cdd_state_changed

{
  "headers": {
    "Content-Type": "application/json",
    "User-Agent": "DiligentAI/1.0",
    "X-Webhook-Id": "...",
    "X-Event-Id": "...",
    "X-Customer-Id": "...",
    "X-Target-type": "CDD",
    "X-Event-Name": "CDD_COMPLETED",
    "X-Signature": "sha256=..."
  },
  "payload": "<CDD object as JSON string>"
}

monitoring_alert_fired

{
  "headers": {
    "Content-Type": "application/json",
    "User-Agent": "DiligentAI/1.0",
    "X-Webhook-Id": "...",
    "X-Event-Id": "...",
    "X-Customer-Id": "...",
    "X-Target-type": "MONITORING_ALERT",
    "X-Event-Name": "MONITORING_ALERT_FIRED",
    "X-Signature": "sha256=..."
  },
  "payload": {
    "alert_id": "...",
    "monitoring_id": "...",
    "type": "FRAUD",
    "details": {
      "reason": "Suspicious activity detected",
      "triggered_at": "2025-07-31T05:12:03.123Z"
    }
  }
}
  • payload: Alert object with details about the triggered alert.

cdd_document_fetched

{
  "headers": {
    "Content-Type": "application/json",
    "User-Agent": "DiligentAI/1.0",
    "X-Webhook-Id": "...",
    "X-Event-Id": "...",
    "X-Customer-Id": "...",
    "X-Target-type": "CDD",
    "X-Event-Name": "CDD_DOCUMENT_FETCHED",
    "X-Signature": "sha256=..."
  },
  "payload": "<Full CDD object as JSON string>"
}
  • payload: Full CDD object snapshot including all documents (see CDD Object).

search_completed

{
  "headers": {
    "Content-Type": "application/json",
    "User-Agent": "DiligentAI/1.0",
    "X-Webhook-Id": "...",
    "X-Event-Id": "...",
    "X-Customer-Id": "...",
    "X-Target-type": "NAME_SCREENING_SEARCH",
    "X-Event-Name": "SEARCH_COMPLETED",
    "X-Signature": "sha256=..."
  },
  "payload": {
    "id": "search-id-123",
    "reference": "CUST-2024-001",
    "status": "COMPLETED",
    "input": [
      {
        "value": "John Doe",
        "label": "FULL_NAME"
      },
      {
        "value": "INDIVIDUAL",
        "label": "ENTITY_TYPE"
      }
    ],
    "hit_counts": {
      "FALSE_POSITIVE": 2,
      "TRUE_POSITIVE": 1,
      "UNRESOLVED": 3
    },
    "hits": [
      {
        "id": "hit-001",
        "provider_reference": "27318408899",
        "status": "UNRESOLVED",
        "fields": [
          {
            "value": "WX0014675452",
            "label": "Profile ID"
          },
          {
            "value": "John Doe",
            "label": "Name"
          }
        ],
        "hit_categories": ["SANCTION"],
        "remediation": {
          "sync_status": "PENDING",
          "determination": "UNRESOLVED",
          "action": "DO_NOTHING",
          "determined_at": "2024-01-15T10:30:00Z",
          "author": "DILIGENT",
          "summary": "Names match with high confidence"
        }
      }
    ],
    "created_at": "2024-10-02T12:00:00Z",
    "updated_at": "2024-10-02T14:30:00Z"
  }
}
  • payload: Full search object with hits and remediation details.

alert_remediated

{
  "headers": {
    "Content-Type": "application/json",
    "User-Agent": "DiligentAI/1.0",
    "X-Webhook-Id": "...",
    "X-Event-Id": "...",
    "X-Customer-Id": "...",
    "X-Target-type": "NAME_SCREENING_ALERT",
    "X-Event-Name": "ALERT_REMEDIATED",
    "X-Signature": "sha256=..."
  },
  "payload": {
    "id": "714808a0-faf0-4e0f-a3a3-fbe490a10efd",
    "reference": "5jb7h9b1kiu51kbwyrjhog350",
    "alt_reference": "ABIGASQLIM3WR",
    "status": "COMPLETED",
    "remediation_status": "REMEDIATED",
    "profile_facts": [
      {
        "predicate": "has_name",
        "value": "Ryan Bailey",
        "citations": [{ "name": "PROFILE", "url": null }]
      },
      {
        "predicate": "date_of_birth",
        "value": "1992-01-27",
        "citations": [{ "name": "PROFILE", "url": null }]
      }
    ],
    "hits": [
      {
        "reference": "5jb766qtsj0e1kbwyrlh03gpe",
        "hit_categories": ["MEDIA"],
        "evidences": [
          {
            "type": "PRIMARY_NAME",
            "categories": ["NAME_GIVEN_NAME_EXACT_MATCH", "NAME_FAMILY_NAME_VARIANT_MATCH", "NAME_MAIN"],
            "supporting_facts": [
              {
                "predicate": "has_name",
                "value": "Ryan DAILEY",
                "citations": [{ "name": "HIT", "url": null }]
              },
              {
                "predicate": "has_name",
                "value": "Ryan Bailey",
                "citations": [{ "name": "PROFILE", "url": null }]
              }
            ]
          },
          {
            "type": "DOB",
            "categories": ["DOB_AMBIGUOUS", "DOB_YEAR_MISMATCH"],
            "supporting_facts": [
              {
                "predicate": "date_of_birth",
                "value": "1974",
                "citations": [{ "name": "HIT", "url": null }]
              },
              {
                "predicate": "date_of_birth",
                "value": "1975",
                "citations": [{ "name": "ARTICLE", "url": "https://example.com/article" }]
              },
              {
                "predicate": "date_of_birth",
                "value": "1992-01-27",
                "citations": [{ "name": "PROFILE", "url": null }]
              }
            ]
          }
        ],
        "resolution": {
          "status": "NOTHING",
          "summary": "DOB mismatch — all hit dates are 2+ years off the profile DOB",
          "author": "DILIGENT",
          "action": "COMMENT_FALSE_POSITIVE",
          "determination": "FALSE_POSITIVE",
          "applied_rule": {
            "name": "Date of Birth Mismatch"
          }
        }
      }
    ],
    "created_at": "2024-01-15T09:00:00Z",
    "updated_at": "2024-01-15T10:30:00Z"
  }
}
  • payload: Full alert object. See Get Alert for the complete schema reference.
  • Each hit contains evidences with supporting_facts — the specific facts that drove the resolution decision, each with predicate, value, and a citations array indicating the data source (HIT, PROFILE, ARTICLE, REGISTRY, or WEB_SEARCH).

flow_run_completed

{
  "headers": {
    "Content-Type": "application/json",
    "User-Agent": "DiligentAI/1.0",
    "X-Webhook-Id": "...",
    "X-Event-Id": "...",
    "X-Customer-Id": "...",
    "X-Target-type": "FLOW_RUN",
    "X-Event-Name": "FLOW_RUN_COMPLETED",
    "X-Signature": "sha256=..."
  },
  "payload": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "flow_id": "flow-abc123",
    "flow_version_id": "ver-def456",
    "triggered_at": "2025-07-31T10:00:00.000Z",
    "status": "COMPLETED",
    "started_at": "2025-07-31T10:00:01.000Z",
    "completed_at": "2025-07-31T10:00:45.000Z",
    "input": {
      "subject": "Acme Corp"
    },
    "report": "s3://flows-artifacts/reports/run-a1b2c3d4.json",
    "error": null,
    "meta": {
      "case_ref": "CASE-001"
    },
    "created_at": "2025-07-31T10:00:00.000Z",
    "updated_at": "2025-07-31T10:00:45.000Z"
  }
}
  • payload: Full flow run object — the same shape returned by GET /v1/flow-runs/{runId}.
  • Delivered only when the run status transitions to COMPLETED (not on intermediate states such as QUEUED or RUNNING).

flow_run_failed

{
  "headers": {
    "Content-Type": "application/json",
    "User-Agent": "DiligentAI/1.0",
    "X-Webhook-Id": "...",
    "X-Event-Id": "...",
    "X-Customer-Id": "...",
    "X-Target-type": "FLOW_RUN",
    "X-Event-Name": "FLOW_RUN_FAILED",
    "X-Signature": "sha256=..."
  },
  "payload": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "flow_id": "flow-abc123",
    "flow_version_id": "ver-def456",
    "triggered_at": "2025-07-31T10:00:00.000Z",
    "status": "FAILED",
    "started_at": "2025-07-31T10:00:01.000Z",
    "completed_at": "2025-07-31T10:00:12.000Z",
    "input": {
      "subject": "Acme Corp"
    },
    "report": null,
    "error": {
      "code": "EXECUTION_ERROR",
      "message": "entityName is required",
      "step": null
    },
    "created_at": "2025-07-31T10:00:00.000Z",
    "updated_at": "2025-07-31T10:00:12.000Z"
  }
}
  • payload: Full flow run object — the same shape returned by GET /v1/flow-runs/{runId}.
  • Delivered only when the run status transitions to FAILED.
  • CANCELLED runs do not trigger either flow run webhook event.

3. Webhook Flow Diagram

Below is a simple flow of how a webhook is triggered and received:
  • Diligent AI triggers the webhook when an event occurs.
  • Your server receives a POST request with custom headers and event payload.
  • Your server should process the event and return a 200 OK status to acknowledge receipt.
For best practices on securing your endpoint and verifying signatures, see Securing Webhooks.