# Public Screener API (AI Scans)

Open, read-only API over the screener tables (stock metrics + corporate announcements).
No login, no key. Served by the Go hft service; meant for the draamview.com "AI Scans" pages,
Claude, and MCP clients.

- **Base URL:** `https://hft.draamview.com/api/public/v1`
- **Methods:** `GET` only. CORS open (`*`).
- **Rate limit:** 60 requests per minute per IP. Over the limit → `429` with `Retry-After` (seconds).
- **Caching:** responses send `Cache-Control: public, max-age=60`. Data refreshes hourly in
  market hours (prices, returns, technicals, valuation) and daily (financials, holdings, scores).
- **Errors:** non-2xx bodies are `{"status": "error", "message": "<plain english>"}`.
  `400` bad parameter · `404` unknown stock · `429` rate limited · `503` data store unavailable.
- **Nulls:** any metric can be `null` (not reported for that stock). Sorting puts nulls last.
- **Coverage:** about 6,700 NSE and BSE stocks, each listed once (NSE symbol when it has one).
  Announcements cover the current quarter only (from its first day).

## For AI assistants: answering a question

1. Map the question to columns. The column table at the end of this guide (and `/screener/meta`)
   gives every `key`, its unit and meaning. Industries are exact names from `/screener/meta`
   (e.g. banks are `Private Banks`, `PSU Banks`, `Small Finance Banks`, `Payments Banks`).
2. Build one `/screener/stocks` URL: filters as `<column>_min` / `<column>_max`, a `sort` and a
   `view` that shows the columns you filtered on (or `view=all`). URL-encode spaces as `%20`.
3. Read `total` to say how many stocks matched; fetch at most a page or two (`limit` up to 200).
4. Name stocks as `name (EXCHANGE:SYMBOL)`, give units (₹ crore, %), say which values are
   `null`, and quote `last_synced`. This is research data, not investment advice.
5. If your fetch tool only opens URLs already in the conversation, use the recipe URLs below
   (change only the numbers), or show the user the URL you built and ask them to paste it back.

Sanity checks before you present results:
- Very small companies (market cap under ~₹500 crore) often have extreme or one-off ratios
  (ROE 600%, P/E 0.4, net margin over 100%). Add `market_cap_cr_min=500` (or higher) to
  quality scans unless the user asks for micro caps.
- A negative `debt_to_equity` means losses have wiped out shareholders' equity (and ROE is then
  meaningless), so pair every "low debt" filter with `debt_to_equity_min=0`.
- A promoter holding change of tens of percentage points is usually a takeover or a
  reclassification, not promoters buying shares in the market.
- A stock can exist with every metric `null` (announcements only, data not synced yet).

## Market-cap size buckets

SEBI defines size by rank on full market cap: **large cap** = top 100, **mid cap** = 101–250,
**small cap** = 251 and below. Read the live cut-offs from the ranking itself:

- 100th largest: `/screener/stocks?sort=market_cap_cr&limit=1&offset=99` (≈ ₹1,08,000 crore in October 2026)
- 250th largest: `/screener/stocks?sort=market_cap_cr&limit=1&offset=249` (≈ ₹36,000 crore in October 2026)

So "small caps" ≈ `market_cap_cr_max=36000`, "mid caps" ≈ `market_cap_cr_min=36000&market_cap_cr_max=108000`,
"large caps" ≈ `market_cap_cr_min=108000`. Below ~₹500 crore is usually called micro cap.

## Recipes

Paths are relative to the base URL. Every one of these returns results today.

| question | URL |
|---|---|
| Look up a stock by name | `/screener/stocks?q=infosys&limit=5` → then `/screener/stocks/NSE/INFY` |
| Profitable small caps, ROE > 20%, debt/equity < 0.5 | `/screener/stocks?view=valuation&market_cap_cr_min=500&market_cap_cr_max=36000&roe_pct_min=20&debt_to_equity_min=0&debt_to_equity_max=0.5&npm_pct_min=0&sort=roe_pct&limit=20` |
| Banks with the best 1-year return | `/screener/stocks?view=performance&industry=Private%20Banks&industry=PSU%20Banks&industry=Small%20Finance%20Banks&sort=returns_1y_pct&limit=20` |
| Near the 52-week high with strong 3-month momentum | `/screener/stocks?view=performance&high_52w_distance_pct_max=5&returns_3m_pct_min=20&market_cap_cr_min=1000&sort=returns_3m_pct&limit=20` |
| Promoters increased their holding over the last year | `/screener/stocks?view=holdings&promoter_holding_chg_1y_min=0.01&market_cap_cr_min=1000&sort=promoter_holding_chg_1y&limit=20` |
| Compare two stocks (e.g. TCS vs Infosys) | `/screener/stocks/NSE/TCS` and `/screener/stocks/NSE/INFY` (every metric each) |
| An industry's peers on growth | `/screener/stocks?view=growth&industry=IT%20Services&sort=market_cap_cr&limit=10` |
| Cheapest profitable large caps | `/screener/stocks?view=valuation&market_cap_cr_min=108000&pe_min=0.01&sort=pe&order=asc&limit=20` |
| Highest-rated stocks | `/screener/stocks?view=scores&score_status=outperforming&sort=score&limit=20` |
| Today's board meeting announcements | `/screener/announcements?q=board%20meeting&from=2026-10-07&to=2026-10-07&limit=100` (use today's date) |
| Latest filing date | `/screener/announcements?limit=1` → its `announced_on` |
| One company's filings | `/screener/announcements?exchange=NSE&symbol=TCS` |

"Profitable" = `npm_pct_min=0` (positive net margin); `pe` is `null` for loss-makers, so
`pe_min=0.01` also keeps only profitable companies. "Fell from its high" = a large
`high_52w_distance_pct`.

**Searching announcements.** `q` is one case-insensitive phrase matched inside the title or
description (not separate words), so use a distinctive phrase: `board meeting`,
`outcome of board meeting`, `financial result`, `dividend`, `record date`, `credit rating`,
`acquisition`, `allotment`, `press release`, `investor meet`, `resignation`, `appointment`,
`buy back`, `rights issue`, `split`, `bonus`, `trading window`. Avoid short fragments
(`AGM` also matches "manAGeMent"). `announced_on` is the Indian (IST) date; if "today" has
nothing yet (early morning), use the latest `announced_on` and say so.

## Units

Every column in `/screener/meta` carries a `unit`:

| unit | meaning | example |
|---|---|---|
| `inr` | rupees | close_price `1207.7` = ₹1,207.70 |
| `inr_cr` | ₹ crore | market_cap_cr `1634324` = ₹16.3 lakh crore |
| `pct` | percent | returns_1y_pct `-12.79` = −12.79% |
| `pp` | percentage points | promoter_holding_chg_1y `0.41` = +0.41 pp |
| `ratio` | plain ratio (×) | pe `21.87` |
| `index` | 0–100 indicator | rsi_14d `42.3` |
| `score` | 0–100 score | score `100` |
| `text` | string | industry, score_status |

## Endpoints

### `GET /screener/meta`

Everything a client needs to render or query the screener: views (column groups), the column
catalogue with plain-English descriptions, industries with stock counts, and freshness.

```json
{
  "views": [
    {"id": "overview", "label": "Overview", "description": "Price, size, valuation and growth at a glance.",
     "columns": ["close_price", "market_cap_cr", "returns_1d_pct", "pe", "revenue_cr", "revenue_growth_ttm_pct", "pat_growth_ttm_pct", "score"]}
  ],
  "groups": [{"id": "valuation", "label": "Valuation"}],
  "columns": [
    {"key": "pe", "label": "P/E", "unit": "ratio", "group": "valuation", "change": false,
     "description": "Share price divided by yearly earnings per share. Lower can mean cheaper, but compare within the same industry."}
  ],
  "industries": [{"name": "Refineries", "count": 12}],
  "total_stocks": 6714,
  "last_synced": {"market": "2026-10-08T10:15:02Z", "fundamentals": "2026-10-07T12:40:11Z"}
}
```

View ids: `overview`, `performance`, `technical`, `valuation`, `growth`, `financials`,
`holdings`, `scores`. Each column's `group` is a `groups` id. `change` is `true` for moves
whose sign is good or bad news (returns, growth, holding changes, score change) and `false`
for levels (ROE, margins, holdings, `high_52w_distance_pct`, which is positive: 25 means 25%
below the 52-week high). `last_synced` values are RFC 3339 UTC or `null`.

### `GET /screener/stocks`

Lists stocks with one view's columns. All query parameters are optional.

| param | default | meaning |
|---|---|---|
| `view` | `overview` | a view id, or `all` for every column |
| `q` | – | case-insensitive match inside symbol or company name (`q=hdfc` finds every HDFC company; results follow `sort`, so the biggest comes first) |
| `industry` | – | industry name from `/screener/meta` (any case). Repeat for several: `industry=Private%20Banks&industry=PSU%20Banks`. Unknown name → `400` |
| `exchange` | – | `NSE` or `BSE` |
| `sort` | `market_cap_cr` | `name`, or any numeric column key (not `industry` / `score_status`) |
| `order` | `desc` | `asc` or `desc` |
| `limit` | `50` | 1–200 |
| `offset` | `0` | rows to skip |
| `<column>_min` / `<column>_max` | – | inclusive bounds on any numeric column, e.g. `pe_max=15&roe_pct_min=20` |
| `score_status` | – | exact value: `outperforming` (strongest), `accumulating`, `consolidating` or `underperforming` (weakest) |

```json
{
  "view": "overview",
  "columns": ["close_price", "market_cap_cr", "..."],
  "total": 6714,
  "limit": 50,
  "offset": 0,
  "items": [
    {"exchange": "NSE", "symbol": "RELIANCE", "name": "Reliance Industries Ltd", "industry": "Refineries",
     "close_price": 1207.7, "market_cap_cr": 1634324.25, "returns_1d_pct": -0.85, "pe": 21.87, "...": "..."}
  ],
  "last_synced": {"market": "2026-10-08T10:15:02Z", "fundamentals": "2026-10-07T12:40:11Z"}
}
```

Every item always has `exchange`, `symbol`, `name`, `industry` plus the view's `columns`.

### `GET /screener/stocks/{exchange}/{symbol}`

One stock with every metric and its 20 latest announcements. `exchange` is `NSE` or `BSE`,
case-insensitive. Unknown stock → `404`.

```json
{
  "stock": {
    "exchange": "NSE", "symbol": "RELIANCE", "name": "Reliance Industries Ltd", "industry": "Refineries",
    "metrics": {"close_price": 1207.7, "market_cap_cr": 1634324.25, "pe": 21.87, "score_status": "outperforming", "...": "..."},
    "market_synced_at": "2026-10-08T10:15:02Z",
    "fundamentals_synced_at": "2026-10-07T12:40:11Z"
  },
  "announcements": [ /* same shape as /screener/announcements items */ ]
}
```

`metrics` holds every column key from `/screener/meta`.

### `GET /screener/announcements`

Corporate announcements across all stocks, newest first.

| param | default | meaning |
|---|---|---|
| `q` | – | one case-insensitive phrase matched inside the title or description (see Recipes) |
| `exchange` + `symbol` | – | only this stock's announcements (both required together) |
| `from` / `to` | – | inclusive `YYYY-MM-DD` bounds on `announced_on` (IST date); `from` after `to` → `400` |
| `limit` | `30` | 1–100 |
| `offset` | `0` | rows to skip |

```json
{
  "total": 4643,
  "limit": 30,
  "offset": 0,
  "items": [
    {"id": 101, "exchange": "NSE", "symbol": "ZENTEC", "name": "Zen Technologies Ltd",
     "announced_on": "2026-10-07",
     "title": "Announcement under Regulation 30 (LODR)-Allotment of ESOP / ESPS",
     "description": "Allotment of ESOP / ESPS - Transfer of equity shares ...",
     "document_url": "https://stockscans-assets.s3.ap-south-1.amazonaws.com/company-docs/abzg7r0fkvrnvph63gzibroe.pdf",
     "published_at": "2026-10-07T18:25:36Z"}
  ]
}
```

`document_url` is `null` when the filing has no PDF. `published_at` is RFC 3339 UTC or `null`.

### `GET /guide`

This document for AI assistants, as `text/markdown`, with the live column catalogue appended.
Point Claude (or any MCP client) here first.

## Views

| view | shows | columns |
|---|---|---|
| `overview` | Price, size, valuation and growth at a glance. | close_price, market_cap_cr, returns_1d_pct, pe, revenue_cr, revenue_growth_ttm_pct, pat_growth_ttm_pct, score |
| `performance` | How the share price has moved, and how it compares with the market and its industry. | close_price, returns_1d_pct, returns_1w_pct, returns_1m_pct, returns_3m_pct, returns_6m_pct, returns_1y_pct, returns_3y_pct, returns_5y_pct, high_52w_distance_pct, returns_vs_nifty500_1w_pct, returns_vs_nifty500_3m_pct, returns_vs_industry_1w_pct, returns_vs_industry_3m_pct |
| `technical` | Momentum and trend-strength indicators traders use. | close_price, returns_1d_pct, rsi_14d, rsi_14w, adx_14d, adx_14w |
| `valuation` | Is the stock cheap or expensive, and how profitable and indebted is the business? | market_cap_cr, pe, ps, debt_to_equity, npm_pct, opm_pct, roce_pct, roe_pct |
| `growth` | How fast revenue and profits are growing. | revenue_growth_qoq_pct, revenue_growth_yoy_pct, revenue_growth_ttm_pct, pat_growth_qoq_pct, pat_growth_yoy_pct, pat_growth_ttm_pct, pbt_growth_ttm_pct, eps_growth_ttm_pct |
| `financials` | What the company owns and owes, and where its cash comes from and goes. | revenue_cr, total_assets_cr, debt_cr, cash_equivalents_cr, inventory_cr, cwip_cr, operating_cash_flow_cr, investing_cash_flow_cr, financing_cash_flow_cr, free_cash_flow_cr, net_cash_flow_cr |
| `holdings` | Who owns the company and whether big investors are buying or selling. | promoter_holding_pct, fii_holding_pct, dii_holding_pct, retail_holding_pct, promoter_holding_chg_1q, promoter_holding_chg_1y, fii_holding_chg_1q, fii_holding_chg_1y, dii_holding_chg_1q, dii_holding_chg_1y, retail_holding_chg_1q, retail_holding_chg_1y |
| `scores` | An overall 0–100 rating for each stock. | score, score_status, score_change_1m, market_cap_cr, returns_1y_pct |

## Columns

| key | label | unit | meaning |
|---|---|---|---|
| `industry` | Industry | text | The business the company is in. |
| `close_price` | Price | inr | Latest share price in rupees. |
| `market_cap_cr` | Market cap | inr_cr | Total value of all the company's shares, in ₹ crore. Bigger means a larger company. |
| `returns_1d_pct` | 1D return | pct | Price change over the last trading day. |
| `returns_1w_pct` | 1W return | pct | Price change over the last week. |
| `returns_1m_pct` | 1M return | pct | Price change over the last month. |
| `returns_3m_pct` | 3M return | pct | Price change over the last 3 months. |
| `returns_6m_pct` | 6M return | pct | Price change over the last 6 months. |
| `returns_1y_pct` | 1Y return | pct | Price change over the last year. |
| `returns_3y_pct` | 3Y return | pct | Yearly average price change over the last 3 years. |
| `returns_5y_pct` | 5Y return | pct | Yearly average price change over the last 5 years. |
| `high_52w_distance_pct` | Below 52W high | pct | How far the price is below its highest price of the last year, as a positive percent. 0 means at the high. |
| `returns_vs_nifty500_1w_pct` | vs Nifty 500 (1W) | pct | 1-week return minus the Nifty 500 index's. Positive means it beat the market. |
| `returns_vs_nifty500_3m_pct` | vs Nifty 500 (3M) | pct | 3-month return minus the Nifty 500 index's. Positive means it beat the market. |
| `returns_vs_industry_1w_pct` | vs industry (1W) | pct | 1-week return minus its industry's average. Positive means it beat its peers. |
| `returns_vs_industry_3m_pct` | vs industry (3M) | pct | 3-month return minus its industry's average. Positive means it beat its peers. |
| `rsi_14d` | RSI (daily) | index | Momentum from 0 to 100 on daily prices. Above 70 is often called overbought, below 30 oversold. |
| `rsi_14w` | RSI (weekly) | index | The same momentum measure on weekly prices, for the longer trend. |
| `adx_14d` | ADX (daily) | index | Trend strength from 0 to 100 on daily prices. Above 25 usually means a strong trend, up or down. |
| `adx_14w` | ADX (weekly) | index | Trend strength on weekly prices. |
| `pe` | P/E | ratio | Share price divided by yearly earnings per share. Lower can mean cheaper; compare within the same industry. |
| `ps` | P/S | ratio | Market cap divided by yearly revenue. Useful when profits are small or negative. |
| `debt_to_equity` | Debt to equity | ratio | Borrowings divided by shareholders' money. Below 1 is generally comfortable; 0 means no debt. Negative means losses have wiped out shareholders' money. |
| `npm_pct` | Net profit margin | pct | Share of revenue left as profit after all costs and taxes. |
| `opm_pct` | Operating margin | pct | Share of revenue left after running costs, before interest and taxes. |
| `roce_pct` | ROCE | pct | Return on capital employed: profit earned on all money invested in the business. |
| `roe_pct` | ROE | pct | Return on equity: profit earned on shareholders' money. Above 15% is usually good. |
| `revenue_cr` | Revenue | inr_cr | Sales over the last 12 months, in ₹ crore. |
| `revenue_growth_qoq_pct` | Revenue growth (QoQ) | pct | Revenue change versus the previous quarter. |
| `revenue_growth_yoy_pct` | Revenue growth (YoY) | pct | Latest quarter's revenue versus the same quarter last year. |
| `revenue_growth_ttm_pct` | Revenue growth (TTM) | pct | Last 12 months' revenue versus the 12 months before. |
| `pat_growth_qoq_pct` | Profit growth (QoQ) | pct | Net profit change versus the previous quarter. |
| `pat_growth_yoy_pct` | Profit growth (YoY) | pct | Latest quarter's net profit versus the same quarter last year. |
| `pat_growth_ttm_pct` | Profit growth (TTM) | pct | Last 12 months' net profit versus the 12 months before. |
| `pbt_growth_ttm_pct` | Pre-tax profit growth (TTM) | pct | Last 12 months' profit before tax versus the 12 months before. |
| `eps_growth_ttm_pct` | EPS growth (TTM) | pct | Change in earnings per share over the last 12 months. |
| `total_assets_cr` | Total assets | inr_cr | Everything the company owns, in ₹ crore. |
| `total_liabilities_cr` | Total liabilities | inr_cr | Everything the company owes plus shareholders' equity, in ₹ crore (it equals total assets). |
| `debt_cr` | Debt | inr_cr | Borrowings, in ₹ crore. |
| `cash_equivalents_cr` | Cash | inr_cr | Cash and near-cash investments, in ₹ crore. |
| `inventory_cr` | Inventory | inr_cr | Goods held for sale or production, in ₹ crore. |
| `cwip_cr` | Capital work in progress | inr_cr | Factories, plants and projects still being built, in ₹ crore. |
| `operating_cash_flow_cr` | Operating cash flow | inr_cr | Cash the business itself generated, in ₹ crore. Positive is healthy. |
| `investing_cash_flow_cr` | Investing cash flow | inr_cr | Cash spent on (negative) or received from (positive) investments and assets, in ₹ crore. |
| `financing_cash_flow_cr` | Financing cash flow | inr_cr | Cash from borrowing or issuing shares (positive) or repaying and paying dividends (negative), in ₹ crore. |
| `net_cash_flow_cr` | Net cash flow | inr_cr | Overall change in cash, in ₹ crore. |
| `free_cash_flow_cr` | Free cash flow | inr_cr | Operating cash left after spending on assets, in ₹ crore. Money the company could return to shareholders. |
| `promoter_holding_pct` | Promoters | pct | Share of the company owned by its founders and promoter group. |
| `fii_holding_pct` | Foreign investors (FII) | pct | Share owned by foreign institutional investors. |
| `dii_holding_pct` | Domestic institutions (DII) | pct | Share owned by Indian mutual funds, insurers and banks. |
| `retail_holding_pct` | Public / retail | pct | Share owned by individual investors and others. |
| `promoter_holding_chg_1q` | Promoters Δ 1Q | pp | Change in promoter holding over the last quarter, in percentage points. |
| `promoter_holding_chg_1y` | Promoters Δ 1Y | pp | Change in promoter holding over the last year, in percentage points. |
| `promoter_holding_chg_2y` | Promoters Δ 2Y | pp | Change in promoter holding over 2 years, in percentage points. |
| `promoter_holding_chg_3y` | Promoters Δ 3Y | pp | Change in promoter holding over 3 years, in percentage points. |
| `fii_holding_chg_1q` | FII Δ 1Q | pp | Change in foreign investor holding over the last quarter, in percentage points. |
| `fii_holding_chg_1y` | FII Δ 1Y | pp | Change in foreign investor holding over the last year, in percentage points. |
| `fii_holding_chg_2y` | FII Δ 2Y | pp | Change in foreign investor holding over 2 years, in percentage points. |
| `fii_holding_chg_3y` | FII Δ 3Y | pp | Change in foreign investor holding over 3 years, in percentage points. |
| `dii_holding_chg_1q` | DII Δ 1Q | pp | Change in domestic institution holding over the last quarter, in percentage points. |
| `dii_holding_chg_1y` | DII Δ 1Y | pp | Change in domestic institution holding over the last year, in percentage points. |
| `dii_holding_chg_2y` | DII Δ 2Y | pp | Change in domestic institution holding over 2 years, in percentage points. |
| `dii_holding_chg_3y` | DII Δ 3Y | pp | Change in domestic institution holding over 3 years, in percentage points. |
| `retail_holding_chg_1q` | Retail Δ 1Q | pp | Change in retail holding over the last quarter, in percentage points. |
| `retail_holding_chg_1y` | Retail Δ 1Y | pp | Change in retail holding over the last year, in percentage points. |
| `retail_holding_chg_2y` | Retail Δ 2Y | pp | Change in retail holding over 2 years, in percentage points. |
| `retail_holding_chg_3y` | Retail Δ 3Y | pp | Change in retail holding over 3 years, in percentage points. |
| `score` | Score | score | Overall 0–100 rating from the data provider combining the stock's numbers and price trend. Higher is stronger. |
| `score_status` | Score status | text | The rating's verdict: outperforming (strongest), accumulating or consolidating (in between), or underperforming (weakest). |
| `score_change_1m` | Score Δ 1M | score | Change in the score over the last month. |
