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

# Create Webhook Subscription

> Register a webhook endpoint and generate a signing secret.

## Method

`POST` `/v1/webhooks/subscriptions`

## Headers

<ParamField header="Authorization" type="string">Bearer token (requires `webhooks:write`).</ParamField>
<ParamField header="content-type" type="string">`application/json`</ParamField>

## Body Parameters

<ParamField name="url" type="string" required>HTTPS endpoint that receives events.</ParamField>
<ParamField name="events" type="array" required>Array of event keys (`product.created`, `booking.*`, `*`). Must include at least one value.</ParamField>
<ParamField name="maxRetries" type="integer">Maximum retry attempts (0–10). Defaults to 5.</ParamField>
<ParamField name="headers" type="object">Optional custom headers (string key/value pairs) stored with the subscription.</ParamField>
<ParamField name="description" type="string">Optional description shown in dashboards.</ParamField>

## Request Example

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://api.voyantcloud.com/v1/webhooks/subscriptions" \
    -H "Authorization: Bearer $VOYANT_API_KEY" \
    -H "content-type: application/json" \
    -d '{
      "url": "https://example.com/webhooks/voyant",
      "events": ["product.*", "booking.created"],
      "headers": {"X-Env": "production"},
      "maxRetries": 5,
      "description": "Primary catalog listener"
    }'
  ```

  ```javascript Node.js theme={null}
  const payload = {
    url: "https://example.com/webhooks/voyant",
    events: ["*"],
    maxRetries: 3,
  }

  const res = await fetch("https://api.voyantcloud.com/v1/webhooks/subscriptions", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.VOYANT_API_KEY}`,
      "content-type": "application/json",
    },
    body: JSON.stringify(payload),
  })
  const { data } = await res.json()
  // Store data.secret securely; it will not be returned again
  ```

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

  payload = {
    "url": "https://example.com/webhooks/voyant",
    "events": ["booking.*"],
    "maxRetries": 4
  }

  resp = requests.post(
    "https://api.voyantcloud.com/v1/webhooks/subscriptions",
    headers={
      "Authorization": f"Bearer {os.environ['VOYANT_API_KEY']}",
      "content-type": "application/json",
    },
    json=payload,
  )
  subscription = resp.json()["data"]
  ```
</RequestExample>

## Response Example

<ResponseExample>
  ```json 201 Created theme={null}
  {
    "data": {
      "subscription": {
        "id": "whsub_01J0J3Y3TFX2V22Y7DQ0A6J5G5",
        "workspace_id": "ws_4a82d5bd-3330-4ad3-bf46-1b6a9a5d5d6a",
        "url": "https://example.com/webhooks/voyant",
        "events": ["product.*", "booking.created"],
        "active": true,
        "max_retries": 5,
        "headers": {"X-Env": "production"},
        "description": "Primary catalog listener",
        "created_at": "2025-03-01T09:12:33.000Z",
        "updated_at": "2025-03-01T09:12:33.000Z",
        "last_delivery_at": null,
        "failure_count": 0
      },
      "secret": "f8c6d3fc4c7103f9a8043f08ff9347bd0f52d23941e874a28ea844e5a27a0ce2"
    }
  }
  ```
</ResponseExample>

<Warning>
  Voyant returns the generated secret only once. Store it immediately and delete it from logs. Subsequent GET requests do not expose the secret.
</Warning>
