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

# Create a webhook

> Register a URL to receive signed event notifications.

export const Notice = ({kind = "note", title, children}) => {
  const kinds = {
    warning: {
      label: "User notice",
      icon: <>
          <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" />
          <path d="M12 9v4" />
          <path d="M12 17h.01" />
        </>
    },
    gotcha: {
      label: "Gotcha",
      icon: <>
          <circle cx="12" cy="12" r="10" />
          <path d="M12 16v-4" />
          <path d="M12 8h.01" />
        </>
    },
    note: {
      label: "Note",
      icon: <>
          <circle cx="12" cy="12" r="10" />
          <path d="M12 16v-4" />
          <path d="M12 8h.01" />
        </>
    }
  };
  const k = kinds[kind];
  return <div className="notice my-6 rounded-xl border border-zinc-200 bg-white p-5 dark:border-zinc-800 dark:bg-zinc-950">
      <div className={`${kind === "warning" ? "not-prose flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wide text-red-400/80 dark:text-red-400/70" : kind === "gotcha" ? "not-prose flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wide text-amber-500/80 dark:text-amber-400/70" : "not-prose flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wide text-zinc-400 dark:text-zinc-500"}`}>
        <svg className="h-3.5 w-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
          {k.icon}
        </svg>
        {k.label}
      </div>
      {title && <div className="not-prose mt-2 text-base font-semibold text-zinc-900 dark:text-zinc-100">{title}</div>}
      <div className="notice-body mt-3 text-sm leading-6 text-zinc-700 dark:text-zinc-300">{children}</div>
    </div>;
};

Registers a [webhook](/agents-api/webhooks/overview) for your organization. The response includes the signing `secret`. This is the only time it is returned, so store it securely.

**Returns** `201` with the created webhook object plus its `secret`.

<Notice kind="warning" title="Save the secret now">
  The `secret` is returned once and cannot be retrieved later. To replace it, use [Rotate](/agents-api/webhooks/rotate).
</Notice>

***

## Request body

<ParamField body="url" type="string" required>
  Target URL for deliveries. Must be `https://` and publicly reachable: the platform sends a `HEAD` request at creation time and rejects the webhook if the endpoint cannot be reached. Any HTTP status counts as reachable. Your endpoint does not need to accept `HEAD`.
</ParamField>

<ParamField body="enabled_events" type="string[]" default={["*"]}>
  Event types delivered to this webhook. `"*"` subscribes to the `session.status_updated` firehose. Granular `session.*` types are delivered only when listed explicitly. See the [event catalog](/agents-api/webhooks/events) for supported types.
</ParamField>

<ParamField body="description" type="string">
  Optional label for the webhook (max 255 characters).
</ParamField>

***

## Examples

<CodeGroup>
  ```bash cURL theme={"system"}
  curl -X POST https://agp.eu.hcompany.ai/api/v2/webhooks \
    -H "Authorization: Bearer $HAI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url": "https://example.com/hooks/h",
      "enabled_events": ["session.status_updated"],
      "description": "Production listener"
    }'
  ```

  ```python Python theme={"system"}
  from hai_agents import Client

  client = Client()

  webhook = client.webhooks.create_webhook(
      url="https://example.com/hooks/h",
      enabled_events=["session.status_updated"],
      description="Production listener",
  )
  print(webhook.secret)  # shown only once; store it securely
  ```

  ```typescript TypeScript theme={"system"}
  import { HaiAgentsClient } from "hai-agents";

  const client = new HaiAgentsClient();

  const webhook = await client.webhooks.createWebhook({
    url: "https://example.com/hooks/h",
    enabledEvents: ["session.status_updated"],
    description: "Production listener",
  });
  console.log(webhook.secret); // shown only once; store it securely
  ```
</CodeGroup>

```json Response theme={"system"}
{
  "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "url": "https://example.com/hooks/h",
  "enabled_events": ["session.status_updated"],
  "description": "Production listener",
  "disabled": false,
  "last_delivery_status": null,
  "last_delivery_error": null,
  "last_delivery_at": null,
  "last_success_at": null,
  "consecutive_failures": 0,
  "created_at": "2026-06-11T15:04:05Z",
  "updated_at": "2026-06-11T15:04:05Z",
  "secret": "whsec_k3TQyhq2mPv8WdJ4cN7xLbR9sF1aZ6uE0gYoHiC5jXw"
}
```

***

## Errors

| Status | Cause                                                                                                                    |
| ------ | ------------------------------------------------------------------------------------------------------------------------ |
| `400`  | Organization webhook limit reached (10), URL does not resolve to a public address, or the endpoint could not be reached. |
| `422`  | Body failed validation: non-`https` URL, empty or unknown `enabled_events`.                                              |
