# PATCH /v2/webhooks/{id}

**Update a webhook**

Partial update — send only the fields you want to change. Editable: `name`, `cadence`, `target_url`, `enabled`. The trigger itself (`q`/ticker/signal/universe scope) and the `channel` are immutable after creation — to change what fires or where a Discord/mobile subscription delivers, delete and re-subscribe. Changing `target_url` does NOT re-validate the endpoint (no handshake); confirm delivery with `POST /v2/webhooks/{id}/test`. Setting `target_url` to `null` or `""` switches delivery to in-app. `enabled: false` disables the webhook; re-enabling routes through `POST /v2/webhooks/{id}/enable` (which re-checks your plan’s webhook cap), so `enabled: true` on a disabled webhook is a 400 pointing there.

## Plan access

- **Plan access.** Paid plans (Hobby and above).
- **Cadence.** Real-time on every paid plan — evaluated on every data refresh (~1×/min), so a match is delivered within seconds of it landing. Optionally throttle a webhook to hourly or at-market-open.
- **Capacity.** Hobby 10 · Pro 100 · Scale 1,000 · Enterprise unlimited.

## Body parameters

| Name | In | Type | Required | Description |
|------|----|----|----------|-------------|
| `id` | path | string | yes | Webhook id. Example: `wh_smRsF3-z36o`. |
| `name` | body | string | no | New display name. Non-empty, max 80 characters. |
| `cadence` | body | string | no | Evaluation cadence. Ungated user preference on every plan. Enum: `realtime`, `hourly`, `nyse_open`. |
| `target_url` | body | string | no | New https:// delivery URL (webhook channel only — a Discord/mobile subscription 400s here). `null` or empty switches to in-app delivery and re-activates a URL-less record. |
| `enabled` | body | boolean | no | `false` disables the webhook (status → `disabled`). `true` is a no-op unless disabled, in which case use `POST /v2/webhooks/{id}/enable` instead. |

## Status codes

- **200** — The updated webhook record (`signing_secret` stripped). An empty patch body returns the current record unchanged.
- **400** — Invalid id format, bad field value, `target_url` on a non-webhook channel, or `enabled: true` on a disabled webhook.
- **404** — Webhook not found, or owned by another account.

## Sample response

```json
{
  "as_of": "2026-07-27T14:02:11.000Z",
  "id": "wh_smRsF3-z36o",
  "name": "NVDA · gap_up AND high_volume_alert",
  "q": "ticker = 'NVDA' AND (gap_up AND high_volume_alert)",
  "cadence": "realtime",
  "target_url": "https://your-app.example.com/hooks/tickerbot-v2",
  "delivery": "webhook",
  "status": "active",
  "created_at": 1778720416,
  "updated_at": 1785160931
}
```

## Examples

### Re-point the delivery URL

Request:

```shell
curl -X PATCH "https://api.tickerbot.io/v2/webhooks/wh_smRsF3-z36o" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"target_url":"https://your-app.example.com/hooks/tickerbot-v2"}'
```

Response (`200`):

```json
{
  "as_of": "2026-07-27T14:02:11.000Z",
  "id": "wh_smRsF3-z36o",
  "name": "NVDA · gap_up AND high_volume_alert",
  "q": "ticker = 'NVDA' AND (gap_up AND high_volume_alert)",
  "cadence": "realtime",
  "target_url": "https://your-app.example.com/hooks/tickerbot-v2",
  "delivery": "webhook",
  "status": "active",
  "created_at": 1778720416,
  "updated_at": 1785160931
}
```

## Notes

- After changing `target_url`, fire `POST /v2/webhooks/{id}/test` to verify the new endpoint receives and verifies a signed delivery.

---

Interactive sandbox + parameter editor: https://tickerbot.io/docs/endpoints/webhooks/update
