# GET /v2/signals

**List signals catalog**

Returns the unified signal catalog: every built-in column on the live schema (tagged `kind: 'builtin'`, carrying `name`, `type`, `source`) plus the caller's own custom signals (tagged `kind: 'expression'`, carrying `name`, `description`, `expr`, `created_at`, `updated_at`).

Pagination applies only to the custom-signal slice — built-ins are returned in their entirety on every page since they're a small fixed set.

## Plan access

- **Plan access.** Included on every plan, Hobby through Enterprise.
- **Rate limit.** Hobby 600/min · Pro 2,000/min · Scale 10,000/min.
- **Universe.** All ~12,000 tracked tickers on every plan.

## Query / path parameters

| Name | In | Type | Required | Description |
|------|----|----|----------|-------------|
| `kind` | query | string | no | Filter by kind. Omit to return both. Enum: `builtin`, `custom`. |
| `limit` | query | integer | no | Page size for the custom-signal slice. Max 200. Default: `50`. |
| `cursor` | query | string | no | Opaque cursor from a prior response. |

## Status codes

- **200** — `{ as_of, count_builtin, count_custom, next_cursor, signals: [...] }`. Custom signals come first in the array, then built-ins.
- **400** — `bad_request` — invalid `kind` value or malformed cursor.

## Sample response

```json
{
  "as_of": "2026-05-30T18:55:00.000Z",
  "count_builtin": 119,
  "count_custom": 1,
  "next_cursor": null,
  "signals": [
    {
      "name": "rsi_oversold_with_volume",
      "kind": "expression",
      "description": "RSI < 30 confirmed by a 2x relative-volume burst.",
      "expr": "rsi_14 < 30 AND volume_ratio_20d > 2",
      "created_at": 1779389700,
      "updated_at": 1779389700
    },
    { "name": "above_sma_50",    "kind": "builtin", "type": "boolean", "source": "state" },
    { "name": "at_52w_high",     "kind": "builtin", "type": "boolean", "source": "state" },
    { "name": "market_cap",      "kind": "builtin", "type": "numeric", "source": "ticker" },
    { "name": "rsi_14",          "kind": "builtin", "type": "numeric", "source": "state" }
  ]
}
```

## Examples

### Catalog with one custom signal and (truncated) built-ins

Request:

```shell
curl "https://api.tickerbot.io/v2/signals" \
  -H "Authorization: Bearer YOUR_KEY"
```

Response (`200`):

```json
{
  "as_of": "2026-05-30T18:55:00.000Z",
  "count_builtin": 119,
  "count_custom": 1,
  "next_cursor": null,
  "signals": [
    {
      "name": "rsi_oversold_with_volume",
      "kind": "expression",
      "description": "RSI < 30 confirmed by a 2x relative-volume burst.",
      "expr": "rsi_14 < 30 AND volume_ratio_20d > 2",
      "created_at": 1779389700,
      "updated_at": 1779389700
    },
    { "name": "above_sma_50",    "kind": "builtin", "type": "boolean", "source": "state" },
    { "name": "at_52w_high",     "kind": "builtin", "type": "boolean", "source": "state" },
    { "name": "market_cap",      "kind": "builtin", "type": "numeric", "source": "ticker" },
    { "name": "rsi_14",          "kind": "builtin", "type": "numeric", "source": "state" }
  ]
}
```

## Notes

- Built-in rows carry only `name` + `type` + `source` — descriptions live in the Signal Reference on the docs site, layered client-side.
- Custom signals are private and keyed on `(user_id, name)`. Different users may use the same name for different signals.

---

Interactive sandbox + parameter editor: https://tickerbot.io/api/endpoints/signals/catalog
