# POST /v2/signals/{signal}/subscribe

**Subscribe to a signal**

For boolean signals (e.g. `at_52w_high`, `golden_cross`), the predicate is `signal = true` and `condition` is ignored. For numeric signals (e.g. `rsi_14`, `change_1m`), `condition` is required and takes the shape `">70"`, `"<30"`, `">=100"`, `"=50"`. Optionally restrict the scope to a single ticker or a universe.

## Plan access

- **Plan access.** Included on every plan.
- **Cadence.** Hobby 5m · Pro 1m · Scale 1m · Enterprise 1m.
- **Capacity.** Unlimited on every paid plan.

## Body parameters

| Name | In | Type | Required | Description |
|------|----|----|----------|-------------|
| `signal` | path | string | yes | Signal name from the schema (case-insensitive). Example: `at_52w_high`. |
| `condition` | body | string | no | Required for numeric signals; ignored for boolean signals. Shape: `">70"`, `"<30"`, `">=100"`, `"=50"`. |
| `ticker` | body | string | no | Restrict to a single ticker. Default: any ticker. |
| `universe` | body | string | no | Restrict to a system or user-owned universe (e.g. `top_100`). |
| `target_url` | body | string | no | https:// URL to POST when fired. Omit for in-app delivery. |
| `cadence` | body | string | no | Allowed: `1m`, `5m`, `15m`, `hourly`, `nyse_open`. Defaults to plan max. Enum: `1m`, `5m`, `15m`, `hourly`, `nyse_open`. |
| `name` | body | string | no | Human-readable label (up to 80 chars). |

## Status codes

- **200** — Webhook subscription created.
- **400** — `bad_request` — invalid signal name, missing `condition` on a numeric signal, malformed `condition`, etc.
- **403** — `webhook_tier_required`, `webhook_limit_reached`, or `cadence_above_plan_max`.
- **404** — `unknown_signal` — signal does not exist.

## Sample response

```json
{
  "id": "wh_pZk5Mq-h81n",
  "name": "at_52w_high",
  "q": "at_52w_high = true",
  "cadence": "hourly",
  "target_url": "https://example.com/hook",
  "delivery": "webhook",
  "status": "pending_verification",
  "subscription_origin": { "type": "signal", "ref": "at_52w_high", "condition": "at_52w_high" },
  "created_at": 1737580800
}
```

## Examples

### Boolean signal — fire on any 52-week high

Request:

```shell
curl -X POST "https://api.tickerbot.io/v2/signals/at_52w_high/subscribe" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"target_url":"https://example.com/hook","cadence":"hourly"}'
```

Response (`200`):

```json
{
  "id": "wh_pZk5Mq-h81n",
  "name": "at_52w_high",
  "q": "at_52w_high = true",
  "cadence": "hourly",
  "target_url": "https://example.com/hook",
  "delivery": "webhook",
  "status": "pending_verification",
  "subscription_origin": { "type": "signal", "ref": "at_52w_high", "condition": "at_52w_high" },
  "created_at": 1737580800
}
```

### Numeric signal — RSI above 70 on top_100

Request:

```shell
curl -X POST "https://api.tickerbot.io/v2/signals/rsi_14/subscribe" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"condition":">70","universe":"top_100","cadence":"5m"}'
```

Response (`200`):

```json
{
  "id": "wh_aB3cD9-x14m",
  "name": "rsi_14 > 70",
  "q": "rsi_14 > 70",
  "cadence": "5m",
  "subscription_origin": { "type": "signal", "ref": "rsi_14", "condition": "rsi_14 > 70" },
  "created_at": 1737580800
}
```

---

Interactive sandbox + parameter editor: https://tickerbot.io/docs/endpoints/signals/subscribe
