# Gotchas

Things that have caught real users.

## `BTC` is not bitcoin

Symbols are namespaced by asset class. We don't auto-resolve. Passing `BTC` to a stock endpoint returns the Grayscale Bitcoin Mini Trust ETF, not bitcoin spot. Use `X:BTCUSD` for the crypto. Same for `GOLD` (Barrick Gold equity) vs `CMD:GOLD` (gold spot).

## Crypto has no `session_open` / `session_high` / `session_low`

Markets that never close don't have a session. For crypto, use rolling 24-hour columns instead. Corporate-event flags (`earnings_this_week` and friends) always come back `false` for crypto.

## Edge-triggered flags stay true all session

Flags like `breakout`, `gap_up_3pct`, and `golden_cross_today` flip true the moment the condition is met and stay true for the rest of the trading session even if the underlying condition reverses. They reset at the start of the next session.

## Numeric literals are fully specified

Write `1500000000`, not `1.5B`. Write `0.05` for 5%, not `5` — percentage columns are decimals.

## Cursors are opaque

Don't parse them, don't cache them across deploys. The token bakes in the sort key, page size, and original filters; changing any query parameter mid-walk invalidates it.

## Daily-only signals can't be pulled at 1m or 1h

SMAs, RSI, MACD, fundamentals: daily snapshots only. Request `1d` for any slow-moving signal. Minute-tier columns are price, day_change_pct, gap_pct, volume, relative_volume, day_vwap, and position-from-extremes columns.

## DELETE endpoints return 204 No Content

`DELETE /v2/webhooks/{id}`, `DELETE /v2/universes/{id}`, and `DELETE /v2/rules/{id}` all return `204 No Content` on success. There's no JSON to parse; check the status code.

## `as_of` means different things on different endpoints

On live endpoints, `as_of` is the server time at which the response was assembled. On historical endpoints (`/tickers/{t}/history`, `/scan?asof=`), `as_of` is the date you asked about.

## Canceled subscriptions fall back to a no-feature tier

When a subscription is canceled, the API key keeps working at a fallback tier with no webhook / universe / rule capacity. Read endpoints continue. Mutations return `webhook_tier_required` etc. until you resubscribe.

## System universe slugs are reserved

`top_10` and `top_100` you don't own. You can fetch them; you can't collide with their slugs on POST (`slug_taken`); you can't delete or edit them (`403`).

## Webhook deliveries can fire after delete

Deliveries queued at the moment you call `DELETE` can still fire. They capture the target URL + signing secret at queue time. To pause without this race, stop responding 2xx at your target and the subscription will flip to `disabled`.

## Plan-gated history applies to /scan?asof and /signals/.../history

Both windows are plan-gated and enforced at request time. Hobby reaches one year back, Pro five, Scale and Enterprise all-time. Going past returns `history_window_exceeded` with `earliest_allowed_asof` so your code can clamp.
