The data contract
What the JSON API and the MCP server promise inside v1, and the files a program reads to hold them to it.
Four promises
Fields are added, never removed or redefined
Inside /api/v1/, a field is added and never removed, renamed, retyped or given another meaning. A field kept for compatibility is listed in deprecations.json with what replaces it, and keeps answering for as long as v1 is served. A change that would break a field is published under a new version path, never inside v1.
How to check it: deprecations.json lists what is kept for compatibility; the OpenAPI description types every field; the manifest's schema digest is read from the tables of fields the reference is written from, never from the files' data, and a field, a code or a type added to those tables moves it.
Every holdings figure is dated and sourced
Every fund file names its source (source_layer, and the filing's address for a fund read from SEC filings) and the date of what it states: the date of its holdings (holdings_as_of), or for a fund with no holdings yet the day its prospectus was filed, and the date of its prices (as_of) beside the figures computed from them. Every holder listed in a stock file carries the date of its fund's file or filing. The overlap of a written comparison and the ETF ownership figure name their method, published with its formula and test vectors in methods.json.
How to check it: the build stops before it publishes when a fund file names no source_layer or no date for what it states, and the manifest gives each source's version, date and age in days.
A key follows the listing, and an old key keeps answering
A holding is keyed by the line it is: a US line by its ticker, a line abroad by its local code and its market (7203.JP). A key written before lines abroad carried their market reads as its new keys, in reads_as and in the aliases of the holders shard of its first character. A fund address listed under aliases in deprecations.json answers 301 to the fund's file under its new ticker. A fund read from SEC filings whose ticker the directory of US-listed funds now gives another fund or a company is not served under it, and a figure that was published under the wrong security is recorded in corrections.json, as SPCX and AFIF were.
How to check it: deprecations.json lists every alias the Worker answers, read from its code.
No silent rewrite
A published figure changes for one of three reasons: a newer source file or price, each with its own date; a new version of a method, with a new id in methods.json, or of one of the readers and computations the manifest names under calculation.readers, either of which moves the manifest's calculation version; or a correction, recorded in corrections.json with its date, the families of files it touched, the tickers and what changed. Every night's files are listed with their sha256, so a program that keeps each night's list can tell exactly which files changed between two nights.
How to check it: corrections.json and the manifest's sha256sums.txt.gz; changelog.json for every other dated change.
The files
| File | What it holds |
|---|---|
/api/v1/manifest.json | The state of one build: its date, the schema and calculation versions, each source with its version, date and age in days, and one sha256 for each family of files. Written every night, after every other file. |
/api/v1/sha256sums.txt.gz | The sha256 of every file under /api/v1/, gzipped, in the format of sha256sum. |
/api/v1/changelog.json | Every dated change of the site and its data, as What changed prints it, each with an id. |
/api/v1/deprecations.json | What still answers but has a replacement: fields, addresses, keys and MCP tool names. |
/api/v1/corrections.json | The corrections registry: each published figure that was wrong, with its date, scope, tickers and what changed. |
/api/v1/methods.json | The methods of the computed figures, with their formulas, rules and test vectors: ti-ownership/1 and ti-ownership-index/1 and ti-overlap/1. |
/api/v1/status.json | What the last build did, and the date of each layer of the data. The status page draws it with the live checks. |
Checking a copy against the manifest
Each night's manifest lists every file under /api/v1/ with its sha256, in sha256sums.txt.gz, and gives one digest per family of files: a directory such as fund/, or a file at the top such as index.json. A family's digest is the sha256 of its lines of the list, in their order, each ending with a newline, so two nights whose digest for fund/ is the same served the same fund files. A copy kept under the same paths is checked with one command, run from the folder that holds it (shasum -a 256 -c on a Mac):
curl -s https://tickerinside.com/api/v1/sha256sums.txt.gz | gunzip | sha256sum -c
To cite an exact state, give the manifest's built_at beside the figure, with its calculation.version. That version moves when a method's id or the version of a reader or computation named under calculation.readers does, and on no other night. The schema digest is read from the tables of fields the reference is written from, never from the files' data: a night's figures never move it, and a field, a code or a type added to those tables does.
Corrections
Each figure that was published wrong and then corrected, newest first, dated by the night the correction reached the files.
Private company holdings the funds filed were left out
· How an issuer file or a filing was read · Files: private-companies · Tickers, for example: ARKK, ARKF, ARKW, DXYZ
Before. A holding counted only when the fund marked it a restricted security or a private placement, filed it as common or preferred stock, gave its series and its value in dollars. ARK Innovation ETF, ARK Next Generation Internet ETF and ARK Blockchain and Fintech Innovation ETF file their OpenAI shares without the mark, BlackRock Private Investments Fund files Anthropic under OTHER, ARK Venture Fund and Destiny Tech100 file without a series, and a row in pounds or euros was dropped although the filing gives its value in dollars: OpenAI was held by 69 funds instead of 83 on the 2026q3 data set, Anthropic by 110 instead of 120.
After. Once two funds hold a company as a marked private placement, a level 3 preferred share of it counts without the mark, and so does any level 3 share of a company whose names the site joins by hand, such as OpenAI and Anthropic, under OTHER too. A fund without a series is its registrant. Every value is the filing's dollars. A fund holding a vehicle that names the company is listed apart, never counted. A report for the first or second month of a fiscal quarter, which is not public, is not read.
A merger was ranked as ETF selling
· ETF flows · Files: flows · Tickers: BLFS, RGEN
Before. The ETF flows of the first night ranked BLFS among the largest net reductions of the day: the funds' BLFS lines left their files when BLFS merged into RGEN, which read as sales.
After. A corporate action is published as one, dated at the first close where any of its lines were flagged, and its securities leave the rankings of that close.
A fund was served under a ticker that now names a company
· A ticker reused or moved · Files: fund, sec, holders · Tickers: SPCX, SPCK
Before. The SPAC and New Issue ETF trades as SPCK, and Nasdaq Trader's directory of 2 October 2026 gives SPCX to Space Exploration Technologies' Class A common stock. The SEC's ticker file still gave the fund's series SPCX, so /api/v1/fund/spcx.json served the fund's filing under the company's ticker.
After. The fund is served as SPCK, from the same filing, and SPCX's one file is the company's stock file under /api/v1/sec/. A fund whose every ticker now names a company of another name is refused.
Two fund files were read from the filings of an earlier fund
· A ticker reused or moved · Files: fund, sec, holders · Tickers: AFIF, GBXB
Before. AFIF and GBXB had fund files built from SEC filings of the series the SEC's ticker file still gave their tickers: AFIF from the filing of Hypatia Women CEO, a fund whose ticker is now Anfield Universal Fixed Income's, and GBXB from a filing of 2025 of a buffer fund no longer listed.
After. A series whose name shares no significant word with the name the directory gives its ticker today, or whose portfolio is more than nine months old, is not served under that ticker. The two files were removed that night.
Two companies sharing a local code were added together
· How securities are keyed · Files: fund, sec, holders, compare, history · Tickers, for example: TM, 7203.JP, 7203.SA, SAN.ES, SAN.FR
Before. A line listed outside the United States was keyed by its local code alone. A fund that held two companies under one code saw them added together (7203 was Toyota in Tokyo and Elm in Riyadh, SAN Banco Santander in Madrid and Sanofi in Paris), and the Malaysia fund, where TM is Telekom Malaysia, was listed as the heaviest holder of Toyota's TM.
After. Each line abroad is keyed by its local code and its market (7203.JP, 7203.SA, SAN.ES, SAN.FR), and US tickers did not change. Each earlier key is listed with the keys it reads as now, under aliases in the holders shard of its first character.
Vanguard weights were inflated
· How an issuer file or a filing was read · Files: fund, sec, holders, compare · Tickers, for example: VWO, VT
Before. On the files of 24 September 2026: Vanguard weights were normalised over the named rows only, which raised every row: VWO's TSMC read 18.28%. A page limit cut VT's file at about 6,000 rows.
After. Each weight is the row's market value over every row's: VWO's TSMC reads 15.45%, and VT has its 9,451 rows.
Orion S.A. was published as Orion Group Holdings
· How securities are keyed · Files: fund, sec, holders · Tickers: OEC, ORN
Before. Orion S.A., which every fund that files it writes as OEC, was published as ORN, the ticker of Orion Group Holdings, in 19 funds read from SEC filings, and in 10 of them it was added to their real ORN position.
After. A line is kept under the ticker its filers agree on when that ticker is on the US list: Orion S.A. is OEC, and ORN is Orion Group Holdings alone.
Invesco files lost some kinds of rows
· How an issuer file or a filing was read · Files: fund, sec, holders, compare · Tickers, for example: KBWD, CVY, EELV, PSP, PXH, IMVP, RSPA, QQQ, CGW, CUT, CZA, EEMO, EFAA, ERTH, IDLV, IMFL, IPKW, IQSZ, MTRA, PDN, PEY, PID, PIE, PWV, PXF, PXJ, QEW, QQA, QQI, SOXQ
Before. On the files of 24 September 2026: business development companies, MLPs, NVDRs, preference shares, units and listed trusts were dropped from Invesco's files (KBWD listed 60.1% of its weight, CVY 74.9%), and equity-linked notes were read as the issuing bank's shares: RSPA showed Wells Fargo at 1.72% for a true 0.14%. QQQ had no ASML line.
After. Those rows are read: KBWD lists 99.5% of its weight and CVY 95.0%, the notes are no longer read as bank shares, and QQQ has its ASML line. Between the archived files of 26 and 28 September 2026, 26 Invesco funds gained rows and more than one point of weight, EEMO from 91.0% to 100.6%.
Two spellings of one security were two holdings
· How securities are keyed · Files: fund, sec, holders, compare · Tickers, for example: BRK.B, BRKB, IVV, SPY
Before. Issuers spell some securities differently, so BRKB and BRK.B were two holdings, and the overlap of two funds of two issuers was understated: IVV against SPY read 97.8%.
After. Each security has one spelling across issuers, settled when the holdings are stored, and two spellings whose issuer names share no word stay two securities. IVV against SPY reads 99.2%, and 13 other pairs of funds of two issuers moved with it.
Some holdings dates were in the issuer's own format
· How an issuer file or a filing was read · Files: fund, holders · Tickers, for example: SPY
Before. 93 holdings dates were written as the issuer writes them, so SPY's read 02-Sep-2026 beside QQQ's 2026-09-02.
After. Every date is written YYYY-MM-DD.
Deprecations
Each of these keeps answering for as long as v1 is served.
| Since | What | Use instead | How it answers |
|---|---|---|---|
| 2026-09-28 | left_out | same_code_abroad, earlier_key_reads_as | An empty list for a stock with a page, and null without one. |
| 2026-09-28 | A key of a line listed abroad without its market, such as 7203 | The keys it reads as now: reads_as in the 404 under /sec/, and the aliases of /api/v1/holders/{c}.json | A 404 under /sec/ with reason earlier_key and reads_as. |
| 2026-10-04 | 404 with reason in_another_layer under /api/v1/fund/{ticker}.json | The answer /fund/ composes from the fund's file under /etf/, with holdings_kind and listed_pct | Only to the Python client before 0.3.0 and the MCP package up to 1.7.1, by the version in their User-Agent. |
| 2026-10-06 | /api/v1/etf/{ticker}.json for a fund of the stock layers | /api/v1/fund/{ticker}.json | 301 to the fund's file under /fund/. |
| 2026-10-09 | The category by its name: c in funds.json, categories in funds-columns.json, category in funds.csv and in /api/v1/screen | cat_id in funds.json, category_ids and category_labels in funds-columns.json, category_id in funds.csv and /api/v1/screen, the category block of each fund file | TickerInside's own category by its name: its label, except for the nine US size and style categories, which keep the names these fields gave them before 9 October 2026, Large Blend to Small Value. |
| 2026-10-09 | A category name the site printed before 9 October 2026, asked of /api/v1/screen?category= | The category's id, as /api/v1/screen?category=international-large-blend | The funds of the category that category_aliases in funds-columns.json maps the name to, with the name asked under filters.category_asked. |
| 2026-09-29 | /api/v1/fund/glov.json | /api/v1/fund/gswo.json | 301 to /api/v1/fund/gswo.json, and its .csv to that file's. |
| 2026-09-29 | /api/v1/fund/rpsa.json | /api/v1/fund/rspa.json | 301 to /api/v1/fund/rspa.json, and its .csv to that file's. |
| 2026-09-29 | /api/v1/fund/netz.json | /api/v1/fund/pwrd.json | 301 to /api/v1/fund/pwrd.json, and its .csv to that file's. |
| 2026-09-29 | /api/v1/fund/fluk.json | /api/v1/fund/flgb.json | 301 to /api/v1/fund/flgb.json, and its .csv to that file's. |
| 2026-09-29 | /api/v1/fund/iscb.json | /api/v1/fund/msml.json | 301 to /api/v1/fund/msml.json, and its .csv to that file's. |
| 2026-10-08 | list_funds | list_etfs | Exactly the answer of list_etfs. |
| 2026-10-08 | fund_profile | get_etf_holdings | Exactly the answer of get_etf_holdings. |
| 2026-10-08 | compare_funds | compare_etfs | Exactly the answer of compare_etfs. |
| 2026-10-08 | overlap_matrix | get_etf_overlap_matrix | Exactly the answer of get_etf_overlap_matrix. |
| 2026-10-08 | look_through | get_etf_portfolio_lookthrough | Exactly the answer of get_etf_portfolio_lookthrough. |
| 2026-10-08 | risk_decomposition | get_etf_portfolio_risk | Exactly the answer of get_etf_portfolio_risk. |
| 2026-10-08 | stock_exposure | find_etfs_holding_stock | Exactly the answer of find_etfs_holding_stock. |
| 2026-10-08 | etf_ownership | get_etf_ownership | Exactly the answer of get_etf_ownership. |
| 2026-10-08 | fund_history | get_etf_holdings_history | Exactly the answer of get_etf_holdings_history. |
| 2026-10-08 | fund_changes | get_etf_holdings_changes | Exactly the answer of get_etf_holdings_changes. |
Reason codes
A 404 under /api/v1/ always carries error not_covered and a reason; a tool of the MCP server that finds a ticker not covered answers with reason_codes, one per ticker, or reason_code. The codes:
| Code | Where | Meaning |
|---|---|---|
has_security_file | REST | A ticker asked for as a fund has a stock file or a holders-only answer; security gives its address. |
is_a_fund | REST, MCP | A ticker asked for as a stock is a covered fund. |
in_another_layer | REST | Sent only to the TickerInside clients released before /fund/ answered for every fund: the fund's file is under /etf/. |
not_in_directory | REST, MCP | The ticker has no file and is not in Nasdaq Trader's directory of US-listed funds of that night: a stock, a mutual fund, a fund listed abroad, or a ticker that is not listed. |
no_file | REST, MCP | The ticker has no file; the directory could not be read to say why, or the answer reads no list. The fund's own address answers with the specific reason. |
funds_not_covered | REST | Under /overlap, /lookthrough and /diversify: several funds the answer needs are not covered; reasons gives each one's code. |
not_held | REST | Under /sec/: no covered fund holds this key. |
earlier_key | REST, MCP | A key written before lines abroad carried their market; reads_as gives the keys it reads as now. |
no_such_endpoint | REST | The address is no endpoint of the API. |
no_written_comparison | REST | Under /compare/: no comparison file for this pair, in either order. |
not_a_shard | REST | Under /holders/: the address is not a shard. |
not_in_archive | REST, MCP | The fund has no holdings history: the history is kept for the funds read from their issuers' own files. |
holdings_at_date_not_enabled | REST | Holdings at a date come from the fund's quarterly SEC reports, and this fund has none here. |
before_first_report | REST | The date is before the fund's first quarterly SEC report here. |
not_in_sec_history | REST | Under /quarterly/: the fund has no quarterly SEC report here. |
invalid_date | REST | The date is not a calendar date written YYYY-MM-DD, or it is after today. |
not_held_by_daily_funds | REST, MCP | No fund read daily from its issuer's files held the key or moved it in the window the flows cover. |
listed_abroad | MCP | get_etf_ownership: a line listed outside the US, which has no ownership figure. |
other_class | MCP | get_etf_ownership: a class with no stock file whose company's figure is under another class's ticker. |
no_security_file | MCP | get_etf_ownership: the ticker has no stock file, so no ownership figure. |
etn | REST, MCP | A ticker of the directory with no file: An exchange-traded note is a debt of the bank that issues it, not a fund, and holds nothing to list. Told from a fund by its name (ETN, ETNs, ETRACS, iPath, X-Links), unless the name also says ETF. |
other_product | REST, MCP | A ticker of the directory with no file: Not a fund: a trust certificate, which holds nothing to list. Told by its name. |
no_filing_yet | REST, MCP | A ticker of the directory with no file: The SEC lists the fund's ticker and it has filed no public Form N-PORT yet. A new fund files its first about two to five months after it lists. |
not_in_sec_list | REST, MCP | A ticker of the directory with no file: Not in the SEC's list of fund tickers yet, so it has no Form N-PORT to read. A new fund reaches that list after it lists. |
other_fund | REST, MCP | A ticker of the directory with no file: The SEC's ticker file still gives this ticker the series of another fund, and that series' newest filing is under the other fund's name, so the ETF's own holdings are not read from it. It joins when its own filing does. |
stale_filing | REST, MCP | A ticker of the directory with no file: The newest public Form N-PORT found for this ticker describes a portfolio more than nine months old, so it is not served as current holdings. It joins when a newer filing does. |
no_prospectus_found | REST, MCP | A ticker of the directory with no file: No holdings file yet, and no prospectus of the fund was found on EDGAR. It is looked up again every few days. |
A wrong figure, or an answer that breaks a promise here: write to contact@tickerinside.com with the address and the figure. The status page gives the state of the service and of the last build, and the API reference documents each file field by field.