# Block Company Source: https://docs.godiligent.ai/api-reference/blocked-companies/block POST /blocked-companies Block company by various data points # List blocked companies Source: https://docs.godiligent.ai/api-reference/blocked-companies/list GET /blocked-companies List all blocked companies by various data points # Unblock Company Source: https://docs.godiligent.ai/api-reference/blocked-companies/unblock DELETE /blocked-companies/{id} Unblock company by id # Add Document Source: https://docs.godiligent.ai/api-reference/cdd/add-document POST /cdds/{id}/documents Add supporting documents to a CDD case # Get CDD Source: https://docs.godiligent.ai/api-reference/cdd/get-cdd GET /cdds/{id} Retrieve details of a specific CDD request # Get CDD Report Source: https://docs.godiligent.ai/api-reference/cdd/get-report GET /cdds/{id}/report Download a detailed CDD report # List CDDs Source: https://docs.godiligent.ai/api-reference/cdd/list-cdds GET /cdds Retrieve a list of CDD requests # Perform CDD Source: https://docs.godiligent.ai/api-reference/cdd/perform-cdd POST /cdds Perform Customer Due Diligence checks # Pull registry documents Source: https://docs.godiligent.ai/api-reference/cdd/pull-registry-documents POST /cdds/{id}/pull-registry-documents Pull registry documents from official registries, supported only in IT and DE # Run risk checks Source: https://docs.godiligent.ai/api-reference/cdd/run-checks POST /cdds/{id}/run-checks Run risk checks on a completed CDD case # Identify Company Source: https://docs.godiligent.ai/api-reference/company/identify GET /companies/identify Get company by various data points # Get Run Source: https://docs.godiligent.ai/api-reference/flows/get-run GET /flow-runs/{runId} Poll a Flow run for its status and result ## Behavior * Poll this endpoint with the `id` returned by [Run](/api-reference/flows/trigger-run) until `status` reaches a terminal value (`COMPLETED`, `FAILED`, `CANCELLED`, or `SKIPPED`). * **`report`** is the full analyst-facing result as Markdown text. It is only set once `status` is `COMPLETED`. * **`output_ref`** is set once structured output has been captured for the run. Its presence (not its value) is the signal that [Get Run Output URL](/api-reference/flows/get-run-output-url) can be called to download the structured output file. * **`error`** is only set when `status` is `FAILED`. * Returns `404` if `runId` does not exist, or belongs to a different customer. # Get Run Output URL Source: https://docs.godiligent.ai/api-reference/flows/get-run-output-url GET /flow-runs/{runId}/output-url Get a download URL for a Flow run structured output ## Behavior * Returns a presigned URL to download the run's structured output file. The URL expires after `expires_in` seconds (currently 300). * Only call this once [Get Run](/api-reference/flows/get-run) shows `output_ref` set on the run. * Returns `404` with code `RUN_NOT_FOUND` if `runId` does not exist, or belongs to a different customer. * Returns `404` with code `OUTPUT_NOT_AVAILABLE` if the run has not captured structured output — for example if it has not completed yet, or if the Flow doesn't produce structured output. # Run Source: https://docs.godiligent.ai/api-reference/flows/trigger-run POST /flows/{flowId}/runs Queue a run of a Flow with the given input ## Behavior * **Asynchronous.** This call queues the run and returns immediately with the new run's `id` — it does not wait for the run to finish. * **Input** must match the Flow's active version input schema. This is validated before the run is queued. * Poll [Get Run](/api-reference/flows/get-run) with the returned `id` to check status and retrieve the result. * Returns `404` if `flowId` does not exist, or belongs to a different customer. * Returns `400` with `code: "VALIDATION_ERROR"` if `input` does not satisfy the active version's input schema. The response body includes `details`, an array of `{ field, message }` objects identifying each failing field: ```json theme={null} { "code": "VALIDATION_ERROR", "message": "Input does not match the flow's input schema", "details": [ { "field": "/name", "message": "must have required property 'name'" } ] } ``` # Acknowledge Monitoring Alerts Source: https://docs.godiligent.ai/api-reference/monitorings/acknowledge-alerts POST /monitoring-alerts/acknowledge Acknowledge (mark as seen) one or all monitoring alerts. ## Overview Acknowledge (mark as seen) one or all monitoring alerts for the authenticated customer. ## Request * **Method**: `POST` * **Path**: `/monitoring-alerts/acknowledge` * **Body**: JSON object specifying either a single alert ID or all alerts ### Request Body * `alert_id` (string, optional) - ID of the alert to acknowledge * `all` (boolean, optional) - If true, acknowledges all alerts for the customer * Exactly one of `alert_id` or `all` must be provided ### Example Request (single alert) ```json theme={null} { "alert_id": "532ebbd3-269d-4c8f-b73b-2269eb83f1ae" } ``` ### Example Request (all alerts) ```json theme={null} { "all": true } ``` ## Success Response * **Status**: 200 OK ### Response Body (single alert) ```json theme={null} { "success": true, "message": "Alert acknowledged", "unacknowledged_count": 5 } ``` ### Response Body (all alerts) ```json theme={null} { "success": true, "message": "7 alerts acknowledged", "unacknowledged_count": 0 } ``` ## Error Handling * **400 Bad Request** * Invalid request body or both `alert_id` and `all` provided * Example: `{ "error": "Either alert_id OR all must be provided, but not both" }` * **404 Not Found** * Alert with specified ID was not found * Example: `{ "error": "Alert not found" }` * **401 Unauthorized** * Missing or invalid customer authentication * **500 Internal Server Error** * Unexpected server error ## Notes * Only the owner (customer) may acknowledge their alerts * Bulk acknowledgment returns the number of alerts updated # Bulk Create Monitorings Source: https://docs.godiligent.ai/api-reference/monitorings/bulk-create-monitorings POST /monitorings/bulk-create Create multiple monitorings for a customer in a single request. Maximum of 200 monitorings per request. ## Overview The bulk create monitorings endpoint allows you to create multiple monitoring configurations in a single API call. This endpoint is useful for onboarding multiple websites or setting up monitoring for a large portfolio efficiently. ## Key Features * **Batch Processing**: Create up to 200 monitorings in one request * **Duplicate Detection**: Duplicate websites within the same request will be rejected with an error (all or nothing rule applies, unless `skip_duplicate` flag is set to true) * **Existing Monitoring Check**: If any monitoring already exists for a website for this customer, the entire request is rejected with a list of duplicates * **Immediate Execution**: Option to run monitoring checks immediately after creation (`run_now` flag) * **Flexible Scheduling**: Configure custom frequencies and expiration dates * **Atomic Operation**: If there are any validation or duplicate errors, no monitorings are created. (This is disabled if `skip_duplicate` flag is set to true) * **URL Security**: All website URLs are validated and sanitized for security ## Request * **Method**: `POST` * **Path**: `/monitorings/bulk-create` * **Body**: JSON array of monitoring objects (minimum 1, maximum 200) Each object must include: * `website` (string, required, unique in array) - The URL to monitor (will be validated and sanitized) * `checks` (array, required) - Array of monitoring checks to perform: * `"non_operational_website"` - Check if website is operational * `"high_risk_diligent_classification"` - Check for high-risk classification * `"catalog_contain_loan_flipping_indicators"` - Check for loan flipping indicators * `frequency` (string, required, case-insensitive) - How often to run checks: * `"weekly"` - Every 7 days * `"every_2_weeks"` - Every 14 days (default) * `"every_3_weeks"` - Every 21 days * `"every_4_weeks"` - Every 28 days * `expires_at` (ISO8601 string, optional) - When monitoring expires (defaults to 6 months from creation) * Must be a future date * Must be at least N days ahead where N equals the frequency period (e.g., weekly requires at least 7 days ahead) * `run_now` (boolean, optional) - Execute immediately after creation (defaults to true) * `external_id` (string, optional) - External ID for the monitoring * `skip_duplicate` (boolean, optional) - If any of the monitorings in the request has this flag set to true, and If an existing, active monitoring exist with the same site skip don't fail. ### Example Request ```json theme={null} [ { "website": "https://example.com", "checks": ["non_operational_website", "high_risk_diligent_classification"], "frequency": "weekly", "run_now": true, "expires_at": "2024-12-31T23:59:59.000Z", "external_id": "external_id_123", "skip_duplicate": true //This will enable skipping duplicates for all monitorings in the request. }, { "website": "https://shop.example.com", "checks": ["catalog_contain_loan_flipping_indicators"], "frequency": "every_4_weeks", "run_now": false, //No need to set skip_duplicate for this monitoring as it is already set in the previous record } ] ``` ## Success Response * **Status**: 200 OK ```json theme={null} { "is_successful": true, "items": [ { "id": "string", "website": "https://example.com", "checks": ["non_operational_website", "high_risk_diligent_classification"], "frequency": "weekly", "expires_at": "2024-12-31T23:59:59.000Z", "customer_id": "string", "created_at": "2024-06-03T10:46:00.000Z", "updated_at": "2024-06-03T10:46:00.000Z", "external_id": "external_id_123", "is_active": true, "running_state": "IDLE", "next_run_at": "2024-06-10T10:46:00.000Z", "last_execution": null, "execution_results": [] } ] } ``` ## Error Handling * **400 Bad Request** * Invalid JSON body, schema validation errors, duplicate websites in request, or monitorings already exist for one or more websites for this customer. * **Invalid JSON**: ```json theme={null} { "error": "Invalid JSON body:: Unexpected token '}' in JSON at position 1" } ``` * **Validation errors**: ```json theme={null} { "error": "[{\"code\":\"custom\",\"message\":\"Invalid check name(s)\",\"path\":[\"checks\"]}]" } ``` * **Duplicate websites in request**: ```json theme={null} { "error": "[{\"code\":\"custom\",\"message\":\"Duplicate monitoring found for website: https://example.com\",\"path\":[1,\"website\"]}]" } ``` * **Existing monitorings**: ```json theme={null} { "error": { "message": "Duplicate monitorings found", "duplicates": [ { "website": "https://example.com", "index": 0 }, { "website": "https://shop.duplicate.com", "index": 2 } ] } } ``` * **401 Unauthorized** * Missing or invalid customer authentication. * Example: ```json theme={null} { "error": "Unauthorized: no customer id" } ``` * **500 Internal Server Error** * Unexpected server error during creation or SQS publishing. * Example: ```json theme={null} { "error": "Failed to create monitorings" } ``` ## Validation Rules * **Website URLs**: All URLs are validated and sanitized for security. Invalid or disallowed URLs will be rejected. * **Unique Checks**: Each monitoring must have unique check names (no duplicates within the same monitoring). * **Frequency**: Case-insensitive input (e.g., "WEEKLY" becomes "weekly"). Must be one of the supported frequencies. * **Expiration Date**: * Must be a valid ISO8601 date string * Must be a future date * Must be at least N days ahead based on frequency (weekly=7 days, every\_2\_weeks=14 days, etc.) * Defaults to 6 months from creation if not provided * **Array Limits**: Minimum 1 monitoring, maximum 200 monitorings per request * **Duplicate Detection**: * No duplicate websites allowed within the same request or existing for the customer * If any of the monitorings in the request has `skip_duplicate` flag set to true, and if an existing, active monitoring exist with the same site skip don't fail ## Notes * All monitorings must have unique websites in the request and not already exist for the customer. * If `run_now` is set to true, the monitoring will be queued for immediate execution after creation. * Frequency input is case-insensitive and will be normalized to lowercase. * The system processes monitorings in batches for SQS publishing (batch size: 10). # Deactivate Monitoring Source: https://docs.godiligent.ai/api-reference/monitorings/deactivate-monitorings DELETE /monitorings/{id}/deactivate Deactivate a monitoring configuration for a customer. Idempotent and safe to repeat. ## Overview Deactivate a monitoring configuration for the authenticated customer. This operation is idempotent: if the monitoring is already inactive, the request will still succeed. ## Request * **Method**: `DELETE` * **Path**: `/monitorings/{id}/deactivate` * **Path Parameters**: * `id` (string, required): The monitoring ID to deactivate * **Authentication**: Requires valid customer authentication ### Example Request ```http theme={null} DELETE /monitorings/123e4567-e89b-12d3-a456-426614174000/deactivate ``` ## Responses * **204 No Content** * Monitoring was successfully deactivated * **200 OK** * Monitoring was already inactive (no response body) * **404 Not Found** * Monitoring with the specified ID was not found for the customer * Example: ```json theme={null} { "error": "Monitoring not found" } ``` * **500 Internal Server Error** * Unexpected server error during deactivation * Example: ```json theme={null} { "error": "" } ``` ## Error Handling * Returns `404` if the monitoring does not exist for the customer * Returns `500` with error details if an unexpected error occurs ## Notes * This endpoint is safe to call multiple times; deactivating an already inactive monitoring is not an error * Only the owner (customer) of the monitoring may deactivate it # List Monitoring Alerts Source: https://docs.godiligent.ai/api-reference/monitorings/list-alerts GET /monitoring-alerts Retrieve a paginated list of monitoring alerts for failed monitorings. ## Overview Retrieve a paginated list of monitoring alerts for the failed monitoring runs. Supports filtering by seen/unseen status and execution time, and provides an unseen alert count. ## Request * **Method**: `GET` * **Path**: `/monitoring-alerts` * **Query Parameters**: Optional filters and pagination ### Query Parameters * `page_size` (integer, optional) - Number of alerts per page * Default: 10 * Range: 1-100 * Must be a positive integer * `next_token` (string, optional) - Pagination token for next page * `only_unacknowledged` (boolean, optional) - If true, returns only unacknowledged alerts * `acknowledged` (boolean, optional) - If true, returns only acknowledged alerts * `execution_time_before` (ISO8601 string, optional) - Only include alerts executed before this time * `execution_time_after` (ISO8601 string, optional) - Only include alerts executed after this time ### Example Request ``` GET /monitoring-alerts?page_size=20&only_unacknowledged=true ``` ## Success Response * **Status**: 200 OK ### Response Body * `items` (array) - List of alert objects * `id` (string) - Unique identifier for the alert * `monitoring_id` (string) - ID of the monitoring that triggered this alert * `customer_id` (string) - ID of the customer that owns this monitoring * `execution_result_id` (string) - ID of the execution result * `website` (string) - URL of the monitored website * `failed_checks` (array) - List of checks that failed * `check` (string) - The type of check that failed * `explanation` (string) - Explanation of the failure * `method_used` (string) - Method used for checking * `status` (string) - Status of the check * `execution_time` (string) - ISO8601 timestamp of when the monitoring was executed * `created_at` (string) - ISO8601 timestamp of when the alert was created * `acknowledged_at` (string|null) - ISO8601 timestamp of when the alert was acknowledged, or null if not acknowledged * `external_id` (string, optional) - External reference ID * `unacknowledged_count` (integer) - Number of unacknowledged alerts for the customer * `next_token` (string|null) - Token for next page (null if no more pages) ### Example Response ```json theme={null} { "items": [ { "id": "532ebbd3-269d-4c8f-b73b-2269eb83f1ae", "monitoring_id": "c3853e7e-46dc-4c1f-afb4-028b3bdfce19", "customer_id": "69df5d81-2b74-4f42-a401-13eb96ba0619", "execution_result_id": "e79a2fe0-041f-4357-8b3b-43aa8410ab0b", "website": "https://dokanstore-sa.com/", "failed_checks": [ { "check": "non_operational_website", "explanation": "No Website Data found", "method_used": "", "status": "FAILED" } ], "execution_time": "2025-06-20T18:25:51.409Z", "created_at": "2025-06-20T20:45:48.460Z", "acknowledged_at": null, "external_id": "cb7f0fab-38b7-4043-bd7f-5976ed4b5e19" }, { "id": "f085ca1e-8079-4a6c-8b1d-c17796c0aff5", "monitoring_id": "288888fc-b5b4-4131-bac8-d45c33e9e32b", "customer_id": "69df5d81-2b74-4f42-a401-13eb96ba0619", "execution_result_id": "bccc5556-96bf-492a-aa69-09a1faefed15", "website": "https://example-02.com/", "failed_checks": [ { "check": "non_operational_website", "explanation": "No Website Data found", "method_used": "", "status": "FAILED" } ], "execution_time": "2025-06-20T18:25:45.215Z", "created_at": "2025-06-20T20:45:48.460Z", "acknowledged_at": null, "external_id": "cb7f0fab-38b7-4043-bd7f-5976ed4b5e19" } ], "unacknowledged_count": 2, "next_token": null } ``` ## Error Handling * **400 Bad Request** * Invalid query parameter values * Example: `{ "error": "page_size must be a positive integer between 1 and 100" }` * **401 Unauthorized** * Missing or invalid customer authentication * **500 Internal Server Error** * Unexpected server error ## Pagination The API uses cursor-based pagination with Base64-encoded tokens: 1. First request: Don't include `next_token` 2. Subsequent requests: Use the `next_token` from the previous response 3. Last page: `next_token` will be `null` # List Monitoring Runs Source: https://docs.godiligent.ai/api-reference/monitorings/list-monitoring-executions GET /monitoring-executions Retrieve a paginated list of monitoring runs (executions), regardless of whether they produced alerts. ## Overview Retrieve a paginated list of monitoring runs for the authenticated customer. A "run" is one execution of a monitoring, returned whether or not it produced alerts — useful for reconciliation against your own records. Queries are bounded to a maximum 60-day window per request. If you do not pass `from` and `to`, the endpoint returns the last 30 days. ## Request * **Method**: `GET` * **Path**: `/monitoring-executions` * **Query Parameters**: All optional ### Query Parameters * `from` (ISO 8601 string, optional) - Start of the window. Defaults to 30 days before `to`. * `to` (ISO 8601 string, optional) - End of the window. Defaults to now. * `page_size` (integer, optional) - Number of runs per page * Default: 10 * Range: 1-100 * `next_token` (string, optional) - Pagination token for next page (Base64-encoded) ### Example Request ``` GET /monitoring-executions?from=2026-04-01T00:00:00Z&to=2026-04-30T00:00:00Z&page_size=50 ``` ## Success Response * **Status**: 200 OK ### Response Body * `items` (array) - List of monitoring run summaries * `id` (string) - Unique identifier for the run * `monitoring_id` (string) - ID of the monitoring this run belongs to * `website` (string) - Website that was monitored * `execution_time` (string) - ISO 8601 timestamp of when the run was executed * `external_id` (string|null) - External reference ID (null if not set) * `alert_count` (integer) - Number of alerts produced by the run (0 if none) * `next_token` (string|null) - Token for next page (null if no more pages) ### Example Response ```json theme={null} { "items": [ { "id": "d6e3b214-30b1-4401-a1b8-a1bd3c6a84e4", "monitoring_id": "8f1e8e3a-4f4f-4f4f-8f4f-4f4f4f4f4f4f", "website": "https://example.com", "execution_time": "2026-05-21T12:34:56.000Z", "external_id": "ref-123", "alert_count": 0 } ], "next_token": null } ``` ## Error Handling * **400 Bad Request** * Invalid `from` or `to` (must be ISO 8601 date-time) * `from` is after `to` * Date range exceeds 60 days * Invalid `page_size` * Example: `{ "error": "Date range cannot exceed 60 days" }` * **401 Unauthorized** * Missing or invalid customer authentication * **500 Internal Server Error** * Unexpected server error ## Pagination Cursor-based pagination with Base64-encoded tokens: 1. First request: Don't include `next_token` 2. Subsequent requests: Use the `next_token` from the previous response 3. Last page: `next_token` will be `null` # List Monitorings Source: https://docs.godiligent.ai/api-reference/monitorings/list-monitorings GET /monitorings Get a paginated list of monitoring configurations for a customer ## Overview Retrieve a paginated list of monitoring configurations for the authenticated customer. Supports filtering by website or state, and various sorting options. ## Request * **Method**: `GET` * **Path**: `/monitorings` * **Query Parameters**: Optional filters and pagination ### Query Parameters * `page_size` (integer, optional) - Number of items per page * Default: 10 * Range: 1-100 * Must be a positive integer * `sort_by` (string, optional) - Field to sort results by * Default: `"last_execution"` * Options: * `"last_execution"` - Sort by last execution time * `"next_run"` - Sort by next scheduled run * `"state"` - Sort by running state * `"website"` - Sort by website URL * `sort_direction` (string, optional) - Sort order * Default: `"desc"` * Options: * `"asc"` - Ascending order * `"desc"` - Descending order * `next_token` (string, optional) - Pagination token for next page * Base64 encoded token returned from previous response * Used to fetch subsequent pages of results * `state` (string, optional) - Filter by running state * Returns only monitorings in specified state * Cannot be combined with website filter * `website` (string, optional) - Filter by specific website * Returns only monitorings for the specified URL * Cannot be combined with state filter ### Example Request ``` GET /monitorings?page_size=20&sort_by=next_run&sort_direction=asc ``` ``` GET /monitorings?website=https://example.com ``` ``` GET /monitorings?next_token=eyJjdXN0b21lcl9pZCI6ImN1c3RvbWVyXzEyMyIsImlkIjoiZDZlM2IyMTQtMzBiMS00NDAxLWExYjgtYTFiZDNjNmE4NGU0In0= ``` ## Success Response * **Status**: 200 OK ### Response Body * `items` (array) - List of monitoring objects * `next_token` (string|null) - Token for next page (null if no more pages) ### Example Response ```json theme={null} { "items": [ { "id": "d6e3b214-30b1-4401-a1b8-a1bd3c6a84e4", "website": "https://example.com", "customer_id": "customer_123", "checks": ["non_operational_website", "high_risk_diligent_classification"], "frequency": "weekly", "expires_at": "2024-12-31T23:59:59.000Z", "is_active": true, "running_state": "IDLE", "next_run_at": "2024-06-10T10:46:00.000Z", "last_execution": "2024-06-03T10:46:00.000Z", "execution_results": [ { "check": "non_operational_website", "status": "success", "method_used": "AI", "explanation": "" }, { "check": "catalog_contain_loan_flipping_indicators", "status": "failed", "method_used": "AI", "explanation": "Catlog contains loan flipping indicators" } ], "created_at": "2024-05-01T10:00:00.000Z", "updated_at": "2024-06-03T10:46:00.000Z", "external_id": "external_id_123" } ], "next_token": "eyJjdXN0b21lcl9pZCI6ImN1c3RvbWVyXzEyMyIsImlkIjoiZDZlM2IyMTQtMzBiMS00NDAxLWExYjgtYTFiZDNjNmE4NGU0In0=" } ``` ## Error Handling * **400 Bad Request** * Invalid query parameter values * Example: `{ "error": "page_size must be a positive integer between 1 and 100" }` * **401 Unauthorized** * Missing or invalid customer authentication * **500 Internal Server Error** * Unexpected server error * Example: `{ "error": "Failed to fetch monitorings", "items": [], "next_token": null }` ## Pagination The API uses cursor-based pagination with Base64-encoded tokens: 1. First request: Don't include `next_token` 2. Subsequent requests: Use the `next_token` from the previous response 3. Last page: `next_token` will be `null` ### Example Pagination Flow ```javascript theme={null} // First page GET /monitorings?page_size=10 // Response includes next_token { "items": [...], "next_token": "eyJjdXN0b21lcl9pZCI6ImN1c3RvbWVyXzEyMyIsImxhc3RfZXhlY3V0aW9uIjoiMjAyNC0wNi0wM1QxMDo0NjowMC4wMDBaIn0=" } // Next page GET /monitorings?page_size=10&next_token=eyJjdXN0b21lcl9pZCI6ImN1c3RvbWVyXzEyMyIsImxhc3RfZXhlY3V0aW9uIjoiMjAyNC0wNi0wM1QxMDo0NjowMC4wMDBaIn0= ``` ## Filter Behavior * **Mutually Exclusive Filters**: The `website` and `state` filters cannot be used together * **Filter Precedence**: If both filters are provided, `website` takes precedence and `state` is ignored * **No Pagination with Filters**: When using `website` or `state` filters, all matching results are returned and `next_token` is always `null` * **Sorting with Filters**: Sorting parameters (`sort_by`, `sort_direction`) are ignored when using filters ## Notes * When filtering by `website` or `state`, pagination is not supported (returns all matching results) * The `next_token` is specific to the original query parameters and should not be reused with different filters * Invalid `next_token` values are ignored and treated as if no token was provided # Create Monitoring Source: https://docs.godiligent.ai/api-reference/monitorings/new-monitorings POST /monitorings Create a single monitoring configuration for a customer to receive alerts about website changes and risks. ## Overview Create a new monitoring configuration for a customer's website. The monitoring will continuously check the specified website for various risk factors and operational status according to the configured frequency. ## Request * **Method**: `POST` * **Path**: `/monitorings` * **Body**: JSON object with monitoring configuration ### Request Body * `website` (string, required) - The URL to monitor (will be validated and sanitized) * `checks` (array, required) - Array of monitoring checks to perform: * `"non_operational_website"` - Check if website is operational * `"high_risk_mcc"` - Check for high-risk MCC * `"high_risk_diligent_classification"` - Check for high-risk classification * `"catalog_contain_loan_flipping_indicators"` - Check for loan flipping indicators * `frequency` (string, required, case-insensitive) - How often to run checks: * `"weekly"` - Every 7 days * `"every_2_weeks"` - Every 14 days (default) * `"every_3_weeks"` - Every 21 days * `"every_4_weeks"` - Every 28 days * `expires_at` (ISO8601 string, optional) - When monitoring expires (defaults to 6 months from creation) * Must be a future date * Must be at least N days ahead where N equals the frequency period * `run_now` (boolean, optional) - Execute immediately after creation (defaults to true) * `external_id` (string, optional) - External ID for the monitoring * `skip_duplicate` (boolean, optional) - If an existing, active monitoring exist with the same site skip don't fail ### Example Request ```json theme={null} { "website": "https://example.com", "checks": ["non_operational_website", "high_risk_diligent_classification"], "frequency": "weekly", "run_now": true, "expires_at": "2024-12-31T23:59:59.000Z", "external_id": "external_id_123", "skip_duplicate":false } ``` ## Success Response * **Status**: 201 Created ```json theme={null} { "id": "d6e3b214-30b1-4401-a1b8-a1bd3c6a84e4", "website": "https://example.com", "customer_id": "customer_123", "checks": ["non_operational_website", "high_risk_diligent_classification"], "frequency": "weekly", "expires_at": "2024-12-31T23:59:59.000Z", "is_active": true, "running_state": "IDLE", "next_run_at": "2024-06-10T10:46:00.000Z", "last_execution": null, "execution_results": [], "created_at": "2024-06-03T10:46:00.000Z", "updated_at": "2024-06-03T10:46:00.000Z", "external_id": "external_id_123" } ``` ## Error Handling * **400 Bad Request** * **Schema validation errors**: ```json theme={null} { "error": [{"code": "custom", "message": "Invalid check name(s)", "path": ["checks"]}] } ``` * **Monitor already exists**: ```json theme={null} { "error": "Monitor already exists" } ``` * **URL validation failed**: ```json theme={null} { "error": [{"code": "custom", "message": "URL is disallowed or invalid", "path": ["website"]}] } ``` * **401 Unauthorized** * Missing or invalid customer authentication * **500 Internal Server Error** * Unexpected server error during creation or execution ## Validation Rules * **Website URL**: Must be a valid, allowed URL that passes security validation * **Unique Checks**: Each monitoring must have unique check names (no duplicates) * **Frequency**: Case-insensitive input, normalized to lowercase * **Expiration Date**: Must be future date, at least N days ahead based on frequency * **Duplicate Prevention**: Cannot create monitoring for website that already exists for this customer ## Notes * If `run_now` is true, the monitoring will be queued for immediate execution via SQS * Frequency input is case-insensitive and normalized to lowercase * All URLs are validated and sanitized for security before storage * Default expiration is 6 months from creation if not specified # Create Search Source: https://docs.godiligent.ai/api-reference/name-screening/create-search POST /v1/name-screenings/searches Create a new name screening search to query providers for matches ## Behavior * **New searches** begin with status `PENDING` and transition to `COMPLETED` or `FAILED` * **Provider queries** run asynchronously and populate hits when matches are found * **Search IDs** are UUIDs that can be used with the [Get Search](/api-reference/name-screening/get-search) endpoint ## Workflow After creating a search, the system will: 1. Generate a unique search ID 2. Initialize the search with status `PENDING` 3. Query the configured screening provider 4. Populate hits array with any matches found 5. Update search status to `COMPLETED` and trigger a webhook, check [Webhooks](/guides/webhooks/working-with-webhooks#search-completed) for more details If the provider query fails, the search status becomes `FAILED`. Use this ID to: * Check search status with [GET /name-screenings/searches/](/api-reference/name-screening/get-search) * Retrieve hits from the search response * Monitor provider query progress # Get Alert Source: https://docs.godiligent.ai/api-reference/name-screening/get-alert GET /v1/name-screenings/alerts/{id} Retrieve a name screening alert with enriched evidence and supporting facts ## Behavior * Returns a fully enriched alert including all hits, evidences, and supporting facts * Each evidence contains `supporting_facts` — the specific facts that contributed to the resolution decision * `UNREMEDIATED` alerts return `404` to prevent exposure of unprocessed data * The alert must belong to the authenticated customer ## Response Shape The response includes `profile_facts` at the alert level — facts about the screened subject. Each hit contains `evidences`, which are categorized as `PRIMARY_NAME` or grouped by evidence category (e.g. `DOB`, `LOCATION`). Each evidence contains: * **`categories`** — the signal types (e.g. `NAME_GIVEN_NAME_EXACT_MATCH`, `DOB_YEAR_MISMATCH`) * **`supporting_facts`** — the facts that drove the evidence, each with: * **`predicate`** — e.g. `has_name`, `date_of_birth` * **`value`** — the extracted value * **`citations`** — array with one citation indicating the data source (`HIT`, `PROFILE`, `ARTICLE`, `REGISTRY`, or `WEB_SEARCH`) and optionally a `url` # Get Search Source: https://docs.godiligent.ai/api-reference/name-screening/get-search GET /v1/name-screenings/searches/{id} Retrieve a name screening search with hits and remediation data # Remediation Source: https://docs.godiligent.ai/api-reference/name-screening/submit-remediation POST /v1/name-screenings/alerts/remediate Submit an externally-screened alert for AI-powered remediation **Beta** — This endpoint is under active development. The contract may change based on early adopter feedback. ## Behavior * Accepts an alert with subject profile and hits that you have already screened externally * Processing is **asynchronous** — returns an `id` immediately, remediation runs in the background * Results are retrieved via [Get Alert](/api-reference/name-screening/get-alert) using the returned `id` * Triggers an `alert_remediated` webhook when complete (see [Webhooks](/guides/webhooks/working-with-webhooks#alert-remediated)) ## Workflow After submitting, the system will: 1. Validate the request and persist the alert 2. Return `{ "id": "..." }` with status `201` 3. Enrich each hit (registry, web search, articles) based on your configured enrichments 4. Run entity resolution and the rule engine against your configured rules and segments 5. Generate evidence reports and summaries for each hit 6. Trigger the `alert_remediated` webhook Use the returned `id` to: * Retrieve full results with [GET /name-screenings/alerts/](/api-reference/name-screening/get-alert) * Correlate with webhook notifications See the [Remediation API Guide](/guides/name-screening/remediation-api) for recommended field labels, best practices, and detailed examples. # Scan Website Source: https://docs.godiligent.ai/api-reference/screening/scan-website POST /screen Screen a website instantly for operational status (Experimental) # Delete Webhook Source: https://docs.godiligent.ai/api-reference/webhooks/delete DELETE /webhooks/{webhook_id} Delete a webhook endpoint. ## Endpoint `DELETE /webhooks/{webhook_id}` Removes a webhook. Event delivery to its endpoint stops immediately — no further events are sent, and there are no dangling deliveries. ## Path Parameters | Parameter | Type | Required | Description | | ----------- | ------ | -------- | -------------------------------- | | webhook\_id | string | Yes | The ID of the webhook to delete. | ## Responses ### 204 No Content The webhook was deleted. No response body. ### 404 Not Found No webhook with that ID exists for the authenticated customer. ### 500 Internal Server Error Unexpected error occurred. ## Authentication This endpoint requires authentication. You can only delete webhooks owned by the authenticated customer. # Get Webhook Source: https://docs.godiligent.ai/api-reference/webhooks/get GET /webhooks/{webhook_id} Retrieve a single webhook by ID. ## Endpoint `GET /webhooks/{webhook_id}` Returns a single webhook, including its derived delivery status. ## Path Parameters | Parameter | Type | Required | Description | | ----------- | ------ | -------- | ---------------------------------- | | webhook\_id | string | Yes | The ID of the webhook to retrieve. | ## Response A webhook object. See [List Webhooks](./list-webhooks) for the field reference. The signing `secret` is never returned; `has_secret` indicates whether one is configured. ```json theme={null} { "id": "df89eb16-4c6a-439f-b668-7cca0cd786fa", "webhook_url": "https://crm.example.com/diligent", "is_active": true, "has_secret": true, "status": "failing", "last_delivery_at": "2025-07-31T02:51:34.155Z", "last_delivery_status": 500, "events": ["cdd_state_changed", "alert_remediated"] } ``` ### 404 Not Found No webhook with that ID exists for the authenticated customer. ## Authentication This endpoint requires authentication. You can only retrieve webhooks owned by the authenticated customer. # List Deliveries Source: https://docs.godiligent.ai/api-reference/webhooks/list GET /webhooks/{webhook_id}/events List recent webhook deliveries for a specific webhook. ## Endpoint `GET /webhooks/{webhook_id}/events` Returns a list of recent webhook delivery attempts for the specified webhook. Results are sorted by most recent first. ## Path Parameters | Parameter | Type | Required | Description | | ----------- | ------ | -------- | --------------------------------------------- | | webhook\_id | string | Yes | The ID of the webhook to list deliveries for. | ## Response Returns a JSON array of delivery objects. Each object contains: | Field | Type | Description | | ------------ | ------ | -------------------------------------------------- | | id | string | Unique identifier for the delivery event. | | event\_type | string | The type of event delivered. | | timestamp | string | ISO timestamp of when the delivery occurred. | | status\_code | number | HTTP status code returned by the webhook endpoint. | | request | object | The request payload sent to the webhook. | | response | object | The response returned by the webhook endpoint. | ### Example Responses #### cdd\_state\_changed ```json theme={null} { "id": "54ef493d-7672-4cd8-8080-599601e9609d", "event_type": "cdd_state_changed", "timestamp": "2025-07-31T02:51:34.155Z", "status_code": 500, "request": { "headers": { "Content-Type": "application/json", "User-Agent": "DiligentAI/1.0", "X-Webhook-Id": "df89eb16-4c6a-439f-b668-7cca0cd786fa", "X-Event-Id": "54ef493d-7672-4cd8-8080-599601e9609d", "X-Customer-Id": "69df5d81-2b74-4f42-a401-13eb96ba0619", "X-Target-type": "CDD", "X-Event-Name": "CDD_COMPLETED", "X-Signature": "sha256=..." }, "payload": "" }, "response": { "body": "..." } } ``` * **payload**: The full CDD object as a JSON string. See the [CDD Object documentation](../cdd/cdd-object.mdx) for details. * **headers**: All headers sent to your endpoint, including: * `Content-Type`: Always `application/json` * `User-Agent`: Sender identifier * `X-Webhook-Id`: Webhook unique ID * `X-Event-Id`: Event unique ID * `X-Customer-Id`: Authenticated customer ID * `X-Target-type`: Always `CDD` * `X-Event-Name`: Specific CDD event (e.g., `CDD_COMPLETED`) * `X-Signature`: HMAC signature for authenticity #### monitoring\_alert\_fired ```json theme={null} { "id": "f9e2b3a7-2b4c-4d7d-9a2f-7f7c6f7c6f7c", "event_type": "monitoring_alert_fired", "timestamp": "2025-07-31T05:12:03.123Z", "status_code": 200, "request": { "headers": { "Content-Type": "application/json", "User-Agent": "DiligentAI/1.0", "X-Webhook-Id": "df89eb16-4c6a-439f-b668-7cca0cd786fa", "X-Event-Id": "f9e2b3a7-2b4c-4d7d-9a2f-7f7c6f7c6f7c", "X-Customer-Id": "69df5d81-2b74-4f42-a401-13eb96ba0619", "X-Target-type": "MONITORING_ALERT", "X-Event-Name": "MONITORING_ALERT_FIRED", "X-Signature": "sha256=..." }, "payload": { "alert_id": "alrt_01HZY9V7FZJQ3K0KZP1YQ9E5X2", "monitoring_id": "mon_01HZY9V7FZJQ3K0KZP1YQ9E5X2", "type": "FRAUD", "details": { "reason": "Suspicious activity detected", "triggered_at": "2025-07-31T05:12:03.123Z" } } }, "response": { "body": "ok" } } ``` * **payload**: The alert object, with all relevant fields for the alert event. * **headers**: Same structure as above, with `X-Target-type` as `MONITORING_ALERT` and `X-Event-Name` as `MONITORING_ALERT_FIRED`. #### flow\_run\_completed ```json theme={null} { "id": "54ef493d-7672-4cd8-8080-599601e9609d", "event_type": "flow_run_completed", "timestamp": "2025-07-31T10:00:45.000Z", "status_code": 200, "request": { "headers": { "Content-Type": "application/json", "User-Agent": "DiligentAI/1.0", "X-Webhook-Id": "df89eb16-4c6a-439f-b668-7cca0cd786fa", "X-Event-Id": "54ef493d-7672-4cd8-8080-599601e9609d", "X-Customer-Id": "69df5d81-2b74-4f42-a401-13eb96ba0619", "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", "status": "COMPLETED", "input": { "subject": "Acme Corp" }, "report": "s3://flows-artifacts/reports/run-a1b2c3d4.json" } }, "response": { "body": "ok" } } ``` * **payload**: The full flow run object (same as `GET /v1/flow-runs/{runId}`). * **headers**: Same structure as above, with `X-Target-type` as `FLOW_RUN` and `X-Event-Name` as `FLOW_RUN_COMPLETED`. #### flow\_run\_failed ```json theme={null} { "id": "f9e2b3a7-2b4c-4d7d-9a2f-7f7c6f7c6f7c", "event_type": "flow_run_failed", "timestamp": "2025-07-31T10:00:12.000Z", "status_code": 200, "request": { "headers": { "Content-Type": "application/json", "User-Agent": "DiligentAI/1.0", "X-Webhook-Id": "df89eb16-4c6a-439f-b668-7cca0cd786fa", "X-Event-Id": "f9e2b3a7-2b4c-4d7d-9a2f-7f7c6f7c6f7c", "X-Customer-Id": "69df5d81-2b74-4f42-a401-13eb96ba0619", "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", "status": "FAILED", "input": { "subject": "Acme Corp" }, "error": { "code": "EXECUTION_ERROR", "message": "entityName is required" } } }, "response": { "body": "ok" } } ``` * **payload**: The full flow run object (same as `GET /v1/flow-runs/{runId}`). * **headers**: Same structure as above, with `X-Target-type` as `FLOW_RUN` and `X-Event-Name` as `FLOW_RUN_FAILED`. ## Errors ### 500 Internal Server Error Unexpected error occurred. ```json theme={null} { "error": "Internal server error" } ``` ## Authentication This endpoint requires authentication. Only deliveries for webhooks owned by the authenticated customer are returned. # List Webhooks Source: https://docs.godiligent.ai/api-reference/webhooks/list-webhooks GET /webhooks List all webhooks registered for your account. ## Endpoint `GET /webhooks` Returns all webhooks registered for the authenticated customer. ## Response A JSON array of webhook objects. The signing `secret` is never returned; `has_secret` indicates whether one is configured. | Field | Type | Description | | ---------------------- | -------------- | -------------------------------------------------------------------------------------- | | id | string | Unique webhook ID. | | webhook\_url | string | The endpoint URL. | | is\_active | boolean | Whether the webhook is active. | | has\_secret | boolean | Whether a signing secret is configured. | | status | string | Derived health: `disabled` (inactive), `failing` (last delivery non-2xx), or `active`. | | last\_delivery\_at | string \| null | ISO timestamp of the most recent delivery attempt, or `null` if none. | | last\_delivery\_status | number \| null | HTTP status of the most recent delivery attempt, or `null` if none. | | events | string\[] | Subscribed event types. | ### Example Response ```json theme={null} [ { "id": "df89eb16-4c6a-439f-b668-7cca0cd786fa", "webhook_url": "https://crm.example.com/diligent", "is_active": true, "has_secret": true, "status": "active", "last_delivery_at": "2025-07-31T02:51:34.155Z", "last_delivery_status": 200, "events": ["cdd_state_changed", "alert_remediated"] }, { "id": "5a1c0b2e-9f3d-4a7b-8c6d-2e1f0a9b8c7d", "webhook_url": "https://warehouse.example.com/ingest", "is_active": false, "has_secret": false, "status": "disabled", "last_delivery_at": null, "last_delivery_status": null, "events": ["search_completed"] } ] ``` ## Authentication This endpoint requires authentication. Only webhooks owned by the authenticated customer are returned. # Redeliver Webhook Source: https://docs.godiligent.ai/api-reference/webhooks/redeliver POST /webhooks/{webhook_id}/events/{event_id}/redeliver Redeliver a webhook event # Register Webhook Source: https://docs.godiligent.ai/api-reference/webhooks/register POST /webhooks Register a webhook endpoint for your account. ## Endpoint `POST /webhooks` Creates a **new** webhook endpoint for the authenticated customer. You can register up to **10 webhooks**, each with its own URL, secret, and event filter. Event delivery fans out to every active webhook whose filter matches the event. **Behavior change:** this endpoint previously upserted a single webhook per customer — repeated `POST`s updated the same record. It now **always creates a new webhook**. To modify an existing webhook, use [`PATCH /webhooks/{webhook_id}`](./update). To remove one, use [`DELETE /webhooks/{webhook_id}`](./delete). ## Request Body JSON object with the following fields: | Field | Type | Required | Description | | ------------ | --------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------ | | webhook\_url | string | Yes | HTTPS URL to receive webhook events. Must start with `https://`. | | secret | string | No | Secret used to sign webhook payloads (`X-Signature` header). Write-only — never returned by the API. Empty string is treated as no secret. | | is\_active | boolean | No | Whether the webhook is active. Defaults to `true`. | | events | string\[] | No | List of event types to subscribe to. Defaults to an empty list (no events). | ### Supported Event Types * `cdd_state_changed`: When the state of a CDD changes to either inconclusive or complete. * `monitoring_alert_fired`: When a monitoring alert is fired on failure. * `cdd_document_fetched`: When a new document is successfully added to a CDD case. * `search_completed`: When a name screening search completes and results are available. * `alert_remediated`: When a name screening alert has been remediated (all hits resolved). * `flow_run_completed`: When a flow run finishes successfully (`COMPLETED`). * `flow_run_failed`: When a flow run fails (`FAILED`). ### Example Request ```json theme={null} { "webhook_url": "https://www.testing-webhooks.com", "is_active": true, "secret": "some-secret", "events": ["cdd_state_changed", "monitoring_alert_fired", "search_completed"] } ``` ## Responses ### 201 Created The webhook was created. The response body is the created webhook (the `secret` is never echoed — `has_secret` indicates whether one is set). ```json theme={null} { "id": "df89eb16-4c6a-439f-b668-7cca0cd786fa", "webhook_url": "https://www.testing-webhooks.com", "is_active": true, "has_secret": true, "status": "active", "last_delivery_at": null, "last_delivery_status": null, "events": ["cdd_state_changed", "monitoring_alert_fired", "search_completed"] } ``` ### 400 Bad Request Input validation failed. ```json theme={null} { "error": [ { "code": "invalid_type", "expected": "string", "received": "number", "path": ["webhook_url"], "message": "Expected string, received number" } ] } ``` ### 409 Conflict The customer already has the maximum of 10 webhooks. Delete one before creating another. ```json theme={null} { "error": "Webhook limit reached (max 10 per customer)" } ``` ### 500 Internal Server Error Unexpected error occurred. ```json theme={null} { "error": "Internal server error" } ``` ## Authentication This endpoint requires authentication. The webhook is associated with the authenticated customer. # Update Webhook Source: https://docs.godiligent.ai/api-reference/webhooks/update PATCH /webhooks/{webhook_id} Update an existing webhook endpoint. ## Endpoint `PATCH /webhooks/{webhook_id}` Partially updates an existing webhook. Only the fields you supply are changed; omitted fields keep their current values. ## Path Parameters | Parameter | Type | Required | Description | | ----------- | ------ | -------- | -------------------------------- | | webhook\_id | string | Yes | The ID of the webhook to update. | ## Request Body All fields are optional. Supply only what you want to change. | Field | Type | Description | | ------------ | --------- | -------------------------------------------------------------------------------------------------------------------------- | | webhook\_url | string | HTTPS URL to receive webhook events. Must start with `https://`. | | secret | string | Write-only. **Omit** to keep the current secret, send an **empty string** to remove it, or send a **value** to replace it. | | is\_active | boolean | Whether the webhook is active. | | events | string\[] | Replaces the full list of subscribed event types. | ### Example Request Disable a webhook and narrow its event filter, leaving the secret untouched: ```json theme={null} { "is_active": false, "events": ["search_completed"] } ``` ## Responses ### 200 OK The updated webhook (the `secret` is never echoed — `has_secret` indicates whether one is set). ```json theme={null} { "id": "df89eb16-4c6a-439f-b668-7cca0cd786fa", "webhook_url": "https://www.testing-webhooks.com", "is_active": false, "has_secret": true, "status": "disabled", "last_delivery_at": "2025-07-31T02:51:34.155Z", "last_delivery_status": 200, "events": ["search_completed"] } ``` ### 400 Bad Request Input validation failed. ### 404 Not Found No webhook with that ID exists for the authenticated customer. ### 500 Internal Server Error Unexpected error occurred. ## Authentication This endpoint requires authentication. You can only update webhooks owned by the authenticated customer. # Customer Due Diligence (CDD) Flow Source: https://docs.godiligent.ai/guides/cdd/cdd-case-flow Overview of how a CDD case progresses through the workflow The Customer Due Diligence (CDD) process runs through two high-level workflows. One workflow collects data about the customer and the second performs the checks and creates the final report. ## Workflows 1. **Data collection** – gathers registry information, online screening results and optional catalog data or reviews. When complete, the case moves on to the checks workflow. 2. **Checks** – performs risk and compliance checks using the gathered information and generates the CDD report. ## Case States A CDD case moves through several high level states which are returned by the API: | State | Description | | ---------------- | ----------------------------------------------------------------------------- | | `INITIATED` | The case was created and is waiting to start processing. | | `IN_PROGRESS` | The system is gathering data such as registry records and online information. | | `RUNNING_CHECKS` | Risk an Compliance checks are running and a report is being produced. | | `COMPLETED` | Checks finished successfully and the final report is available. | | `INCONCLUSIVE` | Processing finished but did not collect enough structured data. | | `FAILED` | An unrecoverable error occurred during processing. | ## Transitions The diagram below illustrates the typical flow between states: ```mermaid theme={null} stateDiagram INITIATED --> IN_PROGRESS IN_PROGRESS --> RUNNING_CHECKS IN_PROGRESS --> FAILED RUNNING_CHECKS --> COMPLETED COMPLETED --> RUNNING_CHECKS RUNNING_CHECKS --> INCONCLUSIVE RUNNING_CHECKS --> FAILED ``` The data collection workflow moves the case from `INITIATED` to `IN_PROGRESS` and then hands it off to the checks workflow, which brings the case into the `RUNNING_CHECKS` state. Failures in either workflow transition the case to `FAILED`. # High-Risk Industry Categories Source: https://docs.godiligent.ai/guides/cdd/high-risk-categories Comprehensive guide to understanding high-risk business categories identified during CDD screening ## Overview During the Customer Due Diligence (CDD) process, businesses are classified into industry categories. Some industries are inherently higher risk for Anti-Money Laundering (AML) and financial crime compliance purposes. This guide provides a comprehensive overview of all high-risk categories identified by the Diligent platform. Businesses classified under these categories require enhanced due diligence and additional scrutiny during the onboarding and monitoring processes. ## High-Risk Categories The following table lists all industry categories considered high-risk: | Category Code | Category Name | Description | | ------------------------------------- | ----------------------------------- | --------------------------------------------------------------------------------- | | `ADULT_CONTENT` | Adult Content | Businesses involved in adult entertainment, content creation, or related services | | `TRAVEL` | Travel | Travel agencies, booking platforms, and tourism services | | `CANNABIS` | Cannabis | Legal cannabis dispensaries, cultivation, and related products | | `GAMBLING` | Gambling | Online and offline gambling, betting, casinos, and gaming platforms | | `FINANCIAL_SERVICES` | Financial Services | Payment processors, lending, investment services, and financial intermediaries | | `VIRTUAL_ASSETS` | Virtual Assets | Cryptocurrency exchanges, NFT marketplaces, blockchain services, digital assets | | `SOCIAL_IMPACT_INITIATIVES` | Social Impact Initiatives | Charities, NGOs, crowdfunding platforms, and social enterprises | | `PUBLIC_ADMINISTRATION` | Public Administration | Government agencies, public services, and administrative bodies | | `DRUGS_AND_PHARMACEUTICALS` | Drugs and Pharmaceuticals | Pharmaceutical manufacturing, distribution, and online pharmacies | | `ALCOHOL_SALE` | Alcohol Sale | Retail and wholesale alcohol sales, breweries, and distilleries | | `E_CIGARETTES` | E-Cigarettes | Electronic cigarettes, vaping products, and accessories | | `TOBACCO` | Tobacco | Tobacco products, cigars, cigarettes, and related accessories | | `WEAPONS` | Weapons | Firearms, ammunition, military equipment, and related products | | `SOCIAL_MEDIA_ACTIVITY` | Social Media Activity | Social media marketing, influencer services, and engagement platforms | | `HIGH_VALUE_JEWELRY` | High-Value Jewelry | Luxury jewelry, precious stones, and high-value accessories | | `UNAUTHORIZED_STREAMING` | Unauthorized Streaming | Illegal content streaming, piracy services, and copyright violations | | `IN_GAME_CURRENCY_SALE` | In-Game Currency Sale | Virtual goods, game currency, and digital item trading | | `AUCTION_HOUSES_AND_FINE_ART_DEALERS` | Auction Houses and Fine Art Dealers | Art auctions, galleries, and high-value art trading | | `VOUCHERS/GIFT_CARDS` | Vouchers/Gift Cards | Gift card sales, voucher platforms, and prepaid card services | | `ESOTERIC_AND_SORCERY` | Esoteric and Sorcery | Fortune telling, psychic services, spiritual healing, and occult products | | `PRECIOUS_METALS_AND_STONE_DEALERS` | Precious Metals and Stone Dealers | Gold, silver, diamonds, and other precious material trading | | `PAWN_BROKERS` | Pawn Brokers | Pawn shops, collateral lending, and second-hand goods trading | | `DEBT_COLLECTION_AGENCY` | Debt Collection Agency | Debt collection services and credit recovery | | `PHONE_CHARGES` | Phone Charges | Premium rate services, phone billing, and telecommunications charges | | `VPN` | VPN | Virtual Private Network services and anonymity tools | | `COMPANY_FORMATION_SERVICES` | Company Formation Services | Business incorporation, registered agent services, and corporate structuring | | `BANKNOTE_SALE` | Banknote Sale | Currency dealing, numismatics, and rare note trading | | `WEIGHT_LOSS` | Weight Loss | Diet products, weight loss supplements, and related programs | | `GET_RICH_QUICK` | Get Rich Quick | Investment schemes, multi-level marketing, and "guaranteed return" programs | ## Category Assignment Industry categories are determined through: * **Online Screening** - Analysis of business website, social media, photos, videos, of products, and services ## Related Resources * [CDD Case Flow](/guides/cdd-case-flow) - Understanding the due diligence process * [Risk Check Configuration](/guides/risk-check-set-id) - Configuring risk checks for different use cases * [Webhooks](/guides/webhooks/create-webhook) - Setting up alerts for high-risk detections # Using risk_check_set_id Source: https://docs.godiligent.ai/guides/cdd/risk-check-set-id Control which risk checks run when performing CDD A `risk_check_set_id` tells the API which set of risk checks to run for a Customer Due Diligence (CDD) case. If you do not supply this field, your account's default risk check set is applied automatically. ## Default behaviour By default, every account has a risk check set configured in the dashboard. When `risk_check_set_id` is omitted from a request, the CDD case uses this default set of checks. ## Providing a custom risk\_check\_set\_id when create CDD case Specify `risk_check_set_id` in the request body to apply a different set of checks. The value must be the UUID of a risk check set that exists for your account. ```json theme={null} { "risk_check_set_id": "550e8400-e29b-41d4-a716-446655440000" } ``` You can create or modify risk check sets in the **Dashboard** under **Settings > Risk Checks**. The dashboard lists the IDs of all configured sets. ## When to use Use `risk_check_set_id` when you need to tailor the checks for a specific case or workflow. For most integrations, omitting the field and relying on the default configuration is sufficient. ### Examples Risk check sets let you run different checks depending on the selling channel or customer type. For example: * `online-sellers` – run enhanced verification for sellers that only operate online * `in-store-sellers` – apply simplified checks for customers selling exclusively in store Similarly, a business might define `inbound-in-store` and `outbound-in-store` sets to apply different checks depending on how customers engage. Set the appropriate `risk_check_set_id` when creating the case so the API performs the correct checks. # Using Flows Source: https://docs.godiligent.ai/guides/flows/guide Trigger a Flow run, poll for completion, and read the report and structured output A **Flow** is a named automation that Diligent runs for you — for example KYC enrichment or adverse-media review. You start a run with an API call; the work happens in the background. This guide covers the public run API: how to trigger a run, how to read the result, and how the async lifecycle works. You need a published Flow and its `flowId`. Find both in the Diligent dashboard, or ask your Diligent contact. ## How a run works Starting a run is **asynchronous**. `POST /flows/{flowId}/runs` validates the input, queues the run, and returns immediately with a run `id`. It does not wait for the Flow to finish. **The only way to read the result today is to poll `GET /flow-runs/{runId}`** until `status` is terminal. There is no result in the trigger response, and no push of the finished report on the run API. ```mermaid theme={null} sequenceDiagram participant Client participant API participant Worker Client->>API: POST /flows/{flowId}/runs API-->>Client: 202 Accepted { id } Note over Client: Trigger returns immediately API->>Worker: Queue the run Worker->>Worker: QUEUED → RUNNING → COMPLETED or FAILED loop Poll until status is terminal Client->>API: GET /flow-runs/{runId} API-->>Client: QUEUED or RUNNING end Client->>API: GET /flow-runs/{runId} API-->>Client: COMPLETED + report opt output_ref is set Client->>API: GET /flow-runs/{runId}/output-url API-->>Client: Presigned URL (expires in 300s) Client->>Client: Download structured output end ``` Typical statuses: | Status | Meaning | | ----------- | ----------------------------------------------------- | | `QUEUED` | Accepted, waiting for a worker | | `RUNNING` | The Flow is executing | | `COMPLETED` | Finished successfully — `report` is available | | `FAILED` | Execution failed — see `error` | | `CANCELLED` | Stopped before finishing | | `SKIPPED` | Not executed (for example a trigger guard skipped it) | `COMPLETED`, `FAILED`, `CANCELLED`, and `SKIPPED` are **terminal**. Once a run reaches one of these, `status` does not change again. ## Quick start ### 1. Trigger a run `input` must match the Flow's active version input schema. The fields below are an example — use the schema for your Flow. ```bash theme={null} curl -X POST https://api.godiligent.ai/flows/flow-abc123/runs \ -H "X-API-KEY: your-api-key" \ -H "Content-Type: application/json" \ -d '{ "input": { "fullName": "Sossio Sorrentino", "email": "sossio.sorrentino@example.com", "phone": "+393510000000", "country": "Italy", "city": "Napoli" } }' ``` **Response (`202 Accepted`):** ```json theme={null} { "id": "8f14e45f-ceea-4c6b-a1b2-3c4d5e6f7890" } ``` Save `id`. That is the only handle you have for polling. If `input` does not match the schema, the call fails immediately with `400` and does not queue a run: ```json theme={null} { "code": "VALIDATION_ERROR", "message": "Input does not match the flow's input schema", "details": [ { "field": "/fullName", "message": "must have required property 'fullName'" } ] } ``` A `404` with `FLOW_NOT_FOUND` means the `flowId` does not exist or belongs to another customer. ### 2. Poll the run Call [Get Run](/api-reference/flows/get-run) with the `id` from step 1. Repeat until `status` is terminal. ```bash theme={null} curl -X GET https://api.godiligent.ai/flow-runs/8f14e45f-ceea-4c6b-a1b2-3c4d5e6f7890 \ -H "X-API-KEY: your-api-key" ``` **While the run is in progress:** ```json theme={null} { "id": "8f14e45f-ceea-4c6b-a1b2-3c4d5e6f7890", "flow_id": "flow-abc123", "status": "RUNNING", "triggered_at": "2026-09-08T10:00:00.000Z", "started_at": "2026-09-08T10:00:01.000Z", "completed_at": null, "input": { "fullName": "Sossio Sorrentino", "email": "sossio.sorrentino@example.com", "phone": "+393510000000", "country": "Italy", "city": "Napoli" }, "report": null, "output_ref": null, "error": null, "created_at": "2026-09-08T10:00:00.000Z", "updated_at": "2026-09-08T10:00:01.000Z" } ``` **When the run completes:** ```json theme={null} { "id": "8f14e45f-ceea-4c6b-a1b2-3c4d5e6f7890", "flow_id": "flow-abc123", "status": "COMPLETED", "triggered_at": "2026-09-08T10:00:00.000Z", "started_at": "2026-09-08T10:00:01.000Z", "completed_at": "2026-09-08T10:02:14.000Z", "input": { "fullName": "Sossio Sorrentino", "email": "sossio.sorrentino@example.com", "phone": "+393510000000", "country": "Italy", "city": "Napoli" }, "report": "# Screening report\n\n**Subject:** Sossio Sorrentino\n\nNo confirmed adverse media.\n", "output_ref": "runs/8f14e45f/output.json", "error": null, "created_at": "2026-09-08T10:00:00.000Z", "updated_at": "2026-09-08T10:02:14.000Z" } ``` What to read from the completed run: | Field | When it is set | What it is | | ------------ | ------------------------------ | --------------------------------------------------------------------------------------------------------- | | `report` | `status` is `COMPLETED` | Full analyst-facing result as Markdown | | `output_ref` | Structured output was captured | Presence (not the value) means you can call [Get Run Output URL](/api-reference/flows/get-run-output-url) | | `error` | `status` is `FAILED` | `{ code, message }` describing the failure | `report` is `null` until the run completes. Do not treat a missing report as a finished empty result. ### 3. Download structured output (optional) Some Flows also write a structured output file (JSON). If Get Run shows `output_ref` set, request a short-lived download URL: ```bash theme={null} curl -X GET https://api.godiligent.ai/flow-runs/8f14e45f-ceea-4c6b-a1b2-3c4d5e6f7890/output-url \ -H "X-API-KEY: your-api-key" ``` **Response:** ```json theme={null} { "url": "https://s3.eu-west-1.amazonaws.com/...", "expires_in": 300 } ``` Download `url` before it expires (currently 300 seconds). If the run has no structured output, this endpoint returns `404` with `OUTPUT_NOT_AVAILABLE`. ## Examples ### Poll until the run finishes (bash) Poll every 3 seconds and stop when the status is terminal. Then print the report. ```bash theme={null} API="https://api.godiligent.ai" KEY="your-api-key" FLOW_ID="flow-abc123" RUN_ID=$(curl -s -X POST "$API/flows/$FLOW_ID/runs" \ -H "X-API-KEY: $KEY" \ -H "Content-Type: application/json" \ -d '{"input":{"fullName":"Sossio Sorrentino","country":"Italy"}}' \ | jq -r '.id') echo "Queued run $RUN_ID" while true; do BODY=$(curl -s "$API/flow-runs/$RUN_ID" -H "X-API-KEY: $KEY") STATUS=$(echo "$BODY" | jq -r '.status') echo "status=$STATUS" case "$STATUS" in COMPLETED|FAILED|CANCELLED|SKIPPED) break ;; esac sleep 3 done if [ "$STATUS" = "COMPLETED" ]; then echo "$BODY" | jq -r '.report' else echo "$BODY" | jq '.error' exit 1 fi ``` ### Poll until the run finishes (Python) ```python theme={null} import time import requests API = "https://api.godiligent.ai" HEADERS = {"X-API-KEY": "your-api-key"} TERMINAL = {"COMPLETED", "FAILED", "CANCELLED", "SKIPPED"} created = requests.post( f"{API}/flows/flow-abc123/runs", headers={**HEADERS, "Content-Type": "application/json"}, json={"input": {"fullName": "Sossio Sorrentino", "country": "Italy"}}, ) created.raise_for_status() run_id = created.json()["id"] while True: run = requests.get(f"{API}/flow-runs/{run_id}", headers=HEADERS) run.raise_for_status() body = run.json() status = body["status"] if status in TERMINAL: break time.sleep(3) if body["status"] != "COMPLETED": raise RuntimeError(body.get("error") or body) print(body["report"]) if body.get("output_ref"): output = requests.get(f"{API}/flow-runs/{run_id}/output-url", headers=HEADERS) output.raise_for_status() file_url = output.json()["url"] data = requests.get(file_url) data.raise_for_status() print(data.json()) ``` ### Failed run When execution fails, polling still ends on a terminal status. Read `error` instead of `report`. ```json theme={null} { "id": "8f14e45f-ceea-4c6b-a1b2-3c4d5e6f7890", "flow_id": "flow-abc123", "status": "FAILED", "triggered_at": "2026-09-08T10:00:00.000Z", "started_at": "2026-09-08T10:00:01.000Z", "completed_at": "2026-09-08T10:00:12.000Z", "input": { "fullName": "Sossio Sorrentino" }, "report": null, "output_ref": null, "error": { "code": "EXECUTION_ERROR", "message": "entityName is required" }, "created_at": "2026-09-08T10:00:00.000Z", "updated_at": "2026-09-08T10:00:12.000Z" } ``` ## Polling guidance * **Poll `GET /flow-runs/{runId}`** — that is the current way to learn status and read `report`. * Start with a 2–5 second interval. Runs can take seconds to minutes depending on the Flow. * Stop when `status` is `COMPLETED`, `FAILED`, `CANCELLED`, or `SKIPPED`. * Persist the run `id` in your system so you can resume polling after a restart. * Treat `report` as ready only when `status` is `COMPLETED`. * Call the output-url endpoint only after `output_ref` is set. The download URL expires quickly; fetch the file right away. ## Next steps * [Run](/api-reference/flows/trigger-run) * [Get Run](/api-reference/flows/get-run) * [Get Run Output URL](/api-reference/flows/get-run-output-url) # Introduction Source: https://docs.godiligent.ai/guides/introduction Complete reference for the Diligent API ## Welcome to Diligent API The Diligent API enables you to integrate comprehensive business verification and screening capabilities into your applications. Our API follows RESTful principles and provides access to products designed for different compliance needs. ## Our Products Verify companies worldwide using official registries, documents, and automated risk assessments Screen individuals and entities against global databases with AI-powered false positive detection Trigger a published Flow, poll the run until it finishes, and read the report and structured output ## Base URLs The API is available in both sandbox and production environments: ```bash theme={null} # Production Environment https://api.godiligent.ai # Sandbox Environment https://api.sandbox.godiligent.ai ``` ## Authentication All API requests require authentication using an API key. Include your API key in the `X-API-KEY` header with each request: ```bash theme={null} X-API-KEY: your_api_key_here ``` Keep your API keys secure and never expose them in client-side code or public repositories. ## Rate Limiting The API implements rate limiting to ensure fair usage. The current limits are: * 10 concurrent CDD cases per account * 20 concurrent name screening requests per account ## Getting Started Choose your use case: **For Customer Due Diligence**: Start with our [CDD guide](/guides/cdd/cdd-case-flow) to learn how to perform comprehensive business checks **For Name Screening**: Check our [Name Screening guide](/guides/name-screening/guide) to understand AI-powered screening and false positive remediation **For Flows**: Follow the [Using Flows guide](/guides/flows/guide) to trigger a run and poll for the report **Set up Webhooks**: Configure webhooks to receive real-time notifications for CDD, name screening, and flow run lifecycle events ## OpenAPI Specification View the complete API specification in OpenAPI format Download Postman Collection ## Need Help? If you need assistance or have questions: * Contact [support@godiligent.ai](mailto:support@godiligent.ai) * Visit our [Support Page](/support) * Check our [Webhooks documentation](/guides/webhooks/working-with-webhooks) for integration guidance # Name Screening: AI Remediation Source: https://docs.godiligent.ai/guides/name-screening/guide Automated alert remediation using AI-powered entity resolution Diligent's AI Remediation Agent automatically analyzes name screening alerts and hits with AI-powered entity resolution, providing evidence-based FALSE\_POSITIVE or TRUE\_POSITIVE determinations. ## Overview The remediation agent processes alerts created from your searches: 1. **Monitor for new alerts** - Automatically detects alerts from completed searches or polls provider 2. **Gather intelligence** - Enriches alerts with registry data (company records, officer information) 3. **Analyze matches** - Uses AI to compare subject profiles against hit profiles with evidence-based reasoning 4. **Post resolutions** - Automatically posts FALSE\_POSITIVE or TRUE\_POSITIVE determinations to your provider 5. **Track sync status** - Updates alert remediation\_status to reflect sync progress All processing happens automatically in the background. **No API calls required!** ## Remediation Workflow The remediation status tracks the alert through its lifecycle: 1. **UNREMEDIATED** - Alert created, awaiting AI analysis 2. **PENDING\_SYNC** - AI has made resolutions, waiting to sync to provider 3. **REMEDIATED\_SYNCED** - Resolutions successfully synced to provider 4. **REMEDIATED\_UNSYNCED** - Resolutions made but couldn't sync (manual intervention may be needed) ## How It Works ### 1. Alert Detection The system continuously monitors your screening provider for new alerts. When a new case appears: * Alert is automatically ingested with full profile data * All hits (potential matches) are retrieved * Related articles and media are captured ### 2. AI Analysis & Enrichment The AI engine enriches each alert with additional intelligence and performs deep analysis: * Gathers supporting data from public registries and databases * Compares the subject against each potential match using multiple data points * Identifies supporting and contradicting evidence * Generates a confidence score and human-readable explanation * Determines whether the match is a FALSE\_POSITIVE or TRUE\_POSITIVE All of this happens automatically within minutes of a new alert appearing in your provider. ### 3. Resolution Posting For each hit, the system: * Posts a comment and a resolution (FALSE\_POSITIVE or TRUE\_POSITIVE) to provider if so configured * Includes summary explaining the determination * Preserves any existing manual comments from your team * Adds "Diligent AI: " prefix for tracking ## How the AI Makes Decisions The AI evaluates each potential match by comparing multiple data points: * **Identity information**: Names, dates of birth, incorporation dates * **Location data**: Addresses, countries of residence or operation * **Identifiers**: Company registration numbers, tax IDs, passport numbers * **Contextual data**: Industry codes, related entities, historical records Each piece of evidence is evaluated for strength (strong, moderate, or weak) and whether it supports or contradicts the match. The AI then generates an overall confidence score and a clear explanation of its reasoning. **Key principle**: Any strong contradicting evidence (such as a temporal impossibility) results in an immediate FALSE\_POSITIVE determination, regardless of other supporting factors. ## Example Resolution **Subject**: Sarah Mitchell, DOB: 1988-03-15, UK **Hit**: Sarah MITCHELL, INACTIVE PEP, spouse of political figure (born 1965) **AI Determination**: FALSE\_POSITIVE (Score: 0/100) **Reasoning**: "Temporal impossibility: Sarah Mitchell was born in 1988, but the hit profile indicates marriage to a political figure in 1992—when the subject would have been 4 years old. Additional evidence from public records shows the hit individual must have been born before 1965 to marry in 1992. These are different individuals with the same name." **Evidence**: * ✅ MATCH (STRONG): Exact name match - "Sarah Mitchell" * ✅ MATCH (MODERATE): Nationality - United Kingdom * ❌ MISMATCH (STRONG): Temporal impossibility - marriage date incompatible with DOB * ❌ MISMATCH (STRONG): Age discrepancy - 20+ year difference inferred ## Provider Integration The remediation agent works seamlessly with: ### WorldCheck (LSEG World-Check One) * Monitors cases via date-based search * Posts resolutions using WorldCheck resolution toolkit * Maps AI determinations to configured risk/reason taxonomy * Preserves existing remarks when updating ### ComplyAdvantage CSOM * Monitors searches via API pagination * Posts resolutions as entity comments * Prefixes AI comments with "Diligent AI: " for tracking * Supports both comment-only and full status updates ### LexisNexis Bridger * Monitors records via predefined search queries * Posts resolutions to case assignment system * Updates case status and adds remarks * Maintains assignment role/division configuration ## Configuration **Contact us at [support@godiligent.ai](mailto:support@godiligent.ai) to enable AI remediation for your account.** To get started, please provide the following information for your screening provider: ### WorldCheck (LSEG World-Check One) * **API Key**: Your WorldCheck API key * **API Secret**: Your WorldCheck API secret * **Account ID**: Your WorldCheck account identifier * **Group ID**: The group ID to use when creating new cases (determines screening scope and available fields) * **Risk Label**: Default risk category for resolutions (e.g., `"LOW"`, `"MEDIUM"`, `"HIGH"`, `"UNKNOWN"`) * **Reason Label**: Default reason category for resolutions (e.g., `"No Match"`, `"Full Match"`, `"Partial Match"`) ### ComplyAdvantage CSOM * **API Key**: Your ComplyAdvantage API key * **Search Profile ID** (optional): Default search profile to use for new searches * **Region**: API region - EU (`api.eu.complyadvantage.com`) or US (`api.us.complyadvantage.com`) ### LexisNexis Bridger * **API Key**: Your LexisNexis Bridger API key * **Username**: Account username in format `client_id/user_id` * **Password**: Account password * **Predefined Search Name**: Name of your predefined search configuration * **Assignment Role** (optional): Default role to assign cases to * **Assignment Division** (optional): Default division to assign cases to ### AI Behavior Configuration The remediation agent's decision-making can be customized based on your risk appetite and compliance requirements. Configuration options include: **Hit Category Rules** * Define different behavior for different alert types (SANCTION, PEP, WATCHLIST, MEDIA) * For example: conservative rules for sanctions (comment-only analysis) vs. permissive rules for adverse media (auto-resolve clear false positives) **Evidence Thresholds** * Set minimum evidence strength required for auto-resolution (weak, moderate, or strong) * Configure separate thresholds for name evidence vs. additional evidence (DOB, location, identifiers, etc.) * Use multiple rule segments per category for nuanced decision-making **Resolution Actions** * **Auto-resolve**: AI posts definitive resolution status to provider (e.g., mark as FALSE\_POSITIVE) * **Comment-only**: AI adds analysis as a comment without changing hit status (human reviews and decides) * Configure different actions based on evidence confidence **Example Configurations**: * **Conservative (sanctions)**: Comment-only for all cases, even with strong contradicting evidence * **Balanced (PEP)**: Auto-resolve slam-dunk false positives, comment on edge cases * **Permissive (media)**: Auto-resolve both clear false positives and clear true positives Contact [support@godiligent.ai](mailto:support@godiligent.ai) to discuss your preferred configuration strategy. ## Support For questions, configuration assistance, or to get started with AI remediation: **Contact us at [support@godiligent.ai](mailto:support@godiligent.ai)** # Remediation API Source: https://docs.godiligent.ai/guides/name-screening/remediation-api Submit externally-screened alerts for AI-powered remediation **Beta** — This API is under active development. The contract may change based on early adopter feedback. Please contact the team before integrating. The Remediation API enables customers who perform name screening themselves to submit their alerts directly for AI-powered analysis. Instead of Diligent querying a screening provider, you provide the screening subject and hits, and Diligent's AI resolves each hit with evidence-based reasoning. ## Overview This is a companion to the [Create Search](/api-reference/name-screening/create-search) workflow. Where Create Search screens a subject against a provider's databases and then remediates, the Remediation API skips the provider step — you bring the hits, we bring the AI. ```mermaid theme={null} sequenceDiagram participant Client participant API participant AI as AI Workflow participant Webhook Client->>API: POST /name-screenings/alerts/remediate API->>Client: Returns { id } (201) API->>AI: Enqueue for processing AI->>AI: Enrich (registry, web search, articles) AI->>AI: Entity resolution + rule engine AI->>AI: Generate report + summary AI->>Webhook: POST alert_remediated event Webhook->>Client: Notification received Client->>API: GET /name-screenings/alerts/{id} API->>Client: Full resolution results ``` ## Quick Start ### 1. Submit an Alert Provide your screening subject and hits: ```bash theme={null} curl -X POST https://api.godiligent.ai/v1/name-screenings/alerts/remediate \ -H "X-API-KEY: your-api-key" \ -H "Content-Type: application/json" \ -d '{ "reference": "WC-CASE-2026-001", "alt_reference": "CUST-SCREENING-42", "input": [ {"label": "full_name", "value": "John Alexander Doe"}, {"label": "entity_type", "value": "INDIVIDUAL"}, {"label": "date_of_birth", "value": "1985-03-15"}, {"label": "country_code", "value": "DE"} ], "hits": [ { "reference": "WC-RESULT-12345", "profile_reference": "WC-ENTITY-789", "categories": ["SANCTION"], "fields": [ {"label": "Name", "value": "John A. Doe"}, {"label": "Date of Birth", "value": "1985-03-15"}, {"label": "Nationality", "value": "German"}, {"label": "Listed On", "value": "EU Sanctions List"} ] }, { "reference": "WC-RESULT-67890", "categories": ["PEP"], "fields": [ {"label": "Name", "value": "Jonathan Doe"}, {"label": "Position", "value": "Member of Parliament"}, {"label": "Country", "value": "United Kingdom"} ] } ] }' ``` **Response:** ```json theme={null} { "id": "550e8400-e29b-41d4-a716-446655440000", "reference": "WC-CASE-2026-001", "alt_reference": "CUST-SCREENING-42", "hits": [ { "reference": "WC-RESULT-12345", "profile_reference": "WC-ENTITY-789" }, { "reference": "WC-RESULT-67890", "profile_reference": "WC-RESULT-67890" } ] } ``` ### 2. Receive Webhook Notification If you have registered a webhook for the `alert_remediated` event (see [Working with Webhooks](/guides/webhooks/working-with-webhooks)), you will receive a notification when processing completes. The payload follows the standard `alert_remediated` format. Alternatively, poll the GET endpoint until it returns `200`. The endpoint returns `404` until processing is complete. Typical processing time is 10-60 seconds depending on the number of hits and configured enrichments. ### 3. Retrieve Results ```bash theme={null} curl https://api.godiligent.ai/v1/name-screenings/alerts/550e8400-e29b-41d4-a716-446655440000 \ -H "X-API-KEY: your-api-key" ``` The response is identical to the standard [Get Alert](/api-reference/name-screening/get-alert) endpoint. Each hit includes: * **`action`** — The action taken (e.g. `COMMENT_FALSE_POSITIVE`, `SET_AS_MATCH`) * **`determination`** — Simplified result: `TRUE_POSITIVE`, `FALSE_POSITIVE`, or `UNRESOLVED` * **`applied_rule`** — Which rule triggered the action * **`summary`** — Human-readable explanation of the AI's reasoning * **`evidences`** — Supporting facts with citations to data sources ## Request Reference ### Alert Fields | Field | Type | Required | Description | | --------------- | ------ | -------- | ----------------------------------------------------------------------------- | | `reference` | string | Yes | Provider reference for the alert (e.g. case ID from your screening provider). | | `alt_reference` | string | No | Your own client reference for the same alert (e.g. internal case number). | | `input` | array | Yes | Subject profile as label/value pairs. See [Subject Fields](#subject-fields). | | `hits` | array | Yes | Screening hits to remediate. At least one required. | ### Hit Fields | Field | Type | Required | Description | | ------------------- | --------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `reference` | string | Yes | Provider reference for this hit (e.g. result ID or match ID). Must be unique within the alert. | | `profile_reference` | string | No | Provider's unique reference for the matched profile/entity. May differ from `reference` — some providers use separate IDs for the match result vs the underlying entity. Enables enrichment caching across alerts. Defaults to `reference` if omitted. | | `categories` | string\[] | Yes | One or more of: `SANCTION`, `PEP`, `MEDIA`. | | `fields` | array | Yes | Hit entity profile as label/value pairs. See [Hit Profile Fields](#hit-profile-fields). | ### Subject Fields The `input` array accepts freeform label/value pairs. The AI uses LLM-based extraction, so exact labels are flexible. The following are recommended for best results: **Individuals:** | Label | Example | Notes | | ---------------- | ---------------------- | -------------------------------------------- | | `full_name` | `"John Alexander Doe"` | Full name, or use `first_name` + `last_name` | | `first_name` | `"John"` | Given name (alternative to `full_name`) | | `last_name` | `"Doe"` | Family name (alternative to `full_name`) | | `entity_type` | `"INDIVIDUAL"` | `INDIVIDUAL` or `BUSINESS` | | `date_of_birth` | `"1985-03-15"` | ISO 8601 (YYYY-MM-DD) or year only (YYYY) | | `place_of_birth` | `"Munich, Germany"` | Freeform | | `country_code` | `"DE"` | ISO alpha-2, alpha-3, or full name | **Businesses:** | Label | Example | Notes | | -------------------- | ---------------------- | ------------------------------ | | `name` | `"Acme Holdings GmbH"` | Full name including legal form | | `entity_type` | `"BUSINESS"` | | | `country_code` | `"AT"` | Country of registration | | `company_identifier` | `"FN 123456a"` | Registration number, LEI, etc. | ### Hit Profile Fields Hit `fields` are freeform — use whatever labels your provider gives you. Common examples: | Label | Description | | --------------- | --------------------------------- | | `Name` | Entity name as listed | | `Date of Birth` | DOB if available | | `Nationality` | Nationality or citizenship | | `Country` | Country of origin or registration | | `Position` | Political or corporate position | | `Listed On` | Sanctions list or source | | `AKA` | Aliases / also-known-as | ## Actions Reference The AI assigns one of these actions to each hit based on evidence and your configured rules: | Action | Determination | Description | | ------------------------ | ---------------- | ------------------------------------------- | | `SET_AS_MATCH` | `TRUE_POSITIVE` | High-confidence match. | | `COMMENT_MATCH` | `TRUE_POSITIVE` | Likely match — review recommended. | | `DO_NOTHING` | `UNRESOLVED` | Insufficient evidence to decide. | | `COMMENT_FALSE_POSITIVE` | `FALSE_POSITIVE` | Likely false positive — review recommended. | | `SET_AS_FALSE_POSITIVE` | `FALSE_POSITIVE` | High-confidence false positive. | ## Status Codes | Code | Description | | ----- | ----------------------------------------------------------------------- | | `201` | Alert accepted for remediation. | | `400` | Validation error (missing fields, invalid format). See `details` array. | | `404` | Customer configuration not found. Rules must be configured first. | | `500` | Internal server error. | ## Configuration Before using this endpoint, your account needs a name screening configuration with: * **Rules** — Define how evidence maps to actions * **Segments** (optional) — Category-specific rule sets (e.g. stricter rules for sanctions) * **Enrichments** — Which external sources to consult (registry, web search, articles) Configuration is managed through the Diligent dashboard. Contact support for setup. ## Best Practices ### Use Stable Profile References If you screen the same entity across multiple alerts, provide a consistent `profile_reference` on the hit. This enables Diligent to cache enrichment data (web searches, registry lookups) and significantly speed up subsequent remediations. ### Provide Rich Hit Profiles The more data you include in hit `fields`, the better the AI can resolve. Name alone produces weaker evidence than name + DOB + nationality. ### Use Webhooks for Production Polling works for development, but register for the `alert_remediated` webhook event for production integrations. See [Working with Webhooks](/guides/webhooks/working-with-webhooks). ### Store Alert IDs Persist the returned `id` for audit trails and result retrieval. ### Duplicate Prevention **Not idempotent** — Submitting the same `reference` twice will create a new alert each time. If you need to prevent duplicates, check for an existing alert by its `reference` before resubmitting. ## Example: Business Entity ```bash theme={null} curl -X POST https://api.godiligent.ai/v1/name-screenings/alerts/remediate \ -H "X-API-KEY: your-api-key" \ -H "Content-Type: application/json" \ -d '{ "reference": "CA-SEARCH-2026-002", "alt_reference": "CUST-KYB-99", "input": [ {"label": "name", "value": "Acme Holdings GmbH"}, {"label": "entity_type", "value": "BUSINESS"}, {"label": "country_code", "value": "AT"}, {"label": "company_identifier", "value": "FN 123456a"} ], "hits": [ { "reference": "CA-MATCH-456", "categories": ["SANCTION"], "fields": [ {"label": "Name", "value": "Acme Holdings Ltd"}, {"label": "Country of Registration", "value": "Cyprus"}, {"label": "Listed On", "value": "OFAC SDN"} ] } ] }' ``` ## Next Steps * [Get Alert API Reference](/api-reference/name-screening/get-alert) — Retrieve full resolution results * [Working with Webhooks](/guides/webhooks/working-with-webhooks) — Set up `alert_remediated` notifications * [Securing Webhooks](/guides/webhooks/securing-webhooks) — Verify webhook signatures * [Name Screening Guide](/guides/name-screening/guide) — AI remediation overview # OKTA Integration Setup Source: https://docs.godiligent.ai/guides/okta-integration Step-by-step guide to configure OKTA SSO integration with Diligent ## Overview This guide walks you through setting up OKTA Single Sign-On (SSO) integration with Diligent. Follow these steps to enable your team to authenticate using your OKTA account. You'll need admin access to your OKTA Admin Console to complete this setup. ## Step 1: Create a New App Integration 1. Log in to your **OKTA Admin Console** 2. Navigate to **Applications** in the left sidebar 3. Click the **Create App Integration** button OKTA Applications page ## Step 2: Select Sign-in Method and Application Type In the "Create a new app integration" dialog: 1. **Sign-in method**: Select **OIDC - OpenID Connect** * This provides OAuth 2.0 authentication for Single Sign-On (SSO) through API endpoints 2. **Application type**: Select **Web Application** * Server-side applications where authentication and tokens are handled on the server 3. Click **Next** to continue Create new app integration dialog ## Step 3: Configure Login Settings Configure the following settings: ### App integration name Enter a name for your app integration, e.g., "DiligentAI" ### Sign-in redirect URIs Add your Diligent callback URL: ``` https://login.godiligent.ai/callback ``` 4. Click **Save** to create the application Login settings configuration ## Step 4: Configure Client Credentials After saving, you'll see the **Client Credentials** page: 1. **Client ID**: This is automatically generated (e.g., `0oay65p7y5W88sD7V697`) * This is the public identifier required for all OAuth flows 2. **Client authentication**: Select **Client secret** * This option uses a client secret for authentication 3. **Proof Key for Code Exchange (PKCE)**: Check **Require PKCE as additional verification** * This adds an extra security layer to the authentication flow Client credentials configuration ## Step 5: Retrieve Client Credentials 1. On the Client Credentials page, copy your **Client ID** 2. Click **Show** or navigate to the credentials section to reveal your **Client Secret** 3. Copy the **Client Secret** Keep your Client Secret secure. Never share it publicly or commit it to version control. ## Step 6: Share Credentials with Diligent Send the following information to our support team at **[support@godiligent.ai](mailto:support@godiligent.ai)**: * **Client ID**: `[Your Client ID]` * **Client Secret**: `[Your Client Secret]` * **OKTA Domain**: `[Your OKTA domain, e.g., yourcompany.okta.com]` Our team will configure the integration on our end and notify you once it's ready. ## Testing the Integration Once our team confirms the integration is complete: 1. Navigate to `https://app.godiligent.ai` Client credentials configuration 2. Click **Sign in with corproate email** 3. You'll be redirected to your OKTA login page 4. Enter your OKTA credentials 5. You'll be redirected back to Diligent and logged in ## Troubleshooting Make sure you've assigned the users or groups to the application in the Assignments tab. Verify that the Sign-in redirect URI in OKTA matches exactly: `https://login.godiligent.ai/callback` Contact [support@godiligent.ai](mailto:support@godiligent.ai) with the error message. We'll verify the Client ID and Secret are configured correctly. ## Need Help? If you encounter any issues during setup: * Email: [support@godiligent.ai](mailto:support@godiligent.ai) * Include your OKTA domain and any error messages you're seeing # Securing Webhooks Source: https://docs.godiligent.ai/guides/webhooks/securing-webhooks Guide to securely configure and validate webhook deliveries using a shared secret ## How to Secure Webhook Deliveries To ensure that webhook payloads are securely transmitted and verified. This guide explains how to configure and validate webhook deliveries using a shared secret. ### How It Works When setting up a webhook, a secret is configured on both the sender (our system) and the receiver (your endpoint). Each webhook payload is signed using this secret, allowing the receiver to verify its authenticity. #### Step 1: Configuring Your Webhook Secret 1. When creating a webhook in our system, specify a unique secret key. This secret should be a strong, randomly generated string. 2. Store this secret securely on your server; it should never be exposed publicly. #### Step 2: Receiving Webhook Payloads When your server receives a webhook event, the request will include an `X-Signature` header containing a HMAC signature of the payload. Example header: ``` X-Signature: sha256=abcdef1234567890... ``` #### Step 3: Validating the Webhook Signature To verify the webhook payload: 1. Retrieve the `X-Signature` value from the request headers. 2. Compute the HMAC SHA-256 signature of the request payload using your webhook secret. 3. Compare the computed signature with the one in the `X-Signature` header. 4. If they match, the webhook is valid. #### (Python) ```python theme={null} import hashlib import hmac import json def verify_webhook_signature(secret, payload, signature): computed_signature = hmac.new(secret.encode(), payload.encode(), hashlib.sha256).hexdigest() expected_signature = f"sha256={computed_signature}" return hmac.compare_digest(expected_signature, signature) # Example usage: secret = "your_webhook_secret" payload = json.dumps({"event": "example"}) received_signature = "sha256=abcdef1234567890..." if verify_webhook_signature(secret, payload, received_signature): print("Valid webhook received!") else: print("Invalid webhook signature!") ``` #### (JavaScript) ```javascript theme={null} const crypto = require('crypto'); function verifyWebhookSignature (secret, payload, signature) { const computedSignature = `sha256=${crypto.createHmac('sha256', secret) .update(payload) .digest('hex')}`; return crypto.timingSafeEqual(Buffer.from(computedSignature), Buffer.from(signature)); } // Example usage: const secret = "your_webhook_secret"; const payload = JSON.stringify({ event: "example" }); const receivedSignature = "sha256=abcdef1234567890..."; if (verifyWebhookSignature(secret, payload, receivedSignature)) { console.log("Valid webhook received!"); } else { console.log("Invalid webhook signature!"); } ``` #### Security Considerations * Always use HTTPS to prevent interception of webhook payloads. * Reject webhook requests that fail signature validation. * Rotate secrets periodically to enhance security. By following this guide, you ensure that webhook deliveries are secure and trusted. # Working with webhooks Source: https://docs.godiligent.ai/guides/webhooks/working-with-webhooks # 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 & path | Purpose | | ------------------------------- | ----------------------------------------- | | `POST /webhooks` | Create a webhook | | `GET /webhooks` | List 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: ```json theme={null} // 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): ```json theme={null} { "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: ```json theme={null} // PATCH /webhooks/df89eb16-4c6a-439f-b668-7cca0cd786fa { "events": ["cdd_state_changed", "alert_remediated", "search_completed"], "is_active": false } ``` **Delete a webhook** — `DELETE /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](../../api-reference/webhooks/register) 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: | Header | Description | | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Content-Type | Always `application/json` | | User-Agent | Sender identifier (e.g., `DiligentAI/1.0`) | | X-Webhook-Id | Unique ID of your webhook | | X-Event-Id | Unique ID of this delivery event | | X-Customer-Id | Your customer ID | | X-Target-type | Entity type (`CDD`, `MONITORING_ALERT`, `NAME_SCREENING_SEARCH`, `NAME_SCREENING_ALERT`, or `FLOW_RUN`) | | X-Event-Name | Name of the triggered event (`CDD_STATE_CHANGED`, `MONITORING_ALERT_FIRED`, `SEARCH_COMPLETED`, `CDD_DOCUMENT_FETCHED`, `ALERT_REMEDIATED`, `FLOW_RUN_COMPLETED`, `FLOW_RUN_FAILED`) | | X-Signature | HMAC signature for authenticity | ### Example Payloads #### cdd\_state\_changed ```json theme={null} { "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": "" } ``` * `payload`: Full CDD object (see [CDD Object](../../api-reference/cdd/get-cdd)). #### monitoring\_alert\_fired ```json theme={null} { "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 ```json theme={null} { "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": "" } ``` * `payload`: Full CDD object snapshot including all documents (see [CDD Object](../../api-reference/cdd/get-cdd)). #### search\_completed ```json theme={null} { "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 ```json theme={null} { "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](../../api-reference/name-screening/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 ```json theme={null} { "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 ```json theme={null} { "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: ```mermaid theme={null} sequenceDiagram participant Diligent AI participant YourServer Diligent AI->>Diligent AI: Event occurs (e.g. CDD completed) Diligent AI->>YourServer: POST webhook with headers and payload YourServer->>Diligent AI: Responds with status code (200 OK if 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](securing-webhooks).