# Indian IPO Tracker - SEBI DRHP, GMP & Listing API (`contented_academy/indian-ipo-tracker`) Actor

Track every Indian mainboard & SME IPO from DRHP to listing. Multi-source GMP, live subscription, webhook alerts on lifecycle changes.

- **URL**: https://apify.com/contented\_academy/indian-ipo-tracker.md
- **Developed by:** [Ujjawal Yadav](https://apify.com/contented_academy) (community)
- **Categories:** Automation, Other
- **Stats:** 36 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $50.00 / 1,000 ipo records

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Indian IPO Tracker — SEBI, GMP & Listing Data

> *Every Indian IPO from DRHP filing to listing pop — one normalized feed, real-time webhooks, zero spreadsheet work.*

Track the full lifecycle of every Indian mainboard and SME IPO in a single Apify Dataset. Connect it to Google Sheets, Slack, Make, or n8n in minutes.

***

### Quick start (one click)

Select **"Track all current IPOs"** in the preset dropdown and hit **Start**. Results appear in 1–2 minutes. That's it.

```json
{ "preset": "track_all_current" }
```

No other fields required. This single input gives you every active Indian IPO with all sources enabled and sensible rate limits.

***

### What you get per IPO

| Field group | What's inside |
|---|---|
| **Lifecycle status** | `DRHP_FILED → SEBI_APPROVED → SUBSCRIPTION_OPEN → LISTED` — always know what stage an IPO is in |
| **DRHP / RHP details** | Filing date, PDF URL (HEAD-verified when `verify_drhp_pdf:true`), issue size, price band, lot size, fresh issue vs OFS split. *Issue size / fresh-issue vs OFS split / face value / promoter list are populated from BSE/NSE/RHP after RHP filing — DRHP cover-page content extraction is on the roadmap (`parse_drhp_cover`, separate plan).* |
| **Subscription** | QIB / NII / retail multiples at each day's close + full timeline history |
| **Grey Market Premium** | Reconciled GMP from InvestorGain + Chittorgarh + IPO Watch, with per-source breakdown and disagreement score |
| **Listing day** | BSE + NSE opening price, listing pop %, D+1 and D+7 close |
| **SME IPOs** | BSE SME and NSE Emerge coverage alongside mainboard |
| **Source attribution** | Every field carries `{source, captured_utc, source_url}` — full audit chain |

#### Sample output record

```json
{
  "ipo_id": "ZEPTO-2026-IPO-XXXXXXXX",
  "company_name": "Zepto",
  "current_status": "SUBSCRIPTION_OPEN",
  "lifecycle": {
    "drhp_filed_date": "2025-11-14",
    "subscription_open_date": "2026-05-06",
    "subscription_close_date": "2026-05-08",
    "listing_date": "2026-05-13"
  },
  "issue_details": {
    "issue_size_cr": 3600,
    "price_band_lower": 255,
    "price_band_upper": 270,
    "lot_size": 55
  },
  "subscription": {
    "qib_subscription_x": 4.2,
    "nii_subscription_x": 2.1,
    "retail_subscription_x": 1.8,
    "total_subscription_x": 2.9,
    "timeline": [
      { "captured_utc": "2026-05-06T11:00:00Z", "total_x": 0.3, "source": "bse" },
      { "captured_utc": "2026-05-07T11:00:00Z", "total_x": 1.4, "source": "bse" }
    ]
  },
  "grey_market": {
    "current_gmp": 32,
    "gmp_per_source": { "investorgain": 30, "chittorgarh": 33, "ipowatch": 33 },
    "disagreement_score": 0.05
  },
  "schema_version": "1.0.1"
}
```

***

### Webhook alerts

Set a `webhook_url` and `webhook_secret` and the Actor POSTs a signed JSON payload whenever something changes. No polling required.

**Events you can subscribe to:**

| Event | When it fires |
|---|---|
| `lifecycle_status_change` | IPO moves to a new stage (SEBI approved, RHP filed, listing day, etc.) |
| `gmp_threshold_crossed` | GMP changes by ≥ N% since the last snapshot |
| `listing_pop_calculated` | Listing opening price captured |
| `subscription_milestone_crossed` | Total subscription crosses 1×, 5×, or 10× |
| `subscription_acceleration_detected` | Day-over-day subscription jumps ≥ 3× (NII pile-on signal) |
| `coverage_gap_detected` | A source returns significantly fewer records than its baseline |

**Minimal webhook input:**

```json
{
  "preset": "track_all_current",
  "webhook_url": "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK",
  "webhook_secret": "your-32-character-or-longer-secret",
  "webhook_events_subscribed": ["lifecycle_status_change", "gmp_threshold_crossed"]
}
```

Payloads are **HMAC-SHA256 signed** via the `X-IPO-Tracker-Signature: sha256=<hex>` header.

```js
// Node.js — verify the signature
import { createHmac, timingSafeEqual } from 'crypto';
function verify(body, header, secret) {
  const expected = createHmac('sha256', secret).update(body).digest('hex');
  return timingSafeEqual(Buffer.from(expected), Buffer.from(header.replace('sha256=', '')));
}
```

```python
## Python — verify the signature
import hmac, hashlib
def verify(body: bytes, header: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, header.removeprefix("sha256="))
```

***

### Integrations

| Tool | How |
|---|---|
| **Google Sheets** | [Apify → Google Sheets integration](https://apify.com/integrations) — sync dataset rows to a sheet automatically |
| **Slack** | Set `webhook_url` to a Slack [incoming webhook URL](https://api.slack.com/messaging/webhooks) — get IPO alerts in any channel |
| **Make (Integromat)** | Apify trigger module → fan results into 1,000+ apps |
| **n8n** | [Apify Cloud node](https://n8n.io/integrations/apify/) — run Actor + consume dataset in any workflow |
| **Zapier** | [Apify Zap](https://zapier.com/apps/apify) → 7,000+ Zapier integrations |

***

### Pricing

This Actor uses Apify's **pay-per-event** model — you only pay for what you use.

| Event | Price |
|---|---|
| `ipo-record-returned` | $0.05 per record |
| `lifecycle-status-change-detected` | $0.10 per event |
| `gmp-threshold-crossed` | $0.10 per event |
| `listing-pop-calculated` | $0.10 per event |
| `subscription-milestone-crossed` | $0.10 per event |
| `subscription-acceleration-detected` | $0.20 per event |
| `webhook-delivered-ok` | $0.05 per delivery |
| `coverage-gap-detected` | $0.10 per event |

**Typical run cost** (28 active IPOs, no events): **$1.40**. Daily schedule: ~$42/month.

**Free trial**: First 5 `ipo-record-returned` events per account per month are free — run once and check the output before subscribing.

***

### Run modes

| Preset | Best for |
|---|---|
| **Track all current IPOs** | Daily schedule — incremental refresh of all active IPOs |
| **GMP only** | Fastest run — only grey-market premium, no lifecycle scraping |
| **Track a specific IPO** | Deep-dive on one company by `ipo_id` |
| **Listed IPOs post-mortem** | Research on recently listed IPOs |
| **Custom** | Full control over every advanced field |

***

### Data sources

| Source | What it contributes |
|---|---|
| **SEBI public-issues portal** | Canonical DRHP filing date + PDF URL |
| **BSE forthcoming issues** | Price band, lot size, subscription multiples (mainboard) |
| **BSE SME platform** | SME IPO lifecycle and issue details |
| **NSE upcoming issues** | Cross-reference + listing prices + live subscription |
| **NSE Emerge** | SME IPO supplementary data |
| **InvestorGain, Chittorgarh, IPO Watch** | Grey Market Premium (three independent sources, reconciled) |

All sources are publicly accessible. Data is scraped politely via residential Indian proxies.

***

### Limitations

- Subscription data captured once per day (after bid close, ~16:30 IST), not intraday.
- SEBI confidential pre-filings are tracked by count only until SEBI exposes a queryable endpoint.
- DRHP PDF cover-page parsing (issue size, fresh-issue/OFS split, face value, promoters, registrar) is on the roadmap (`parse_drhp_cover` flag, separate plan). The `verify_drhp_pdf` flag does HTTP HEAD only; it does not parse content.
- `mode: prospectus_parse` requires that at least one default-mode run (`track_all_current` / `incremental` / `full`) has already populated the Postgres `ipos` table. A standalone first run exits cleanly with `queue_size: 0`.

### Roadmap

- **v1.1** — GMP accuracy backtest (MAE per publisher over trailing 50 IPOs), expanded backfill
- **v2.0** — DRHP/RHP structured data: 3-year financials, peer comparison table, use of proceeds, promoter holding, lock-in schedule
- **v2.1** — Basis of Allotment data, anchor quality scoring, live peer comparison enrichment
- **v3.0** — Lock-in exit tracker, bulk/block deal monitoring, post-listing performance tracking

***

### Compliance & disclaimers

All scraped data is publicly available. SEBI public-issues filings are statutorily required to be public. Grey Market Premium is **unofficial, unregulated** data published by third-party websites — it is surfaced for informational purposes only. **This is not investment advice. We do not endorse or facilitate grey-market trading.**

### Support

Open an issue on the project repository or contact via the Apify Store listing page.

# Actor input Schema

## `preset` (type: `string`):

Pick a preset for one-click usage. Choose 'Custom' to configure every advanced field yourself.

## `mode` (type: `string`):

Advanced. Use `incremental` for hourly polling. Use `full` for first run or after long downtime. Use `specific` to scrape only the IPOs in `ipo_filter`. The narrow modes (`gmp_only`, `subscription_checkpoint`, `bulk_deals_daily`, `listing_day_oneshot`) run a single sub-pipeline at high cadence. Ignored unless preset = Custom.

## `ipo_filter` (type: `array`):

Specific `ipo_id` values to scrape. Required if `mode = specific`.

## `max_ipos` (type: `integer`):

Maximum IPOs to process in one run (1–1000).

## `sources_enabled` (type: `array`):

Sources scraped for DRHP, RHP, SEBI status, and exchange listing data.

## `gmp_sources_enabled` (type: `array`):

Grey-Market-Premium publishers to scrape. Disable any source to reduce cost or in response to a kill-switch event.

## `webhook_url` (type: `string`):

HTTPS endpoint that receives event POSTs. Payloads are HMAC-SHA256 signed via the `X-IPO-Tracker-Signature` header.

## `webhook_secret` (type: `string`):

32–128 character shared secret used to HMAC-sign webhook payloads. Length is enforced at actor start time.

## `webhook_events_subscribed` (type: `array`):

Event types to deliver to the webhook URL.

## `gmp_threshold_pct` (type: `integer`):

Trigger a `gmp_threshold_crossed` webhook when reconciled GMP changes by at least this percent since the prior snapshot.

## `verify_drhp_pdf` (type: `boolean`):

Issue an HTTP HEAD against every DRHP PDF URL discovered on the SEBI detail page. Confirms accessibility (filters dead/403 links) and records `lifecycle.drhp_pdf_content_length` + `lifecycle.drhp_pdf_verified_at` for audit. **Does not download or parse PDF content** — for cover-page field extraction (issue size, promoters, registrar, face value, fresh-issue/OFS split) use the upcoming `parse_drhp_cover` flag (separate plan, pending). Costs ~1 extra HEAD request per detail page; default off.

## `confidential_filings_enabled` (type: `boolean`):

Enable the SEBI confidential-filings scraper (pre-filed acknowledgements). Disable as a kill-switch if SEBI changes the surface and the scraper starts erroring.

## `force_reparse` (type: `boolean`):

Ground-up reseed only. In `prospectus_parse` mode, re-extract every DRHP/RHP even when the PDF SHA is unchanged (bypasses the HEAD + SHA idempotency skips). Combined with the bumped prompt-version constants, this re-runs the extractors and the structured-output (responseSchema) LLM path over the whole corpus. Heavy and billable (re-bills the LLM cleaners). The R2 parsed-JSON cache is still reused — identical PDF bytes are not re-OCR'd. Default off.

## `native_pdf_gapfill` (type: `boolean`):

Per-run opt-in. When true, fields the flatten+text path leaves null on a text-extractable DRHP (PAT/EBITDA, promoter pre-issue %, peer revenue-in-₹Cr / P-E) are re-read by sending the located section's NATIVE PDF page-range to Gemini with a structured schema. Fill-nulls-only (never overwrites a populated value); provenance stays `pdf`. Billable (~$0.005/doc, budget-capped). Default off.

## `proxy_configuration` (type: `object`):

Apify Proxy configuration. Defaults to the residential pool with India geolocation.

## `max_concurrency` (type: `integer`):

Maximum concurrent requests across all sources.

## `request_rate_per_minute` (type: `integer`):

Maximum requests per minute against any single source domain. Lower is politer; higher is faster but more block-prone.

## `dataset_mode` (type: `string`):

`snapshot` writes one record per IPO per run (latest state). `append` writes one record per state change (audit trail).

## `debug_mode` (type: `boolean`):

Enable verbose per-source logs and skip webhook dispatch.

## Actor input object example

```json
{
  "preset": "track_all_current",
  "mode": "incremental",
  "ipo_filter": [],
  "max_ipos": 200,
  "sources_enabled": [
    "sebi",
    "bse",
    "nse"
  ],
  "gmp_sources_enabled": [
    "investorgain",
    "chittorgarh",
    "ipowatch"
  ],
  "webhook_events_subscribed": [
    "lifecycle_status_change"
  ],
  "gmp_threshold_pct": 20,
  "verify_drhp_pdf": false,
  "confidential_filings_enabled": true,
  "force_reparse": false,
  "native_pdf_gapfill": false,
  "proxy_configuration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "countryCode": "IN"
  },
  "max_concurrency": 4,
  "request_rate_per_minute": 2,
  "dataset_mode": "snapshot",
  "debug_mode": false
}
```

# Actor output Schema

## `record_type` (type: `string`):

'ipo' = standard IPO record. 'pipeline\_meta' = run-level SEBI filing pipeline summary (one per run).

## `ipo_id` (type: `string`):

Stable canonical ID e.g. ZEPTO-2026-IPO-XXXXXXXX. Consistent across all runs for the same offering.

## `company_name` (type: `string`):

Normalised short trading name.

## `company_legal_name` (type: `string`):

Full registered entity name from SEBI/BSE/NSE filings.

## `category` (type: `string`):

'mainboard' = BSE/NSE main board. 'sme' = BSE SME or NSE Emerge platform.

## `industry` (type: `string`):

Sector/industry tag from DRHP. Null until DRHP is parsed.

## `current_status` (type: `string`):

Current stage: DRHP\_FILED → SEBI\_OBSERVATIONS → SEBI\_APPROVED → RHP\_FILED → SUBSCRIPTION\_OPEN → SUBSCRIPTION\_CLOSED → LISTED. Also: WITHDRAWN, EXPIRED.

## `lifecycle` (type: `string`):

Object. Key milestone dates: drhp\_filed\_date, drhp\_pdf\_url, sebi\_approval\_date, rhp\_filed\_date, subscription\_open\_date, subscription\_close\_date, listing\_date, sebi\_observations\_dates\[], filing\_visibility.

## `issue_details` (type: `string`):

Object. Pricing and sizing terms from the RHP: issue\_size\_cr (number), fresh\_issue\_cr, ofs\_cr, price\_band\_lower, price\_band\_upper, lot\_size, face\_value. All monetary values in ₹ crore.

## `subscription` (type: `string`):

Object. Demand multiples: qib\_subscription\_x, nii\_subscription\_x, retail\_subscription\_x, total\_subscription\_x (all numbers). Also: timeline\[] (per-snapshot bidding history), final (frozen close snapshot), nii\_subscription\_acceleration\_detected (boolean).

## `grey_market` (type: `string`):

Object. current\_gmp (₹, trimmed-median reconciled), implied\_listing\_price, gmp\_per\_source {investorgain, chittorgarh, ipowatch}, disagreement\_score (0–1), kostak\_rate, source\_accuracy {MAE per publisher over trailing ≤50 LISTED IPOs}.

## `listing` (type: `string`):

Object. Post-listing prices: listing\_price\_bse (₹), listing\_price\_nse (₹), listing\_pop\_pct (% vs issue price), d1\_close (D+0 close ₹), d7\_close (D+7 close ₹).

## `leadership` (type: `string`):

Object. promoters\[] (string array), brlms\[] (book-running lead managers, string array), registrar (string).

## `documents` (type: `string`):

Object (1.2.0). Official SEBI-published document URLs: drhp\_urls\[] (PDF URLs only, 1.2.0 — was HTML detail page in 1.1.0), rhp\_urls\[], addendum\_urls\[]. New 1.2.0 fields: sebi\_detail\_page\_url (HTML), detail\_page\_scraped (boolean — distinguishes 'no addenda' from 'scrape failed'), classified\_urls\[] (semantic classification per PDF: drhp/rhp/addendum/abridged/corrigendum/unknown).

## `derived_metrics` (type: `string`):

Object. Cross-source computations (all numbers or null): days\_drhp\_to\_approval, days\_approval\_to\_rhp, days\_rhp\_to\_listing, days\_drhp\_to\_listing, gmp\_implied\_listing\_price, gmp\_pct\_of\_issue\_price, listing\_pop\_vs\_gmp\_implied\_pct.

## `basis_of_allotment` (type: `string`):

Object (1.1.0). Per-category allotment data captured from registrar (LinkIntime / KFintech / Bigshare) + Chittorgarh aggregator. Key sub-fields: registrar, parse\_confidence, by\_category.{retail,snii,bnii,qib,employee,shareholder} each with {shares\_offered, shares\_allotted, applications\_received, subscription\_x, allocation\_method ('full'|'proportionate'|'lottery'), ratio\_raw, ratio\_probability}, anchor\_allocations\_count, anchor\_top\_3\_concentration\_pct, confirmed\_listing\_date, cross\_verified.

## `prospectus` (type: `string`):

Object (1.1.0; populated by W10-W13 prospectus parser). Versioned DRHP/RHP/UDRHP/addendum metadata + extracted financials, peer comparison, use of proceeds, promoter holding, BRLMs, registrar, anchor book.

## `source_attribution_v2` (type: `string`):

Object. Per-field provenance. For each key field: {source, captured\_utc, source\_url}. Audit chain showing exactly which scrape provided each value.

## `data_quality_score` (type: `string`):

Number 0.0–1.0 (1.2.0: now computed, was hardcoded ladder). Fraction of stage-expected fields populated. See data\_quality\_detail for the field-level breakdown (expected\_fields\[], populated\_fields\[], missing\_fields\[]).

## `data_quality_definition` (type: `string`):

Which fields count toward data\_quality\_score at this lifecycle stage.

## `last_updated_utc` (type: `string`):

ISO 8601 UTC timestamp of the most recent scrape that modified this record.

## `schema_version` (type: `string`):

Semver of the output schema. Current: 1.2.0.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("contented_academy/indian-ipo-tracker").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("contented_academy/indian-ipo-tracker").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call contented_academy/indian-ipo-tracker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,contented_academy/indian-ipo-tracker"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/dEIq9KiY4N9o6Rqhx/builds/zdzbf8yTnDLOodfys/openapi.json
