---
title: "Api Screener"
method: GET
path: "/api/screener"
---

# Api Screener

`GET /api/screener`

## Request

- Base URL: `https://www.oxfordledge.com` (the document declares no server; this is the origin it was published from)
- URL: `https://www.oxfordledge.com/api/screener`
- Auth: none declared

Stock screener with in-memory + PG fallback. Soft paywall: free
users get 3-row teaser + `locked: true` so they can see what the
screener does before upgrading (user-panel Marcus deal-breaker).

QA 2026-10-13 P1 (R3): a viewer who may not see vendor prices gets the
price-derived filters and sorts REFUSED, not applied and named in
`filters_not_applied` -- a filter applied on a withheld column answered
range questions about it, which recovers the column. The service ranks that
viewer's rows by ticker, never by market cap (`_price_blind`).

## Response `200`

Successful Response

- ScreenerResponse: `/api/screener` — main stock screener with soft-paywall teaser. F4 boundary backfill 2026-05-08 (Initiative 6). Public (no auth); free users get a 3-row teaser + `locked: true` so they can see the screener works before upgrading. The FE iterates `data.results` with a `|| []` fallback already, so the boundary test pins the presence of the key — not the value.
  - `results` unknown[], required: Filtered stock rows. Empty list when no rows match or in error path. FE iterates with `data.results || []`.
    - unknown
  - `_vendor_prices_withheld` boolean, nullable: OWNER R3 (2026-10-12): true on an anonymous teaser whose vendor-price columns were nulled because OL_PUBLIC_VENDOR_PRICES is off. FE (screener-options.ts) then shows `_price_notice` instead of reading the nulls as zero. Absent otherwise.
  - `_price_notice` string, nullable: The plain-language withheld-price notice that travels with `_vendor_prices_withheld` (services/public_price_gate.py NOTICE_KEY).
  - `price_filters_available` boolean, nullable: QA 2026-10-13 P1: false when this viewer may not see vendor prices, so the price-derived filters (P/E, EV/EBITDA, EBIT/EV, market cap, dividend yield, P/B, near 52-week low) are refused rather than applied. FE disables those inputs.
  - `filters_not_applied` string[], nullable: The requested filter/sort params that were REFUSED and not applied (services/public_price_gate.SCREENER_PRICE_FILTER_KEYS). Absent when nothing was refused.
  - `filters_not_applied_reason` string, nullable: Why `filters_not_applied` were refused: they need market prices, which are shown to signed-in users.
  - `total` integer, nullable: Rows that matched the applied filters before any teaser cap. The FE count reads it as 'N matches'.
  - `universe_size` integer, nullable: Tickers scanned (the snapshot universe plus the viewer's recently viewed tickers).
  - `coverage_note` string, nullable: Plain-language description of the scanned universe.
  - `coverage` object, nullable: {total_checked, passed, filtered_out, applied_filters, post_filters}: which filters shaped the rows. FE banner reads it.
  - `locked` boolean, nullable: True on the free/anonymous teaser: only the first rows are returned and the rest need an upgrade. FE renders the lock row (screener-options.ts _scrLockInfo).
  - `locked_total` integer, nullable: True match count behind a locked teaser, so the lock row and count can say 'N matches (3 shown)'.
  - `upgrade` object, nullable: {message, url} for the lock row's call to action. Present only when `locked` is true.
  - `insider_filter` object, nullable: P0 2026-10-18: present when the request carried insider_days / insider_min_buys / insider_net_positive. {applied, available, days, min_buys, net_positive, window, counting, tickers_matched | message}. `applied` and `available` are both true only when every row passed the Form 4 insider aggregate (rows then carry insiderBuys / insiderSells / insiderNet / insiderNetShares); false with a 503 and no rows when the aggregate could not be read. The FE shows no row under an insider caption unless both are true.

---

[API](https://skmtc.dev/oxfordledge/apis/oxford-ledge-api.md) · [All operations](https://skmtc.dev/oxfordledge/apis/oxford-ledge-api/llms.txt) · [OpenAPI document](https://skmtc.dev/oxfordledge/apis/oxford-ledge-api/revisions/e832a1260f0b?raw)
