{"openapi":"3.1.0","info":{"title":"Tarutha API","description":"**Indonesian market data with context.** End-of-day and monthly data on IDX equities and indices, KSEI ownership and flows, government bonds (SBN), mutual funds, IDX disclosures and filings, and news. Every figure carries its source, period and caveats.\n\n# Getting started\n\n## Quickstart\n\n1. **Get an API key.** Keys come with a Tarutha founding membership: see [tarutha.co/#pricing](https://tarutha.co/#pricing) to join. Members sign in to the Terminal at https://app.tarutha.co and create keys from the account menu. Keys look like `tarutha_…`. Keep them secret and use them only on a server.\n2. **Authenticate every request.** Send `Authorization: Bearer tarutha_…`. Only this specification (`/v1/openapi.json`) and `/v1/status` answer without a key. Also send your own `User-Agent` header, because some default library user agents, such as Python's urllib, are refused at our network edge.\n3. **Mind the limit.** A member's keys share 300 requests a minute. Above that the API answers 429 with the code RATE_LIMITED and a Retry-After header.\n4. **Discover.** Hit `GET /v1/equities` to see every ticker you can query (~970 IDX-listed names).\n5. **Drill in.** For any ticker:\n   - `GET /v1/equities/{ticker}`: the company profile\n   - `GET /v1/equities/{ticker}/prices`: daily OHLCV history\n   - `GET /v1/equities/{ticker}/fundamentals`: market cap, P/E, analyst targets…\n   - `GET /v1/equities/{ticker}/ownership`: insider/institutional holders\n6. **Zoom out.** `GET /v1/indices` (IHSG & 44 more), `GET /v1/movers` (daily gainers/losers with foreign flow), `GET /v1/idx/disclosures`, `GET /v1/ksei/corporate-actions` (dividend/rights schedules).\n7. **Go deep.** `GET /v1/idx/securities` (listing master), `GET /v1/idx/uma` + `GET /v1/idx/suspensions` (risk flags), `GET /v1/idx/broker-summary` (daily broker flow), `GET /v1/idx/corporate-actions` (dilution history), `GET /v1/idx/ipo` (pipeline), `GET /v1/idx/financial-reports` (XBRL/PDF filings), `GET /v1/ksei/announcements` (new-instrument registrations), `GET /v1/ksei/archives` + `GET /v1/ksei/statistics-pdfs` (monthly depository snapshots to 2012).\n\nOr try it right here: open the **Auth** pane on the left, paste your `tarutha_…` key, then hit **Send** on any endpoint.\n\n## Endpoint map\n\nWhich endpoint answers which question:\n\n| You want to know… | Start here |\n|---|---|\n| What can I query? | `GET /v1/equities` (tickers) · `GET /v1/idx/securities` (full listing master) · `GET /v1/indices` (index catalog) |\n| About one company | `/v1/equities/{ticker}` profile · `/prices` OHLCV · `/fundamentals` valuation · `/ownership` who holds it |\n| What moved today? | `GET /v1/movers` (gainers/losers/most-active + foreign flow) · `GET /v1/indices` (index levels) |\n| Is this stock risky right now? | `GET /v1/idx/uma` (unusual-activity flags) · `/v1/idx/suspensions` · `/v1/idx/disclosures` |\n| Dividends & corporate actions | `GET /v1/ksei/corporate-actions` (schedules) · `GET /v1/idx/corporate-actions` (share-issuance history) |\n| Filings & reports | `GET /v1/idx/financial-reports` (quarterly/audited, XBRL + PDF) |\n| Who is trading? | `GET /v1/idx/broker-summary` (per-firm daily volume/value) |\n| Who **owns** it: including bonds | `GET /v1/instruments/{isin}/ownership` (nine investor types × local/foreign, monthly) |\n| Who has been buying or selling it | `GET /v1/instruments/{isin}/flows` (net position change, monthly) |\n| What is coming to market? | `GET /v1/idx/ipo` (IPO & relisting pipeline) |\n| Is the data current? | `GET /v1/status` (per source: newest date, cadence, verdict; no key needed) |\n| Market-wide structure | `GET /v1/ksei/datasets` (demographics, custody values) · `/v1/ksei/announcements` · `/v1/ksei/archives` · `/v1/ksei/statistics-pdfs` |\n| News | `GET /v1/news/articles` (ticker-tagged, confidence-scored) |\n\n## Data coverage & freshness\n\n| Family | Source | Depth | Refresh |\n|---|---|---|---|\n| Equity prices | Yahoo Finance, with the IDX trading summary filling any day Yahoo has not landed | full listing history (~25y for old names) | nightly, plus each IDX trading day |\n| Equity fundamentals | Yahoo Finance | current snapshot | nightly after US close |\n| Official IDX daily (movers, indices, broker summary) | idx.co.id trading summaries | rolling from 2026-04 onward, growing daily | each trading day |\n| IDX reference (securities, IPO, issuance, reports, UMA, suspensions, disclosures) | idx.co.id | current snapshots + recent history | daily |\n| KSEI structure (datasets, CA schedules, announcements, archives) | web.ksei.co.id | monthly series back to 2012–2017 depending on dataset | daily (schedules) / monthly (archives) |\n| News | CNBC ID, Detik, Bisnis, IDX Channel, Yahoo | rolling archive | every 15 minutes |\n| Instrument ownership & flows | KSEI depository records (Balancepos + StatisEfek) | 37 months, every instrument class: equities, corporate bonds, sukuk, government bonds, SBSN | monthly |\n\n**On ownership percentages.** KSEI reports two different totals: the amount *issued*, and the amount held in C-BEST *custody*. They agree on roughly two thirds of instruments and differ enormously on the rest: a government bond can have Rp 2.4tn issued against Rp 58.5bn in custody, because most government paper settles at Bank Indonesia. `foreign_pct` is therefore the share of custody, which is meaningful everywhere, and every row carries `custody_pct` so you can see what that represents. Dividing by the wrong denominator is the easiest mistake to make with this data.\n\nEvery response's `meta.ts` tells you when it was generated, not how old the data is; price-like rows carry their own dates. **To date a figure you publish, cite the row's own date, its `as_of`, or the dataset's period, never `meta.ts`.**\n\n## Authentication\n\nEvery `/v1` endpoint expects a bearer token:\n\n```bash\ncurl -H \"Authorization: Bearer tarutha_YOUR_KEY\" \\\n  https://api.tarutha.co/v1/equities\n```\n\nA missing or invalid key returns `401` with `error.code = \"UNAUTHORIZED\"`. Rotate a leaked key by asking for a replacement: old keys are revoked, not expired, so nothing breaks silently.\n\n# Guides\n\n## Recipes\n\nThe endpoints are designed to chain. Three common flows:\n\n### 1 · Company snapshot: profile → prices → fundamentals\n\n```bash\nBASE=https://api.tarutha.co\nAUTH=\"Authorization: Bearer tarutha_YOUR_KEY\"\n\ncurl -H \"$AUTH\" $BASE/v1/equities/BMRI                     # who is BMRI?\ncurl -H \"$AUTH\" \"$BASE/v1/equities/BMRI/prices?from=2026-01-01&to=2026-06-30\"\ncurl -H \"$AUTH\" $BASE/v1/equities/BMRI/fundamentals        # P/E, market cap, targets\n```\n\n### 2 · News monitor: what happened to the tickers I hold?\n\n```bash\ncurl -H \"$AUTH\" \"$BASE/v1/news/articles?ticker=BMRI&limit=20\"\n```\n\nEach article carries `tickers` + `match_confidence`, so you can filter to high-confidence mentions (≥ 0.9) before alerting. Poll with `offset += limit` while `pagination.has_more` is true; results are newest-first.\n\n### 3 · Market structure: KSEI demographics drill-down\n\n```bash\ncurl -H \"$AUTH\" $BASE/v1/ksei/datasets                     # catalog: 12 datasets\ncurl -H \"$AUTH\" \"$BASE/v1/ksei/datasets/share-values-at-ksei?series=Aset%20Asing\"\n```\n\nCall the catalog first: it tells you each dataset's `granularity`, `unit`, `series`, and stored period range, so you never guess at slugs or dimensions.\n\n### 4 · Pre-trade risk screen: any red flags before I buy?\n\n```bash\ncurl -H \"$AUTH\" \"$BASE/v1/idx/uma?ticker=SDMU\"            # unusual-activity flags\ncurl -H \"$AUTH\" \"$BASE/v1/idx/suspensions?ticker=SDMU\"    # halted before?\ncurl -H \"$AUTH\" \"$BASE/v1/idx/disclosures?ticker=SDMU&limit=10\"\n```\n\nA UMA flag or a fresh suspension is the exchange telling you to look closer: chain all three before acting on a mover from `GET /v1/movers`.\n\n### 5 · Dividend calendar: what pays out this month?\n\n```bash\ncurl -H \"$AUTH\" \"$BASE/v1/ksei/corporate-actions?type=cash-dividend&from=2026-07-01&to=2026-07-31\"\n```\n\nEach row links the official KSEI PDF with cum/ex/record/payment dates. Cross-check dilution history with `GET /v1/idx/corporate-actions?ticker=…` before computing per-share amounts.\n\n### 6 · Daily market pulse: one call pair after each close\n\n```bash\ncurl -H \"$AUTH\" $BASE/v1/indices                          # every index level\ncurl -H \"$AUTH\" \"$BASE/v1/movers?by=value&limit=10\"       # where the money went\n```\n\nMovers rows carry `foreign_buy`/`foreign_sell`, so the same call shows you which names foreign money entered or left.\n\n## Connect an AI agent (MCP)\n\nTarutha runs a hosted MCP server at `https://api.tarutha.co/v1/mcp`. There is nothing to install. Any MCP client that can send a request header can use it, for example Claude Code, Cursor, or an agent built with the Claude Agent SDK. Send your key as the header `Authorization: Bearer tarutha_…` and keep the key on your own machine or server.\n\nClaude Code:\n\n```bash\nclaude mcp add --transport http tarutha https://api.tarutha.co/v1/mcp --header \"Authorization: Bearer tarutha_…\"\n```\n\nThe Claude desktop app and the claude.ai web and mobile apps add remote servers through OAuth only, so they cannot use a Tarutha key today.\n\n### Tools\n\n| Tool | What the agent gets |\n|---|---|\n| `list_equities` | Every IDX ticker (~970): discovery and validation |\n| `get_equity_profile` | Name, sector, ISIN, listing date |\n| `get_prices` | Daily OHLCV history (IDR), `from`/`to` bounded |\n| `get_fundamentals` | Market cap, P/E, dividend yield, analyst targets |\n| `search_news` | Ticker-tagged Indonesian capital-market news with confidence scores |\n| `list_ksei_datasets` | Catalog of 12 KSEI market-structure datasets |\n| `get_ksei_dataset` | KSEI datapoints, filterable by series or category |\n| `market_data` | **One tool, many kinds**: ownership, indices and history, movers with foreign flow, UMA flags, suspensions, disclosures, securities master, broker summary, issuance history, IPO pipeline, financial reports, KSEI corporate actions, announcements, archives and statistics, the ISIN instrument directory with per-instrument depository ownership and flows, and mutual funds with NAV, units outstanding and per-fund net flows |\n| `company_snapshot` | **One-call research brief**: profile, fundamentals, about 30 trading days and the latest news, joined |\n\nErrors surface the same stable codes as the REST API (`NOT_FOUND`, `RATE_LIMITED`, and the rest) with hints, so agents self-correct. A bad ticker points the agent back to `list_equities`.\n\n# Reference\n\n## Pagination\n\nMost list endpoints (news, disclosures, suspensions, UMA, broker summary, financial reports, corporate actions, KSEI datasets…) return a `pagination` block: `{ total, limit, offset, has_more }`. Walk pages with `offset += limit` until `has_more` is false. `limit` is capped per endpoint: over-asking silently clamps, it never errors.\n\n## Rate limits\n\nLimits are per **account**, over a rolling minute. A member's keys share **300 requests per minute**. Every response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` (seconds until the window resets), so you can pace yourself. Exceed it and you get `429` with the code `RATE_LIMITED` and a `Retry-After` header: wait that many seconds and retry.\n\nFailed keys are limited separately, per address: more than 20 requests with a wrong, malformed or revoked key in one minute block that address for 10 minutes. During the block every request from it gets `429` with code `AUTH_LOCKOUT` and `Retry-After`, including requests with a valid key. A revoked key answers `401` with the message `key revoked` and does not count.\n\n## Errors\n\nAny non-2xx response uses the same shape: `{ \"error\": { \"code\", \"message\", \"request_id\" } }`. Switch on `error.code`: it is stable across versions:\n\n| Code | Status | Meaning |\n|---|---|---|\n| `BAD_REQUEST` | 400 | Malformed ticker, bad date, `from > to` |\n| `UNAUTHORIZED` | 401 | Missing/invalid bearer key |\n| `NOT_FOUND` | 404 | Unknown ticker, or no data in the range |\n| `RATE_LIMITED` | 429 | Quota exhausted: honor `Retry-After` |\n| `AUTH_LOCKOUT` | 429 | Too many failed keys from your network: honor `Retry-After` before sending any key |\n| `INTERNAL` | 500 | Our fault: report it with the `request_id` |\n\n`error.message` is for your logs, not your UI: wording may change. The `request_id` is also in the `X-Request-Id` response header; quote it when reporting issues.\n\n## License\n\nUse of the data is governed by the [Tarutha Data Licence](https://tarutha.co/terms#data-licence), part of the [terms of service](https://tarutha.co/terms). Keys come with a paid membership. The licence says what members may do and what they may not do. The source publishers keep their own rights in their publications.","termsOfService":"https://tarutha.co/terms","contact":{"name":"Tarutha","url":"https://tarutha.co"},"license":{"name":"Tarutha Data Licence","url":"https://tarutha.co/terms#data-licence"},"version":"1.0.0"},"servers":[{"url":"https://api.tarutha.co","description":"This instance"}],"paths":{"/v1/equities":{"get":{"tags":["Equities"],"summary":"List every IDX equity you can query: start here.","description":"Returns the catalog of every IDX-listed ticker symbol Tarutha tracks\n(~970 today). **Use this first** to discover what is available before\ncalling the per-ticker endpoints below. The list is sorted A → Z and\nchanges only when IDX adds or delists a name.","operationId":"list_equities","responses":{"200":{"description":"Success: array of all available ticker symbols.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EquitiesResponse"}}}},"401":{"description":"Missing or invalid `Authorization: Bearer` header. Get a key from your Tarutha admin.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"You hit the rate limit (default 60/min). Wait the seconds in `Retry-After` and try again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Something broke on our side. Retry with backoff and quote the `request_id` if it persists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/equities/{ticker}":{"get":{"tags":["Equities"],"summary":"Look up the company behind one ticker.","description":"Returns the issuer's legal name, sector, ISIN, listing date, and listing\nstatus for the ticker you pass in. Use this for \"About this company\"\ninfo; if you want **prices** use `/prices`, if you want **valuation**\nmetrics use `/fundamentals`.\n\n**Tip:** the path parameter is case-insensitive (`bmri` and `BMRI`\nboth work).","operationId":"get_equity","parameters":[{"name":"ticker","in":"path","description":"IDX ticker symbol: typically 4 alphanumeric characters. Case is ignored.","required":true,"schema":{"type":"string"},"example":"BMRI"}],"responses":{"200":{"description":"Success: reference data for the requested ticker.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EquityResponse"}}}},"400":{"description":"The ticker is not valid (only letters and digits are allowed). Example of a valid one: `BBCA`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"We do not have this ticker. Call `GET /v1/equities` to see the full catalog.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/equities/{ticker}/fundamentals":{"get":{"tags":["Equities"],"summary":"Get the key numbers analysts care about for one ticker.","description":"A daily-refreshed snapshot of ~30 fundamental metrics: market cap,\ntrailing & forward P/E, dividend yield, profit margins, return on equity,\n52-week high/low, beta, analyst recommendation and price targets, plus\nthe company description. Sourced from Yahoo Finance `quoteSummary`.\n\n> **Important:** every field except `ticker` may be `null`. Null means\n> Yahoo does not carry that field for this symbol: it does NOT mean\n> zero. Do not compute on `null` without a guard.","operationId":"equity_fundamentals","parameters":[{"name":"ticker","in":"path","description":"IDX ticker symbol.","required":true,"schema":{"type":"string"},"example":"BMRI"}],"responses":{"200":{"description":"Success: fundamentals snapshot (any field except `ticker` may be null).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FundamentalsResponse"}}}},"400":{"description":"The ticker is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"We do not have a fundamentals snapshot for this ticker yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/equities/{ticker}/ownership":{"get":{"tags":["Equities"],"summary":"Who owns the stock: insider/institutional breakdown and top holders.","description":"Parsed from the latest Yahoo Finance holders snapshot for the ticker:\nthe insider vs institutional split, the largest institutional and fund\npositions (with report dates and position changes), and recent net\ninstitutional buying.\n\n> **Reading Indonesian issuers:** `insiders_pct` usually reflects the\n> controlling shareholder (e.g. the founding conglomerate), so a high\n> number is normal here: it is not US-style management ownership.","operationId":"get_ownership","parameters":[{"name":"ticker","in":"path","description":"IDX ticker symbol. Case is ignored.","required":true,"schema":{"type":"string"},"example":"BBCA"}],"responses":{"200":{"description":"Success: latest ownership snapshot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OwnershipResponse"}}}},"400":{"description":"The ticker is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No ownership snapshot for this ticker yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/equities/{ticker}/prices":{"get":{"tags":["Equities"],"summary":"Get the daily price history (OHLCV) for one ticker.","description":"Returns one bar per IDX trading day (Mon–Fri excluding IDX holidays),\nsorted oldest → newest. Each bar carries open / high / low / close\nprices in **IDR** plus the day's traded `volume` in shares.\n\n**Defaults:** if you omit `from` and `to`, you get the **last 365 days**\nup to today. Pass either or both to narrow or widen the window. Maximum\nuseful range is ~25 years; expect ~5,500 bars for a full historical pull.\n\n**Not adjusted:** prices are raw IDX closes: splits, bonus issues, and\ndividends are NOT back-adjusted. If you need adjusted series, wait for\nthe corporate-actions feed (Phase 3).\n\n**Sources:** the series is stitched from two feeds. The Yahoo Finance\nsweep supplies the deep history and wins wherever it carries a day; the\nIDX Trading Summary scrape fills any day Yahoo has not landed, which\nkeeps the tail of the series current when the Yahoo sweep is behind.\nBoth carry raw IDR OHLCV on the same trading calendar, so bars are\ndirectly comparable.","operationId":"equity_prices","parameters":[{"name":"ticker","in":"path","description":"IDX ticker symbol.","required":true,"schema":{"type":"string"},"example":"BMRI"},{"name":"from","in":"query","description":"Start date (inclusive), `YYYY-MM-DD`. Defaults to `to − 365 days`.","required":false,"schema":{"type":"string"},"example":"2026-01-01"},{"name":"to","in":"query","description":"End date (inclusive), `YYYY-MM-DD`. Defaults to today.","required":false,"schema":{"type":"string"},"example":"2026-04-30"}],"responses":{"200":{"description":"Success: array of daily OHLCV bars sorted oldest → newest.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricesResponse"}}}},"400":{"description":"Either the ticker is malformed, the dates are not `YYYY-MM-DD`, or `from` is after `to`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No prices in your requested range. Try a wider window: or confirm the ticker is in `GET /v1/equities`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/funds":{"get":{"tags":["Funds"],"summary":"Every mutual fund OJK publishes, for one month.","description":"Defaults to the most recent month available. Pass `period` for a specific\none. Around 2,100 funds are live in a current month; roughly a quarter sit\nat zero units, which is a matured fund rather than missing data.","operationId":"list_funds","parameters":[{"name":"q","in":"query","description":"Match on fund name or manager.","required":false,"schema":{"type":"string"},"example":"DANAMAS"},{"name":"fund_type","in":"query","description":"OJK fund class filter.","required":false,"schema":{"type":"string"},"example":"Money Market Fund"},{"name":"mi","in":"query","description":"Investment manager filter (substring).","required":false,"schema":{"type":"string"},"example":"Mandiri"},{"name":"period","in":"query","description":"Month `YYYY-MM`. Defaults to the latest available.","required":false,"schema":{"type":"string"},"example":"2026-07"},{"name":"limit","in":"query","description":"Page size (1–1000, default 200).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":50},{"name":"offset","in":"query","description":"Rows to skip (default 0).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: matching funds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FundDirectoryResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Nothing matches.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/funds/categories":{"get":{"tags":["Funds"],"summary":"Monthly mean and median return per OJK fund class.","description":"`funds_with_return` counts funds with a computable return, not funds in the\nclass: see the field description. Ranking against it ranks against\nsurvivors of that filter.","operationId":"categories","parameters":[{"name":"fund_type","in":"query","description":"OJK fund class, exactly as OJK writes it, for example\n`Fixed Income Fund`. A display label will match nothing and return an\nempty list.","required":false,"schema":{"type":"string"}},{"name":"period","in":"query","description":"`YYYY-MM`. Omit for every period.","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Page size (1–1000, default 200).","required":false,"schema":{"type":"integer","format":"int32","minimum":0}},{"name":"offset","in":"query","description":"Rows to skip (default 0).","required":false,"schema":{"type":"integer","format":"int32","minimum":0}}],"responses":{"200":{"description":"Category aggregates, newest period first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FundCategoriesResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/funds/{fund_id}/flows":{"get":{"tags":["Funds"],"summary":"Monthly net flows for one fund: money in and out, separated from market\nmovement.","description":"## Read `signal` before reading the number\n\n* `clean`: units above zero in both months. Ordinary flow. ~72% of rows.\n* `terminated`: units went to zero, because the fund wound up or a\n  protected fund matured. Only 0.8% of rows but **29% of all industry outflow**,\n  because Capital Protected Funds retire in cohorts. Priced at the\n  previous month's unit value, since a closed fund has no current price.\n* `reactivated`: units rose from zero.\n* `dormant`: zero units in both months. Correct, not missing data: about\n  27% of rows are already-matured funds sitting at zero.\n* `gap`: the months are not adjacent, so no monthly change exists.\n* `suspect`: OJK's unit count cannot be true (the per-unit value moved\n  more than 10x in a month, or one unit holds over Rp 1m). The flow is\n  withheld rather than published wrong (74 rows when it went live on\n  12 Sep 2026).\n* `partial_month`: OJK published this month or the previous one only\n  partially (industry status `partial`: 2010-12, and 2010-01 from 12 Sep\n  2026), so no flow is published across it. Flow withheld.\n\n`net_change_idr` and `performance_idr` are null on `dormant`, `gap`,\n`suspect` and `partial_month` rather than zero, so a consumer cannot accidentally sum a\nnon-measurement into a total.\n\n## What this cannot see\n\nOJK reports a month-**end** snapshot. An investor who subscribed and fully\nredeemed inside the same month is invisible, and no processing recovers\nthem. That is why every field is named `net_change` and not `flow`.","operationId":"get_fund_flows","parameters":[{"name":"fund_id","in":"path","description":"16-hex fund identifier from `/v1/funds`.","required":true,"schema":{"type":"string"},"example":"3f9a2c1e7b40d5a8"},{"name":"from","in":"query","description":"Earliest month `YYYY-MM`.","required":false,"schema":{"type":"string"},"example":"2026-01"},{"name":"to","in":"query","description":"Latest month `YYYY-MM`.","required":false,"schema":{"type":"string"},"example":"2026-07"},{"name":"flow_only","in":"query","description":"Return only months that carry a real flow.","required":false,"schema":{"type":"boolean"},"example":true},{"name":"limit","in":"query","description":"Page size (1–1000, default 200).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":200},{"name":"offset","in":"query","description":"Rows to skip (default 0).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: flow months, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FundFlowsResponse"}}}},"400":{"description":"Malformed fund_id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown fund, or no months in range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/funds/{fund_id}/metrics":{"get":{"tags":["Funds"],"summary":"Risk and return for one fund, with the window each number covers.","description":"Every windowed return is anchored on **this fund's own last priced month**,\nso `from` and `to` differ between funds and are carried per window. A\n`null` return means the fund had no priced month at the start of that\nwindow; it is never approximated from a shorter span.","operationId":"fund_metrics","parameters":[{"name":"fund_id","in":"path","description":"16-hex fund id from /v1/funds.","required":true,"schema":{"type":"string"},"example":"0a1b2c3d4e5f6071"}],"responses":{"200":{"description":"Risk and return metrics for the fund.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FundMetricsResponse"}}}},"400":{"description":"fund_id is not 16 hexadecimal characters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No metrics for this fund. It may exist in /v1/funds without enough priced months to measure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/funds/{fund_id}/nav":{"get":{"tags":["Funds"],"summary":"Monthly NAV and units outstanding for one fund.","description":"`nav_per_unit` is the price a holder sees. `units` is what moves when\ninvestors subscribe or redeem: the two together are what\n`/v1/funds/{fund_id}/flows` decomposes.","operationId":"nav","parameters":[{"name":"fund_id","in":"path","description":"16-hex fund identifier from `/v1/funds`.","required":true,"schema":{"type":"string"},"example":"3f9a2c1e7b40d5a8"},{"name":"from","in":"query","description":"Earliest month `YYYY-MM`.","required":false,"schema":{"type":"string"},"example":"2026-01"},{"name":"to","in":"query","description":"Latest month `YYYY-MM`.","required":false,"schema":{"type":"string"},"example":"2026-07"},{"name":"limit","in":"query","description":"Page size (1–1000, default 200).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":200},{"name":"offset","in":"query","description":"Rows to skip (default 0).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: NAV series, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FundNavResponse"}}}},"400":{"description":"Malformed fund_id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown fund, or no months in range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/idx/broker-summary":{"get":{"tags":["IDX reference"],"summary":"IDX daily broker summary: each securities firm's traded volume, value,\nand trade count.","description":"One trading day per request (defaults to the latest stored), ranked by\ntraded value. Filter with `firm` to follow one broker; add `from`/`to` to\nfollow it across days, newest first. Note that every trade has a buying\nand a selling broker, so all firms' value sums to about twice the\nmarket's value traded.","operationId":"broker_summary","parameters":[{"name":"date","in":"query","description":"Trading date `YYYY-MM-DD` (default: latest stored day). Ignored when `from` or `to` is given.","required":false,"schema":{"type":"string"},"example":"2026-05-04"},{"name":"from","in":"query","description":"Earliest trading date `YYYY-MM-DD`. Switches the response to a date range, newest first.","required":false,"schema":{"type":"string"},"example":"2026-08-01"},{"name":"to","in":"query","description":"Latest trading date `YYYY-MM-DD`.","required":false,"schema":{"type":"string"},"example":"2026-08-31"},{"name":"firm","in":"query","description":"Filter to one broker code.","required":false,"schema":{"type":"string"},"example":"AD"},{"name":"limit","in":"query","description":"Page size (1–200, default 50).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":50},{"name":"offset","in":"query","description":"Rows to skip.","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: brokers ranked by traded value.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrokerSummaryResponse"}}}},"400":{"description":"Bad date or firm code.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No broker rows match the filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/idx/corporate-actions":{"get":{"tags":["IDX reference"],"summary":"IDX share-issuance history: the corporate actions that changed each\ncompany's share count (splits, warrants, rights, stock dividends).","description":"Newest first. Filter with `ticker` to trace one issuer's dilution history.","operationId":"issued_actions","parameters":[{"name":"ticker","in":"query","description":"Filter to one IDX ticker.","required":false,"schema":{"type":"string"},"example":"GRPM"},{"name":"limit","in":"query","description":"Page size (1–200, default 50).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":50},{"name":"offset","in":"query","description":"Rows to skip.","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: paginated issuance events, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssuedActionsResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No issuance events match the filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/idx/disclosures":{"get":{"tags":["IDX announcements"],"summary":"IDX company disclosures: ratings, corporate actions, filings.","description":"Newest first. Filter with `ticker` to watch one issuer. Each row links\nthe official PDF attachments on idx.co.id.","operationId":"disclosures","parameters":[{"name":"ticker","in":"query","description":"Filter to one IDX ticker.","required":false,"schema":{"type":"string"},"example":"WIKA"},{"name":"limit","in":"query","description":"Page size (1–200, default 50).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":50},{"name":"offset","in":"query","description":"Rows to skip.","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: paginated disclosures, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisclosuresResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No disclosures match the filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/idx/financial-reports":{"get":{"tags":["IDX reference"],"summary":"IDX financial-report metadata: every quarterly and audited filing with\nits XBRL and PDF download URLs.","description":"Newest first. Filter by `ticker`, `year`, and `period` to pinpoint one\nfiling; the `files` array carries the actual statement downloads.","operationId":"financial_reports","parameters":[{"name":"ticker","in":"query","description":"Filter to one IDX ticker.","required":false,"schema":{"type":"string"},"example":"AADI"},{"name":"year","in":"query","description":"Filter to one report year.","required":false,"schema":{"type":"integer","format":"int32"},"example":2026},{"name":"period","in":"query","description":"Filter to one period: `tw1`, `tw2`, `tw3`, `audit`.","required":false,"schema":{"type":"string","description":"Reporting period of an IDX financial report: quarters 1-3 (`tw1`..`tw3`) or the audited full year.","enum":["tw1","tw2","tw3","audit"]},"example":"tw1"},{"name":"limit","in":"query","description":"Page size (1–200, default 50).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":50},{"name":"offset","in":"query","description":"Rows to skip.","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: paginated filings, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinancialReportsResponse"}}}},"400":{"description":"Bad ticker, year, or period.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No filings match the filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/idx/ipo":{"get":{"tags":["IDX reference"],"summary":"IDX IPO and relisting pipeline: companies coming to (or back to) the\nexchange, with planned proceeds and listing dates.","description":"Newest first.","operationId":"ipo","parameters":[{"name":"year","in":"query","description":"Filter to one listing year.","required":false,"schema":{"type":"integer","format":"int32"},"example":2026},{"name":"limit","in":"query","description":"Page size (1–200, default 50).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":50},{"name":"offset","in":"query","description":"Rows to skip.","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: paginated IPO plans, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpoResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No IPO plans match the filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/idx/securities":{"get":{"tags":["IDX reference"],"summary":"IDX securities master: every listed stock with board, listing date, and\nshares outstanding.","description":"Sorted by ticker. Filter with `board` or search with `q`.","operationId":"securities","parameters":[{"name":"board","in":"query","description":"Filter to one listing board.","required":false,"schema":{"type":"string"},"example":"Utama"},{"name":"q","in":"query","description":"Case-insensitive search on ticker or company name.","required":false,"schema":{"type":"string"},"example":"astra"},{"name":"limit","in":"query","description":"Page size (1–200, default 50).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":50},{"name":"offset","in":"query","description":"Rows to skip.","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: paginated securities, ticker order.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecuritiesResponse"}}}},"400":{"description":"Bad board or search string.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No securities match the filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/idx/suspensions":{"get":{"tags":["IDX announcements"],"summary":"IDX trading suspensions and reopenings.","description":"Newest first. `info_type` distinguishes suspensions (`SUS`) from\nunsuspensions (`UPT`). Filter with `ticker` to watch one issuer.","operationId":"suspensions","parameters":[{"name":"ticker","in":"query","description":"Filter to one IDX ticker.","required":false,"schema":{"type":"string"},"example":"IFSH"},{"name":"limit","in":"query","description":"Page size (1–200, default 50).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":50},{"name":"offset","in":"query","description":"Rows to skip.","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: paginated notices, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuspensionsResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No notices match the filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/idx/uma":{"get":{"tags":["IDX announcements"],"summary":"IDX unusual market activity (UMA) flags: the exchange's public risk\nsignal for stocks moving outside normal patterns.","description":"Newest first. Filter with `ticker` to watch one issuer.","operationId":"uma","parameters":[{"name":"ticker","in":"query","description":"Filter to one IDX ticker.","required":false,"schema":{"type":"string"},"example":"LUCY"},{"name":"limit","in":"query","description":"Page size (1–200, default 50).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":50},{"name":"offset","in":"query","description":"Rows to skip.","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: paginated UMA flags, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UmaResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No UMA flags match the filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/indices":{"get":{"tags":["Indices"],"summary":"Latest level of every IDX stock index.","description":"One row per index (45 today: `COMPOSITE`/IHSG, `LQ45`, `IDX30`, sector\nindices, …), each showing its most recent trading-day bar. Use the\n`index_code` with `GET /v1/indices/{code}` for the daily history.","operationId":"list_indices","responses":{"200":{"description":"Success: latest bar per index, sorted by index_code.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IndicesResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/indices/{code}":{"get":{"tags":["Indices"],"summary":"Daily history for one IDX index.","description":"Bars are sorted oldest → newest. Codes are case-insensitive; get the\ncatalog from `GET /v1/indices`.","operationId":"index_history","parameters":[{"name":"code","in":"path","description":"IDX index code, case-insensitive.","required":true,"schema":{"type":"string"},"example":"COMPOSITE"},{"name":"from","in":"query","description":"Earliest date (inclusive), `YYYY-MM-DD`.","required":false,"schema":{"type":"string"},"example":"2026-01-01"},{"name":"to","in":"query","description":"Latest date (inclusive), `YYYY-MM-DD`.","required":false,"schema":{"type":"string"},"example":"2026-04-30"},{"name":"limit","in":"query","description":"Page size (1–200, default 50).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":50},{"name":"offset","in":"query","description":"Rows to skip.","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: paginated daily bars, oldest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IndexHistoryResponse"}}}},"400":{"description":"Malformed index code or dates.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown index code: see `GET /v1/indices` for the catalog.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/instruments":{"get":{"tags":["Instruments"],"summary":"Find an instrument and get its ISIN.","description":"The entry point for this route family: everything else here is keyed on\nISIN, and this is how you get one from a ticker, a company name or an\ninstrument code. Covers **every security KSEI registers** (3,810 on 12 Sep 2026),\nequities alongside bonds, sukuk, government paper, warrants and\ncrowdfunding instruments.\n\nReconciled from four sources that disagreed with each other, with KSEI's\nregistry winning on identity, IDX winning on listing board and share\ncounts. Bond terms (maturity, coupon, payment frequency) come through on\nthe instruments they apply to.\n\nSearch `q` matches code or name. `BBCA` gets you the bank; `FR00` gets you\nthe government bond series.\n\n**For instruments that exist today, filter `in_latest_master=true`.**\n`status` is KSEI's own registry label and it lags: 149 codes still read\n`ACTIVE` although they have matured or been delisted, so `status=ACTIVE`\nalone returns them. `status` is left exactly as KSEI keeps it, so the field\nand its filter always agree; `in_latest_master` is the \"exists now\" test.","operationId":"list_instruments","parameters":[{"name":"q","in":"query","description":"Match on code or company name.","required":false,"schema":{"type":"string"},"example":"BBCA"},{"name":"isin","in":"query","description":"Exact ISIN lookup.","required":false,"schema":{"type":"string"},"example":"IDG000006800"},{"name":"security_type","in":"query","description":"Instrument class filter.","required":false,"schema":{"type":"string"},"example":"GOVERNMENT BOND"},{"name":"status","in":"query","description":"KSEI status label filter, e.g. `ACTIVE`. KSEI's label lags; see `in_latest_master`.","required":false,"schema":{"type":"string"},"example":"ACTIVE"},{"name":"in_latest_master","in":"query","description":"`true`: only codes in KSEI's latest monthly securities master, i.e. instruments that exist today.","required":false,"schema":{"type":"boolean"},"example":true},{"name":"limit","in":"query","description":"Page size (1–1000, default 200).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":50},{"name":"offset","in":"query","description":"Rows to skip (default 0).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: matching instruments.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstrumentDirectoryResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Nothing matches.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/instruments/{isin}/flows":{"get":{"tags":["Instruments"],"summary":"Month-over-month change in who holds this instrument.","description":"Derived from the ownership series: how many units each investor type added\nor shed, and how the foreign share of custody moved in percentage points.\nAvailable for bonds and sukuk as well as equities.\n\n**This is net change, not trading volume.** The source is a month-end\nsnapshot, so a position opened and closed inside one month is invisible\nhere and no field should be read as \"bought\".\n\n**Check `signal` before drawing conclusions.** A raw delta conflates three\ndifferent events: someone genuinely changing a position, paper migrating\ninto or out of the depository, and corporate actions that multiply every\nunit count at once. Only `clean`, `pure_split` and `issuance_change` are\nposition changes, and `is_position_signal` says so directly. On\n`pure_split` months use `adjusted_foreign_net_change_total`: the raw\nfigure is dominated by the split itself, and one real example moved\n+36.8bn units raw against −65.8m adjusted.\n\nPass `position_only=true` to drop the ambiguous months entirely.","operationId":"get_instrument_flows","parameters":[{"name":"isin","in":"path","description":"12-character ISIN.","required":true,"schema":{"type":"string"},"example":"IDG000006800"},{"name":"from","in":"query","description":"Earliest month, `YYYY-MM`.","required":false,"schema":{"type":"string"},"example":"2025-01"},{"name":"to","in":"query","description":"Latest month, `YYYY-MM`.","required":false,"schema":{"type":"string"},"example":"2026-07"},{"name":"position_only","in":"query","description":"Return only months readable as a position change.","required":false,"schema":{"type":"boolean"},"example":true},{"name":"limit","in":"query","description":"Page size (1–1000, default 200).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":200},{"name":"offset","in":"query","description":"Rows to skip (default 0).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: monthly net change, oldest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstrumentFlowsResponse"}}}},"400":{"description":"Malformed ISIN.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No flow rows for this ISIN in the requested window.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/instruments/{isin}/ownership":{"get":{"tags":["Instruments"],"summary":"Who holds this instrument, month by month, straight from KSEI's depository\nrecords.","description":"Covers **every instrument class KSEI settles**, not just equities: bonds,\nsukuk, government paper and funds included. Holdings are broken across nine\ninvestor types on each of the domestic and foreign sides, so you can see\nwhether a position sits with pension funds, banks, retail or corporates.\n\n**Read `custody_pct` before quoting any percentage.** `foreign_pct` is the\nshare of what sits in C-BEST custody, which is the figure that is\nmeaningful on every row. It is not the share of the whole issue: most\ngovernment paper settles at Bank Indonesia rather than KSEI, so an\ninstrument can show 100% domestic custody while only a few percent of the\nissue is in custody at all. `foreign_pct_of_issued` gives the other\ndenominator where KSEI reports an issued figure.\n\nReturns oldest month first. 37 months of history are available.","operationId":"get_instrument_ownership","parameters":[{"name":"isin","in":"path","description":"12-character ISIN.","required":true,"schema":{"type":"string"},"example":"IDG000006800"},{"name":"from","in":"query","description":"Earliest month, `YYYY-MM`.","required":false,"schema":{"type":"string"},"example":"2025-01"},{"name":"to","in":"query","description":"Latest month, `YYYY-MM`.","required":false,"schema":{"type":"string"},"example":"2026-07"},{"name":"limit","in":"query","description":"Page size (1–1000, default 200).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":200},{"name":"offset","in":"query","description":"Rows to skip (default 0).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: monthly ownership, oldest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstrumentOwnershipResponse"}}}},"400":{"description":"Malformed ISIN.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No ownership rows for this ISIN in the requested window.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/ksei/announcements":{"get":{"tags":["KSEI"],"summary":"KSEI announcements: new ISIN codes, securities registrations, and\noperational notices from the central depository.","description":"Newest first. New-instrument registrations land here before anywhere else.","operationId":"ksei_announcements","parameters":[{"name":"kind","in":"query","description":"Filter to one feed: `isin`, `new_securities`, `today`, `ksei`.","required":false,"schema":{"type":"string","description":"Which KSEI announcement feed a row came from.","enum":["isin","new_securities","today","ksei"]},"example":"isin"},{"name":"from","in":"query","description":"Earliest date, `YYYY-MM-DD`.","required":false,"schema":{"type":"string"},"example":"2026-07-01"},{"name":"to","in":"query","description":"Latest date, `YYYY-MM-DD`.","required":false,"schema":{"type":"string"},"example":"2026-07-31"},{"name":"limit","in":"query","description":"Page size (1–200, default 50).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":50},{"name":"offset","in":"query","description":"Rows to skip.","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: paginated notices, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KseiAnnouncementsResponse"}}}},"400":{"description":"Bad kind or dates.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No notices match the filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/ksei/archives":{"get":{"tags":["KSEI"],"summary":"KSEI monthly archive catalog: the StatisEfek securities-master and\nBalancepos holding-composition snapshots, monthly back to 2012.","description":"Newest first. This is the catalog (file metadata + source URLs); the\narchives themselves are mirrored in the Tarutha data lake.","operationId":"ksei_archives","parameters":[{"name":"kind","in":"query","description":"Filter to one series: `master_securities`, `holding_composition`.","required":false,"schema":{"type":"string","description":"Which KSEI archive series a file belongs to.","enum":["master_securities","holding_composition"]},"example":"master_securities"},{"name":"limit","in":"query","description":"Page size (1–200, default 50).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":50},{"name":"offset","in":"query","description":"Rows to skip.","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: paginated archive files, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KseiArchivesResponse"}}}},"400":{"description":"Bad kind.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No archive files match the filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/ksei/corporate-actions":{"get":{"tags":["KSEI"],"summary":"KSEI corporate-action schedules: dividends, rights, bonuses, meetings.","description":"Newest first. Eleven action types; filter with `type` and/or `ticker`.\nEach row links the official KSEI PDF that carries the full schedule\n(cum date, ex date, recording date, payment date, ratios/amounts).","operationId":"corporate_actions","parameters":[{"name":"type","in":"query","description":"Filter to one action type, e.g. `cash-dividend`, `rights-distribution`, `rups-rupo`.","required":false,"schema":{"type":"string"},"example":"cash-dividend"},{"name":"ticker","in":"query","description":"Filter to one IDX ticker.","required":false,"schema":{"type":"string"},"example":"RUIS"},{"name":"from","in":"query","description":"Earliest announcement date, `YYYY-MM-DD`.","required":false,"schema":{"type":"string"},"example":"2026-07-01"},{"name":"to","in":"query","description":"Latest announcement date, `YYYY-MM-DD`.","required":false,"schema":{"type":"string"},"example":"2026-07-31"},{"name":"limit","in":"query","description":"Page size (1–200, default 50).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":50},{"name":"offset","in":"query","description":"Rows to skip.","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: paginated schedule entries, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CorporateActionsResponse"}}}},"400":{"description":"Bad type, ticker, or dates.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No schedules match the filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/ksei/datasets":{"get":{"tags":["KSEI"],"summary":"List every KSEI dashboard dataset Tarutha tracks.","description":"Use this as a catalog: pick a `slug` (e.g. `share-values-at-ksei`),\nnote its `granularity` (`monthly` / `daily` / `snapshot`), and inspect\nthe available `series` and `categories` before calling\n`GET /v1/ksei/datasets/{slug}` for the actual time series.\n\n**Why these matter:** these are KSEI's structural indicators of the\nIndonesian capital market: total assets in custody, share/bond values,\nforeign vs domestic ownership splits, transfer-instruction volumes,\nnumber of investor sub-accounts. Long-running reference data, ideal\nfor macro-style charts.","operationId":"list_datasets","responses":{"200":{"description":"Success: catalog of all 12 KSEI datasets.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KseiDatasetsResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/ksei/datasets/{slug}":{"get":{"tags":["KSEI"],"summary":"Get the time series for one KSEI dataset, with optional filters.","description":"Datapoints are sorted by `period` ascending (oldest first), then by\n`series` and `category` for tiebreaks. Use the `from` and `to` params\nto bound the period range: format must match the dataset's\n`granularity` (`YYYY-MM` for monthly/snapshot, `YYYY-MM-DD` for daily).\n\n**Tip:** call `GET /v1/ksei/datasets` first to discover the available\n`series` and `categories` for the slug you want.","operationId":"get_dataset","parameters":[{"name":"slug","in":"path","description":"KSEI dataset slug from `GET /v1/ksei/datasets`.","required":true,"schema":{"type":"string"},"example":"share-values-at-ksei"},{"name":"series","in":"query","description":"Filter to one series dimension (e.g. `Aset Asing`). Omit for all.","required":false,"schema":{"type":"string"},"example":"Aset Asing"},{"name":"category","in":"query","description":"Filter to one category (snapshot datasets only).","required":false,"schema":{"type":"string"},"example":"Emiten"},{"name":"from","in":"query","description":"Earliest period (lexicographic), `YYYY-MM` or `YYYY-MM-DD`.","required":false,"schema":{"type":"string"},"example":"2023-01"},{"name":"to","in":"query","description":"Latest period (lexicographic).","required":false,"schema":{"type":"string"},"example":"2024-12"},{"name":"limit","in":"query","description":"Page size (1–1000, default 200).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":200},{"name":"offset","in":"query","description":"Rows to skip (default 0).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: paginated datapoints sorted by period ascending.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KseiDatapointsResponse"}}}},"400":{"description":"Invalid slug: must be lowercase alphanumeric with hyphens.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No datapoints match the slug + filter combination.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/ksei/statistics-pdfs":{"get":{"tags":["KSEI"],"summary":"KSEI monthly statistics PDFs: the official public-statistics reports\n(investor counts, asset values, demographic splits), one per month.","description":"Newest first. Catalog only; PDFs are mirrored in the Tarutha data lake.","operationId":"ksei_statistics_pdfs","parameters":[{"name":"limit","in":"query","description":"Page size (1–200, default 50).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":50},{"name":"offset","in":"query","description":"Rows to skip.","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: paginated monthly reports, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KseiStatisticsPdfsResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No reports stored yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/ksei/statistik":{"get":{"tags":["KSEI"],"summary":"Monthly capital-market structure series parsed from KSEI's official\nStatistik PDF decks.","description":"Coverage starts 2024-01 and tracks four families of metrics:\ninvestor totals per platform (`sid_total`), C-BEST custody detail per\nsecurity type (`cbest_*`: counts, local/foreign splits, values in Rp\ntrillion), S-INVEST mutual-fund AUM per fund type (`sinvest_*`), and\ndomestic investor share per region (`regional_investor_share`).\nSorted by `period` ascending, then `metric`.","operationId":"statistik","parameters":[{"name":"metric","in":"query","description":"Metric key filter (e.g. `sid_total`, `cbest_value_rp_t`, `sinvest_aum`, `regional_investor_share`).","required":false,"schema":{"type":"string"},"example":"sid_total"},{"name":"platform","in":"query","description":"`segment.platform` filter: `pasar_modal`, `s_invest`, `c_best`, `sbn`.","required":false,"schema":{"type":"string","description":"`segment.platform` values in the KSEI statistics.","enum":["pasar_modal","s_invest","c_best","sbn"]},"example":"pasar_modal"},{"name":"security_type","in":"query","description":"`segment.security_type` filter (cbest_* metrics), e.g. `Equity`.","required":false,"schema":{"type":"string"},"example":"Equity"},{"name":"fund_type","in":"query","description":"`segment.fund_type` filter (sinvest_* metrics), e.g. `Total`.","required":false,"schema":{"type":"string"},"example":"Total"},{"name":"region","in":"query","description":"`segment.region` filter (regional metrics), e.g. `Jawa`.","required":false,"schema":{"type":"string"},"example":"Jawa"},{"name":"from","in":"query","description":"Earliest period, `YYYY-MM`.","required":false,"schema":{"type":"string"},"example":"2024-01"},{"name":"to","in":"query","description":"Latest period, `YYYY-MM`.","required":false,"schema":{"type":"string"},"example":"2026-03"},{"name":"limit","in":"query","description":"Page size (1–1000, default 200).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":200},{"name":"offset","in":"query","description":"Rows to skip (default 0).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: paginated statistik datapoints sorted by period ascending.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KseiStatistikResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No datapoints match the filters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/managers":{"get":{"tags":["Funds"],"summary":"Every investment manager, ranked, for one month.","description":"Defaults to the most recent month. 85 managers reported Jul 2026, and the\n`aum_idr` column sums to OJK's published industry total exactly: if it\ndoes not for some month, treat that month as suspect rather than the\nendpoint.","operationId":"league","parameters":[{"name":"period","in":"query","description":"Month `YYYY-MM`. Defaults to the latest available.","required":false,"schema":{"type":"string"},"example":"2026-07"},{"name":"q","in":"query","description":"Case-insensitive substring match on the manager's name.","required":false,"schema":{"type":"string"},"example":"mandiri"},{"name":"limit","in":"query","description":"Page size (1–1000, default 200).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":50},{"name":"offset","in":"query","description":"Rows to skip (default 0).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: managers ranked by AUM.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManagerLeagueResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No data for that period.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/managers/{id}":{"get":{"tags":["Funds"],"summary":"One investment manager, with their shelf and their rank history.","operationId":"profile","parameters":[{"name":"id","in":"path","description":"Manager slug from `/v1/managers`.","required":true,"schema":{"type":"string"},"example":"mandiri-manajemen-investasi"},{"name":"period","in":"query","description":"Month `YYYY-MM`. Defaults to the latest available.","required":false,"schema":{"type":"string"},"example":"2026-07"}],"responses":{"200":{"description":"Success: one manager.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManagerProfileResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No manager with that slug.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/movers":{"get":{"tags":["Indices"],"summary":"Daily top movers on the IDX: gainers, losers, most traded.","description":"Ranks all IDX stocks for one trading day using official IDX daily data\n(which includes foreign buy/sell flow). `by=pct` with\n`direction=gainers|losers` gives the classic movers lists; `by=value`,\n`by=volume`, or `by=frequency` give the most-active rankings.\nThinly-traded rows (no volume) are excluded.","operationId":"movers","parameters":[{"name":"by","in":"query","description":"Ranking metric: `pct` (default), `value`, `volume`, `frequency`.","required":false,"schema":{"type":"string","description":"Ranking metric for `/v1/movers`.","enum":["pct","value","volume","frequency"]},"example":"pct"},{"name":"direction","in":"query","description":"`gainers` (default) or `losers`: applies to `by=pct`.","required":false,"schema":{"type":"string","description":"Sort direction for `/v1/movers` when `by=pct`.","enum":["gainers","losers"]},"example":"gainers"},{"name":"date","in":"query","description":"Trading date `YYYY-MM-DD`; defaults to latest available.","required":false,"schema":{"type":"string"},"example":"2026-04-30"},{"name":"limit","in":"query","description":"Rows to return (1–50, default 10).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":10}],"responses":{"200":{"description":"Success: ranked movers for the trading day.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MoversResponse"}}}},"400":{"description":"Bad `by`, `direction`, or `date`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No trading data for the requested date.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/news/articles":{"get":{"tags":["News"],"summary":"Browse the latest Indonesian capital-market news, filterable by source,\nticker, and date range.","description":"Articles are aggregated continuously (polled every 15 minutes) from 20+\nIndonesian financial, business, and policy outlets (including CNBC\nIndonesia, Kontan, Bisnis, Kompas, Katadata, Detik Finance, IDN Financials,\nInvestor.id, and IDX Channel), plus macro and regulator coverage of Bank\nIndonesia and OJK. Each article is tagged with the IDX tickers it mentions,\nso you can filter to one ticker to build a per-stock news feed.\n\n**Sorting:** newest `published_at` first.\n\n**Pagination:** offset/limit (max `limit=100`). The `pagination` block\nin the response carries `total`, `limit`, `offset`, and `has_more`.","operationId":"list_articles","parameters":[{"name":"source","in":"query","description":"Filter to one source key (e.g. `cnbc_indonesia`).","required":false,"schema":{"type":"string"},"example":"cnbc_indonesia"},{"name":"ticker","in":"query","description":"Filter to articles mentioning this IDX ticker. Case-insensitive.","required":false,"schema":{"type":"string"},"example":"MEDC"},{"name":"from","in":"query","description":"Earliest `published_at` (inclusive), `YYYY-MM-DD`.","required":false,"schema":{"type":"string"},"example":"2026-04-01"},{"name":"to","in":"query","description":"Latest `published_at` (inclusive), `YYYY-MM-DD`.","required":false,"schema":{"type":"string"},"example":"2026-05-02"},{"name":"limit","in":"query","description":"Page size (1–100, default 20).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":20},{"name":"offset","in":"query","description":"Rows to skip (default 0).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: paginated array of articles, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticlesResponse"}}}},"400":{"description":"A date filter was not `YYYY-MM-DD`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/sbn/series":{"get":{"tags":["SBN"],"summary":"Every government security outstanding on one snapshot date.","description":"Defaults to the most recent snapshot. Later years snapshot weekly, earlier\nones monthly, so pass `as_of` for an exact date rather than assuming\nmonth-ends exist.","operationId":"list_sbn_series","parameters":[{"name":"q","in":"query","description":"Match on series code.","required":false,"schema":{"type":"string"},"example":"FR00"},{"name":"instrument_class","in":"query","description":"`GOVERNMENT_DEBT` or `GOVERNMENT_ISLAMIC`.","required":false,"schema":{"type":"string"},"example":"GOVERNMENT_ISLAMIC"},{"name":"currency","in":"query","description":"Denomination filter.","required":false,"schema":{"type":"string"},"example":"IDR"},{"name":"tradable","in":"query","description":"Tradable secondary-market paper only.","required":false,"schema":{"type":"boolean"},"example":true},{"name":"as_of","in":"query","description":"Snapshot date `YYYY-MM-DD`. Defaults to the latest.","required":false,"schema":{"type":"string"},"example":"2026-07-31"},{"name":"limit","in":"query","description":"Page size (1–1000, default 200).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":50},{"name":"offset","in":"query","description":"Rows to skip (default 0).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: matching series.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SbnSeriesResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Nothing matches.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/sbn/series/{series}/outstanding":{"get":{"tags":["SBN"],"summary":"Amount outstanding for one series over time, newest first.","description":"History reaches back to **2002**. Snapshot frequency is not constant:\nweekly in later years, monthly in earlier ones, so treat this as an\nirregular time series rather than a monthly one.","operationId":"outstanding","parameters":[{"name":"series","in":"path","description":"Series code from `/v1/sbn/series`.","required":true,"schema":{"type":"string"},"example":"FR0087"},{"name":"from","in":"query","description":"Earliest date `YYYY-MM-DD` or `YYYY-MM`.","required":false,"schema":{"type":"string"},"example":"2020-01"},{"name":"to","in":"query","description":"Latest date `YYYY-MM-DD` or `YYYY-MM`.","required":false,"schema":{"type":"string"},"example":"2026-07"},{"name":"limit","in":"query","description":"Page size (1–1000, default 200).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":200},{"name":"offset","in":"query","description":"Rows to skip (default 0).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: outstanding history.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SbnOutstandingResponse"}}}},"400":{"description":"Malformed series code.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown series, or nothing in range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/sbn/series/{series}/ownership":{"get":{"tags":["SBN"],"summary":"Who holds one government security, month by month, against both\ndenominators.","description":"## Read `custody_pct_of_outstanding` before either percentage\n\nMost Indonesian government paper settles at Bank Indonesia rather than\nKSEI, so KSEI's depository view often covers a small fraction of an issue.\n`FR0087` in 2026-07: foreign is 2.25% **of custody** but 0.042% **of the\nissue**, because only 1.88% of the issue is in custody. Both are correct;\nthey answer different questions.\n\n## Coverage\n\n**37 months, 2023-07 onward**: where KSEI's depository records overlap\nDJPPR's. `/outstanding` on the same series reaches back to 2002. The short\nwindow here is the join, not missing data.","operationId":"get_sbn_ownership","parameters":[{"name":"series","in":"path","description":"Series code from `/v1/sbn/series`.","required":true,"schema":{"type":"string"},"example":"FR0087"},{"name":"from","in":"query","description":"Earliest month `YYYY-MM`.","required":false,"schema":{"type":"string"},"example":"2024-01"},{"name":"to","in":"query","description":"Latest month `YYYY-MM`.","required":false,"schema":{"type":"string"},"example":"2026-07"},{"name":"limit","in":"query","description":"Page size (1–1000, default 200).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":200},{"name":"offset","in":"query","description":"Rows to skip (default 0).","required":false,"schema":{"type":"integer","format":"int32","minimum":0},"example":0}],"responses":{"200":{"description":"Success: ownership months, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SbnOwnershipResponse"}}}},"400":{"description":"Malformed series code.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Series has no KSEI overlap, or nothing in range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/status":{"get":{"tags":["Status"],"summary":"Data freshness per source. No key needed.","operationId":"get_status","responses":{"200":{"description":"Freshness of every source, worst first inside each source's list order.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}},"429":{"description":"Rate limit hit: see `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{}]}},"/v1/watchlists":{"get":{"tags":["Watchlists"],"summary":"Every watchlist belonging to the calling key.","operationId":"list","responses":{"200":{"description":"Success: your watchlists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchlistsResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Watchlists"],"summary":"Create a watchlist.","operationId":"create","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchlistInput"}}},"required":true},"responses":{"200":{"description":"Created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchlistResponse"}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/watchlists/{id}":{"get":{"tags":["Watchlists"],"summary":"One watchlist.","operationId":"get","parameters":[{"name":"id","in":"path","description":"Watchlist id.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchlistResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No watchlist with that id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"tags":["Watchlists"],"summary":"Replace a watchlist's contents.","operationId":"update","parameters":[{"name":"id","in":"path","description":"Watchlist id.","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchlistInput"}}},"required":true},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchlistResponse"}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No watchlist with that id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["Watchlists"],"summary":"Delete a watchlist.","operationId":"delete","parameters":[{"name":"id","in":"path","description":"Watchlist id.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchlistDeletedResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No watchlist with that id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/watchlists/{id}/alerts":{"get":{"tags":["Watchlists"],"summary":"What this watchlist would be told about the latest confirmed month.","description":"Computed, not sent. Read this against real data before wiring delivery.","operationId":"alerts","parameters":[{"name":"id","in":"path","description":"Watchlist id.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success: what would be sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertReportResponse"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No watchlist with that id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"components":{"schemas":{"Alert":{"type":"object","required":["kind","subject_kind","subject","subject_name","message","severity"],"properties":{"kind":{"type":"string","description":"What kind of change this is: stable enough to switch on.","example":"rank_moved"},"message":{"type":"string","description":"One sentence a reader can act on without opening anything else."},"severity":{"type":"string","description":"`high` when it concerns a threshold or a disappearance, else `normal`.","example":"normal"},"subject":{"type":"string","description":"Slug, fund id, or type name.","example":"mandiri-manajemen-investasi"},"subject_kind":{"type":"string","description":"`manager`, `fund` or `fund_type`.","example":"manager"},"subject_name":{"type":"string","description":"Human-readable name of the subject."}}},"AlertReport":{"type":"object","required":["watchlist_id","watchlist_name","status","alerts"],"properties":{"alerts":{"type":"array","items":{"$ref":"#/components/schemas/Alert"}},"compared_with":{"type":["string","null"],"description":"The month it was compared against."},"note":{"type":["string","null"],"description":"Why nothing was computed, when `status` is not `ready`."},"period":{"type":["string","null"],"description":"The confirmed month the alerts describe."},"status":{"type":"string","description":"`ready` when a confirmed month was compared, `awaiting_confirmation`\nwhen the newest data has not been re-read enough times yet.","example":"ready"},"watchlist_id":{"type":"string"},"watchlist_name":{"type":"string"}}},"AlertReportResponse":{"type":"object","description":"What a watchlist would be told about the latest confirmed month.","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/AlertReport"},"meta":{"$ref":"#/components/schemas/Meta"}}},"Article":{"type":"object","description":"One scraped news article tagged with the IDX tickers it mentions.","required":["id","url","title","published_at","first_seen_at","source","tickers"],"properties":{"first_seen_at":{"type":"string","description":"When Tarutha first observed the article.","example":"2026-05-02T14:42:29Z"},"id":{"type":"string","description":"Mongo ObjectId hex (24 chars). Stable for the article's lifetime.","example":"69f60d55f8fe0d6b69fe2956"},"language":{"type":["string","null"],"description":"ISO 639-1 language code (`id`, `en`).","example":"id"},"match_confidence":{"type":["object","null"],"description":"Per-ticker match confidence score (0.0 = weak, 1.0 = explicit).\nSame set of keys as `tickers`. `null` when no tickers matched.","additionalProperties":{"type":"number","format":"double"},"propertyNames":{"type":"string"},"example":{"MEDC":0.95}},"published_at":{"type":"string","description":"Publication time as reported by the source, RFC 3339.","example":"2026-05-02T07:45:08Z"},"redistributable":{"type":["boolean","null"],"description":"Whether Tarutha has the right to redistribute the headline+summary\n(RSS terms permitting). The full article body is never stored.","example":true},"source":{"type":"string","description":"Source key (e.g. `cnbc_indonesia`, `kontan`, `bisnis`, `katadata`,\n`idn_financials`). Stable per publisher, so it is safe to filter on.","example":"cnbc_indonesia"},"source_type":{"type":["string","null"],"description":"How the source was scraped (`rss`, `html`, `api`).","example":"rss"},"summary":{"type":["string","null"],"description":"Lead paragraph or RSS-provided summary. May be null when the source\ndoes not carry one.","example":"Medco Energi mencatat laba bersih kuartal I-2026 melonjak menjadi US$72,15 juta. Namun, tekanan biaya dan utang tinggi membayangi kinerja positif ini."},"tickers":{"type":"array","items":{"type":"string"},"description":"IDX tickers mentioned in the article. Empty array when no IDX\nticker was matched.","example":["MEDC"]},"title":{"type":"string","description":"Article headline (publisher's wording).","example":"Kinerja Medco (MEDC) Dibayangi Beban Bunga"},"url":{"type":"string","description":"Canonical URL to the original article on the publisher's site.","example":"https://www.cnbcindonesia.com/market/20260502081658-17-731637/kinerja-medco--medc--dibayangi-beban-bunga"}}},"ArticlesResponse":{"type":"object","description":"What you get back from `GET /v1/news/articles`.\n\n**`data`**: newest-first array of articles (max 100 per page). Each\narticle carries the publisher URL, headline, summary, source key,\npublication time, and the IDX tickers the scraper matched.\n\n**`pagination`**: `total` (matching rows), `limit`, `offset`,\n`has_more`. Use `offset += limit` to walk to the next page.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Article"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}},"example":{"data":[{"id":"69f60d55f8fe0d6b69fe2956","url":"https://www.cnbcindonesia.com/market/20260502081658-17-731637/kinerja-medco--medc--dibayangi-beban-bunga","title":"Kinerja Medco (MEDC) Dibayangi Beban Bunga","summary":"Medco Energi mencatat laba bersih kuartal I-2026 melonjak menjadi US$72,15 juta. Namun, tekanan biaya dan utang tinggi membayangi kinerja positif ini.","published_at":"2026-05-02T07:45:08Z","first_seen_at":"2026-05-02T14:42:29Z","source":"cnbc_indonesia","source_type":"rss","tickers":["MEDC"],"match_confidence":{"MEDC":0.95},"language":"id","redistributable":true}],"meta":{"request_id":"abc12345-678d-9012-345e-67890abcdef1","ts":"2026-05-02T15:00:00Z","source":"tarutha"},"pagination":{"total":185,"limit":20,"offset":0,"has_more":true}}},"Attachment":{"type":"object","description":"One attachment on an IDX disclosure.","properties":{"filename":{"type":["string","null"],"example":"20260709_WIKA_Laporan Hasil Pemeringkatan.pdf"},"url":{"type":["string","null"],"example":"https://www.idx.co.id/StaticData/NewsAndAnnouncement/ANNOUNCEMENTSTOCK/From_EREP/202607/e08b30aeaf.pdf"}}},"BrokerDay":{"type":"object","description":"One broker's aggregate trading for one day.","properties":{"date":{"type":["string","null"],"description":"Trading date, `YYYY-MM-DD`.","example":"2026-05-04"},"firm_id":{"type":["string","null"],"description":"Two-letter IDX broker code.","example":"AD"},"firm_name":{"type":["string","null"],"example":"Sukadana Prima Sekuritas"},"frequency":{"type":["number","null"],"format":"double","description":"Number of trades."},"value":{"type":["number","null"],"format":"double","description":"Traded value, IDR."},"volume":{"type":["number","null"],"format":"double","description":"Shares traded."}}},"BrokerSummaryResponse":{"type":"object","description":"What you get back from `GET /v1/idx/broker-summary`: one trading day's\nbroker aggregates, ranked by traded value.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BrokerDay"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"Cadence":{"type":"string","description":"How often the source publishes. Only the cadences a dataset uses exist here,\nso the spec lists what the route can answer.","enum":["trading-day","monthly","continuous"]},"CategoryExclusions":{"type":"object","description":"Why a fund priced in this period contributed no return to the aggregate.\n\nFour reasons, kept apart because they mean different things and are wildly\ndifferent sizes. Measured on 2026-07, of 668 excluded funds (before the\nfourth existed):\n\n- `no_nav_per_unit`: **646**, dormant funds sitting at zero units. Not a\n  defect and not missing data: a matured or wound-up fund correctly has no\n  price per unit. This is the overwhelming majority.\n- `no_prior_month`: a gap in the series, so no adjacent month to compare\n  against. A coverage problem.\n- `non_positive_prior_nav`: a fund whose return cannot be computed at all.\n- `suspect_units`: OJK's unit count cannot be true (the per-unit value\n  moved more than 10x in a month, or one unit holds over Rp 1m), so the\n  return is withheld (SCRAPPER-95, live 12 Sep 2026; 57 category rows have\n  one or more). `null` on rows written before it existed.\n\nThe four together are what separates `funds_in_category` from\n`funds_with_return`. Collapsing them into one number would hide that 97% of\nthe gap is ordinary dormancy rather than anything wrong.","properties":{"no_nav_per_unit":{"type":["integer","null"],"format":"int64"},"no_prior_month":{"type":["integer","null"],"format":"int64"},"non_positive_prior_nav":{"type":["integer","null"],"format":"int64"},"suspect_units":{"type":["integer","null"],"format":"int64"}}},"CategoryRow":{"type":"object","required":["fund_type","period","excluded"],"properties":{"excluded":{"$ref":"#/components/schemas/CategoryExclusions","description":"Why the rest were left out. `null` until the writer emits it."},"fund_type":{"type":"string"},"funds_in_category":{"type":["integer","null"],"format":"int64","description":"Funds priced in this period: the honest peer count, and the\ndenominator a rank should be taken against.\n\n`null` until `build_analytics.py` emits it. Measured on 2026-07, the\ngap this closes is large: 2,127 funds were priced while 1,459 had a\ncomputable return, so a rank against the latter is wrong by 31.4%.\nFixed Income read 352 against 523 actually priced."},"funds_with_return":{"type":["integer","null"],"format":"int64","description":"Funds that had a **computable** return: previous month present and\nadjacent, and a positive prior NAV. `mean_return` and `median_return`\nare computed over exactly this set, so it is their denominator, but it\nis NOT the peer count. Use `funds_in_category` for that."},"mean_return":{"type":["number","null"],"format":"double","description":"Mean return across `funds_with_return`, not across the category."},"median_return":{"type":["number","null"],"format":"double","description":"Upper-middle value rather than the mean of the two middle values on an\neven count, as the writer computes it. Biased high on even counts."},"period":{"type":"string"},"survivorship_free":{"type":["boolean","null"],"description":"Whether dead funds are included in the cohort. Derived per row by the\nwriter as of 9d00765; it was a hardcoded constant before that, so an\nolder document states a property of the pipeline rather than of itself."}}},"CorporateAction":{"type":"object","description":"One KSEI corporate-action schedule entry.","required":["ca_type"],"properties":{"ca_type":{"type":"string","description":"Action type: `cash-dividend`, `share-dividend`, `mix-dividend`,\n`share-bonus`, `rights-distribution`, `masr`,\n`interest-principal-distribution`, `meeting-announcement`,\n`meeting-convocation`, `minutes-of-meeting`, `rups-rupo`.","example":"cash-dividend"},"date":{"type":["string","null"],"description":"Announcement date, `YYYY-MM-DD`.","example":"2026-07-07"},"letter_no":{"type":["string","null"],"description":"KSEI letter number.","example":"KSEI-17760/JKU/0726"},"pdf_url":{"type":["string","null"],"description":"Official KSEI PDF with the full schedule (cum/ex/record/payment dates)."},"subject":{"type":["string","null"],"description":"Indonesian subject line describing the action.","example":"Revisi Jadwal Dividen Tunai atas efek RADIANT UTAMA INTERINSCO Tbk (RUIS)."},"ticker":{"type":["string","null"],"description":"IDX ticker (absent for some bond/meeting notices).","example":"RUIS"}}},"CorporateActionsResponse":{"type":"object","description":"What you get back from `GET /v1/ksei/corporate-actions`: schedule\nentries newest first, each linking the official KSEI PDF.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CorporateAction"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"CrisisBehaviour":{"type":"object","description":"Behaviour across one historical drawdown window.","required":["crisis","from","to"],"properties":{"crisis":{"type":"string","description":"`gfc_2008`, `taper_2013`, `selloff_2015` or `covid_2020`."},"from":{"type":"string"},"max_drawdown":{"type":["number","null"],"format":"double","description":"Worst peak-to-trough fall inside the window."},"to":{"type":"string"},"total_return":{"type":["number","null"],"format":"double","description":"Return across the window. `null` when the fund did not exist yet, which\nis itself the answer to \"how did it do in 2008\"."}}},"Datapoint":{"type":"object","description":"One time-series datapoint from a KSEI dashboard dataset.","required":["period","series","value","fetched_at"],"properties":{"category":{"type":["string","null"],"description":"Snapshot-only: extra dimension (e.g. `Emiten`, `Reksadana`).\n`null` for monthly/daily.","example":"Emiten"},"fetched_at":{"type":"string","description":"When Tarutha last refreshed this datapoint from KSEI.","example":"2026-05-02T10:06:19Z"},"period":{"type":"string","description":"Period label: interpretation depends on the dataset's `granularity`:\n`YYYY-MM` (monthly / snapshot), `YYYY-MM-DD` (daily).","example":"2024-12"},"period_label":{"type":["string","null"],"description":"Indonesian human-readable label (e.g. `\"Desember 2024\"`).","example":"Desember 2024"},"series":{"type":"string","description":"Series dimension (`Total`, `Aset Asing`, `Aset Lokal`, etc.).","example":"Aset Asing"},"value":{"type":"number","format":"double","description":"Numeric value, in the dataset's `unit`.","example":3521.344}}},"Dataset":{"type":"object","description":"Catalog entry for one KSEI dataset (one `slug`).","required":["slug","title_en","granularity","unit","series","categories","count"],"properties":{"categories":{"type":"array","items":{"type":"string"},"description":"All `category` keys observed (only populated for `snapshot`\ngranularity; use as the `category` query param).","example":["Emiten","Reksadana","Obligasi Korporasi"]},"count":{"type":"integer","format":"int64","description":"Total datapoints stored for this slug.","example":96,"minimum":0},"granularity":{"type":"string","description":"`monthly` (period = `YYYY-MM`), `daily` (period = `YYYY-MM-DD`), or\n`snapshot` (period = `YYYY-MM`, with an extra `category` dimension).","example":"monthly"},"period_max":{"type":["string","null"],"description":"Latest period in the dataset.","example":"2024-12"},"period_min":{"type":["string","null"],"description":"Earliest period in the dataset (lexicographically smallest).","example":"2017-01"},"series":{"type":"array","items":{"type":"string"},"description":"All `series` keys observed for this slug (use as the `series` query\nparam when fetching the time series).","example":["Total","Aset Asing","Aset Lokal"]},"slug":{"type":"string","description":"Stable URL slug (use this in `/v1/ksei/datasets/{slug}`).","example":"share-values-at-ksei"},"title_en":{"type":"string","description":"Human-readable English title.","example":"Share values at KSEI"},"unit":{"type":"string","description":"Unit the `value` field is in (`trillion_idr`, `count`, `percent`,\netc.). Stable per slug.","example":"trillion_idr"}}},"DatasetStatus":{"type":"object","description":"One dataset's freshness.","required":["key","label","cadence","unit","verdict","note"],"properties":{"cadence":{"$ref":"#/components/schemas/Cadence"},"key":{"type":"string","example":"idx_prices_daily"},"label":{"type":"string","example":"IDX daily summary"},"lag":{"type":["integer","null"],"format":"int64","description":"How far `newest` trails now, in `unit`.","example":1},"newest":{"type":["string","null"],"description":"The newest date the source states for its data, as stored: an instant,\na `YYYY-MM-DD` date or a `YYYY-MM` month. Null when the dataset is\nempty or did not answer in time.","example":"2026-09-11"},"note":{"type":"string","description":"What the verdict means for this source, in its own terms."},"unit":{"$ref":"#/components/schemas/Unit","description":"The unit `lag` is measured in."},"verdict":{"$ref":"#/components/schemas/Verdict"}}},"DirectoryEntry":{"type":"object","description":"One instrument in the reconciled directory.","required":["code"],"properties":{"code":{"type":"string","description":"KSEI instrument code. For equities this is the IDX ticker.","example":"FR0037"},"currency":{"type":["string","null"]},"in_latest_master":{"type":["boolean","null"],"description":"`true` when the code is in KSEI's LATEST monthly securities master,\nwhich is the test for \"exists today\". `false` for a code that matured or\nwas delisted, even if `status` still says `ACTIVE`.","example":true},"interest":{"type":["number","null"],"format":"double"},"interest_freq":{"type":["string","null"]},"interest_type":{"type":["string","null"]},"isin":{"type":["string","null"],"description":"The identifier to use everywhere else in this family.","example":"IDG000006800"},"issuer":{"type":["string","null"]},"listing_board":{"type":["string","null"],"description":"IDX listing board. Null for anything not on an IDX equity board."},"master_month":{"type":["string","null"],"description":"The month of the latest KSEI securities master that lists this code,\n`YYYY-MM`. Older than the newest month means KSEI stopped listing it.","example":"2026-08"},"maturity_date":{"type":["string","null"],"description":"Bond terms: null where they do not apply."},"name":{"type":["string","null"],"example":"OBLIGASI NEGARA REPUBLIK INDONESIA SERI FR0037"},"sector":{"type":["string","null"]},"security_type":{"type":["string","null"],"example":"GOVERNMENT BOND"},"status":{"type":["string","null"],"description":"KSEI's registry label, exactly as KSEI keeps it. ⚠️ It lags reality:\n149 codes are still `ACTIVE` here although they have matured or been\ndelisted (12 Sep 2026). Use `in_latest_master` to tell them apart.","example":"ACTIVE"}}},"Disclosure":{"type":"object","description":"One IDX company disclosure / announcement.","required":["attachments"],"properties":{"announcement_no":{"type":["string","null"],"example":"SE.01.00/A.CORSEC.000204/2026"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Attachment"}},"kind":{"type":["string","null"],"description":"`STOCK`, `BOND`, etc.","example":"STOCK"},"published":{"type":["string","null"],"description":"Publication date, `YYYY-MM-DD`.","example":"2026-07-10"},"subject":{"type":["string","null"],"description":"**Always `null`. Use `title`.** IDX never fills the subject field it\npublishes (null on 6,023 of 6,023 disclosures, measured 12 Sep 2026), so\nthis carries no information. Deprecated; it stays in `/v1` because\nremoving a field is a breaking change, and goes in the next version.","deprecated":true},"ticker":{"type":["string","null"],"description":"IDX ticker the disclosure is about (may be empty for exchange-wide notices).","example":"WIKA"},"title":{"type":["string","null"],"example":"Laporan Hasil Pemeringkatan Pemeringkatan Tahunan"}}},"DisclosuresResponse":{"type":"object","description":"What you get back from `GET /v1/idx/disclosures`: company announcements\nnewest first, each linking its official PDF attachments.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Disclosure"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"EquitiesResponse":{"type":"object","description":"What you get back from `GET /v1/equities`.\n\n**`data`**: the array of every ticker symbol you are allowed to query.\nUse this list to discover what is available before calling other\nendpoints.\n\n**`meta`**: bookkeeping (timestamp, your request id).\nSame shape on every successful response, you can safely ignore it\nwhile exploring.","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"string"},"description":"Every IDX ticker symbol Tarutha tracks, sorted A → Z.\nRoughly 970 entries today; grows as new IDX listings happen."},"meta":{"$ref":"#/components/schemas/Meta"}},"example":{"data":["AADI","AALI","ABBA","ABDA","ABMM","..."],"meta":{"request_id":"54ce5a97-c4f7-4f2b-a575-a5961ff3e29a","ts":"2026-05-02T13:21:14Z","source":"tarutha"}}},"EquityResponse":{"type":"object","description":"What you get back from `GET /v1/equities/{ticker}`.\n\n**`data`**: the company behind the ticker (name, sector, ISIN, when it\nlisted). Slowly-changing data: feel free to cache for a day.","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/TickerInfo"},"meta":{"$ref":"#/components/schemas/Meta"}},"example":{"data":{"ticker":"BMRI","name":"BANK MANDIRI (PERSERO) Tbk, PT","sector":"BANK","isin":"ID1000095003","listing_date":"2003-07-14","status":"ACTIVE","stock_exchange":"IDX"},"meta":{"request_id":"db32219a-0175-44f6-ac97-d9446eb0e066","ts":"2026-05-02T13:21:14Z","source":"tarutha"}}},"ErrorBody":{"type":"object","description":"Inner body of every non-2xx response.","required":["code","message","request_id"],"properties":{"code":{"type":"string","description":"Stable machine-readable code: safe to switch on in client code.\nPossible values:\n- `BAD_REQUEST`: invalid input (malformed ticker, bad date, `from > to`).\n- `UNAUTHORIZED`: missing or invalid `Authorization: Bearer` header.\n- `NOT_FOUND`: ticker not in the catalog, or no data in the requested range.\n- `RATE_LIMITED`: quota exhausted; honor the `Retry-After` response header.\n- `AUTH_LOCKOUT`: too many failed keys from your network; honor `Retry-After` before sending any key.\n- `INTERNAL`: server-side failure. Please report with the `request_id`.","example":"NOT_FOUND"},"message":{"type":"string","description":"Human-readable message: meant for **developer logs**, not for\nend-user display. Wording may change between releases and can leak\ninternal context (table names, range bounds), so never surface it\nverbatim in your own product UI.","example":"no prices for BMRI in 2026-04-01..2026-04-30"},"request_id":{"type":"string","description":"Echo of the request id for support correlation. Same value as the\n`X-Request-Id` response header.","example":"5a60a888-2e00-4d59-b829-7a8187cee46a"}}},"ErrorResponse":{"type":"object","description":"What you get back when **anything goes wrong** (any non-2xx status).\n\nThe shape is always `{ \"error\": { code, message, request_id } }` no\nmatter the HTTP status. Switch on `error.code` in your client code\n(it is stable); show your own friendly message to end users.","required":["error"],"properties":{"error":{"$ref":"#/components/schemas/ErrorBody"}},"example":{"error":{"code":"NOT_FOUND","message":"no prices for BMRI in 2024-01-01..2024-01-02","request_id":"5a60a888-2e00-4d59-b829-7a8187cee46a"}}},"FinancialReport":{"type":"object","description":"One company's financial-report filing for one period.","required":["files"],"properties":{"files":{"type":"array","items":{"$ref":"#/components/schemas/ReportFile"}},"modified":{"type":["string","null"],"description":"Last modification on IDX's side, `YYYY-MM-DD`."},"name":{"type":["string","null"],"example":"PT Adaro Andalan Indonesia Tbk"},"period":{"type":["string","null"],"description":"Reporting period: `tw1`, `tw2`, `tw3` (quarters) or `audit` (full year).","example":"tw1"},"ticker":{"type":["string","null"],"example":"AADI"},"year":{"type":["integer","null"],"format":"int32","example":2026}}},"FinancialReportsResponse":{"type":"object","description":"What you get back from `GET /v1/idx/financial-reports`: filing metadata\nwith XBRL/PDF download URLs, newest first.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FinancialReport"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"FlowPoint":{"type":"object","description":"One month of net position change for one instrument.","required":["period","prev_period","months_gap","code","local_net_change","foreign_net_change","signal","is_position_signal"],"properties":{"adjusted_foreign_net_change_total":{"type":["number","null"],"format":"double","description":"On `pure_split` rows, the change with the split effect removed. This is\nthe number to use: the raw one is dominated by the multiplication."},"code":{"type":"string"},"custody_change":{"type":["number","null"],"format":"double","description":"Change in total custody. Large values mean paper entered or left the\ndepository, which is not trading."},"foreign_net_change":{"$ref":"#/components/schemas/HolderSplit","description":"Change in foreign holdings, by investor type."},"foreign_pct_change_pp":{"type":["number","null"],"format":"double","description":"Movement in foreign share of custody, in percentage points.","example":-0.17},"is_position_signal":{"type":"boolean","description":"`true` when the change can be read as a position change. False for\n`custody_shift` and `mixed_action`, where the source data cannot\nseparate trading from custody migration or an uneven corporate action.","example":true},"issued_change":{"type":["number","null"],"format":"double","description":"Change in the issued amount."},"local_net_change":{"$ref":"#/components/schemas/HolderSplit","description":"Change in domestic holdings, by investor type."},"months_gap":{"type":"integer","format":"int32","description":"Whole months between the two. Anything but 1 means a gap in coverage.","example":1},"period":{"type":"string","description":"Month the change lands in, `YYYY-MM`.","example":"2026-07"},"prev_period":{"type":"string","description":"Month it is measured against.","example":"2026-06"},"security_type":{"type":["string","null"]},"signal":{"type":"string","description":"What kind of month this was: `clean`, `pure_split`, `issuance_change`,\n`custody_shift`, `mixed_action`, `gap`.","example":"clean"}}},"FundCategoriesResponse":{"type":"object","description":"What you get back from `GET /v1/funds/categories`: one row per OJK fund\nclass and month, newest period first. `limit`/`offset` page the list, but\nno `pagination` block is returned; that is a known gap, not an omission here.","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CategoryRow"}},"meta":{"$ref":"#/components/schemas/Meta"}}},"FundDirectoryResponse":{"type":"object","description":"What you get back from `GET /v1/funds`: every mutual fund OJK publishes for\none month, largest by NAV first.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FundEntry"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"FundEntry":{"type":"object","description":"One fund as of a single month.","required":["fund_id","fund_name","period"],"properties":{"currency":{"type":["string","null"],"description":"The fund's denomination. **Not** the unit of `nav`: see module docs.","example":"IDR"},"custodian_name":{"type":["string","null"],"description":"Custodian bank."},"fund_id":{"type":"string","description":"Stable across months. Use it for the `nav` and `flows` routes.","example":"3f9a2c1e7b40d5a8"},"fund_name":{"type":"string","example":"DANAMAS STABIL"},"fund_type":{"type":["string","null"],"description":"OJK's fund class, e.g. `Fixed Income Fund`, `Capital Protected Fund`.","example":"Fixed Income Fund"},"mi_name":{"type":["string","null"],"description":"Investment manager.","example":"Sinarmas Asset Management, PT"},"nav":{"type":["number","null"],"format":"double","description":"Net asset value, **always IDR**.","example":16489289882751.0},"period":{"type":"string","description":"Month this row describes, `YYYY-MM`.","example":"2026-07"},"units":{"type":["number","null"],"format":"double","description":"Units outstanding. Zero means a matured or dormant fund.","example":3115154363.0}}},"FundFlowPoint":{"type":"object","description":"One month of net subscription/redemption for one fund.","required":["period","prev_period","months_gap","signal","is_flow_signal"],"properties":{"is_flow_signal":{"type":"boolean","description":"Whether this month carries a real flow. False for `dormant`, `gap`, `suspect` and `partial_month`."},"months_gap":{"type":"integer","format":"int32","description":"Months between this row and the previous one. Anything but 1 is a\n`gap` and carries no flow."},"nav":{"type":["number","null"],"format":"double"},"nav_change":{"type":["number","null"],"format":"double"},"nav_per_unit":{"type":["number","null"],"format":"double"},"nav_prev":{"type":["number","null"],"format":"double"},"net_change_idr":{"type":["number","null"],"format":"double","description":"`units_net_change × nav_per_unit`, in IDR. **Null unless\n`is_flow_signal`.** Negative is money leaving the fund.","example":-1430763855938.0},"performance_idr":{"type":["number","null"],"format":"double","description":"The part of `nav_change` the market did, rather than investors:\n`nav_change − net_change_idr`.","example":8740068307049.0},"period":{"type":"string","example":"2026-07"},"prev_period":{"type":"string","example":"2026-06"},"signal":{"type":"string","description":"`clean` · `terminated` · `reactivated` · `dormant` · `gap` · `suspect` · `partial_month`.","example":"clean"},"units":{"type":["number","null"],"format":"double"},"units_net_change":{"type":["number","null"],"format":"double","description":"Change in units outstanding: the raw subscription/redemption in units."},"units_prev":{"type":["number","null"],"format":"double"}}},"FundFlowsResponse":{"type":"object","description":"What you get back from `GET /v1/funds/{fund_id}/flows`: monthly net\nsubscription and redemption for one fund, separated from market movement.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FundFlowPoint"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"FundMetrics":{"type":"object","required":["fund_id","windows","crises","series_break_reasons","large_moves_kept","untrusted_months"],"properties":{"alive":{"type":["boolean","null"],"description":"`false` means the fund is absent from the newest month in the data. It\nis kept rather than dropped, because dropping it is survivorship bias."},"annual_vol":{"type":["number","null"],"format":"double"},"crises":{"type":"array","items":{"$ref":"#/components/schemas/CrisisBehaviour"},"description":"Always the four crises, for the same reason."},"downside_dev_monthly":{"type":["number","null"],"format":"double"},"first_period":{"type":["string","null"],"description":"First month this fund was priced."},"fund_id":{"type":"string"},"fund_name":{"type":["string","null"]},"fund_type":{"type":["string","null"]},"large_moves_kept":{"type":"array","items":{"$ref":"#/components/schemas/LargeMove"},"description":"Very large moves KEPT as real and already inside the numbers above.\nEmpty when the fund has none."},"last_period":{"type":["string","null"],"description":"Last month this fund was priced, and the anchor for every window below."},"max_drawdown":{"type":["number","null"],"format":"double"},"mi_name":{"type":["string","null"]},"monthly_vol":{"type":["number","null"],"format":"double"},"months_priced":{"type":["integer","null"],"format":"int64","description":"Number of months actually priced. This is the denominator behind every\nother number here: a fund with 14 priced months has no honest `3y`."},"series_break_reasons":{"type":"array","items":{"$ref":"#/components/schemas/SeriesBreak"},"description":"Months where the series was cut, and why. Empty when the fund has none.\nRead this before comparing this fund with another: no return or window\ncrosses a break."},"untrusted_months":{"type":"array","items":{"type":"string"},"description":"Months whose price is LEFT OUT of every measurement above, `YYYY-MM`,\nsorted. Empty when the fund has none.\n\nThree kinds are excluded: residue rows (1 unit or less holding over\nRp 1m), spikes of more than 10x into and out of one month, and\nexcursions, a move of more than 4x that the price reverses within six\nmonths.\n\nTwo things this does NOT mean. The net move ACROSS an excursion still\ncounts as an ordinary return, so the return is not missing, only the\nround trip. And `first_period`, `last_period` and `months_priced` still\ncount every month OJK reported, so they will not agree with the number\nof months actually measured: that is the honest reading, not a gap."},"windows":{"type":"array","items":{"$ref":"#/components/schemas/WindowReturn"},"description":"Always the five windows, in order, even when every `total` is `null`.\nA missing element would be indistinguishable from a window nobody asked\nfor."}}},"FundMetricsResponse":{"type":"object","description":"What you get back from `GET /v1/funds/{fund_id}/metrics`: one fund's risk\nand return metrics (APIDOC-44: declared so the schema is reachable).","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/FundMetrics"},"meta":{"$ref":"#/components/schemas/Meta"}}},"FundNavResponse":{"type":"object","description":"What you get back from `GET /v1/funds/{fund_id}/nav`: monthly NAV and\nunits outstanding for one fund, newest month first.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/NavPoint"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"Fundamentals":{"type":"object","description":"Curated subset of Yahoo Finance's `quoteSummary` modules: reduced from\nthe raw ~50 KB nested camelCase blob to the ~30 fields that actually drive\nan investment-research UI. Refreshed daily by the Tarutha scraper.\n\n**Nullability:** every field except `ticker` is nullable. Yahoo simply\nomits whatever it does not have for a given symbol, and we do not fabricate\nsubstitutes. Treat `null` as *\"not reported\"*, not zero.\n\n**Currency:** all monetary values are in **IDR** (Indonesian Rupiah),\nunrounded.\n\n**Source caveat:** `quoteSummary` mixes IDX-confirmed data (close,\ndividends) with Yahoo-derived metrics (PE, recommendations). When IDX and\nYahoo disagree (e.g. corporate actions on the same day), Yahoo lags by\nup to 1 trading day.","required":["ticker"],"properties":{"analyst_count":{"type":["number","null"],"format":"double","description":"Number of analysts contributing to the consensus. Stored as f64 by\nYahoo even though it is always integral.","example":14.0},"average_volume":{"type":["number","null"],"format":"double","description":"Average daily traded volume over the trailing 3 months, in shares.","example":95000000.0},"beta":{"type":["number","null"],"format":"double","description":"5-year monthly beta vs the JKSE composite (Yahoo's default\nbenchmark). `< 1` = historically less volatile than the broader\nmarket; `> 1` = more volatile.","example":1.12},"book_value":{"type":["number","null"],"format":"double","description":"Book value per share in IDR (shareholders' equity ÷ diluted shares).","example":4100.0},"current_price":{"type":["number","null"],"format":"double","description":"Latest reported close in IDR. May differ from the same-day\n`Ohlcv.close` by a few rupiah due to Yahoo's intraday last-trade\nsnapshot.","example":4720.0},"debt_to_equity":{"type":["number","null"],"format":"double","description":"Total debt / total equity as a **percentage** (78.5 = ~78.5%).\nHeads-up: this is Yahoo's quirk, and most other vendors give it as a\npure ratio, so divide by 100 if you mix sources.","example":78.5},"dividend_yield":{"type":["number","null"],"format":"double","description":"Trailing 12-month dividend yield expressed as a **decimal**\n(0.045 = 4.5%). Excludes special / one-off dividends.","example":0.045},"earnings_quarterly_growth":{"type":["number","null"],"format":"double","description":"Most-recent quarterly earnings growth, year-over-year, as a\n**decimal** (0.12 = 12%).","example":0.12},"enterprise_value":{"type":["number","null"],"format":"double","description":"Enterprise value in IDR, computed as\n`market_cap + total_debt − cash_and_equivalents`.","example":450000000000000.0},"fifty_two_week_high":{"type":["number","null"],"format":"double","description":"Highest closing price over the trailing 52 weeks, in IDR.","example":7475.0},"fifty_two_week_low":{"type":["number","null"],"format":"double","description":"Lowest closing price over the trailing 52 weeks, in IDR.","example":4280.0},"float_shares":{"type":["number","null"],"format":"double","description":"Free float: shares available to the public after excluding\ninsider, government, and treasury holdings.","example":32500000000.0},"forward_pe":{"type":["number","null"],"format":"double","description":"Forward (next-fiscal-year) P/E based on consensus analyst EPS\nestimate. Null when there is no analyst coverage.","example":10.1},"industry":{"type":["string","null"],"description":"GICS-style industry name. Finer taxonomy than `TickerInfo.sector`\n(which is the IDX top-level code).","example":"Banks—Regional"},"long_business_summary":{"type":["string","null"],"description":"Multi-paragraph English business description from Yahoo. Useful as\nthe source for \"About this company\" cards or LLM context.","example":"PT Bank Mandiri (Persero) Tbk provides banking products and services to individuals, small and medium-sized enterprises, and corporates in Indonesia and internationally..."},"market_cap":{"type":["number","null"],"format":"double","description":"Market capitalization in IDR. Computed by Yahoo as\n`shares_outstanding × current_price`. For dual-listed names this is\nthe IDX-only float, not the global aggregate.","example":409733336924160.0},"peg_ratio":{"type":["number","null"],"format":"double","description":"5-year expected PEG ratio (forward P/E ÷ projected earnings growth).\nNull when growth estimates are missing.","example":1.4},"price_to_book":{"type":["number","null"],"format":"double","description":"Price-to-book ratio (`current_price ÷ book_value`).","example":1.15},"profit_margins":{"type":["number","null"],"format":"double","description":"Net profit margin as a **decimal** (0.21 = 21%).","example":0.21},"recommendation_key":{"type":["string","null"],"description":"Aggregate analyst recommendation enum. One of: `strong_buy`, `buy`,\n`hold`, `sell`, `strong_sell`, `none`. `none` (or null) means no\nanalyst coverage.","example":"buy"},"recommendation_mean":{"type":["number","null"],"format":"double","description":"Numeric form of `recommendation_key`. Scale: 1.0 = strong buy →\n5.0 = strong sell. Convenient for sorting / scoring.","example":2.1},"return_on_equity":{"type":["number","null"],"format":"double","description":"Return on equity as a **decimal** (0.18 = 18%). Trailing 12-month.","example":0.18},"shares_outstanding":{"type":["number","null"],"format":"double","description":"Total shares outstanding (basic, **not** diluted). Stored as f64 by\nYahoo for very large numbers.","example":86799000000.0},"snapshot_date":{"type":["string","null"],"description":"Date Yahoo refreshed the underlying `quoteSummary` blob, ISO 8601\n(`YYYY-MM-DD`). May lag the latest IDX trading day by 1 if the\ndaily scrape ran before close.","example":"2026-04-30"},"target_high_price":{"type":["number","null"],"format":"double","description":"Highest analyst 12-month price target, in IDR.","example":6500.0},"target_low_price":{"type":["number","null"],"format":"double","description":"Lowest analyst 12-month price target, in IDR.","example":5100.0},"target_mean_price":{"type":["number","null"],"format":"double","description":"Mean 12-month price target across covering analysts, in IDR.","example":5800.0},"ticker":{"type":"string","description":"Ticker the snapshot belongs to (uppercase).","example":"BMRI"},"total_revenue":{"type":["number","null"],"format":"double","description":"Trailing 12-month consolidated revenue in IDR.","example":92000000000000.0},"trailing_pe":{"type":["number","null"],"format":"double","description":"Trailing-twelve-month price-to-earnings ratio. Null when EPS is\nnegative or unreported.","example":11.4}}},"FundamentalsResponse":{"type":"object","description":"What you get back from `GET /v1/equities/{ticker}/fundamentals`.\n\n**`data`**: the latest snapshot of the numbers analysts care about\n(market cap, P/E, dividend yield, profit margin, analyst price targets,\ncompany description). Refreshed daily.\n\n> **Heads up:** every field except `ticker` may be `null`. Null means\n> Yahoo did not have it for this symbol, NOT that the value is zero.","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/Fundamentals"},"meta":{"$ref":"#/components/schemas/Meta"}},"example":{"data":{"ticker":"BMRI","snapshot_date":"2026-04-30","market_cap":409733336924160.0,"trailing_pe":11.4,"forward_pe":10.1,"dividend_yield":0.045,"fifty_two_week_high":7475.0,"fifty_two_week_low":4280.0,"current_price":4720.0,"recommendation_key":"buy","target_mean_price":5800.0,"industry":"Banks—Regional"},"meta":{"request_id":"abc12345-678d-9012-345e-67890abcdef1","ts":"2026-05-02T13:21:14Z","source":"tarutha"}}},"Holder":{"type":"object","description":"One institutional or fund holder position.","required":["organization"],"properties":{"organization":{"type":"string","example":"VANGUARD STAR FUNDS-Vanguard Total International Stock Index Fund"},"pct_change":{"type":["number","null"],"format":"double","description":"Change in position since the prior report, in percent (`-84` = −84%).","example":-84.0},"pct_held":{"type":["number","null"],"format":"double","description":"Share of shares outstanding held, in percent (0–100).","example":0.59},"position":{"type":["number","null"],"format":"double","description":"Shares held."},"report_date":{"type":["string","null"],"description":"Reporting date, `YYYY-MM-DD`.","example":"2026-01-31"},"value":{"type":["number","null"],"format":"double","description":"Position value in IDR."}}},"HolderSplit":{"type":"object","description":"The nine KSEI investor-type codes, local and foreign alike.","required":["is","cp","pf","ib","id","mf","sc","fd","ot","total"],"properties":{"cp":{"type":"number","format":"double","description":"Corporates."},"fd":{"type":"number","format":"double","description":"Foundations."},"ib":{"type":"number","format":"double","description":"Banks and other financial institutions."},"id":{"type":"number","format":"double","description":"Individuals: retail."},"is":{"type":"number","format":"double","description":"Insurance companies."},"mf":{"type":"number","format":"double","description":"Mutual funds."},"ot":{"type":"number","format":"double","description":"Other."},"pf":{"type":"number","format":"double","description":"Pension funds."},"sc":{"type":"number","format":"double","description":"Securities companies."},"total":{"type":"number","format":"double","description":"Sum of the nine above, as reported by KSEI."}}},"HoldersBreakdown":{"type":"object","description":"Percentage split of who holds the shares.","properties":{"insiders_pct":{"type":["number","null"],"format":"double","description":"Held by insiders, in percent of all shares (0–100). For Indonesian\nissuers this is typically the controlling shareholder / conglomerate\nstake.","example":60.81},"institutions_count":{"type":["number","null"],"format":"double","description":"Number of institutions reporting a position.","example":402},"institutions_float_pct":{"type":["number","null"],"format":"double","description":"Held by institutions, in percent of the FLOAT (0–100).","example":47.97},"institutions_pct":{"type":["number","null"],"format":"double","description":"Held by institutions, in percent of ALL shares (0–100).","example":18.8}}},"IndexBar":{"type":"object","description":"One daily bar for an IDX stock index (e.g. `COMPOSITE` = IHSG).","required":["index_code","date"],"properties":{"change":{"type":["number","null"],"format":"double","description":"Point change vs previous close.","example":-144.422},"close":{"type":["number","null"],"format":"double","example":6956.804},"date":{"type":"string","description":"Trading date, `YYYY-MM-DD`.","example":"2026-04-30"},"frequency":{"type":["number","null"],"format":"double","description":"Total trades."},"high":{"type":["number","null"],"format":"double","example":7109.004},"index_code":{"type":"string","description":"IDX index code (`COMPOSITE`, `LQ45`, `IDX30`, …).","example":"COMPOSITE"},"low":{"type":["number","null"],"format":"double","example":6876.576},"market_capital":{"type":["number","null"],"format":"double","description":"Combined market cap in IDR."},"number_of_stock":{"type":["number","null"],"format":"double","description":"Number of constituent stocks.","example":913},"previous":{"type":["number","null"],"format":"double","example":7101.226},"value":{"type":["number","null"],"format":"double","description":"Traded value in IDR."},"volume":{"type":["number","null"],"format":"double","description":"Shares traded across constituents."}}},"IndexHistoryResponse":{"type":"object","description":"What you get back from `GET /v1/indices/{code}`: paginated daily bars,\noldest first.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/IndexBar"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"IndicesResponse":{"type":"object","description":"What you get back from `GET /v1/indices`: the latest bar for every IDX\nindex (45 today), sorted by `index_code`.","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/IndexBar"}},"meta":{"$ref":"#/components/schemas/Meta"}}},"InstrumentDirectoryResponse":{"type":"object","description":"What you get back from `GET /v1/instruments`: the reconciled instrument\ndirectory, the place to turn a ticker or name into an ISIN.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DirectoryEntry"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"InstrumentFlowsResponse":{"type":"object","description":"What you get back from `GET /v1/instruments/{isin}/flows`: monthly net\nposition change for one instrument, oldest month first.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FlowPoint"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"InstrumentOwnershipResponse":{"type":"object","description":"What you get back from `GET /v1/instruments/{isin}/ownership`: monthly\ndepository holdings for one instrument, oldest month first.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/OwnershipPoint"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"Ipo":{"type":"object","description":"One IPO or relisting plan.","properties":{"board":{"type":["string","null"],"description":"Target listing board.","example":"Pengembangan"},"ipo_value":{"type":["number","null"],"format":"double","description":"Planned IPO proceeds, IDR."},"listing_date":{"type":["string","null"],"description":"(Planned) listing date, `YYYY-MM-DD`.","example":"2026-07-10"},"name":{"type":["string","null"],"example":"PT Rans Entertainmen Indonesia Tbk"},"security_type":{"type":["string","null"],"description":"Security type: `saham`, `obligasi`, `etf`…","example":"saham"},"status":{"type":["string","null"],"description":"Plan status: `baru` (new listing) or `relisting`.","example":"baru"},"ticker":{"type":["string","null"],"example":"RANS"}}},"IpoResponse":{"type":"object","description":"What you get back from `GET /v1/idx/ipo`: IPO and relisting plans,\nnewest first.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Ipo"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"IssuedAction":{"type":"object","description":"One share-issuance event: split, warrant exercise, rights issue, bonus.","properties":{"action":{"type":["string","null"],"description":"Action type in Indonesian: `waran`, `stock split`, `right issue`, `dividen saham`…","example":"waran"},"date":{"type":["string","null"],"description":"Recording date, `YYYY-MM-DD`.","example":"2026-07-10"},"shares_after":{"type":["number","null"],"format":"double","description":"Total shares outstanding after the action."},"shares_issued":{"type":["number","null"],"format":"double","description":"Shares added by the action."},"ticker":{"type":["string","null"],"example":"GRPM"}}},"IssuedActionsResponse":{"type":"object","description":"What you get back from `GET /v1/idx/corporate-actions`: share-issuance\nevents, newest first.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/IssuedAction"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"KseiAnnouncement":{"type":"object","description":"One KSEI registration or operational notice.","properties":{"date":{"type":["string","null"],"description":"Announcement date, `YYYY-MM-DD`.","example":"2026-07-10"},"kind":{"type":["string","null"],"description":"Feed: `isin` (new ISIN codes), `new_securities` (registrations),\n`today` (today's notices), `ksei` (operational announcements).","example":"isin"},"letter_no":{"type":["string","null"],"description":"KSEI letter number.","example":"PENG-360/KSEI.3.JKU/ISIN/072026"},"pdf_url":{"type":["string","null"],"description":"Official PDF on web.ksei.co.id."},"subject":{"type":["string","null"],"description":"Indonesian subject line."}}},"KseiAnnouncementsResponse":{"type":"object","description":"What you get back from `GET /v1/ksei/announcements`: depository notices,\nnewest first.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/KseiAnnouncement"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"KseiArchive":{"type":"object","description":"One monthly KSEI archive file.","properties":{"filename":{"type":["string","null"],"example":"StatisEfek20260630.txt.zip"},"kind":{"type":["string","null"],"description":"`master_securities` (StatisEfek: full securities master) or\n`holding_composition` (Balancepos: ownership per security).","example":"master_securities"},"sha256":{"type":["string","null"]},"size_bytes":{"type":["number","null"],"format":"double","description":"Compressed size, bytes."},"url":{"type":["string","null"],"description":"Original download URL on web.ksei.co.id."},"year_month":{"type":["string","null"],"description":"Snapshot month, `YYYY-MM`.","example":"2026-06"}}},"KseiArchivesResponse":{"type":"object","description":"What you get back from `GET /v1/ksei/archives`: monthly archive catalog,\nnewest first.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/KseiArchive"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"KseiDatapointsResponse":{"type":"object","description":"What you get back from `GET /v1/ksei/datasets/{slug}`.\n\n**`data`**: array of datapoints for the requested dataset, sorted by\n`period` ascending. Each point carries the period, series dimension,\noptionally a category, the numeric value (in the dataset's `unit`),\nand when Tarutha last refreshed it.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Datapoint"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}},"example":{"data":[{"period":"2024-10","period_label":"Oktober 2024","series":"Aset Asing","category":null,"value":3450.12,"fetched_at":"2026-05-02T10:06:19Z"},{"period":"2024-11","period_label":"November 2024","series":"Aset Asing","category":null,"value":3489.55,"fetched_at":"2026-05-02T10:06:19Z"},{"period":"2024-12","period_label":"Desember 2024","series":"Aset Asing","category":null,"value":3521.344,"fetched_at":"2026-05-02T10:06:19Z"}],"meta":{"request_id":"abc12345-678d-9012-345e-67890abcdef1","ts":"2026-05-02T15:00:00Z","source":"tarutha"},"pagination":{"total":96,"limit":200,"offset":0,"has_more":false}}},"KseiDatasetsResponse":{"type":"object","description":"What you get back from `GET /v1/ksei/datasets`.\n\n**`data`**: catalog of every KSEI dashboard dataset Tarutha tracks (12\ntoday). Each entry tells you the dataset's `granularity`, `unit`,\navailable `series` and `categories`, and the period range stored.\nCall this **first**, then drill into a specific dataset with\n`GET /v1/ksei/datasets/{slug}`.","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Dataset"}},"meta":{"$ref":"#/components/schemas/Meta"}},"example":{"data":[{"slug":"share-values-at-ksei","title_en":"Share values at KSEI","granularity":"monthly","unit":"trillion_idr","series":["Total","Aset Asing","Aset Lokal"],"categories":[],"period_min":"2017-01","period_max":"2024-12","count":96}],"meta":{"request_id":"abc12345-678d-9012-345e-67890abcdef1","ts":"2026-05-02T15:00:00Z","source":"tarutha"}}},"KseiStatisticsPdf":{"type":"object","description":"One monthly KSEI public-statistics report.","properties":{"filename":{"type":["string","null"],"example":"Statistik_Web_-_Desember_20202.pdf"},"sha256":{"type":["string","null"]},"size_bytes":{"type":["number","null"],"format":"double","description":"PDF size, bytes."},"url":{"type":["string","null"],"description":"Original PDF URL on web.ksei.co.id."},"year_month":{"type":["string","null"],"description":"Report month, `YYYY-MM`.","example":"2020-12"}}},"KseiStatisticsPdfsResponse":{"type":"object","description":"What you get back from `GET /v1/ksei/statistics-pdfs`: monthly\npublic-statistics report catalog, newest first.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/KseiStatisticsPdf"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"KseiStatistikResponse":{"type":"object","description":"What you get back from `GET /v1/ksei/statistik`: monthly series\nparsed from KSEI's official Statistik PDF decks (2024-01 onward).","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/StatistikPoint"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"LargeMove":{"type":"object","description":"A very large move that was KEPT as real, not cut out.\n\n⚠️ **A very large fall is included in this fund's returns and drawdown.**\nThese months passed the checks that cut a series, so the number you see\nalready contains them. `factor` is NAV per unit in `month` divided by NAV\nper unit in the previous trusted month, so 0.216 is a fall of about 78%.","required":["month","factor"],"properties":{"factor":{"type":"number","format":"double","description":"This month's NAV per unit over the previous trusted month's.","example":0.215898},"month":{"type":"string","description":"`YYYY-MM`.","example":"2022-06"}}},"ManagerEntry":{"type":"object","required":["id","name","name_raw","period","funds"],"properties":{"aum_idr":{"type":["number","null"],"format":"double","description":"Total NAV across every fund this manager reports, **always IDR**.","example":44012345678.0},"funds":{"type":"integer","format":"int32","description":"Funds reported this month.","example":109,"minimum":0},"id":{"type":"string","description":"Slug derived from the manager's name, with entity markers removed.","example":"mandiri-manajemen-investasi"},"market_effect_idr":{"type":["number","null"],"format":"double","description":"The market moving assets already held. Not a decision by anyone.","example":478900000000.0},"name":{"type":"string","description":"Display name, entity markers removed.","example":"Mandiri Manajemen Investasi"},"name_raw":{"type":"string","description":"Exactly as OJK writes it. Pass to `/v1/funds?mi=` to join back.","example":"Mandiri Manajemen Investasi, PT"},"net_flow_idr":{"type":["number","null"],"format":"double","description":"Units created less redeemed, priced at NAV. Negative is net redemption.","example":-1547400000000.0},"organic_growth_pct":{"type":["number","null"],"format":"double","description":"Net flow over opening AUM, in percent. The number AUM alone hides.","example":-3.43},"period":{"type":"string","description":"Month this row describes, `YYYY-MM`.","example":"2026-07"},"rank":{"type":["integer","null"],"format":"int32","description":"Rank by AUM, 1 = largest. Ties share a rank.","example":5,"minimum":0},"rank_delta":{"type":["integer","null"],"format":"int64","description":"Places climbed since last month. Positive means moved up.","example":0},"rank_prev":{"type":["integer","null"],"format":"int32","description":"Rank last month, or null if the manager did not report then.","example":5,"minimum":0},"share_pct":{"type":["number","null"],"format":"double","description":"Share of the reported industry, in percent.","example":6.7}}},"ManagerHistoryPoint":{"type":"object","required":["period","managers"],"properties":{"aum_idr":{"type":["number","null"],"format":"double","example":44012345678.0},"managers":{"type":"integer","format":"int32","description":"How many managers reported that month: the denominator of `rank`.","example":85,"minimum":0},"period":{"type":"string","example":"2026-07"},"rank":{"type":["integer","null"],"format":"int32","example":5,"minimum":0},"share_pct":{"type":["number","null"],"format":"double","description":"Share of the reported industry that month, in percent.","example":6.7}}},"ManagerLeagueResponse":{"type":"object","description":"What you get back from `GET /v1/managers`: every investment manager\nranked by AUM for one month. The `aum_idr` column sums to OJK's own\npublished industry total.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ManagerEntry"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"ManagerProfile":{"allOf":[{"$ref":"#/components/schemas/ManagerEntry"},{"type":"object","required":["by_type","absent_types","history"],"properties":{"absent_types":{"type":"array","items":{"type":"string"},"description":"Fund types this manager sells nothing in. An absence is a strategy."},"by_type":{"type":"array","items":{"$ref":"#/components/schemas/ManagerTypeShare"},"description":"AUM by fund type, with the industry pool beside it."},"history":{"type":"array","items":{"$ref":"#/components/schemas/ManagerHistoryPoint"},"description":"Rank and share, month by month, most recent last."}}}]},"ManagerProfileResponse":{"type":"object","description":"What you get back from `GET /v1/managers/{id}`: one manager, with the\nfund types they sell, the ones they do not, and their rank history.","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/ManagerProfile"},"meta":{"$ref":"#/components/schemas/Meta"}}},"ManagerTypeShare":{"type":"object","required":["fund_type","aum_idr","funds","industry_aum_idr"],"properties":{"aum_idr":{"type":"number","format":"double","example":19100000000000.0},"fund_type":{"type":"string","description":"OJK's own fund class.","example":"Money Market Fund"},"funds":{"type":"integer","format":"int32","example":20,"minimum":0},"industry_aum_idr":{"type":"number","format":"double","description":"Whole industry AUM in this type, for the same month.","example":133560000000000.0},"share_pct":{"type":["number","null"],"format":"double","description":"This manager's share of the type, in percent.","example":14.3}}},"Meta":{"type":"object","description":"Per-response metadata returned alongside every successful response.\nAlso surfaced in the `X-Request-Id` HTTP response header for log\ncorrelation between client and server.","required":["request_id","ts","source"],"properties":{"request_id":{"type":"string","description":"UUID v4 generated server-side, **unless** the caller supplied an\n`X-Request-Id` request header: in which case the value is echoed\nback unchanged. Use this when filing support tickets so we can\nlocate your request in the `api_usage` log.","example":"54ce5a97-c4f7-4f2b-a575-a5961ff3e29a"},"source":{"type":"string","description":"Origin attribution. Always `tarutha` for v1.","example":"tarutha"},"ts":{"type":"string","description":"RFC 3339 timestamp at **response generation**, UTC: the moment this\nreply was built, not the age of the data in it.\n\n⚠️ **This is not a freshness signal and must not be read as one.** It is\nalways \"now\", whatever the age of the underlying records, so a figure\nscraped months ago arrives beside a timestamp from this second. Until\n16 Aug 2026 this field was documented as \"useful as a freshness check\",\nwhich is false and is the direction that hides staleness.\n\nFor the age of the DATA, use the `as_of` field where a response carries\none (`/v1/equities/{ticker}/ownership` and the `/v1/sbn/*` routes). The\nremaining domains do not expose one yet.","example":"2026-05-02T13:21:14Z"}}},"Mover":{"type":"object","description":"One stock in the movers ranking, from official IDX daily data.","required":["ticker","date"],"properties":{"change":{"type":["number","null"],"format":"double","description":"Point change vs previous close.","example":300.0},"close":{"type":["number","null"],"format":"double","example":11600.0},"date":{"type":"string","description":"Trading date the ranking is for, `YYYY-MM-DD`.","example":"2026-04-30"},"foreign_buy":{"type":["number","null"],"format":"double","description":"Foreign purchases in shares."},"foreign_sell":{"type":["number","null"],"format":"double","description":"Foreign sales in shares."},"frequency":{"type":["number","null"],"format":"double","description":"Number of trades."},"name":{"type":["string","null"],"example":"Adaro Andalan Indonesia Tbk."},"pct_change":{"type":["number","null"],"format":"double","description":"Percent change vs previous close.","example":2.65},"ticker":{"type":"string","example":"AADI"},"value":{"type":["number","null"],"format":"double","description":"Traded value in IDR."},"volume":{"type":["number","null"],"format":"double","description":"Shares traded."}}},"MoversResponse":{"type":"object","description":"What you get back from `GET /v1/movers`: stocks ranked for one trading\nday by the metric you chose (`pct` change, traded `value`, `volume`, or\n`frequency`).","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Mover"}},"meta":{"$ref":"#/components/schemas/Meta"}}},"NavPoint":{"type":"object","description":"One month of NAV and units for one fund.","required":["period"],"properties":{"nav":{"type":["number","null"],"format":"double","description":"Net asset value, **always IDR**."},"nav_per_unit":{"type":["number","null"],"format":"double","description":"`nav / units`: the per-unit price. Null when units are zero."},"period":{"type":"string","example":"2026-07"},"units":{"type":["number","null"],"format":"double","description":"Units outstanding."}}},"NetActivity":{"type":"object","description":"Insider/institutional net buying over the recent period.","properties":{"net_institutional_pct":{"type":["number","null"],"format":"double","description":"Net institutional buying, in percent of institutional holdings.","example":1.3},"net_institutional_shares":{"type":["number","null"],"format":"double","description":"Net shares bought (negative = net selling) by institutions."},"period":{"type":["string","null"],"description":"Window the numbers cover (e.g. `6m`).","example":"6m"},"total_insider_shares":{"type":["number","null"],"format":"double","description":"Total shares held by insiders."}}},"Ohlcv":{"type":"object","description":"One trading day's OHLCV bar for an IDX-listed equity.\n\n**Trading hours:** IDX runs Mon–Fri 09:00–16:30 WIB (UTC+7). Weekends and\nIDX-declared public holidays do **not** appear in the series, so callers\ncomputing rolling windows should use the bar count, not calendar days.\n\n**Currency:** all four price fields are in **IDR** (Indonesian Rupiah),\nunrounded. `volume` is shares.\n\n**Adjustment:** prices are **NOT** adjusted for stock splits, bonus\nissues, or dividends. If you need adjusted series, pair with the\ncorporate actions feed (planned for Phase 3).","required":["date","open","high","low","close","volume"],"properties":{"close":{"type":"number","format":"double","description":"Last traded price of the day, in IDR (closing auction). This is the\nIDX-confirmed close: distinct from Yahoo's intraday last-trade\nsnapshot in `Fundamentals.current_price`.","example":4390.0},"date":{"type":"string","description":"Trading date in ISO 8601 (`YYYY-MM-DD`), Asia/Jakarta time zone.","example":"2026-04-30"},"high":{"type":"number","format":"double","description":"Highest traded price of the day, in IDR.","example":4450.0},"low":{"type":"number","format":"double","description":"Lowest traded price of the day, in IDR.","example":4370.0},"open":{"type":"number","format":"double","description":"First traded price of the day, in IDR (opening auction).","example":4430.0},"volume":{"type":"number","format":"double","description":"Total shares traded across all order books that day.","example":186960200.0}}},"OutstandingPoint":{"type":"object","description":"One snapshot of the amount outstanding for one series.","required":["as_of"],"properties":{"as_of":{"type":"string","example":"2026-07-31"},"coupon_pct":{"type":["number","null"],"format":"double","description":"Coupon in percent; null for zero-coupon. For `VARIABLE` the current reset rate."},"coupon_type":{"type":["string","null"]},"currency":{"type":["string","null"],"example":"IDR"},"outstanding":{"type":["number","null"],"format":"double","description":"Amount outstanding, in `currency`."},"source_kind":{"type":["string","null"],"description":"`pdf_monthly` (2025 onward) or `xlsx_archive` (2002–2024)."},"tradable":{"type":["boolean","null"]}}},"Ownership":{"type":"object","description":"Ownership snapshot for one IDX ticker.","required":["ticker","as_of","breakdown","top_institutions","top_funds"],"properties":{"as_of":{"type":"string","description":"Date of the snapshot, `YYYY-MM-DD`.","example":"2026-05-02"},"breakdown":{"$ref":"#/components/schemas/HoldersBreakdown"},"net_activity":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/NetActivity"}]},"ticker":{"type":"string","example":"BBCA"},"top_funds":{"type":"array","items":{"$ref":"#/components/schemas/Holder"},"description":"Largest fund holders."},"top_institutions":{"type":"array","items":{"$ref":"#/components/schemas/Holder"},"description":"Largest institutional holders, as reported to Yahoo."}}},"OwnershipPoint":{"type":"object","description":"One month of depository ownership for one instrument.","required":["period","code","local","foreign","held_total"],"properties":{"code":{"type":"string","description":"KSEI instrument code.","example":"FR0037"},"custody_pct":{"type":["number","null"],"format":"double","description":"How much of the issued amount sits in custody, in percent. Read this\nbefore interpreting the two above: at 2.42% they describe a small\nslice of the instrument.","example":2.42},"foreign":{"$ref":"#/components/schemas/HolderSplit","description":"Units held by foreign investors, by type."},"foreign_pct":{"type":["number","null"],"format":"double","description":"Foreign share **of custody**, in percent. Safe on every row.","example":0.0},"foreign_pct_of_issued":{"type":["number","null"],"format":"double","description":"Foreign share of the **issued** amount. Null when no issued figure.\n\n⚠️ Derived from KSEI's registry figure `sec_num`, which **lags the\nissuer on roughly one government bond in nine**. Checked against\nDJPPR's published outstanding across 4,175 series-months: 89.0% agree\nto within 0.1%, 11.0% do not, and the gaps are constant month after\nmonth rather than drifting: a stale record, not a timing difference.\n`SPNS22102024` is the worst seen, KSEI Rp 20bn against an actual\nRp 2.045tn, which makes this field ~100× too large for that series.\n\nFor government securities prefer `/v1/sbn/series/{series}/ownership`,\nwhich carries the same ratio computed against the issuer's own number\nalongside `source_agreement` saying whether the two sources match.\n`foreign_pct` (share of custody) is unaffected and remains the safe\nfield on every row."},"held_total":{"type":"number","format":"double","description":"Local + foreign: everything sitting in C-BEST custody.","example":58500000000.0},"issued_total":{"type":["number","null"],"format":"double","description":"Total issued amount. **Not** the same as `held_total`; see\n`custody_pct`. Null where KSEI reports no issued figure.","example":2417000000000.0},"local":{"$ref":"#/components/schemas/HolderSplit","description":"Units held by domestic investors, by type."},"local_pct":{"type":["number","null"],"format":"double","description":"Domestic share **of custody**, in percent.","example":100.0},"period":{"type":"string","description":"Month, `YYYY-MM`.","example":"2026-07"},"price":{"type":["number","null"],"format":"double","description":"KSEI's own price for the instrument that month."},"security_type":{"type":["string","null"],"description":"Instrument class as KSEI classifies it.","example":"GOVERNMENT BOND"}}},"OwnershipResponse":{"type":"object","description":"What you get back from `GET /v1/equities/{ticker}/ownership`: the latest\nholders snapshot: insider vs institutional split plus top positions.","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/Ownership"},"meta":{"$ref":"#/components/schemas/Meta"}}},"Pagination":{"type":"object","description":"Offset/limit pagination block. Returned on list endpoints; absent on\nsingle-resource endpoints. We chose offset/limit for clarity over cursor\nfor v1: at current data volume it is plenty fast, and clients can switch\nto cursor pagination in v2 without breaking changes (cursor would be a\nnew optional query param + new meta field).","required":["total","limit","offset","has_more"],"properties":{"has_more":{"type":"boolean","description":"`true` if there are more rows after this page."},"limit":{"type":"integer","format":"int32","description":"Maximum rows returned per request.","minimum":0},"offset":{"type":"integer","format":"int32","description":"Number of rows skipped before this page.","minimum":0},"total":{"type":"integer","format":"int64","description":"Total matching rows across all pages. Recomputed per request.","minimum":0}}},"PricesResponse":{"type":"object","description":"What you get back from `GET /v1/equities/{ticker}/prices`.\n\n**`data`**: the daily price history (open / high / low / close /\nvolume), one entry per IDX trading day, sorted **oldest → newest**.\nWeekends and IDX holidays are absent. All prices are in **IDR**.","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Ohlcv"},"description":"One daily OHLCV bar per IDX trading day in the requested range,\nsorted oldest → newest."},"meta":{"$ref":"#/components/schemas/Meta"}},"example":{"data":[{"date":"2026-04-28","open":4400.0,"high":4430.0,"low":4380.0,"close":4410.0,"volume":150000000.0},{"date":"2026-04-29","open":4410.0,"high":4440.0,"low":4380.0,"close":4400.0,"volume":140000000.0},{"date":"2026-04-30","open":4430.0,"high":4450.0,"low":4370.0,"close":4390.0,"volume":186960200.0}],"meta":{"request_id":"df776520-8018-4523-8df5-f8cb30313901","ts":"2026-05-02T13:21:14Z","source":"tarutha"}}},"ReportFile":{"type":"object","description":"One file attached to a financial report (XBRL instance, PDF statement…).","properties":{"file_type":{"type":["string","null"],"description":"Extension: `.pdf`, `.xlsx`, `.zip` (XBRL)…","example":".pdf"},"filename":{"type":["string","null"],"example":"FinancialStatement-2026-I-AADI.pdf"},"size":{"type":["number","null"],"format":"double","description":"File size, bytes."},"url":{"type":["string","null"],"description":"Absolute download URL on idx.co.id."}}},"SbnOutstandingResponse":{"type":"object","description":"What you get back from `GET /v1/sbn/series/{series}/outstanding`: the\namount outstanding for one series over time, back to 2002, newest first.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/OutstandingPoint"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"SbnOwnershipPoint":{"type":"object","description":"One month of ownership for one series, against both denominators.","required":["period","as_of"],"properties":{"as_of":{"type":"string","description":"The DJPPR snapshot paired with this month: the last one inside it,\nbecause KSEI's holdings are a month-end position.","example":"2026-07-31"},"custody_pct_of_outstanding":{"type":["number","null"],"format":"double","description":"How much of the issue is in KSEI custody at all. **Read this first.**\nAt 1.88% the two percentages above describe a small slice: most\ngovernment paper settles at Bank Indonesia, not KSEI.","example":1.882901},"foreign_pct_of_custody":{"type":["number","null"],"format":"double","description":"Foreign share **of custody**, in percent. Safe on every row.","example":2.247797},"foreign_pct_of_outstanding":{"type":["number","null"],"format":"double","description":"Foreign share **of the actual issue**, using the issuer's own figure.\nThis is what `foreign_pct_of_issued` on `/v1/instruments` was reaching\nfor, computed against a number that is not stale. In percent.","example":0.042324},"foreign_total":{"type":["number","null"],"format":"double"},"held_total":{"type":["number","null"],"format":"double","description":"Everything sitting in KSEI custody."},"local_total":{"type":["number","null"],"format":"double"},"outstanding_djppr":{"type":["number","null"],"format":"double","description":"Amount outstanding per the **issuer**.","example":182911300000000.0},"period":{"type":"string","example":"2026-07"},"sec_num_delta_pct":{"type":["number","null"],"format":"double","description":"`sec_num_ksei` relative to `outstanding_djppr`, in percent.","example":-0.328028},"sec_num_ksei":{"type":["number","null"],"format":"double","description":"Amount issued per KSEI's **registry**. Can be stale: see\n`source_agreement`.","example":182311300000000.0},"source_agreement":{"type":["string","null"],"description":"`agree` (within 0.1%) or `ksei_stale`. 11% of series-months are stale.","example":"ksei_stale"}}},"SbnOwnershipResponse":{"type":"object","description":"What you get back from `GET /v1/sbn/series/{series}/ownership`: who holds\none series, month by month, against both the issuer's and KSEI's figure\nfor the issue size.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SbnOwnershipPoint"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"SbnSeriesResponse":{"type":"object","description":"What you get back from `GET /v1/sbn/series`: every government security\noutstanding on one snapshot date, largest first.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SeriesEntry"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"SecuritiesResponse":{"type":"object","description":"What you get back from `GET /v1/idx/securities`: the listed-securities\nmaster, ticker order.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Security"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"Security":{"type":"object","description":"One row of the IDX securities master.","properties":{"listing_board":{"type":["string","null"],"description":"Listing board: `Utama`, `Pengembangan`, `Akselerasi`, `Ekonomi Baru`, `Pemantauan Khusus`.","example":"Utama"},"listing_date":{"type":["string","null"],"description":"First trading day, `YYYY-MM-DD`.","example":"1997-12-09"},"name":{"type":["string","null"],"example":"Astra Agro Lestari Tbk."},"shares":{"type":["number","null"],"format":"double","description":"Shares outstanding.","example":1924688333},"ticker":{"type":["string","null"],"example":"AALI"}}},"SeriesBreak":{"type":"object","description":"A month where the series was cut, and why.\n\nA break means the numbers before it and after it are NOT one continuous\nseries: no return, drawdown or window crosses one. Reasons, exactly as the\nwriter records them:\n\n- `type`: a move over 4x in a fund type that cannot move that much in a\n  month (money market, capital protected, fixed income, sukuk). Read as a\n  data fault, so the series restarts.\n- `units`: the unit count, not the price, caused the move over 4x: a\n  unit-count fault or a consolidation. It is not a return.\n- `rise`: a rise over 4x in NAV per unit that never reversed. Not a\n  plausible return, so the series restarts.\n- `payout_inferred`: ⚠️ **INFERRED, with no source document.** A fall over\n  4x in the last three months before the fund's units reached zero, leaving\n  at most 5% of the NAV. Read as capital paid back to holders, NOT a loss.\n- `staged_liquidation_inferred`: ⚠️ **INFERRED, with no source document.**\n  A fall over 4x while the unit count stayed exactly flat for six months or\n  more, in a fund that closed within eighteen months with 5% or less of its\n  value left. Read as assets paid out in stages, NOT a loss.\n- `payout`: RESERVED for a payout confirmed by an OJK or KSEI notice. No\n  fund carries it today; if you see it, a source document exists.\n\nThe two `_inferred` values are our reading of the shape of the data, not a\nfact anyone published. Treat them as a caveat on the fund, not as evidence.","required":["month","reason"],"properties":{"month":{"type":"string","description":"`YYYY-MM`.","example":"2017-07"},"reason":{"type":"string","description":"One of the values above.","example":"staged_liquidation_inferred"}}},"SeriesEntry":{"type":"object","description":"One government security as of one snapshot date.","required":["series","as_of"],"properties":{"as_of":{"type":"string","description":"Snapshot this row describes, `YYYY-MM-DD`.","example":"2026-07-31"},"coupon_pct":{"type":["number","null"],"format":"double","description":"Coupon in percent. Null for zero-coupon. For `VARIABLE` this is the\n**current reset rate**, which is why it differs from KSEI's figure.","example":6.5},"coupon_type":{"type":["string","null"],"description":"`ZERO`, `FIXED` or `VARIABLE`.","example":"FIXED"},"currency":{"type":["string","null"],"description":"Denomination: the unit of `outstanding`, not always IDR.","example":"IDR"},"first_issue_date":{"type":["string","null"]},"instrument_class":{"type":["string","null"],"description":"`GOVERNMENT_DEBT` (conventional) or `GOVERNMENT_ISLAMIC` (sukuk/SBSN).","example":"GOVERNMENT_DEBT"},"maturity_date":{"type":["string","null"]},"outstanding":{"type":["number","null"],"format":"double","description":"Amount outstanding, in `currency`.","example":182911300000000.0},"series":{"type":"string","example":"FR0087"},"tradable":{"type":["boolean","null"],"description":"Tradable on the secondary market, or held-to-maturity paper."}}},"SourceStatus":{"type":"object","description":"One publishing source: the worst of its datasets.","required":["source","label","verdict","datasets"],"properties":{"datasets":{"type":"array","items":{"$ref":"#/components/schemas/DatasetStatus"}},"label":{"type":"string","example":"IDX"},"source":{"type":"string","example":"idx"},"verdict":{"$ref":"#/components/schemas/Verdict"}}},"StatistikPoint":{"type":"object","description":"One datapoint from the parsed KSEI monthly Statistik PDFs.","required":["metric","period","segment","value","unit"],"properties":{"metric":{"type":"string","description":"Metric key, e.g. `sid_total`, `cbest_value_rp_t`, `sinvest_aum`,\n`regional_investor_share`. Call this endpoint without filters and\ngroup by `metric` to discover the full set.","example":"sid_total"},"period":{"type":"string","description":"Month the figure is for, `YYYY-MM`.","example":"2026-03"},"segment":{"description":"Dimension object: keys depend on the metric family:\n`platform` (sid_total), `security_type` (cbest_*),\n`fund_type` (sinvest_*), `region` (regional_*)."},"unit":{"type":"string","description":"`count`, `pct`, or `rp_trillion`.","example":"count"},"value":{"type":"number","format":"double","description":"Numeric value, in `unit`.","example":24744221.0}}},"Status":{"type":"object","description":"Every source, and the worst verdict among them.","required":["as_of","verdict","sources"],"properties":{"as_of":{"type":"string","description":"When this was computed, RFC 3339 UTC. Cached for up to 60 seconds.","example":"2026-09-14T03:30:00Z"},"sources":{"type":"array","items":{"$ref":"#/components/schemas/SourceStatus"}},"verdict":{"$ref":"#/components/schemas/Verdict"}}},"StatusResponse":{"type":"object","description":"What you get back from `GET /v1/status`: every source's freshness.","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/Status"},"meta":{"$ref":"#/components/schemas/Meta"}}},"Suspension":{"type":"object","description":"One IDX trading suspension or unsuspension notice.","properties":{"date":{"type":["string","null"],"description":"Notice date, `YYYY-MM-DD`.","example":"2026-03-17"},"info_type":{"type":["string","null"],"description":"`SUS` = suspended, `UPT` = unsuspended (trading reopened).","example":"UPT"},"pdf_url":{"type":["string","null"],"description":"Official PDF on idx.co.id."},"ticker":{"type":["string","null"],"example":"IFSH"},"title":{"type":["string","null"],"description":"Indonesian notice title.","example":"Pembukaan Kembali Perdagangan Saham PT Ifishdeco Tbk. (IFSH)"}}},"SuspensionsResponse":{"type":"object","description":"What you get back from `GET /v1/idx/suspensions`: suspension (`SUS`) and\nreopening (`UPT`) notices, newest first.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Suspension"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"TickerInfo":{"type":"object","description":"Reference data for one IDX-listed equity: slowly-changing fields\n(issuer name, sector, ISIN, listing date) sourced from KSEI master\nrecords and IDX listings.\n\nThis endpoint does **not** carry market data. For prices use\n`/v1/equities/{ticker}/prices`; for valuation/profitability metrics use\n`/v1/equities/{ticker}/fundamentals`.\n\n**Stability:** these fields rarely change. Cache aggressively\nclient-side (24h is fine).","required":["ticker"],"properties":{"isin":{"type":["string","null"],"description":"ISO 6166 ISIN identifier: 12-character alphanumeric. The\n2-letter country prefix is always `ID` for Indonesian listings.","example":"ID1000095003"},"listing_date":{"type":["string","null"],"description":"First-listing date on IDX, ISO 8601 (`YYYY-MM-DD`). Null when\nKSEI records do not carry the date (mostly pre-2000 listings).","example":"2003-07-14"},"name":{"type":["string","null"],"description":"Issuer legal name as filed with IDX. Stored ALL-CAPS with the\n`Tbk, PT` suffix per Indonesian convention. Apply title-casing\nclient-side for display.","example":"BANK MANDIRI (PERSERO) Tbk, PT"},"sector":{"type":["string","null"],"description":"IDX sector code: top-level taxonomy (`BANK`, `MINING`, `TRADE`,\n`INFRASTRUCTURE`, ...). For finer industry classification use\n`Fundamentals.industry`. Null for unclassified or pre-listed.","example":"BANK"},"status":{"type":["string","null"],"description":"Listing status enum. Currently emitted: `ACTIVE`, `SUSPENDED`,\n`DELISTED`. Future scrape passes may add `PENDING` (IPO in\nprogress) and `RELISTED`.","example":"ACTIVE"},"stock_exchange":{"type":["string","null"],"description":"Exchange code. Always `IDX` for v1; the field exists to support\ncross-exchange (regional / dual-listed) data in later versions.","example":"IDX"},"ticker":{"type":"string","description":"Ticker symbol: uppercase, alphanumeric, **4 chars** for typical\nIDX listings (e.g. `BMRI`, `BBCA`). The endpoint accepts any case\nin the URL and uppercases it before lookup.","example":"BMRI"}}},"Uma":{"type":"object","description":"One unusual-market-activity (UMA) flag from IDX surveillance.","properties":{"announcement_no":{"type":["string","null"],"example":"Peng-UMA-00210/BEI.WAS/07-2026"},"company":{"type":["string","null"],"example":"Lima Dua Lima Tiga Tbk."},"date":{"type":["string","null"],"description":"Announcement date, `YYYY-MM-DD`.","example":"2026-07-08"},"pdf_url":{"type":["string","null"],"description":"Official PDF on idx.co.id."},"ticker":{"type":["string","null"],"example":"LUCY"},"title":{"type":["string","null"],"description":"Indonesian notice title."}}},"UmaResponse":{"type":"object","description":"What you get back from `GET /v1/idx/uma`: unusual-market-activity flags,\nnewest first.","required":["data","meta","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Uma"}},"meta":{"$ref":"#/components/schemas/Meta"},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"Unit":{"type":"string","enum":["weekday","hour","month"]},"Verdict":{"type":"string","description":"`current`: inside the source's normal lag. `due`: the next value is\nexpected but not yet late (the normal state of a monthly source for most of\na month). `late`: a publication was missed. `unknown`: no data or no answer.","enum":["current","due","late","unknown"]},"Watchlist":{"type":"object","required":["id","name","managers","funds","fund_types","created_at","updated_at"],"properties":{"created_at":{"type":"string"},"fund_types":{"type":"array","items":{"type":"string"},"description":"OJK fund classes, e.g. `Money Market Fund`."},"funds":{"type":"array","items":{"type":"string"},"description":"16-hex fund ids from `/v1/funds`."},"id":{"type":"string","example":"66bd0f1c2a4e5b7d8c9f0a1b"},"managers":{"type":"array","items":{"type":"string"},"description":"Manager slugs from `/v1/managers`."},"name":{"type":"string","example":"Our shelf and the houses we lose to"},"updated_at":{"type":"string"}}},"WatchlistDeletedResponse":{"type":"object","description":"Confirmation that a watchlist was removed.","required":["data","meta"],"properties":{"data":{},"meta":{"$ref":"#/components/schemas/Meta"}}},"WatchlistInput":{"type":"object","required":["name"],"properties":{"fund_types":{"type":"array","items":{"type":"string"}},"funds":{"type":"array","items":{"type":"string"}},"managers":{"type":"array","items":{"type":"string"}},"name":{"type":"string","example":"Our shelf and the houses we lose to"}}},"WatchlistResponse":{"type":"object","description":"One watchlist.","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/Watchlist"},"meta":{"$ref":"#/components/schemas/Meta"}}},"WatchlistsResponse":{"type":"object","description":"Every watchlist belonging to the calling key.","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Watchlist"}},"meta":{"$ref":"#/components/schemas/Meta"}}},"WindowReturn":{"type":"object","description":"One windowed return, carrying the window it was measured over.","required":["window","months"],"properties":{"cagr":{"type":["number","null"],"format":"double","description":"Annualised equivalent of `total`. `null` whenever `total` is `null`."},"from":{"type":["string","null"],"description":"First month of the window, derived from this fund's own `last_period`.\nTwo funds with different `last_period` have different `from` for the\nsame `window`."},"months":{"type":"integer","format":"int32","description":"Length of the window in months."},"to":{"type":["string","null"],"description":"Last month of the window, which is this fund's `last_period`."},"total":{"type":["number","null"],"format":"double","description":"Total return across the window as a fraction. `null` when the fund had\nno priced month at the start of it: never approximated from a shorter\nspan, because a 3-year label on eighteen months of data is an error\nnobody catches downstream."},"window":{"type":"string","description":"`1y`, `3y`, `5y`, `10y` or `20y`."}}}},"securitySchemes":{"bearer_auth":{"type":"http","scheme":"bearer","description":"A Tarutha API key, sent as `Authorization: Bearer tarutha_…`. Keys come with a paid membership. Members create them from the account menu in the Terminal. A key is personal: keep it on a server and never share it. A revoked key is refused on the next request with 401. Repeated failed keys from one network are refused for 10 minutes with 429 and the code AUTH_LOCKOUT."}}},"security":[{"bearer_auth":[]}],"tags":[{"name":"Equities","description":"IDX-listed equities: symbols, reference data, OHLCV, fundamentals, ownership."},{"name":"Indices","description":"IDX stock indices (IHSG/COMPOSITE, LQ45, sector indices) and daily top movers, from official IDX trading summaries."},{"name":"IDX announcements","description":"Company disclosures, trading suspensions, and unusual-market-activity flags published on idx.co.id, with links to the official PDFs."},{"name":"IDX reference","description":"Exchange reference data: securities master, daily broker summaries, share-issuance history, the IPO pipeline, and financial-report filings with XBRL/PDF download URLs."},{"name":"News","description":"Indonesian financial, business, and policy news aggregated from 20+ outlets (CNBC Indonesia, Kontan, Bisnis, Kompas, Katadata, IDN Financials, and more) plus macro/regulator coverage of Bank Indonesia and OJK: each article tagged with the IDX tickers it mentions."},{"name":"KSEI","description":"KSEI public dashboard: investor demographics, asset values, transfer instructions. Long-running structural indicators of the Indonesian capital market."},{"name":"SBN","description":"Indonesian government securities from DJPPR: amount outstanding per series back to 2002, conventional and sukuk, tradable and non-tradable, across eight currencies. Amounts are in the series' own currency and are never converted. The ownership route joins this to KSEI's depository records (37 months, 2023-07 onward) and carries BOTH issue-size figures: the issuer's `outstanding_djppr` and KSEI's registry `sec_num_ksei`, which disagree on 11% of series-months by a constant amount, which points to a stale registry entry rather than timing. Read `custody_pct_of_outstanding` before any ownership percentage: most government paper settles at Bank Indonesia rather than KSEI, so the depository view often covers a small slice of an issue."},{"name":"Status","description":"Is the data current? Per source (IDX, KSEI, OJK, DJPPR, Bank Indonesia, PHEI, Yahoo, Gold, News): the newest date the source states for its data, the source's own publication cadence, and a verdict graded against it. No key needed, no customer data. The same rules as the Tarutha terminal's health page."},{"name":"Instruments","description":"KSEI instruments keyed by ISIN: equities, corporate bonds, sukuk, government bonds and SBSN. Ownership and flow data is monthly. The percentages use custody as the denominator; read `custody_pct` first. A bond ISIN can map to more than one instrument."},{"name":"Watchlists","description":"Saved ticker lists and their alerts. These operations belong to the Tarutha dashboard and use a signed-in account, not an API key. A data API integration does not need them."},{"name":"Funds","description":"Indonesian mutual funds from OJK: per-fund NAV, units outstanding, and derived monthly net flows. Units outstanding is what makes flows computable: NAV alone gives returns, NAV plus units separates money moving in and out from market movement. `nav` is always IDR. Note the industry total here counts public mutual funds only, so it is smaller than KSEI's `sinvest_aum`, which also includes Discretionary Fund (managed accounts)."}]}