# POST /v2/rules

**Create a rule**

Save a scan bundle so it can be re-run with `/v2/scan?rule=` or subscribed to via `/v2/webhooks`. The `universe_id` is optional; if unset, the rule runs against your plan default at execution time.

## Plan access

- **Plan access.** Included on every plan.
- **Rate limit.** Hobby 60/min · Pro 2,000/min · Scale 10,000/min.
- **Capacity.** Hobby 5 · Pro 25 · Scale 100 · Enterprise unlimited.

## Body parameters

| Name | In | Type | Required | Description |
|------|----|----|----------|-------------|
| `id` | body | string | no | Optional slug. |
| `name` | body | string | yes | Human-readable label. |
| `description` | body | string | no | Free-form notes. |
| `q` | body | string | yes | SQL WHERE clause. |
| `universe_id` | body | string | no | Slug of a system or caller-owned universe to scope this rule. |
| `order` | body | string | no | Sort column. Default: `day_change_pct`. |
| `dir` | body | string | no | Sort direction. Enum: `asc`, `desc`. |
| `fields` | body | string[] | no | Extra columns to include. |

## Status codes

- **201** — Rule created.
- **400** — Validation error.
- **402** — `premium_signal_required` when `q`/`order`/`fields` reference a premium signal and the plan does not include premium.
- **403** — `resource_limit_reached` over the plan max.
- **404** — `universe_id` not found.
- **409** — `slug_taken`.

## Sample response

```json
{
  "as_of": "2026-05-14T11:41:01.000Z",
  "id": "smallcap_breakouts",
  "name": "Small-cap breakouts",
  "description": null,
  "q": "breakout AND market_cap < 2000000000",
  "universe_id": null,
  "order": "day_change_pct",
  "dir": "desc",
  "fields": ["pe_ratio"],
  "created_at": 1778720416,
  "updated_at": 1778720416
}
```

## Examples

### Save a small-cap breakouts rule

Request:

```shell
curl -X POST https://api.tickerbot.io/v2/rules \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "smallcap_breakouts",
    "name": "Small-cap breakouts",
    "q": "breakout AND market_cap < 2000000000",
    "order": "day_change_pct",
    "dir": "desc",
    "fields": ["pe_ratio"]
  }'
```

Response (`201`):

```json
{
  "as_of": "2026-05-14T11:41:01.000Z",
  "id": "smallcap_breakouts",
  "name": "Small-cap breakouts",
  "description": null,
  "q": "breakout AND market_cap < 2000000000",
  "universe_id": null,
  "order": "day_change_pct",
  "dir": "desc",
  "fields": ["pe_ratio"],
  "created_at": 1778720416,
  "updated_at": 1778720416
}
```

---

Interactive sandbox + parameter editor: https://tickerbot.io/api/endpoints/rules/create
