Distill Markets API
Distill Markets serves SEC data as it was filed. Each financial fact carries the filing it came from, by accession and filing date. Point-in-time reads return what was on file at a past date. Institutional ownership (13F, 13D and 13G) and Form 4 insider transactions are read from the filings themselves, and macro series from the government agencies that publish them. Everything served is factual information, never advice.
Two ways in
- Hosted MCP server:
https://mcp.distillmarkets.com - Point any MCP client at the URL with your key in a header, or sign in through a connector with OAuth. Nothing to install. See MCP Server.
- REST API:
https://api.distillmarkets.com/api/v1 - JSON over HTTPS with one key in
X-Api-Key; your tier decides which scopes the key carries. See Authentication.
What each dataset is, where it comes from, its range and how often it refreshes: What this data is. The most recent dated changes to served values and rules: the change log. Terms used on these pages: Concepts.
Overview
All requests use HTTPS and return JSON. Authenticate with an API key in the X-Api-Key header. Your tier decides which scopes, and so which endpoints, the key can reach: see Tiers & scopes.
Base URL
https://api.distillmarkets.com
Endpoints sit under /api/v1: /sec for SEC and XBRL data, /macro for macro series, and ticker search under /market.
Quickstart
Create a free key on the settings page (no card required), then make a call:
curl https://api.distillmarkets.com/api/v1/macro \-H "X-Api-Key: dmk_your_key_here"
POST /api/v1/sec/screen. A free key screens the whole SEC universe by margins, leverage, R&D, working capital, capex, buybacks and more. The four scored metrics (Altman Z, Piotroski, accruals, M-score) need quality:read (Analyst) and are null on Free.Run any documented call against your own key in the API Playground. Your first call walks through the claude.ai connector, the ChatGPT plugin, Claude Code or Cursor, and curl or Python, each ending with filed data on the free plan.
Measured accuracy
In the published accuracy audit, 72 of 72 XBRL facts and 29 of 30 Form 4 transactions were exact. Both, with their limits: Measured accuracy.
API stability
An agent that loses a field does not get an error. It gets undefined, carries on, and the answer built on it is wrong without saying so. The guarantees below exist because that failure is silent, and because nothing consuming this API reads release notes.
Response shape is additive only
A field served today keeps being served, under the same name and the same type. New behaviour ships as a new field; an existing one is never repurposed. Documented endpoints stay documented.
This is checked rather than intended: a removal, rename or retype of a served field fails our build before it can reach a release.
A change that cannot be made additively goes to a new version path. The version it replaces keeps serving for at least six months from the date it is marked deprecated, and key holders are told by email when it is. That is policy and has not yet been exercised: no endpoint has been deprecated.
Beta routes are the exception. A route marked beta carries beta: true in every response and may change shape without this guarantee while the label is on. Today that is the three news routes (/api/v1/news/...) and their tools get_news, screen_news and news_overview. A route joins the guarantee when its beta label comes off.
Values can change
Shape is frozen. Values are not: companies amend their own filings, and a corpus that ignored that would be wrong on purpose.
A point-in-time read for a past date can change after you first make it. Changes are listed, dated, in the change log.
Latest-value reads follow the filings. Fundamentals, events, health and the screener report the most recent filed position, and they move when a company revises a figure; the as-of routes exist beside them for that reason.
If a figure you relied on has moved, contact support with the value and the date you read it, and we will say which change moved it and when. Coverage and limits: Limits.
Data notices
The most recent changes that moved a served value or widened a field’s meaning, newest first. A field can keep its name and type while what it describes widens, so each such change is recorded here. A shape change never appears here: a removed, renamed or retyped field goes to a new version path.
- rule changed
openMarketSells,totalSellValue,netOpenMarketShares,distinctSellersandtotalBuyValueon/api/v1/sec/insider/{ticker}openMarketSellsand the sell figures beside it now leave out sales a footnote says were made to cover tax withholding on vesting equity. Those are reported under code S but are not the holder's own decision; they are counted in the newtaxWithholdingSalesandtaxWithholdingSellValue, and flagged per row byisTaxWithholdingSale. Sales filed before footnotes were read stay in the sell figures and are counted insellsWithFootnotesUnreaduntil re-read.totalBuyValueis now 0 when there are no buys (it was null); null still means buys exist and none is priced. Code E rows are described and no longer show a price of 0. - rule changed
changeTypeDetail(new) andchangeTypeon/api/v1/sec/revisions/{ticker}A new field,changeTypeDetail, refines a row whosechangeTypeisunclassified.recast-in-filingmarks a single-period change made by a filing that recast income-statement or cash-flow lines over that period, as the balance-sheet side of a spin-off re-presentation is.reclassificationmarks a change offset by an equal and opposite change to another line in the same filing and period. It is null on every other row; the rows left to read as candidate corrections areunclassifiedwith a null detail.changeTypekeeps its four values and its meaning, and the revision feed and the change ledger are unchanged. With aperiod_endfilter, rows are now classified with the filing's other periods in view, as on the unfiltered call, so a row the filter used to show asunclassifiedcan readmulti-period-recastas it does unfiltered. Values are unchanged. - values changed
pctUnclassifiedon/api/v1/sec/capex-cycles,/api/v1/sec/capex-cycles/sector/{sector}and the briefing's capital cyclepctUnclassifiednow counts only the companies that carry no capex label. It used to be everything not labelled accelerating or decelerating, so companies labelled capex outpacing revenue were counted as unclassified. Those companies are now the remainder, 1 −pctAccelerating−pctDecelerating−pctUnclassified. In fiscal 2025 the unclassified share fell from 0.83-0.90 to 0.57-0.76 across the eleven sectors. No other field moved. - values changed
enterpriseValue,evToSales,evToEbitdaandnetDebtBasison/api/v1/sec/valuation/{ticker};longTermDebtandlongTermDebtCurrenton/api/v1/sec/fundamentals/{ticker}and the responses that embed it (/api/v1/analysis/compare,/api/v1/analysis/entity/{tickerOrId});debt_to_ebitdaandnet_debt_to_ebitdaon/api/v1/sec/screen(live, notas_of)Enterprise value and the screener's debt ratios now read total debt, served astotalDebtwithtotalDebtBasis: long-term debt including current maturities, plus short-term borrowings or commercial paper where filed as their own line. Where a company files a current-debt line that covers its current maturities, the total reads that line, so a short-term debt line that holds the maturities is never counted on top of them. They read long-term debt before, which for many companies was the noncurrent portion only.netDebtBasisnow names the lines the total includes. Enterprise value moved for 401 companies and is now computed for 83 more; the screener's debt ratios moved for 340 companies (all upward) and are now populated for 46 more. For a bank or other lender (a deposits line, or a financial company with positive net interest income) enterprise value and the EV multiples are now null, because its borrowings fund its loan book: 189 companies moved from a value to null. Long-term debt filed only in the annual report is now served for up to fifteen months after the fiscal year end, dated bylongTermDebtPeriodEnd: 101 companies moved from null to a value. - values changed
/api/v1/sec/fundamentals/{ticker}and the responses that embed it (/api/public/company/{ticker}/fundamentals,/api/v1/analysis/compare,/api/v1/analysis/entity/{tickerOrId},/api/v1/sec/valuation/{ticker})Some companies, foreign private issuers among them, showed a figure from an earlier period under the latest period. Such a figure now reads null with its*ConceptUseduntil the latest period's figure is served, andlatestPeriodEndnames the period of the figures served.cikNumberis now always ten digits, zero-padded; some companies had served it without the leading zeros. - values changed
sharesOutstandingon/api/v1/sec/fundamentals/{ticker};sharesOutstandingandsharesAsOfon/api/v1/sec/valuation/{ticker}sharesOutstandingnow describes the latest statement period. Where the only cover-page count on file is years old, the company-wide diluted weighted-average count for that period is served instead, named insharesOutstandingConceptUsed; some companies moved from null to a value this way. A count that does not describe the latest period now reads null, so other companies moved from a value to null. On the valuation response,sharesAsOfis now the date of the share count used and null wheneversharesOutstandingis null; it used to repeat the latest statement period end on every response. - values changed
sharesOutstandingand earnings per share on/api/v1/sec/fundamentals/{ticker}and the responses that embed it (/api/v1/analysis/compare,/api/v1/analysis/entity/{tickerOrId},/api/v1/sec/valuation/{ticker})For companies with more than one class of common stock,sharesOutstandingnow combines the cover-page count of every class, stated in the newsharesOutstandingBasisand broken out inshareClasses. Classes convert at the ratio the company states, so a dual-class company whose count read null now serves one, and its per-share figures and valuation multiples with it. 373 companies moved from a weighted-average count to the combined cover count. Where the classes carry different economics and no conversion ratio is stated, the count reads null withsharesOutstandingUnavailableReason: 14 companies moved from a value to null. - values changed
/api/v1/sec/profile/{ticker}A ticker with no profile of its own whose company has one under another of its tickers (a share class, preferred or warrant) now returns that company profile, withsourcesec-edgarand the requested ticker; many tickers moved off the minimal profile. On a minimal profile (sourceticker-history-fallback),lastUpdatedis now the date of the record it was built from rather than the time of the request. - values changed
filedAton/api/v1/sec/filings/{ticker},newFilingsin/api/v1/analysis/changes, the briefing's filing events,createdAton/api/v1/sec/eventsandfiledAton insider activityEvery filing date is now EDGAR's filing date. Some filings accepted in the US Eastern evening were dated by the UTC calendar instead: a day late where EDGAR keeps the Eastern day, or a day early where EDGAR dates the filing the next business day. Events dated from such a filing carry the filing date at midnight UTC. No filing was added or removed. - rule changed
newestPeriodicFilingDate,newestPeriodicFilingForm,newestPeriodicFilingAccessionandnewerFilingPendingon/api/v1/sec/fundamentals/{ticker}(and the same fields inside compare and entity)The newest 10-K or 10-Q is now the newest the company has filed by any record we hold, so it can no longer trail the figures in the same response, and it is found for every share class of the company.newerFilingPendingis now true until the figures in the response include that filing: before, it turned false as soon as the filing's structured data was received, even while the figures still described the earlier report.