# 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:** 4 total users, 2 monthly users, 100.0% runs succeeded, NaN 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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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.

## `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,
  "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("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=contented_academy/indian-ipo-tracker",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Indian IPO Tracker - SEBI DRHP, GMP & Listing API",
        "description": "Track every Indian mainboard & SME IPO from DRHP to listing. Multi-source GMP, live subscription, webhook alerts on lifecycle changes.",
        "version": "0.4",
        "x-build-id": "XC3cd9nh7zY2ciYtd"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/contented_academy~indian-ipo-tracker/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-contented_academy-indian-ipo-tracker",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/contented_academy~indian-ipo-tracker/runs": {
            "post": {
                "operationId": "runs-sync-contented_academy-indian-ipo-tracker",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/contented_academy~indian-ipo-tracker/run-sync": {
            "post": {
                "operationId": "run-sync-contented_academy-indian-ipo-tracker",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "preset"
                ],
                "properties": {
                    "preset": {
                        "title": "What do you want to do?",
                        "enum": [
                            "track_all_current",
                            "track_specific",
                            "gmp_only",
                            "listed_postmortem",
                            "custom"
                        ],
                        "type": "string",
                        "description": "Pick a preset for one-click usage. Choose 'Custom' to configure every advanced field yourself.",
                        "default": "track_all_current"
                    },
                    "mode": {
                        "title": "Run mode",
                        "enum": [
                            "full",
                            "incremental",
                            "specific",
                            "gmp_only",
                            "subscription_checkpoint",
                            "bulk_deals_daily",
                            "listing_day_oneshot",
                            "boa_parse",
                            "prospectus_parse",
                            "discovery",
                            "refresh_worker",
                            "parse_worker"
                        ],
                        "type": "string",
                        "description": "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.",
                        "default": "incremental"
                    },
                    "ipo_filter": {
                        "title": "IPO filter",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Specific `ipo_id` values to scrape. Required if `mode = specific`.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "max_ipos": {
                        "title": "Max IPOs per run",
                        "minimum": 1,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "Maximum IPOs to process in one run (1–1000).",
                        "default": 200
                    },
                    "sources_enabled": {
                        "title": "Primary lifecycle sources",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Sources scraped for DRHP, RHP, SEBI status, and exchange listing data.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "sebi",
                                "bse",
                                "nse"
                            ],
                            "enumTitles": [
                                "SEBI",
                                "BSE",
                                "NSE"
                            ]
                        },
                        "default": [
                            "sebi",
                            "bse",
                            "nse"
                        ]
                    },
                    "gmp_sources_enabled": {
                        "title": "GMP publishers",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Grey-Market-Premium publishers to scrape. Disable any source to reduce cost or in response to a kill-switch event.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "investorgain",
                                "chittorgarh",
                                "ipowatch"
                            ],
                            "enumTitles": [
                                "InvestorGain",
                                "Chittorgarh",
                                "IPO Watch"
                            ]
                        },
                        "default": [
                            "investorgain",
                            "chittorgarh",
                            "ipowatch"
                        ]
                    },
                    "webhook_url": {
                        "title": "Webhook URL",
                        "pattern": "^https://.+",
                        "type": "string",
                        "description": "HTTPS endpoint that receives event POSTs. Payloads are HMAC-SHA256 signed via the `X-IPO-Tracker-Signature` header."
                    },
                    "webhook_secret": {
                        "title": "Webhook signing secret",
                        "type": "string",
                        "description": "32–128 character shared secret used to HMAC-sign webhook payloads. Length is enforced at actor start time."
                    },
                    "webhook_events_subscribed": {
                        "title": "Subscribed webhook events",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Event types to deliver to the webhook URL.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "lifecycle_status_change",
                                "gmp_threshold_crossed",
                                "listing_pop_calculated",
                                "coverage_gap_detected",
                                "subscription_milestone_crossed",
                                "subscription_acceleration_detected",
                                "basis_of_allotment_published"
                            ],
                            "enumTitles": [
                                "Lifecycle status change",
                                "GMP threshold crossed",
                                "Listing pop calculated",
                                "Coverage gap detected",
                                "Subscription milestone crossed (1×, 5×, 10×)",
                                "Subscription acceleration detected (≥3× day-over-day)",
                                "Basis of Allotment published"
                            ]
                        },
                        "default": [
                            "lifecycle_status_change"
                        ]
                    },
                    "gmp_threshold_pct": {
                        "title": "GMP change threshold (%)",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Trigger a `gmp_threshold_crossed` webhook when reconciled GMP changes by at least this percent since the prior snapshot.",
                        "default": 20
                    },
                    "verify_drhp_pdf": {
                        "title": "Verify DRHP PDF URLs (HEAD only)",
                        "type": "boolean",
                        "description": "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.",
                        "default": false
                    },
                    "confidential_filings_enabled": {
                        "title": "Scrape SEBI confidential filings",
                        "type": "boolean",
                        "description": "Enable the SEBI confidential-filings scraper (pre-filed acknowledgements). Disable as a kill-switch if SEBI changes the surface and the scraper starts erroring.",
                        "default": true
                    },
                    "proxy_configuration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Apify Proxy configuration. Defaults to the residential pool with India geolocation.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ],
                            "countryCode": "IN"
                        }
                    },
                    "max_concurrency": {
                        "title": "Max concurrency",
                        "minimum": 1,
                        "maximum": 10,
                        "type": "integer",
                        "description": "Maximum concurrent requests across all sources.",
                        "default": 4
                    },
                    "request_rate_per_minute": {
                        "title": "Per-source rate limit",
                        "minimum": 1,
                        "maximum": 10,
                        "type": "integer",
                        "description": "Maximum requests per minute against any single source domain. Lower is politer; higher is faster but more block-prone.",
                        "default": 2
                    },
                    "dataset_mode": {
                        "title": "Dataset write mode",
                        "enum": [
                            "snapshot",
                            "append"
                        ],
                        "type": "string",
                        "description": "`snapshot` writes one record per IPO per run (latest state). `append` writes one record per state change (audit trail).",
                        "default": "snapshot"
                    },
                    "debug_mode": {
                        "title": "Debug mode",
                        "type": "boolean",
                        "description": "Enable verbose per-source logs and skip webhook dispatch.",
                        "default": false
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
