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

# Create Webhook

> Register a new webhook endpoint and receive its signing secret

## Request

### Headers

```
Authorization: Bearer wbk_your_api_key_here
Content-Type: application/json
```

<Note>
  Requires an API key with the `webhooks:write` permission.
</Note>

### Body Parameters

<ParamField body="url" type="string" required>
  HTTPS URL that will receive event deliveries. Must start with `https://`. URLs that resolve to private IP ranges are rejected (SSRF protection).
</ParamField>

<ParamField body="events" type="array" required>
  Array of event type strings to subscribe to. See [Webhooks](/webhooks) for the full list of 28 supported events.
</ParamField>

<ParamField body="description" type="string">
  Optional human-readable description (max 200 chars).
</ParamField>

<ParamField body="active" type="boolean" default="true">
  Whether the webhook should be active immediately. Set to `false` to register but pause deliveries.
</ParamField>

## Response

<Warning>
  **The `secret` field is returned only once — at creation time.** Store it in a secure secret manager immediately. It cannot be retrieved later; if lost, delete and recreate the webhook to rotate.
</Warning>

<ResponseField name="data" type="object">
  <Expandable title="properties">
    <ResponseField name="webhook" type="object">
      <Expandable title="Webhook object">
        <ResponseField name="id" type="string">
          Unique webhook ID (UUID)
        </ResponseField>

        <ResponseField name="url" type="string">
          The HTTPS target URL
        </ResponseField>

        <ResponseField name="events" type="array">
          Subscribed event types
        </ResponseField>

        <ResponseField name="description" type="string">
          Description
        </ResponseField>

        <ResponseField name="active" type="boolean">
          Whether deliveries are enabled
        </ResponseField>

        <ResponseField name="secret" type="string">
          **Returned only on creation.** The signing secret for HMAC-SHA256 verification. Prefixed with `whsec_`.
        </ResponseField>

        <ResponseField name="created_at" type="string">
          ISO 8601 timestamp
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://data.leadlex.com/functions/v1/api-gateway/v1/webhooks \
    -H "Authorization: Bearer wbk_your_api_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "url": "https://example.com/leadlex/webhook",
      "events": ["contact.created", "deal.updated"],
      "description": "Production CRM sync",
      "active": true
    }'
  ```

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

  API_KEY = "wbk_your_api_key_here"
  BASE_URL = "https://data.leadlex.com/functions/v1/api-gateway"

  response = requests.post(
      f"{BASE_URL}/v1/webhooks",
      headers={
          "Authorization": f"Bearer {API_KEY}",
          "Content-Type": "application/json",
      },
      json={
          "url": "https://example.com/leadlex/webhook",
          "events": ["contact.created", "deal.updated"],
          "description": "Production CRM sync",
          "active": True,
      },
  )

  webhook = response.json()["data"]["webhook"]
  print("SAVE THIS SECRET:", webhook["secret"])  # shown ONCE
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    'https://data.leadlex.com/functions/v1/api-gateway/v1/webhooks',
    {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer wbk_your_api_key_here',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        url: 'https://example.com/leadlex/webhook',
        events: ['contact.created', 'deal.updated'],
        description: 'Production CRM sync',
        active: true,
      }),
    }
  );
  const { data } = await response.json();
  console.log('SAVE THIS SECRET:', data.webhook.secret); // shown ONCE
  ```
</CodeGroup>

### Example Response

```json theme={null}
{
  "data": {
    "webhook": {
      "id": "7f3c4d2a-1b8e-4a9c-9d6f-2e5b8c7a1f3d",
      "url": "https://example.com/leadlex/webhook",
      "events": ["contact.created", "deal.updated"],
      "description": "Production CRM sync",
      "active": true,
      "secret": "whsec_9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f",
      "created_at": "2026-04-17T14:23:05Z"
    }
  }
}
```

## Errors

| Status | Code                       | Description                                                       |
| ------ | -------------------------- | ----------------------------------------------------------------- |
| 400    | `invalid_url`              | URL is not HTTPS, is malformed, or resolves to a private IP range |
| 400    | `invalid_events`           | One or more event names are not recognized                        |
| 400    | `missing_required_field`   | `url` or `events` is missing                                      |
| 401    | `invalid_key`              | Invalid or expired API key                                        |
| 403    | `insufficient_permissions` | Missing `webhooks:write` permission                               |
| 409    | `duplicate_webhook`        | A webhook with this URL already exists                            |
| 429    | `rate_limited`             | Rate limit exceeded                                               |
