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

# Webhooks

> Create and manage webhooks for real-time notifications. Configure endpoints, authentication, and event subscriptions with full CRUD operations.

<Note>
  All operations require authentication using Bearer tokens. Make sure you have
  your API credentials ready.
</Note>

<Warning>
  Webhook endpoints must be publicly accessible and return appropriate HTTP
  status codes.
</Warning>

## Create Webhook

Create a new webhook endpoint to receive real-time notifications for various events.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://secure-api.getclaro.ai/api/v2/webhooks" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: unique-request-id-123" \
    -d '{
      "name": "Dataset Processing Notifications",
      "url": "https://your-app.com/webhooks/claro",
      "events": ["dataset.task.completed", "dataset.task.failed", "datasource.processed"],
      "headers": {
        "Authorization": "Bearer your-webhook-secret",
        "X-Custom-Header": "your-value"
      },
      "secret": "your-webhook-signing-secret"
    }'
  ```

  ```python Python theme={null}
  import requests

  headers = {
      "Authorization": "Bearer YOUR_API_KEY",
      "Content-Type": "application/json",
      "Idempotency-Key": "unique-request-id-123"
  }
  data = {
      "name": "Dataset Processing Notifications",
      "url": "https://your-app.com/webhooks/claro",
      "events": ["dataset.task.completed", "dataset.task.failed", "datasource.processed"],
      "headers": {
          "Authorization": "Bearer your-webhook-secret",
          "X-Custom-Header": "your-value"
      },
      "secret": "your-webhook-signing-secret"
  }

  response = requests.post(
      "https://secure-api.getclaro.ai/api/v2/webhooks",
      headers=headers,
      json=data
  )
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://secure-api.getclaro.ai/api/v2/webhooks", {
    method: "POST",
    headers: {
      Authorization: "Bearer YOUR_API_KEY",
      "Content-Type": "application/json",
      "Idempotency-Key": "unique-request-id-123",
    },
    body: JSON.stringify({
      name: "Dataset Processing Notifications",
      url: "https://your-app.com/webhooks/claro",
      events: [
        "dataset.task.completed",
        "dataset.task.failed",
        "datasource.processed",
      ],
      headers: {
        Authorization: "Bearer your-webhook-secret",
        "X-Custom-Header": "your-value",
      },
      secret: "your-webhook-signing-secret",
    }),
  });
  ```

  ```json Success Response theme={null}
  {
    "webhookId": "webhook_550e8400-e29b-41d4-a716-446655440000",
    "name": "Dataset Processing Notifications",
    "url": "https://your-app.com/webhooks/claro",
    "events": [
      "dataset.task.completed",
      "dataset.task.failed",
      "datasource.processed"
    ],
    "headers": {
      "Authorization": "[REDACTED]",
      "X-Custom-Header": "your-value"
    },
    "secret": "[REDACTED]",
    "status": "active",
    "createdAt": "2024-03-14T15:30:00Z",
    "updatedAt": "2024-03-14T15:30:00Z",
    "lastTriggered": null,
    "totalDeliveries": 0,
    "successfulDeliveries": 0,
    "failedDeliveries": 0
  }
  ```

  ```json Validation Error theme={null}
  {
    "error": "Validation failed",
    "code": "VALIDATION_ERROR",
    "details": {
      "url": "URL must be a valid HTTPS endpoint",
      "events": "At least one event must be specified",
      "secret": "Secret must be at least 16 characters long"
    }
  }
  ```
</CodeGroup>

## List All Webhooks

Retrieve a paginated list of all your webhooks with their current status and statistics.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://secure-api.getclaro.ai/api/v2/webhooks?page=1&limit=20&status=active" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```python Python theme={null}
  import requests

  headers = {"Authorization": "Bearer YOUR_API_KEY"}
  params = {"page": 1, "limit": 20, "status": "active"}

  response = requests.get(
      "https://secure-api.getclaro.ai/api/v2/webhooks",
      headers=headers,
      params=params
  )
  ```

  ```javascript JavaScript theme={null}
  const params = new URLSearchParams({
    page: 1,
    limit: 20,
    status: "active",
  });

  const response = await fetch(
    `https://secure-api.getclaro.ai/api/v2/webhooks?${params}`,
    {
      headers: {
        Authorization: "Bearer YOUR_API_KEY",
      },
    }
  );
  ```

  ```json Success Response theme={null}
  {
    "webhooks": [
      {
        "webhookId": "webhook_550e8400-e29b-41d4-a716-446655440000",
        "name": "Dataset Processing Notifications",
        "url": "https://your-app.com/webhooks/claro",
        "events": ["dataset.task.completed", "dataset.task.failed"],
        "active": true,
        "status": "active",
        "createdAt": "2024-03-14T15:30:00Z",
        "lastTriggered": "2024-03-14T16:45:00Z",
        "totalDeliveries": 25,
        "successfulDeliveries": 23,
        "failedDeliveries": 2,
        "successRate": 92.0
      },
      {
        "webhookId": "webhook_6ba7b810-9dad-11d1-80b4-00c04fd430c8",
        "name": "Task Completion Alerts",
        "url": "https://your-app.com/webhooks/tasks",
        "events": ["dataset.task.completed", "dataset.task.failed"],
        "active": false,
        "status": "paused",
        "createdAt": "2024-03-14T14:00:00Z",
        "lastTriggered": "2024-03-14T15:20:00Z",
        "totalDeliveries": 12,
        "successfulDeliveries": 12,
        "failedDeliveries": 0,
        "successRate": 100.0
      }
    ],
    "pagination": {
      "page": 1,
      "limit": 20,
      "total": 8,
      "totalPages": 1
    }
  }
  ```
</CodeGroup>

## Get Webhook Details

Retrieve detailed information about a specific webhook including delivery logs and configuration.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://secure-api.getclaro.ai/api/v2/webhooks/$WEBHOOK_ID" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```python Python theme={null}
  import requests

  headers = {"Authorization": "Bearer YOUR_API_KEY"}
  webhook_id = "webhook_550e8400-e29b-41d4-a716-446655440000"

  response = requests.get(
      f"https://secure-api.getclaro.ai/api/v2/webhooks/{webhook_id}",
      headers=headers
  )
  ```

  ```javascript JavaScript theme={null}
  const webhookId = "webhook_550e8400-e29b-41d4-a716-446655440000";

  const response = await fetch(
    `https://secure-api.getclaro.ai/api/v2/webhooks/${webhookId}`,
    {
      headers: {
        Authorization: "Bearer YOUR_API_KEY",
      },
    }
  );
  ```

  ```json Success Response theme={null}
  {
    "webhookId": "webhook_550e8400-e29b-41d4-a716-446655440000",
    "name": "Dataset Processing Notifications",
    "url": "https://your-app.com/webhooks/claro",
    "events": [
      "dataset.task.completed",
      "dataset.task.failed",
      "datasource.processed"
    ],
    "headers": {
      "Authorization": "[REDACTED]",
      "X-Custom-Header": "your-value"
    },
    "secret": "[REDACTED]",
    "active": true,
    "status": "active",
    "createdAt": "2024-03-14T15:30:00Z",
    "updatedAt": "2024-03-14T16:45:00Z",
    "lastTriggered": "2024-03-14T16:45:00Z",
    "totalDeliveries": 25,
    "successfulDeliveries": 23,
    "failedDeliveries": 2,
    "successRate": 92.0,
    "recentDeliveries": [
      {
        "deliveryId": "delivery_123",
        "event": "dataset.task.completed",
        "status": "success",
        "responseCode": 200,
        "responseTime": 245,
        "attempts": 1,
        "deliveredAt": "2024-03-14T16:45:00Z"
      },
      {
        "deliveryId": "delivery_124",
        "event": "dataset.task.failed",
        "status": "failed",
        "responseCode": 500,
        "responseTime": 5000,
        "attempts": 3,
        "lastAttemptAt": "2024-03-14T16:30:00Z",
        "error": "Internal Server Error"
      }
    ]
  }
  ```
</CodeGroup>

## Update Webhook

Update webhook configuration including URL, events, headers.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PATCH "https://secure-api.getclaro.ai/api/v2/webhooks/$WEBHOOK_ID" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: unique-update-id-456" \
    -d '{
      "name": "Updated Dataset Notifications",
      "events": ["dataset.task.completed", "dataset.task.failed", "dataset.task.started"],
      "headers": {
        "Authorization": "Bearer updated-webhook-secret",
        "X-API-Version": "v2"
      }
    }'
  ```

  ```python Python theme={null}
  import requests

  headers = {
      "Authorization": "Bearer YOUR_API_KEY",
      "Content-Type": "application/json",
      "Idempotency-Key": "unique-update-id-456"
  }
  data = {
      "name": "Updated Dataset Notifications",
      "events": ["dataset.task.completed", "dataset.task.failed", "dataset.task.started"],
      "headers": {
          "Authorization": "Bearer updated-webhook-secret",
          "X-API-Version": "v2"
      }
  }
  webhook_id = "webhook_550e8400-e29b-41d4-a716-446655440000"

  response = requests.patch(
      f"https://secure-api.getclaro.ai/api/v2/webhooks/{webhook_id}",
      headers=headers,
      json=data
  )
  ```

  ```javascript JavaScript theme={null}
  const webhookId = "webhook_550e8400-e29b-41d4-a716-446655440000";

  const response = await fetch(
    `https://secure-api.getclaro.ai/api/v2/webhooks/${webhookId}`,
    {
      method: "PATCH",
      headers: {
        Authorization: "Bearer YOUR_API_KEY",
        "Content-Type": "application/json",
        "Idempotency-Key": "unique-update-id-456",
      },
      body: JSON.stringify({
        name: "Updated Dataset Notifications",
        events: [
          "dataset.task.completed",
          "dataset.task.failed",
          "dataset.task.started",
        ],
        headers: {
          Authorization: "Bearer updated-webhook-secret",
          "X-API-Version": "v2",
        },
      }),
    }
  );
  ```

  ```json Success Response theme={null}
  {
    "webhookId": "webhook_550e8400-e29b-41d4-a716-446655440000",
    "name": "Updated Dataset Notifications",
    "url": "https://your-app.com/webhooks/claro",
    "events": [
      "dataset.task.completed",
      "dataset.task.failed",
      "dataset.task.started"
    ],
    "headers": {
      "Authorization": "[REDACTED]",
      "X-API-Version": "v2"
    },

    "active": true,
    "status": "active",
    "updatedAt": "2024-03-14T17:30:00Z"
  }
  ```
</CodeGroup>

## Test Webhook

Send a test payload to your webhook endpoint to verify connectivity and authentication.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://secure-api.getclaro.ai/api/v2/webhooks/$WEBHOOK_ID/test" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "event": "webhook.test",
      "testPayload": {
        "message": "This is a test webhook delivery",
        "timestamp": "2024-03-14T17:30:00Z"
      }
    }'
  ```

  ```python Python theme={null}
  import requests

  headers = {
      "Authorization": "Bearer YOUR_API_KEY",
      "Content-Type": "application/json"
  }
  data = {
      "event": "webhook.test",
      "testPayload": {
          "message": "This is a test webhook delivery",
          "timestamp": "2024-03-14T17:30:00Z"
      }
  }
  webhook_id = "webhook_550e8400-e29b-41d4-a716-446655440000"

  response = requests.post(
      f"https://secure-api.getclaro.ai/api/v2/webhooks/{webhook_id}/test",
      headers=headers,
      json=data
  )
  ```

  ```javascript JavaScript theme={null}
  const webhookId = "webhook_550e8400-e29b-41d4-a716-446655440000";

  const response = await fetch(
    `https://secure-api.getclaro.ai/api/v2/webhooks/${webhookId}/test`,
    {
      method: "POST",
      headers: {
        Authorization: "Bearer YOUR_API_KEY",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        event: "webhook.test",
        testPayload: {
          message: "This is a test webhook delivery",
          timestamp: "2024-03-14T17:30:00Z",
        },
      }),
    }
  );
  ```

  ```json Success Response theme={null}
  {
    "deliveryId": "test_delivery_789",
    "status": "success",
    "responseCode": 200,
    "responseTime": 156,
    "responseBody": "OK",
    "deliveredAt": "2024-03-14T17:30:00Z",
    "headers": {
      "content-type": "text/plain",
      "x-webhook-signature": "sha256=abc123..."
    }
  }
  ```

  ```json Test Failed Response theme={null}
  {
    "deliveryId": "test_delivery_790",
    "status": "failed",
    "responseCode": 401,
    "responseTime": 2000,
    "error": "Unauthorized - Invalid webhook signature",
    "deliveredAt": "2024-03-14T17:30:00Z"
  }
  ```
</CodeGroup>

## Get Webhook Delivery Logs

Retrieve detailed delivery logs for a specific webhook.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://secure-api.getclaro.ai/api/v2/webhooks/$WEBHOOK_ID/deliveries?page=1&limit=50&status=failed" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```python Python theme={null}
  import requests

  headers = {"Authorization": "Bearer YOUR_API_KEY"}
  params = {"page": 1, "limit": 50, "status": "failed"}
  webhook_id = "webhook_550e8400-e29b-41d4-a716-446655440000"

  response = requests.get(
      f"https://secure-api.getclaro.ai/api/v2/webhooks/{webhook_id}/deliveries",
      headers=headers,
      params=params
  )
  ```

  ```javascript JavaScript theme={null}
  const webhookId = "webhook_550e8400-e29b-41d4-a716-446655440000";
  const params = new URLSearchParams({
    page: 1,
    limit: 50,
    status: "failed",
  });

  const response = await fetch(
    `https://secure-api.getclaro.ai/api/v2/webhooks/${webhookId}/deliveries?${params}`,
    {
      headers: {
        Authorization: "Bearer YOUR_API_KEY",
      },
    }
  );
  ```

  ```json Success Response theme={null}
  {
    "deliveries": [
      {
        "deliveryId": "delivery_123",
        "event": "dataset.task.completed",
        "status": "success",
        "responseCode": 200,
        "responseTime": 245,
        "attempts": 1,
        "payload": {
          "event": "dataset.task.completed",
          "datasetId": "dataset_123",
          "timestamp": "2024-03-14T16:45:00Z"
        },
        "deliveredAt": "2024-03-14T16:45:00Z"
      },
      {
        "deliveryId": "delivery_124",
        "event": "dataset.task.failed",
        "status": "failed",
        "responseCode": 500,
        "responseTime": 5000,
        "attempts": 3,
        "payload": {
          "event": "dataset.task.failed",
          "datasetId": "dataset_124",
          "error": "Processing timeout",
          "timestamp": "2024-03-14T16:30:00Z"
        },
        "lastAttemptAt": "2024-03-14T16:35:00Z",
        "error": "Internal Server Error",
        "nextRetryAt": "2024-03-14T16:45:00Z"
      }
    ],
    "pagination": {
      "page": 1,
      "limit": 50,
      "total": 25,
      "totalPages": 1
    }
  }
  ```
</CodeGroup>

## Retry Failed Delivery

Manually retry a failed webhook delivery.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://secure-api.getclaro.ai/api/v2/webhooks/$WEBHOOK_ID/deliveries/$DELIVERY_ID/retry" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```python Python theme={null}
  import requests

  headers = {"Authorization": "Bearer YOUR_API_KEY"}
  webhook_id = "webhook_550e8400-e29b-41d4-a716-446655440000"
  delivery_id = "delivery_124"

  response = requests.post(
      f"https://secure-api.getclaro.ai/api/v2/webhooks/{webhook_id}/deliveries/{delivery_id}/retry",
      headers=headers
  )
  ```

  ```javascript JavaScript theme={null}
  const webhookId = "webhook_550e8400-e29b-41d4-a716-446655440000";
  const deliveryId = "delivery_124";

  const response = await fetch(
    `https://secure-api.getclaro.ai/api/v2/webhooks/${webhookId}/deliveries/${deliveryId}/retry`,
    {
      method: "POST",
      headers: {
        Authorization: "Bearer YOUR_API_KEY",
      },
    }
  );
  ```

  ```json Success Response theme={null}
  {
    "deliveryId": "delivery_124_retry_1",
    "originalDeliveryId": "delivery_124",
    "status": "success",
    "responseCode": 200,
    "responseTime": 189,
    "attempts": 1,
    "retriedAt": "2024-03-14T17:45:00Z"
  }
  ```
</CodeGroup>

## Delete Webhook

Permanently delete a webhook. This action cannot be undone.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X DELETE "https://secure-api.getclaro.ai/api/v2/webhooks/$WEBHOOK_ID" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```python Python theme={null}
  import requests

  headers = {"Authorization": "Bearer YOUR_API_KEY"}
  webhook_id = "webhook_550e8400-e29b-41d4-a716-446655440000"

  response = requests.delete(
      f"https://secure-api.getclaro.ai/api/v2/webhooks/{webhook_id}",
      headers=headers
  )
  ```

  ```javascript JavaScript theme={null}
  const webhookId = "webhook_550e8400-e29b-41d4-a716-446655440000";

  const response = await fetch(
    `https://secure-api.getclaro.ai/api/v2/webhooks/${webhookId}`,
    {
      method: "DELETE",
      headers: {
        Authorization: "Bearer YOUR_API_KEY",
      },
    }
  );
  ```

  ```json Success Response theme={null}
  {
    "message": "Webhook deleted successfully",
    "webhookId": "webhook_550e8400-e29b-41d4-a716-446655440000",
    "deletedAt": "2024-03-14T17:45:00Z"
  }
  ```
</CodeGroup>

## Webhook Requirements & Validation

### URL Requirements

* Must use HTTPS protocol
* Must be publicly accessible
* Must respond within 30 seconds
* Must return HTTP status codes 200-299 for success

### Authentication Headers

* Custom headers are supported for authentication
* Headers containing sensitive data are redacted in responses
* Maximum 10 custom headers per webhook

### Secret Validation

* Minimum 16 characters required
* Used for HMAC-SHA256 signature generation
* Signature sent in `X-Webhook-Signature` header

### Idempotency

* Use `Idempotency-Key` header to prevent duplicate operations
* Keys expire after 24 hours
* Duplicate requests return the original response

## Available Events

| Event                    | Description                           | Payload Includes          |
| ------------------------ | ------------------------------------- | ------------------------- |
| `dataset.created`        | New dataset created                   | datasetId, name, type     |
| `dataset.task.started`   | Dataset task execution started        | taskId, type, datasetId   |
| `dataset.task.completed` | Dataset task execution completed      | taskId, results, duration |
| `dataset.task.failed`    | Dataset task execution failed         | taskId, error, details    |
| `dataset.updated`        | Dataset metadata or structure updated | datasetId, changes        |
| `datasource.uploaded`    | New datasource uploaded               | datasourceId, fileName    |
| `datasource.processed`   | Datasource processing completed       | datasourceId, status      |
| `webhook.test`           | Test event for webhook validation     | testPayload               |

## Query Parameters

### List Webhooks

* `page` (integer): Page number (default: 1)
* `limit` (integer): Items per page (default: 20, max: 100)
* `status` (string): Filter by status (`active`, `paused`, `failed`)
* `event` (string): Filter by event type

### Get Delivery Logs

* `page` (integer): Page number (default: 1)
* `limit` (integer): Items per page (default: 50, max: 500)
* `status` (string): Filter by delivery status (`success`, `failed`, `pending`)
* `event` (string): Filter by event type
* `from` (string): Start date (ISO 8601)
* `to` (string): End date (ISO 8601)

## Error Codes

| Code                        | Description                              |
| --------------------------- | ---------------------------------------- |
| `UNAUTHORIZED`              | Authentication required                  |
| `WEBHOOK_NOT_FOUND`         | Webhook doesn't exist                    |
| `DELIVERY_NOT_FOUND`        | Delivery record doesn't exist            |
| `INVALID_URL`               | Webhook URL is invalid or not HTTPS      |
| `INVALID_EVENTS`            | One or more events are not supported     |
| `SECRET_TOO_SHORT`          | Webhook secret must be at least 16 chars |
| `TOO_MANY_HEADERS`          | Maximum 10 custom headers allowed        |
| `DUPLICATE_IDEMPOTENCY_KEY` | Idempotency key already used             |
| `WEBHOOK_LIMIT_EXCEEDED`    | Maximum webhook limit reached            |
| `DELIVERY_ALREADY_RETRIED`  | Delivery has already been retried        |

## Webhook Payload Example

```json theme={null}
{
  "event": "dataset.task.completed",
  "timestamp": "2024-03-14T16:45:00Z",
  "webhookId": "webhook_550e8400-e29b-41d4-a716-446655440000",
  "deliveryId": "delivery_123",
  "data": {
    "taskId": "task_123",
    "datasetId": "dataset_123",
    "name": "Product Analysis Dataset",
    "type": "extraction",
    "status": "completed",
    "rowCount": 1500,
    "columnCount": 8,
    "processingTime": 45000,
    "completedAt": "2024-03-14T16:45:00Z",
    "stats": {
      "successfulRows": 1485,
      "failedRows": 15,
      "averageConfidence": 0.94
    }
  }
}
```
