---
title: "Per-symbol unusual activity"
method: GET
path: "/options-flow/{symbol}"
tags: ["Unusual Activity"]
---

# Per-symbol unusual activity

`GET /options-flow/{symbol}`

## Request

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

Every contract on a single ticker that passed the unusual filter,
ranked by score (`volume_oi_ratio * ln(premium_estimate + 1)`
descending, then `data_date, symbol, option_symbol`). Same filters,
paging and freshness rules as `/options-flow/unusual`; `symbols` is
ignored here.

Default scope is the latest scan day that has data for this symbol.
`date`, `date_from` / `date_to` take precedence. Unlike `/unusual`,
`since` on its own is not combined with a day scope - it selects
matching rows across all days.

## Path parameters

- `symbol` string, required

## Query parameters

- `date` string, date
- `date_from` string, date
- `date_to` string, date
- `since` string, date-time
- `type` 'c' | 'p' | 'all' | 'call' | 'calls' | 'put' | 'puts'
- `min_voloi` number
- `min_premium` number
- `min_iv` number
- `max_dte` integer
- `min_volume` number
- `min_oi` number
- `raw` boolean
- `limit` integer
- `offset` integer

## Response `200`

Contracts for the symbol

- object
  - `symbol` string, required
  - `date` string, date, nullable, required: Resolved scan day; null in range / since mode or when the symbol has no data.
  - `date_from` string, date, nullable, required
  - `date_to` string, date, nullable, required
  - `since` string, date-time, nullable, required
  - `count` integer, required
  - `limit` integer, required
  - `offset` integer, required
  - `filtered_total` integer, required
  - `has_more` boolean, required
  - `sort` 'score_desc,symbol,option_symbol', required
  - `data` UnusualContract[], required
    - `symbol` string
    - `option_symbol` string
    - `symbol_type` 'Call' | 'Put'
    - `base_last_price` string: Numeric string. Underlying price.
    - `strike_price` string: Numeric string.
    - `expiration_date` string: Expiration date as stored by the data source.
    - `days_to_expiration` integer, nullable: Calendar days from data_date to expiration_date, computed by the API (not trading days, no holiday adjustment). Authoritative for max_dte and the /expiry buckets.
    - `last_price` string: Numeric string.
    - `bid_price` string: Numeric string.
    - `midpoint` string: Numeric string.
    - `ask_price` string: Numeric string.
    - `volume` string: Numeric string.
    - `open_interest` string: Numeric string.
    - `volume_oi_ratio` string: Numeric string.
    - `volatility` string: Numeric string. Implied volatility in percent (25.43 = 25.43%).
    - `delta` string: Numeric string.
    - `trade_time` string: Last trade time as stored by the data source.
    - `data_date` string, date: Trading day, YYYY-MM-DD.
    - `first_seen_at` string, date-time, nullable: First 5-minute scan that listed the contract (UTC); null when no intraday appearance was recorded.
    - `last_seen_at` string, date-time, nullable: Most recent regular-session scan that listed the contract (UTC).
    - `sector` string, nullable
    - `industry` string, nullable
    - `premium_estimate` string: Numeric string. last_price * volume * 100, USD, rounded.
    - `is_sweep_like` boolean, nullable: EOD proxy for sweep-quality prints: Vol/OI >= 5, OI >= 100, volume >= 1000, DTE 0-60, premium >= $250k. Null when an input is missing.

## Other responses

- `400`: Invalid input: `INVALID_SYMBOL`, `INVALID_DATE`, `INVALID_DATE_RANGE`, `INVALID_SINCE`, `INVALID_PARAM`.
- `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.
- `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)
