> ## Documentation Index
> Fetch the complete documentation index at: https://docs.godiligent.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Bulk Create Monitorings

> 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).


## OpenAPI

````yaml POST /monitorings/bulk-create
openapi: 3.0.1
info:
  version: 1.5.0
  title: Diligent
  description: >
    Download Postman collection
    [here](https://docs.godiligent.ai/files/postman_collection.json).
servers:
  - url: https://api.godiligent.ai
    description: Production
  - url: https://api.sandbox.godiligent.ai
    description: Sandbox
security:
  - xApiKey: []
tags:
  - name: CDD
    description: Customer Due Diligence
  - name: Company
    description: Company Information
  - name: Blocked Companies
    description: Manage blocked companies
  - name: Monitorings
    description: Website monitoring and alerts for changes and risks
  - name: Webhooks
    description: >

      ## 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

      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

      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.
  - name: Instant Screening (experimental)
    description: Instant Website Screening API
  - name: Name Screening
    description: Name screening search, alert management and remediation
paths:
  /monitorings/bulk-create:
    post:
      tags:
        - Monitorings
      summary: Bulk create monitorings
      description: >-
        Create multiple monitorings in a single request. All websites must be
        unique and not already exist for the customer.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              minItems: 1
              maxItems: 200
              items:
                allOf:
                  - $ref: '#/components/schemas/MonitoringRequest'
                  - type: object
                    properties:
                      run_now:
                        type: boolean
                        description: >-
                          If true, monitoring will be executed immediately after
                          creation.
                      expires_at:
                        type: string
                        format: date-time
                        description: Optional expiration date for the monitoring.
      responses:
        '200':
          description: Successful bulk creation
          content:
            application/json:
              schema:
                type: object
                properties:
                  is_successful:
                    type: boolean
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/Monitoring'
        '400':
          description: Validation or duplicate error
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  duplicates:
                    type: array
                    items:
                      type: object
                      properties:
                        website:
                          type: string
                          description: The duplicate website URL
                        index:
                          type: integer
                          description: >-
                            The index position of the duplicate item in the
                            request array
                    description: >-
                      List of duplicate website objects with their positions in
                      the request array
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
      security:
        - xApiKey: []
components:
  schemas:
    MonitoringRequest:
      type: object
      required:
        - website
        - checks
        - frequency
      properties:
        website:
          type: string
          format: uri
          description: The website URL to monitor
          example: https://example.com
        checks:
          type: array
          minItems: 1
          uniqueItems: true
          items:
            type: string
            enum:
              - non_operational_website
              - high_risk_mcc
              - high_risk_diligent_classification
              - catalog_contain_loan_flipping_indicators
          description: Array of monitoring checks to perform
          example:
            - non_operational_website
            - high_risk_diligent_classification
        frequency:
          type: string
          enum:
            - weekly
            - every_2_weeks
            - every_3_weeks
            - every_4_weeks
          default: every_2_weeks
          description: How often to run the monitoring checks
          example: weekly
        run_now:
          type: boolean
          default: true
          description: Whether to execute the monitoring immediately after creation
        expires_at:
          type: string
          format: date-time
          description: >-
            Optional expiration date for the monitoring (defaults to 6 months
            from creation)
          example: '2024-12-31T23:59:59.000Z'
        skip_duplicate:
          type: boolean
          description: >-
            If an existing, active monitoring exist with the same site skip
            don't fail
          example: false
    Monitoring:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Unique monitoring identifier
          example: d6e3b214-30b1-4401-a1b8-a1bd3c6a84e4
        website:
          type: string
          format: uri
          description: The monitored website URL
          example: https://example.com
        customer_id:
          type: string
          description: Customer identifier
        checks:
          type: array
          items:
            type: string
            enum:
              - non_operational_website
              - high_risk_diligent_classification
              - catalog_contain_loan_flipping_indicators
          description: Active monitoring checks
        frequency:
          type: string
          enum:
            - weekly
            - every_2_weeks
            - every_3_weeks
            - every_4_weeks
          description: Monitoring frequency
        is_active:
          type: boolean
          description: Whether monitoring is active
        running_state:
          type: string
          enum:
            - IDLE
            - RUNNING
            - FAILED
          description: Current execution state
        next_run_at:
          type: string
          format: date-time
          description: Next scheduled execution time
        expires_at:
          type: string
          format: date-time
          description: Monitoring expiration date
        last_execution:
          type: string
          format: date-time
          nullable: true
          description: Timestamp of last execution, null if never executed
        created_at:
          type: string
          format: date-time
          description: Creation timestamp
        updated_at:
          type: string
          format: date-time
          description: Last update timestamp
        execution_results:
          type: array
          items:
            type: object
          description: Results from the latest monitoring execution
        external_id:
          type: string
          description: External identifier for this monitoring
  securitySchemes:
    xApiKey:
      type: apiKey
      name: X-API-KEY
      in: header

````