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

# Create Webhook

> Register a new webhook to receive real-time event notifications

Register a webhook URL to receive `radar` and/or `signal` events as they occur. Shoal will POST a JSON payload to your URL whenever a matching event is detected.

<Note>
  Webhook creation is available only on plans that include webhook access.
</Note>

## Request Body

| Field         | Type      | Required | Description                                                                     |
| ------------- | --------- | -------- | ------------------------------------------------------------------------------- |
| `url`         | string    | Yes      | HTTPS endpoint to receive events. Must not point to a private/internal address. |
| `event_types` | string\[] | Yes      | Array of event types to subscribe to: `radar`, `signal`, or both.               |

### Request

```bash cURL theme={null}
curl -X POST "https://api.shoal.xyz/v1/webhooks" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/shoal-webhook",
    "event_types": ["radar", "signal"]
  }'
```

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

API_KEY = os.environ.get("SHOAL_API_KEY", "YOUR_API_KEY")

r = requests.post(
    "https://api.shoal.xyz/v1/webhooks",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    },
    json={
        "url": "https://example.com/shoal-webhook",
        "event_types": ["radar", "signal"],
    },
)
print(r.json())
```

```javascript JavaScript theme={null}
const API_KEY = process.env.SHOAL_API_KEY || 'YOUR_API_KEY';

const res = await fetch('https://api.shoal.xyz/v1/webhooks', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    url: 'https://example.com/shoal-webhook',
    event_types: ['radar', 'signal'],
  }),
});
console.log(await res.json());
```

### Response (201)

```json theme={null}
{
  "data": {
    "id": 12,
    "url": "https://example.com/shoal-webhook",
    "secret": "a1b2c3d4e5f6...64-char-hex-string",
    "event_types": ["radar", "signal"],
    "active": true,
    "created_at": "2026-03-10T12:00:00Z"
  }
}
```

<Note>
  Save the `secret` from the response — it is only returned once at creation time. You'll need it to verify webhook signatures. See [Webhook Signatures](/guides/webhooks#verifying-signatures).
</Note>

### Errors

| Status | Error                                          | Cause                                |
| ------ | ---------------------------------------------- | ------------------------------------ |
| 400    | `url` is required                              | Missing URL                          |
| 400    | URL must use HTTPS                             | Non-HTTPS URL                        |
| 400    | URL must not point to a private address        | URL resolves to localhost/private IP |
| 400    | `event_types` must be a non-empty array        | Missing or empty event types         |
| 400    | `event_types` must only contain: radar, signal | Invalid event type                   |
| 400    | Maximum 5 webhooks allowed                     | Per-account webhook limit reached    |
