---
title: "Get a webhook"
method: GET
path: "/webhooks/{id}"
tags: ["Webhooks"]
---

# Get a webhook

`GET /webhooks/{id}`

## Request

- Base URL: `https://optionsbell.com/api/v1`
- URL: `https://optionsbell.com/api/v1/webhooks/{id}`
- Auth: API key in header `X-API-Key`

One webhook, including its pause state and delivery timestamps. Never includes the secret.

## Response `200`

The webhook

- Webhook: A registered webhook. Never carries the signing secret.
  - `id` string, required
  - `name` string, required
  - `url` string, uri, required
  - `tickers` string[], required: Upper-cased, de-duplicated. Max 150.
  - `criteria` WebhookCriteria, required: Optional contract filters on top of the always-on base floor (Vol/OI >= 1.5, OI >= 100, premium >= $25,000). `null` (or 0) means no extra constraint. In responses `type` is `c`, `p` or `all`; in requests `call`/`calls` and `put`/`puts` are accepted as well.
    - `type` 'c' | 'p' | 'all': Calls only, puts only, or both.
    - `min_voloi` number, nullable: Vol/OI ratio floor.
    - `min_premium` number, nullable: Estimated premium floor in USD (last_price * volume * 100).
    - `min_iv` number, nullable: Implied volatility floor in percent (60 = 60%).
    - `max_dte` integer, nullable: Max days to expiration (floats are floored).
    - `min_volume` number, nullable: Contract volume floor.
    - `min_oi` number, nullable: Open interest floor.
  - `notify_interval_min` 10 | 30 | 60 | 240 | 480 | 1440, required: Minimum minutes between two deliveries.
  - `active_hours` object, required: Daily window in which the webhook is evaluated, `HH:MM` 24h in America/New_York. `end` is exclusive; a window may wrap past midnight (e.g. 20:00 -> 04:00). `start` equal to `end` never fires.
    - `start` string, required
    - `end` string, required
    - `timezone` 'America/New_York'
  - `is_active` boolean, required: false: not evaluated at all (set via PATCH).
  - `paused_at` string, date-time, nullable, required: Set when the webhook was paused after 20 consecutive failed deliveries; null otherwise. Paused webhooks are still evaluated but not delivered to.
  - `consecutive_failures` integer, required: Failed `unusual_activity` deliveries in a row; reset to 0 by any successful delivery, a successful test, or a PATCH with `url` / `is_active: true`.
  - `last_run_at` string, date-time, nullable, required: Last evaluation (UTC), whether or not anything was delivered.
  - `last_delivered_at` string, date-time, nullable, required: Last successful `unusual_activity` delivery (UTC). The cooldown (`notify_interval_min`) counts from here.
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required

## Other responses

- `401`: Missing or invalid API key: `MISSING_API_KEY`, `INVALID_API_KEY_FORMAT`, `INVALID_API_KEY`. No rate-limit headers.
- `403`: Key is valid but has no usable subscription: `NO_ACTIVE_SUBSCRIPTION` (no Personal plan on the key) or `SUBSCRIPTION_INACTIVE` (past due, paused, expired, or canceled past its period end). No rate-limit headers.
- `404`: `NOT_FOUND`: no webhook with this id on your subscription (app-created alerts are not reachable through this API).
- `429`: Rate limit exceeded: `RATE_LIMIT_MINUTE` (60/min) or `RATE_LIMIT_DAY` (4,000/day). Carries both rate-limit header sets and `Retry-After` (seconds until the exhausted window opens again). Rejected requests count against the minute window, so back off instead of retrying immediately.
- `500`: Unexpected server error: `INTERNAL_ERROR`. The body and the X-Request-Id header carry the request id.
- `503`: Authentication backend unreachable: `AUTH_UNAVAILABLE`. Retry later. No rate-limit headers.

---

[API](https://skmtc.dev/optionsbell/apis/optionsbell-options-flow-api.md) · [All operations](https://skmtc.dev/optionsbell/apis/optionsbell-options-flow-api/llms.txt) · [OpenAPI document](https://skmtc.dev/optionsbell/apis/optionsbell-options-flow-api/revisions/42db9bcaa61f?raw)
