# Create a webhook endpoint

URL: https://docs.fxapis.com/api-reference/webhooks/create-a-webhook-endpoint

> Create a webhook endpoint. Events are POSTed to url as JSON — { id, type, createdAt, data } — signed in the fxapis-signature header with the returned secret.

`POST https://api.fxapis.com/v1/webhooks`

Events are POSTed to `url` as JSON — `{ id, type, createdAt, data }` — signed in the `fxapis-signature` header with the returned `secret`. **The secret is returned once**, here. Retried for about 45 hours on failure; switched off after 20 failures in a row. Up to 10 endpoints per workspace.

Authentication: `Authorization: Bearer <API key>`.

#### Request body (application/json, required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `url` | string | yes | HTTPS on port 443, a public host, no credentials. Example: `"https://example.com/fxapis/webhooks"` |
| `events` | "order.filled" \| "order.rejected" \| "order.unresolved" \| "order.resolved" \| "order.cancelled" \| "position.opened" \| "position.closed" \| "account.state_changed" \| "wave.settled"[] | no | The events this endpoint receives. Empty means every event. |
| `description` | string \| null | no |  |

#### Responses

- `201`
- `400`
- `401`
- `402`
- `403`
- `404`
- `409`

Failures return `{ "error": { "code", "message" } }`; every code is listed at https://docs.fxapis.com/errors.

#### 201 response fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `data` | object | no |  |
| `data.id` | string (uuid) | no |  |
| `data.url` | string | no | Example: `"https://example.com/fxapis/webhooks"` |
| `data.description` | null \| string | no | Example: `"Copier"` |
| `data.events` | "order.filled" \| "order.rejected" \| "order.unresolved" \| "order.resolved" \| "order.cancelled" \| "position.opened" \| "position.closed" \| "account.state_changed" \| "wave.settled"[] | no | The events this endpoint receives. Empty means every event. |
| `data.enabled` | boolean | no | Whether events are being sent. False when you disabled it, or when we did after 20 failed deliveries in a row — see `disabledReason`. |
| `data.disabledAt` | null \| string (date-time) | no | When we switched it off for failing. Null when you disabled it yourself. |
| `data.disabledReason` | null \| string | no | Example: `"20 deliveries in a row failed"` |
| `data.consecutiveFailures` | integer | no | Failed deliveries since the last success. |
| `data.secretHint` | null \| string | no | The signing secret's last characters, to tell secrets apart. Example: `"whsec_…Qx4w"` |
| `data.previousSecretExpiresAt` | null \| string (date-time) | no | After a rotation, deliveries are signed with the old secret too until this time. |
| `data.createdAt` | string (date-time) | no |  |
| `data.updatedAt` | string (date-time) | no |  |
| `data.secret` | string | no | Verifies the `fxapis-signature` header on every delivery. Shown here and never again; lost or leaked, rotate it. Example: `"whsec_3q2-7ZkT0d8m1sQe9yVbW4nX6pLr5aHcUgJf0oKxQx4w"` |