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

# Webhooks

> On this page, we'll dive into the different webhook endpoints you can use to receive real-time event notifications.

Webhooks allow you to receive real-time HTTP notifications when events occur in your organization. Instead of polling the API, you can subscribe to specific events and receive push notifications to your server.

## Available event types

The following event types are available for webhook subscriptions:

* `workflow.started` - A workflow has started execution
* `workflow.completed` - A workflow has completed successfully
* `workflow.failed` - A workflow has failed
* `workflow.step.started` - A workflow step has started
* `workflow.step.completed` - A workflow step has completed
* `workflow.step.failed` - A workflow step has failed

## Webhook payload

When an event occurs, your webhook URL will receive a POST request with the following payload structure:

```json theme={null}
{
  "event_id": "evt_abc123",
  "event_type": "workflow.completed",
  "workflow_id": "wf_xyz789",
  "organization_id": "org_123",
  "timestamp": "2025-12-21T10:30:00Z",
  "data": {
    // Event-specific data
  }
}
```

## Security

If you provide a `secret` when creating a webhook, all requests will include an `X-Webhook-Signature` header containing an HMAC-SHA256 signature of the request body. Verify this signature to ensure requests are authentic.

***

## The webhook subscription model

The webhook subscription model contains information about a webhook configuration.

### Properties

<ResponseField name="id" type="integer">
  Unique identifier for the webhook subscription.
</ResponseField>

<ResponseField name="name" type="string">
  Human-readable name for the webhook.
</ResponseField>

<ResponseField name="url" type="string">
  The target URL where webhook payloads will be delivered.
</ResponseField>

<ResponseField name="events" type="array">
  List of event types this webhook is subscribed to.
</ResponseField>

<ResponseField name="is_active" type="boolean">
  Whether the webhook is currently active.
</ResponseField>

<ResponseField name="created_at" type="timestamp">
  When the webhook subscription was created.
</ResponseField>

<ResponseField name="updated_at" type="timestamp">
  When the webhook subscription was last updated.
</ResponseField>

***

## Create webhook subscription

**`POST /webhooks`**

This endpoint allows you to create a new webhook subscription for your organization.

### Required attributes

<ParamField body="name" type="string" required>
  A human-readable name for the webhook (max 255 characters).
</ParamField>

<ParamField body="url" type="string" required>
  The target URL for webhook delivery (max 2048 characters). Must be HTTPS.
</ParamField>

<ParamField body="events" type="array" required>
  List of event types to subscribe to.
</ParamField>

### Optional attributes

<ParamField body="secret" type="string">
  A secret key for HMAC-SHA256 signature verification (max 255 characters).
</ParamField>

<ParamField body="headers" type="object">
  Custom headers to include in webhook requests.
</ParamField>

<ParamField header="X-Org-Id" type="string">
  Organization identifier (header). If not provided, uses your default organization.
</ParamField>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.elanlanguages.ai/v1/webhooks \
    -H "Authorization: Bearer {token}" \
    -H "X-Org-Id: {orgId}" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Production Webhook",
      "url": "https://api.example.com/webhooks/elan",
      "events": ["workflow.completed", "workflow.failed"],
      "secret": "your-webhook-secret",
      "headers": {
        "X-Custom-Header": "custom-value"
      }
    }'
  ```
</CodeGroup>

```json Response theme={null}
{
  "id": 1,
  "name": "Production Webhook",
  "url": "https://api.example.com/webhooks/elan",
  "events": ["workflow.completed", "workflow.failed"],
  "is_active": true,
  "created_at": "2025-12-21T10:30:00Z",
  "updated_at": null
}
```

***

## List webhook subscriptions

**`GET /webhooks`**

This endpoint returns all webhook subscriptions for your organization.

### Optional attributes

<ParamField header="X-Org-Id" type="string">
  Organization identifier (header). If not provided, uses your default organization.
</ParamField>

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.elanlanguages.ai/v1/webhooks \
    -H "Authorization: Bearer {token}" \
    -H "X-Org-Id: {orgId}"
  ```
</CodeGroup>

```json Response theme={null}
{
  "subscriptions": [
    {
      "id": 1,
      "name": "Production Webhook",
      "url": "https://api.example.com/webhooks/elan",
      "events": ["workflow.completed", "workflow.failed"],
      "is_active": true,
      "created_at": "2025-12-21T10:30:00Z",
      "updated_at": null
    }
  ],
  "total": 1
}
```

***

## Get webhook subscription

**`GET /webhooks/:subscription_id`**

This endpoint returns details of a specific webhook subscription.

### Required attributes

<ParamField path="subscription_id" type="integer" required>
  The unique identifier for the webhook subscription.
</ParamField>

### Optional attributes

<ParamField header="X-Org-Id" type="string">
  Organization identifier (header). If not provided, uses your default organization.
</ParamField>

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.elanlanguages.ai/v1/webhooks/1 \
    -H "Authorization: Bearer {token}" \
    -H "X-Org-Id: {orgId}"
  ```
</CodeGroup>

```json Response theme={null}
{
  "id": 1,
  "name": "Production Webhook",
  "url": "https://api.example.com/webhooks/elan",
  "events": ["workflow.completed", "workflow.failed"],
  "is_active": true,
  "created_at": "2025-12-21T10:30:00Z",
  "updated_at": null
}
```

***

## Update webhook subscription

**`PATCH /webhooks/:subscription_id`**

This endpoint allows you to update an existing webhook subscription. All fields are optional - only provided fields will be updated.

### Required attributes

<ParamField path="subscription_id" type="integer" required>
  The unique identifier for the webhook subscription.
</ParamField>

### Optional attributes

<ParamField body="name" type="string">
  A new name for the webhook.
</ParamField>

<ParamField body="url" type="string">
  A new target URL for webhook delivery.
</ParamField>

<ParamField body="events" type="array">
  Updated list of event types to subscribe to.
</ParamField>

<ParamField body="secret" type="string">
  A new secret key for signature verification.
</ParamField>

<ParamField body="headers" type="object">
  Updated custom headers.
</ParamField>

<ParamField body="is_active" type="boolean">
  Enable or disable the webhook.
</ParamField>

<ParamField header="X-Org-Id" type="string">
  Organization identifier (header). If not provided, uses your default organization.
</ParamField>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PATCH https://api.elanlanguages.ai/v1/webhooks/1 \
    -H "Authorization: Bearer {token}" \
    -H "X-Org-Id: {orgId}" \
    -H "Content-Type: application/json" \
    -d '{
      "events": ["workflow.completed", "workflow.failed", "workflow.started"],
      "is_active": true
    }'
  ```
</CodeGroup>

```json Response theme={null}
{
  "id": 1,
  "name": "Production Webhook",
  "url": "https://api.example.com/webhooks/elan",
  "events": ["workflow.completed", "workflow.failed", "workflow.started"],
  "is_active": true,
  "created_at": "2025-12-21T10:30:00Z",
  "updated_at": "2025-12-21T11:00:00Z"
}
```

***

## Delete webhook subscription

**`DELETE /webhooks/:subscription_id`**

This endpoint deletes a webhook subscription. This action cannot be undone.

### Required attributes

<ParamField path="subscription_id" type="integer" required>
  The unique identifier for the webhook subscription to delete.
</ParamField>

### Optional attributes

<ParamField header="X-Org-Id" type="string">
  Organization identifier (header). If not provided, uses your default organization.
</ParamField>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X DELETE https://api.elanlanguages.ai/v1/webhooks/1 \
    -H "Authorization: Bearer {token}" \
    -H "X-Org-Id: {orgId}"
  ```
</CodeGroup>

```json Response theme={null}
// Returns 204 No Content on success
```

***

## List webhook delivery logs

**`GET /webhooks/:subscription_id/logs`**

This endpoint returns delivery logs for a specific webhook subscription, showing all delivery attempts including retries.

### Required attributes

<ParamField path="subscription_id" type="integer" required>
  The unique identifier for the webhook subscription.
</ParamField>

### Optional attributes

<ParamField query="limit" type="integer">
  Maximum number of logs to return (default: 50).
</ParamField>

<ParamField query="offset" type="integer">
  Number of logs to skip for pagination (default: 0).
</ParamField>

<ParamField header="X-Org-Id" type="string">
  Organization identifier (header). If not provided, uses your default organization.
</ParamField>

<CodeGroup>
  ```bash cURL theme={null}
  curl -G https://api.elanlanguages.ai/v1/webhooks/1/logs \
    -H "Authorization: Bearer {token}" \
    -H "X-Org-Id: {orgId}" \
    -d limit=10
  ```
</CodeGroup>

```json Response theme={null}
{
  "logs": [
    {
      "id": 100,
      "webhook_id": 1,
      "webhook_type": "subscription",
      "event_type": "workflow.completed",
      "event_id": "evt_abc123",
      "target_url": "https://api.example.com/webhooks/elan",
      "status": "delivered",
      "attempts": 1,
      "response_status": 200,
      "error_message": null,
      "created_at": "2025-12-21T10:30:00Z",
      "last_attempt_at": "2025-12-21T10:30:01Z"
    }
  ],
  "total": 45
}
```

***

## List all delivery logs

**`GET /webhooks/logs/all`**

This endpoint returns all webhook delivery logs for your organization, optionally filtered by event type.

### Optional attributes

<ParamField query="event_type" type="string">
  Filter logs by event type.
</ParamField>

<ParamField query="limit" type="integer">
  Maximum number of logs to return (default: 50).
</ParamField>

<ParamField query="offset" type="integer">
  Number of logs to skip for pagination (default: 0).
</ParamField>

<ParamField header="X-Org-Id" type="string">
  Organization identifier (header). If not provided, uses your default organization.
</ParamField>

<CodeGroup>
  ```bash cURL theme={null}
  curl -G https://api.elanlanguages.ai/v1/webhooks/logs/all \
    -H "Authorization: Bearer {token}" \
    -H "X-Org-Id: {orgId}" \
    -d event_type=workflow.completed \
    -d limit=10
  ```
</CodeGroup>

```json Response theme={null}
{
  "logs": [
    {
      "id": 100,
      "webhook_id": 1,
      "webhook_type": "subscription",
      "event_type": "workflow.completed",
      "event_id": "evt_abc123",
      "target_url": "https://api.example.com/webhooks/elan",
      "status": "delivered",
      "attempts": 1,
      "response_status": 200,
      "error_message": null,
      "created_at": "2025-12-21T10:30:00Z",
      "last_attempt_at": "2025-12-21T10:30:01Z"
    }
  ],
  "total": 120
}
```

***

## Test webhook

**`POST /webhooks/:subscription_id/test`**

This endpoint sends a test event to a webhook subscription to verify your configuration. A test `workflow.completed` event will be sent, and the delivery will appear in the subscription's logs.

### Required attributes

<ParamField path="subscription_id" type="integer" required>
  The unique identifier for the webhook subscription to test.
</ParamField>

### Optional attributes

<ParamField header="X-Org-Id" type="string">
  Organization identifier (header). If not provided, uses your default organization.
</ParamField>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.elanlanguages.ai/v1/webhooks/1/test \
    -H "Authorization: Bearer {token}" \
    -H "X-Org-Id: {orgId}"
  ```
</CodeGroup>

```json Response theme={null}
{
  "message": "Test webhook sent successfully",
  "event_id": "evt_test_xyz789"
}
```
