# MetricDuck: guide for AI agents (MCP and REST API) > MetricDuck serves SEC filing data to AI agents over MCP and to code over a REST API: financial > statements, 250+ computed metrics, XBRL facts, filing text, 8-K earnings-release figures, > earnings-call transcripts, IR documents and daily end-of-day stock prices. > SEC figures cite the filing they come from. - MCP server: `https://mcp.metricduck.com/mcp` (remote, streamable HTTP) - REST API base URL: `https://api.metricduck.com` - Setup guide: https://www.metricduck.com/mcp/setup - Tool reference: https://www.metricduck.com/docs/mcp/tools --- ## Contents 1. What MetricDuck is and what it covers 2. How far back the data goes 3. How to connect (MCP and REST) 4. Quotas: what counts as a tool call 5. Which tool for which job 6. Check a figure against its filing 7. Point-in-time data and backtests 8. Monitoring recipe: watch a list of companies 9. Errors and limits 10. REST API reference 11. Links --- ## 1. What MetricDuck is and what it covers ### Sources - **Financial statements, XBRL facts and filing text** come from SEC EDGAR. Freshness, measured on the 8-K and 10-Q filings the SEC accepted from 21:10 UTC on 11-09, when the current pipeline went live, to the end of 11-10, 2026: filing text was available a median of about 7–8 minutes after acceptance, and 9 in 10 within about 20 minutes (515 8-Ks, 440 10-Qs). 10-Q figures were computed on a similar timescale. The recent-filings feed is cached, so a new filing can reach it later: up to 30 minutes in `list_recent_filings`, up to about an hour over REST (`/filings/recent`). Screens and company snapshots refresh on a schedule, so they can lag. SEC figures cite the filing they come from (accession number, filed date, and a link to the filing or the exact fact). - **Earnings-call transcripts and IR documents** (slide decks, event calendars) are management's own words. They are labelled by source tier: SEC-filed, Issuer-published or Machine-transcribed. Treat them as commentary and check the quote; they are not figures from the financial statements. - **Stock prices** come from a market-data feed, not from SEC filings. Prices are not filed, so they carry no filing citation. Valuation multiples (P/E, EV/EBITDA) combine a price with filed figures. ### Coverage - **~6,000 SEC filers:** about 4,800 US companies (10-K, 10-Q, 8-K, DEF 14A) and about 1,200 foreign private issuers (20-F, 40-F, 6-K). Amendments are covered too. - **Foreign private issuers get annual statements only** (from the 20-F or 40-F). They file no interim XBRL statements, so a quarterly `get_financials` request for one returns annual rows, or a note to ask for `period="annual"`. Their interim figures come from 6-K releases: `get_filing_section(ticker, form_type="6-K", section_id="earnings_income_statement")` (also `earnings_balance_sheet` and `earnings_cash_flow`). Some issuers report half-years, so check the period each column covers. - **Prices cover US-listed tickers only:** about 8,400 common-equity tickers on NYSE, Nasdaq and AMEX, end of day. A foreign issuer has a price only if it has a US listing (for example an ADR). - **SEC filers only.** A company listed only on a non-US exchange that does not file with the SEC is not covered. - **Not available:** intraday or real-time prices, options, analyst estimates or consensus, insider-transaction feeds (Forms 3/4/5) and institutional holdings (13F). Those last two are filed with the SEC; MetricDuck does not ingest them. ### Fiscal periods Labels like "Q2 FY2025" follow the company's own fiscal year, which may not match the calendar (Apple's ends in September). `period_end` is the calendar date the period ended. Match a calendar-dated question on `period_end`, not on the label. ### Trust rule for agents Quote figures as the tools return them. If a tool returns no data, an error or "no coverage", say the figure could not be retrieved from MetricDuck. Do not fill it in from memory or another source without flagging it as unverified. --- ## 2. How far back the data goes - **Filings from 2013.** Depth varies by company: for some companies the structured (XBRL) history starts later than 2013. - **Requests return up to 10 years:** - `get_financials`: `years` 1–10. Annual returns up to 10 fiscal years. **Quarterly returns the latest 12 quarters** at most; use `period="annual"` for a longer span. - `get_metric_history`: `window` up to 40 observations (10 years of quarters). - `list_filings`: `years` up to 7, counted back from today, or from `vantage_date` when you pass one. For an older filing, pin `fiscal_year` (and `fiscal_period`) or pass `vantage_date`. - REST statement routes and `/api/v1/data/metrics`: `years` 1–10. `/data/metrics` without an API key is capped at 2 years. - **Full-text search** (`search_sec_filings`) uses SEC's own EDGAR full-text index, which starts in 2001. That is SEC's corpus, not MetricDuck's. - **Prices:** recent history is dense; history before 2014 may be sparse. - **Delisted companies** resolve by name if they filed with the SEC in roughly the last five years. Pass `cik` with `include_delisted=true` to `list_filings`. --- ## 3. How to connect ### MCP (for agents) Server: `https://mcp.metricduck.com/mcp` - **OAuth (default):** add the server URL to your MCP client and sign in once in the browser (OAuth 2.1 with dynamic client registration and PKCE). Free account, no card. - **API key (headless agents, CI):** send `Authorization: Bearer fda_…`. ```json { "mcpServers": { "metricduck": { "type": "http", "url": "https://mcp.metricduck.com/mcp", "headers": { "Authorization": "Bearer fda_your_api_key_here" } } } } ``` Claude Code: `claude mcp add --transport http -s user metricduck https://mcp.metricduck.com/mcp` The MCP server does not read an `X-API-Key` header. On MCP, the key goes in `Authorization: Bearer`. ### REST API (for code) Send the key in the `X-API-Key` header: ```bash curl -H "X-API-Key: fda_your_api_key" \ "https://api.metricduck.com/api/v1/data/metrics?tickers=AAPL&metrics=revenues&period=quarterly&years=1" ``` - `X-API-Key: fda_…` is the production method. - `?api_key=fda_…` works for a quick browser test only. Keys in URLs end up in logs and browser history; do not use it in production. - **`Authorization: Bearer` is not for API keys on REST.** The REST API reads a Bearer token as a web login session. An `fda_` key sent that way is not recognised: on routes where a key is optional the request is served as an anonymous guest (guest limits, no error), and on routes that require a key it returns 401. - Get a key: https://www.metricduck.com/dashboard/api-keys (create a free account first: https://www.metricduck.com/auth/register). ### Plan differences on REST API access to the statement routes (`income-statement`, `balance-sheet`, `cash-flow`, `ratios`) needs a Pro plan. A Free key gets **403** `insufficient_tier`. On the Free plan, use `/api/v1/data/metrics` over REST, or `get_financials` over MCP, which serves the same statements on Free. --- ## 4. Quotas: what counts as a tool call - **A tool call** is one MCP tool call, or one REST request made with your API key. Over MCP, the requests a tool makes internally are not counted separately. - **Free:** 500 tool calls per UTC day, reset at 00:00 UTC. No card. - **Pro** ($20/month or $200/year): no daily cap. The plan includes 50,000 tool calls per month. - **`send_feedback`** does not count. - **Credits are a separate meter, only on `/api/v1/data/metrics`.** Each request there costs credits = tickers × metrics × periods factor (the periods factor is `years`, or `years` × 4 for quarterly; each dimension adds 1). Free has a daily credit budget of 500 credits per UTC day; Pro has 50,000 credits per month. Add `dry_run=true` to see the cost first. A `/data/metrics` request also counts as one tool call. - **`X-RateLimit-*` response headers describe a per-minute limit**, where an endpoint has one. They are not the daily quota. The daily count is not sent as a header. --- ## 5. Which tool for which job Every tool the MCP server lists, by job. Main parameters are shown; the full schemas are in `tools/list` and at https://www.metricduck.com/docs/mcp/tools. | Job | Tool | Main parameters | |---|---|---| | Find the exact ticker or CIK for a name | `search_companies` | `query`, `limit` (≤20) | | See what MetricDuck holds on a company | `browse_company` | `query`, `include_delisted` | | Quick read on one company now (price, valuation, margins) | `get_company_overview` | `ticker`, `depth` (`snapshot` / `core` / `full`) | | Income statement, balance sheet, cash flow over periods | `get_financials` | `ticker`, `period` (`quarterly` / `annual`), `years` (≤10), `statements`, `vantage_date` | | One metric over time | `get_metric_history` | `ticker`, `metric_id`, `period_type` (`Q` / `FY` / `TTM`), `window` (≤40), `vantage_date` | | How a computed metric is derived | `get_metric_lineage` | `ticker`, `metric`, `period_type`, `fiscal_year`, `fiscal_period`, `segment` | | A figure exactly as filed; segment, geography or customer breakdowns | `get_xbrl_facts` | `ticker`, `search`, `accession_number`, `form_type`, `fiscal_year`, `fiscal_period`, `limit` (≤200), `period_history` | | Compare a company with peers | `compare_companies` | `ticker`, `custom_peers`, `peer_mode` (`sector` / `tags`), `metrics`, `period_type` (`TTM` / `FY` / `Q`) | | Screen companies by metrics | `screen_companies` | `filters`, `sort_by`, `sectors`, `required_tags`, `excluded_tags`, `limit` (≤50) | | List a company's filings; get an accession number | `list_filings` | `ticker` or `cik`, `form_type`, `form_subtype`, `years` (≤7), `fiscal_year`, `fiscal_period`, `vantage_date`, `include_delisted` | | Read a filing section (risk factors, MD&A, 8-K, proxy, call transcript) | `get_filing_section` | `ticker` or `cik`, `section_id`, `accession_number`, `form_type`, `fiscal_year`, `fiscal_period`, `vantage_date`, `query` | | What matters in the latest 10-K or 10-Q | `get_filing_index` | `ticker`, `lens`, `vantage_date` | | Which companies show a red flag or event | `screen_filing_signals` | `signals`, `ticker`, `sectors`, `recency_days` (1–365), `since_date`, `until_date`, `match_mode`, `order_by`, `limit` (≤50) | | Full-text search across SEC filings | `search_sec_filings` | `query`, `company`, `ticker_lookup`, `form_type`, `date_from`, `date_to`, `rank_by`, `sections`, `limit` (≤100) | | What a company just reported in its earnings release | `get_earnings` | `ticker`, `quarters` (1–8), `vantage_date` | | Did management deliver what it guided | `get_guidance_vs_actual` | `ticker`, `fiscal_period` | | Earnings-call trends across quarters | `compare_earnings_calls` | `ticker`, `n_quarters` (2–8), `dimensions`, `vantage_date` | | Which earnings documents exist for each quarter | `get_earnings_reports` | `ticker`, `limit` (1–40) | | IR slide-deck text (guidance, KPIs, segment outlook) | `get_ir_documents` | `ticker` or `cik`, `fiscal_year`, `fiscal_period`, `query`, `mode` (`full` / `list`) | | IR event calendar (next earnings call, conferences) | `get_company_events` | `ticker` | | What filed recently, across companies or a watchlist | `list_recent_filings` | `since`, `form_types`, `form_subtypes`, `tickers` (≤50), `ticker`, `limit` (≤100) | | Share price on a date, or a return between two dates | `get_stock_price` | `ticker`, `start_date`, `end_date`, `limit` (≤2000) | | Report missing data or a wrong value to MetricDuck | `send_feedback` | `category`, `message`, `source` | Callable aliases (not listed, same behaviour as their target): `get_financial_metrics` and `get_company_financials` → `get_financials`; `get_company_facts` → `get_xbrl_facts`; `search_filings` and `search_transcripts` → `search_sec_filings`; `get_earnings_calls` → `compare_earnings_calls`; `get_metric_value` → `get_metric_history`. Replies from most tools are capped at about 20,000 characters and say what was trimmed. The markdown tables abbreviate numbers; exact stored values are in each reply's `` block. --- ## 6. Check a figure against its filing SEC figures cite the filing they come from. This is how an agent traces one back. ### What each tool cites - `get_financials`: the accession number and filed date of each period, in a "Source" footnote; EDGAR index links in ``. Quote exact values from ``; the table abbreviates. - `get_metric_history`: each row with an SEC accession links to the filing in the MetricDuck viewer. - `get_xbrl_facts`: the accession number, and an `edgar` link to the exact fact in the filing's inline XBRL where one exists. - `get_filing_section`: the section text, with viewer links to the quoted passage. - `get_metric_lineage`: the formula and its inputs. A base input carries a filing link; a derived input points to its own lineage. - `get_earnings`: 8-K earnings-release figures. A figure carries a verbatim quote and a deep link when the release has an attested receipt; some figures have none (absence of a receipt is not evidence the value is wrong). ### What is not cited, or is cited differently - **Earnings-call transcripts and IR documents:** management's words, labelled by source tier. Check the quote; they are not statement figures. - **Stock prices** are not filed and carry no filing citation. Price-based multiples combine a market price with filed figures. - **Computed metrics** (margins, ROIC, TTM, derived quarters) are calculated by MetricDuck from filed facts. Check the derivation with `get_metric_lineage`. A quarterly input that was derived from year-to-date facts will not equal any single filed fact. ### Call sequence ``` # 1. The figure, with its citation (accession number and viewer link per row) get_metric_history(ticker="JNJ", metric_id="revenues", period_type="FY", window=5) # 2. The filing that first reported that period list_filings(ticker="JNJ", form_type="10-K", fiscal_year=2022, fiscal_period="FY") # -> its accession_number # 3. The fact as filed in that filing (each fact has an `edgar` link to the iXBRL fact, where one exists) get_xbrl_facts(ticker="JNJ", search="revenue", accession_number="") # or every period's value as first filed: get_xbrl_facts(ticker="JNJ", search="revenue", period_history=true) # 4. For a computed metric, its formula and inputs (call again on a derived input to go deeper) get_metric_lineage(ticker="JNJ", metric="gross_margin", period_type="FY", fiscal_year=2022, fiscal_period="FY") # 5. The sentence in the filing (viewer link to the passage) get_filing_section(ticker="JNJ", section_id="mda_results_operations", accession_number="", query="sales") ``` If step 1 and step 3 disagree, the usual reason is that a later filing restated or recast the period: step 1 serves the latest filed value, step 3 shows what the original filing said. A different concept (step 1 may be a computed metric; step 4 shows its inputs) or a derived quarter (a fiscal Q4 is the year minus three quarters) can also explain a gap. Report which one you quote. --- ## 7. Point-in-time data and backtests ### The rule `vantage_date` (YYYY-MM-DD) **bounds which filings are visible and which filing is cited. It does not rebuild values as they stood on that date.** Tools that serve values return the latest filed value: if a later filing restated or recast a period (including a later 10-K's comparative columns), the later value is served under the citation of the filing that was current at the vantage. A LOOK-AHEAD warning appears only when the period's own filing was later amended; other recasts are not flagged. Replies under `vantage_date` from `get_financials`, `get_metric_history` and `get_filing_index` carry a note saying so. In MetricDuck's own measurement, about 6% of FY2019–2023 annual values changed by more than 0.5% in a later 10-K or 10-K/A. ### Values as originally filed - `get_xbrl_facts(ticker, search, accession_number=)`: the facts exactly as that filing reported them, including its comparative columns as known then. Get the accession of the latest filing on or before your date from `list_filings(ticker, vantage_date=)`. - `get_xbrl_facts(ticker, search, period_history=true)`: each period's value as first filed (the earliest filing for each concept, period and dimension). - REST equivalent: `GET /api/v1/companies/{ticker}/raw-facts` with `accession_number`, or with `period_history=true` and `concept_search`. ### Tool by tool | Tool | As of a past date? | How, and where it falls short | |---|---|---| | `list_filings` | Yes (documents) | `vantage_date` lists only filings filed on or before it, and the `years` window (up to 7) counts back from it. A filing does not change; an amendment is a new accession. | | `get_filing_section` | Yes (documents) | `vantage_date` serves the latest filing filed on or before it; `accession_number` pins one. The text is as filed. | | `get_xbrl_facts` | Yes (as filed) | No `vantage_date`. Pin `accession_number`, or use `period_history=true`. Without either, it reads the latest filing as of today. | | `search_sec_filings` | Yes (documents) | `date_from` / `date_to` filter on SEC filing date. SEC's own index. | | `get_earnings` | Mostly | `vantage_date` serves releases known on or before it, and `quarters` walks back from it. A release is never restated (a revision is a new accession). A figure MetricDuck later re-extracted is served at its current reading; such corrections are rare. | | `get_financials` | No: citation only | `vantage_date` bounds visible filings and cites the filing current then. Values are the latest filed; recasts are served (see the rule above). | | `get_metric_history` | No: citation only | `vantage_date` keeps periods whose original filing was published on or before it. Values are the latest filed; recasts are served. | | `get_filing_index` | Partly | `vantage_date` picks the latest 10-K or 10-Q filed on or before it, but its signals are MetricDuck's current extraction (not a record of what was known then), and its "Period Snapshot" numbers are latest-filed values (same note). | | `compare_earnings_calls` | Partly | `vantage_date` limits the comparison to calls reported on or before it; the signals are MetricDuck's current extraction. | | `screen_filing_signals` | Partly | Rows carry their event or filing dates, and `since_date` / `until_date` / `recency_days` window them. There is no `vantage_date`. Most signals are LLM-classified, and they are MetricDuck's current extraction. | | `get_stock_price` | Close: yes. `adj_close` and share count: no | A past close is the close on that date. `adj_close` is adjusted for later splits (and on some older rows, dividends). The shares-outstanding line uses the latest period end on or before `end_date`, which may have been filed after `end_date`. | | `get_company_overview` | No | Latest snapshot. | | `compare_companies` | No | Latest TTM, FY or Q values. | | `screen_companies` | No | Latest-snapshot values and today's companies. There is no as-of universe screen. | | `get_metric_lineage` | No | Pins a period with `fiscal_year` / `fiscal_period`, but reads today's stored derivation. | | `get_guidance_vs_actual` | No | Joins everything stored today. | | `get_company_events` | No | Upcoming versus past is relative to today. | | `get_earnings_reports` | No | Documents as known today. | | `list_recent_filings` | No | The live feed as of today; `since` filters on SEC filing date. | | `browse_company` | No | Today's inventory. | | `get_ir_documents` | Not date-bounded | Returns a published deck by `fiscal_year` / `fiscal_period`, or the latest. No `vantage_date`. | | `search_companies` | Not applicable | Resolves today's names and tickers. | | `send_feedback` | Not applicable | Sends a message to MetricDuck. | ### A backtest recipe For each company and decision date T: 1. `list_filings(ticker, vantage_date=T, form_type="10-K")` (and `"10-Q"`): the filings known at T. 2. `get_xbrl_facts(ticker, search, accession_number=)`: values as known at T. 3. `get_filing_section(ticker, section_id, vantage_date=T)`: the text as known at T. 4. `get_earnings(ticker, vantage_date=T)`: earnings releases known at T. 5. `get_stock_price(ticker, end_date=T)`: the close on or before T. Use `close`, not `adj_close`. `get_xbrl_facts(..., period_history=true)` returns every period as first filed, including periods first filed after T: keep only rows filed on or before T. Dates have no time of day: a filing made after the market close on T is visible at vantage T. If your strategy trades at T's close, use T minus one day as the vantage. For delisted companies, pass `cik` with `include_delisted=true`. --- ## 8. Monitoring recipe: watch a list of companies ### State to keep - the watchlist (up to 50 tickers per `list_recent_filings` call); - the set of accession numbers you have already processed. ### Each run 1. **Poll:** `list_recent_filings(tickers=[...], since=, limit=100)`. Optionally narrow with `form_types=["8-K", "10-Q", "10-K"]`, or `form_subtypes=["8-K-earnings"]` (which implies 8-K only). Foreign issuers file `6-K`, `20-F` and `40-F`; include those in `form_types` if your watchlist has any. 2. **Dedupe by accession:** skip every row whose accession you already processed. Do not use the last poll's date as the next `since`: a filing appears only once MetricDuck has extracted its text, and a small share (mostly 8-K and 6-K exhibits) is extracted days or weeks after its SEC filing date. A 30-day lookback with dedupe catches them. 3. **If a poll returns `limit` rows,** older rows may have been cut (rows are newest first). Split the watchlist or narrow `form_types`. 4. **For each new filing:** - **8-K earnings release** (`form_subtype` `8-K-earnings`): `get_earnings(ticker, quarters=2)` for the headline figures with receipts; `get_filing_section(ticker, accession_number=, section_id="earnings_press_release", query="outlook")` for guidance text; `get_company_events(ticker)` for the next scheduled call. - **Other 8-K** (`8-K-event`, `8-K-other`): `get_filing_section(ticker, accession_number=)` with no `section_id` returns the filing's outline; then read the section you need. - **10-Q or 10-K:** `get_filing_index(ticker)` for what matters in the new filing (it indexes the latest one); `get_financials(ticker, period="quarterly", years=1)` for the numbers. - **6-K:** `get_filing_section(ticker, accession_number=)` for its outline. - **Flags since the last run:** `screen_filing_signals(signals=["earnings_guidance_lowered_8k", "tone_cautious", "covenant_risk"], ticker=, match_mode="any", since_date=, until_date=)`. 5. **Record the accession** once processed. ### Schedule - **cron or any scheduler:** run your agent on a schedule with MetricDuck configured with an API key (`Authorization: Bearer fda_…`, section 3). Store the processed accessions between runs. - **Claude Code routine:** create a scheduled routine (`/schedule` in Claude Code, or claude.ai/code/routines), paste the steps above as its prompt with your watchlist, and connect the channel the result should go to. ### Quota maths (Free: 500 tool calls per UTC day) - One poll is one tool call, whatever the watchlist size (up to 50 tickers). - Polling every 30 minutes is 48 tool calls a day; hourly is 24; every 5 minutes is 288. - Each new filing costs about 2 to 4 more calls (an earnings 8-K with all the calls above: 4). - Example: 50 tickers polled every 30 minutes (48) plus a busy earnings day with 15 new filings at 4 calls each (60) is 108 tool calls, about a fifth of the free day. In quiet weeks the poll is most of the cost. - At the cap, every tool returns a 429 until 00:00 UTC. The next run catches up, because the lookback and the dedupe do not depend on the last run succeeding. --- ## 9. Errors and limits ### Free daily cap (HTTP 429, `FREE_DAILY_CAP`) Over REST, a call past the free daily limit returns HTTP 429 with a `Retry-After` header (seconds until the reset) and this body: ```json { "success": false, "error": "Daily tool-call limit reached", "error_code": "FREE_DAILY_CAP", "message": "Daily limit reached: the Free plan includes 500 tool calls per day. It resets at 00:00 UTC (in 3h 12m). Plan details: https://www.metricduck.com/plans", "limit": "", "resets_at": "2026-11-10T00:00:00Z" } ``` (`limit` is a number in the real response.) Over MCP, the tool result starts with "Daily limit reached (HTTP 429)" and says every MetricDuck tool will return it until 00:00 UTC. Stop calling MetricDuck tools and tell the user when the limit resets. ### Other errors - **429 `RATE_LIMITED_PER_MINUTE`:** too many calls in the last minute. Wait about 60 seconds and retry with fewer calls at once. Over MCP the text says "the per-minute limit, not the daily one". - **403 `insufficient_tier`:** a REST statement route (`income-statement`, `balance-sheet`, `cash-flow`, `ratios`) called with a Free API key. See section 3. - **401:** a route that requires a key got none it recognised. The message reads "Use cookie, X-API-Key header, or ?api_key= query parameter." Check that the key is in `X-API-Key`, not `Authorization: Bearer`. - **404 on a quarterly statement:** Foreign private issuers (20-F/40-F) file annually; quarterly income-statement and cash-flow usually return 404 for them; use period=annual. - **422:** a parameter the route does not accept, or a value out of range. - **404:** an unknown ticker, or no data for the request. Over MCP, a "no coverage" or empty result means the figure could not be retrieved; do not substitute one. ### Guest access (REST, no key) Some REST routes answer without a key, with tight limits: 10 tickers, 15 metrics and a 2-year window per `/data/metrics` request, 10 requests a minute, 30 rows per `/market/daily` request, and a small daily request count on some routes. A free key lifts these. --- ## 10. REST API reference Base URL `https://api.metricduck.com`. Every example sends `X-API-Key`. API access to the statement and ratio routes needs a Pro plan (section 3); on Free, use `/api/v1/data/metrics`. The live schema is at https://api.metricduck.com/openapi.json. Response examples are omitted here; read the field names from a real response or the OpenAPI schema. ### Companies **Endpoint:** `GET /api/v1/companies/search` Search by ticker, name or CIK (fuzzy). Requires a key. **Query Parameters:** - `query` (required): ticker, company name or CIK - `limit` (optional): max results (default: 20, max: 100) - `include_delisted` (optional): false drops delisted companies from fuzzy matches ```bash curl -H "X-API-Key: fda_your_api_key" \ "https://api.metricduck.com/api/v1/companies/search?query=apple&limit=5" ``` **Endpoint:** `GET /api/v1/public/companies/search` The same search without a key. **Query Parameters:** - `query` (required): ticker, company name or CIK - `limit` (optional): max results (default: 10, max: 30) **Endpoint:** `GET /api/v1/companies/universe` Covered companies with ticker, name, CIK, exchange, SIC and filer type, ordered by market cap. **Query Parameters:** - `tickers` (optional): comma-separated tickers - `limit` (optional): max results (default: 500, max: 5000) **Endpoint:** `GET /api/v1/companies/{ticker}/overview-page` The latest snapshot for one company (price, valuation, profitability, cash flow, balance sheet). ### Financial statements (Pro) **Endpoint:** `GET /api/v1/companies/{ticker}/income-statement` **Query Parameters:** - `period` (optional): `quarterly`, `annual` or `ttm` (default: quarterly) - `years` (optional): years of history, 1–10 (default: 5, max: 10) - `vantage_date` (optional): YYYY-MM-DD; bounds visible periods and the cited filing, does not rebuild values (section 7) - `include_segment_hierarchy` (optional): include the business-segment breakdown where available - `signed` (optional): return deductions with the sign they have on the filed statement **Endpoint:** `GET /api/v1/companies/{ticker}/balance-sheet` **Query Parameters:** - `period` (optional): `quarterly`, `annual` or `ttm` (default: quarterly) - `years` (optional): years of history, 1–10 (default: 5, max: 10) - `vantage_date` (optional): YYYY-MM-DD, as above **Endpoint:** `GET /api/v1/companies/{ticker}/cash-flow` **Query Parameters:** - `period` (optional): `quarterly`, `annual` or `ttm` (default: quarterly) - `years` (optional): years of history, 1–10 (default: 5, max: 10) - `vantage_date` (optional): YYYY-MM-DD, as above **Endpoint:** `GET /api/v1/companies/{ticker}/ratios` **Query Parameters:** - `period` (optional): `quarterly`, `annual` or `ttm` (default: quarterly) - `years` (optional): years of history, 1–10 (default: 5, max: 10) ```bash curl -H "X-API-Key: fda_your_api_key" \ "https://api.metricduck.com/api/v1/companies/AAPL/income-statement?period=annual&years=5" ``` There is no `limit` or `offset` on the statement routes; use `years`. ### Metrics **Endpoint:** `GET /api/v1/data/metrics` Chosen metrics for up to 200 tickers in one request (10 without a key). Metered in credits (section 4). **Query Parameters:** - `tickers` (required): comma-separated tickers, e.g. `AAPL,MSFT,GOOGL` - `metrics` (required): comma-separated metric ids, e.g. `revenues,roic,roe` - `period` (optional): `ttm`, `quarterly` or `annual` (default: ttm) - `years` (optional): years of history, 1–10 (default: 2, max: 10) - `dimensions` (optional): trend and statistics series, e.g. `Q.TREND8,Q.MED8,TTM.YOY` - `price` (optional): `historical` (period-end close) or `current` (latest close) for valuation metrics - `dry_run` (optional): return the credit cost without running the query ```bash curl -H "X-API-Key: fda_your_api_key" \ "https://api.metricduck.com/api/v1/data/metrics?tickers=AAPL,MSFT&metrics=revenues,net_margin&period=ttm&years=2&dry_run=true" ``` **Endpoint:** `GET /api/v1/metrics/catalog` The metric catalog: ids, names, formulas and categories. **Query Parameters:** - `category` (optional): filter by category - `search` (optional): keyword search in name, description or tags ### XBRL facts (as filed) **Endpoint:** `GET /api/v1/companies/{ticker}/raw-facts` The raw XBRL facts of one filing, or a concept's as-filed series across filings. **Query Parameters:** - `accession_number` (optional): the filing; if omitted, resolved from `form_type` and `fiscal_year` - `form_type` (optional): e.g. `10-K`, `10-Q`, used when `accession_number` is omitted - `fiscal_year` (optional): used when `accession_number` is omitted - `fiscal_period` (optional): `Q1`, `Q2`, `Q3`, `Q4` or `FY`; pins the period when resolving by `fiscal_year` - `concept_search` (optional): comma-separated label terms, e.g. `Goodwill,Impairment` - `period_history` (optional): each period's value as first filed, across filings (needs `concept_search`) - `limit` (optional): max facts (default: 500, max: 2000) - `offset` (optional): for paging (default: 0) ```bash curl -H "X-API-Key: fda_your_api_key" \ "https://api.metricduck.com/api/v1/companies/AAPL/raw-facts?concept_search=Revenue&period_history=true" ``` ### Filings feed **Endpoint:** `GET /api/v1/filings/recent` Filings since a date, across all covered companies or a watchlist (the REST twin of `list_recent_filings`). **Query Parameters:** - `since` (required): SEC filing date floor, YYYY-MM-DD (inclusive) - `form_types` (optional): repeat for several, e.g. `form_types=8-K&form_types=10-Q` - `form_subtypes` (optional): `8-K-earnings`, `8-K-transcript`, `8-K-event` or `8-K-other` - `tickers` (optional): repeat for several; up to 50 - `limit` (optional): max rows (default: 50, max: 100) ```bash curl -H "X-API-Key: fda_your_api_key" \ "https://api.metricduck.com/api/v1/filings/recent?since=2026-10-10&tickers=AAPL&tickers=MSFT&limit=100" ``` ### Earnings releases **Endpoint:** `GET /api/v1/earnings/{ticker}/history` Figures from recent 8-K earnings releases, newest first. A figure carries a verbatim quote and a deep link where the release has an attested receipt. `{ticker}` may also be a 10-digit CIK. **Query Parameters:** - `quarters` (optional): how many recent releases (default: 8, max: 8) - `vantage_date` (optional): YYYY-MM-DD; serve releases known on or before this date **Endpoint:** `GET /api/v1/earnings/{ticker}/latest` The latest release only. ### Screener and peers **Endpoint:** `POST /api/v1/screener/screen` Screen on latest-snapshot values. Body fields: `filters` (each with `metric_id`, `period_type`, `operator` one of `lt`, `lte`, `gt`, `gte`, `eq`, `between`, and `value` or `min_value` / `max_value`), `sectors`, `industries`, `tickers`, `include_metrics`, `limit` (1–100, default 20), `page`, `sort_by`, `sort_order`. `period_type` defaults to `ttm`; an unsupported metric and period pair returns 422 naming the supported ones. ```bash curl -X POST -H "X-API-Key: fda_your_api_key" -H "Content-Type: application/json" \ -d '{"filters": [{"metric_id": "pe_ratio", "period_type": "ttm", "operator": "between", "min_value": 10, "max_value": 25}], "sectors": ["TECH"], "limit": 20}' \ "https://api.metricduck.com/api/v1/screener/screen" ``` **Endpoint:** `GET /api/v1/screener/metrics` Metrics available for screening. **Endpoint:** `GET /api/v1/sectors` Sector codes for screener filters. **Endpoint:** `GET /api/v1/peers/{ticker}` A company beside its peers. `{ticker}` may also be a CIK. **Query Parameters:** - `tickers` (optional): comma-separated peer tickers instead of automatic selection - `peer_mode` (optional): `tags` (business-model similarity) or `sector` (sector and market-cap range, the default) - `metrics` (optional): comma-separated metric ids instead of the default table - `period_type` (optional): `TTM` (the default), `FY` or `Q` ### Prices **Endpoint:** `GET /api/v1/market/daily/{ticker}` Daily end-of-day prices for a US-listed ticker, from a market-data feed. **Query Parameters:** - `start_date` (optional): YYYY-MM-DD - `end_date` (optional): YYYY-MM-DD - `limit` (optional): max rows (default: 365, max: 2000; 30 without a key) ### Code example (Python) ```python import requests BASE_URL = "https://api.metricduck.com" HEADERS = {"X-API-Key": "fda_your_api_key"} # Resolve a company companies = requests.get( f"{BASE_URL}/api/v1/companies/search", params={"query": "apple", "limit": 5}, headers=HEADERS, ).json() # Metrics for several companies (credits; check the cost with dry_run first) metrics = requests.get( f"{BASE_URL}/api/v1/data/metrics", params={"tickers": "AAPL,MSFT", "metrics": "revenues,net_margin", "period": "ttm", "years": 2}, headers=HEADERS, ).json() # What filed since a date, for a watchlist recent = requests.get( f"{BASE_URL}/api/v1/filings/recent", params={"since": "2026-10-10", "tickers": ["AAPL", "MSFT"], "limit": 100}, headers=HEADERS, ).json() ``` --- ## 11. Links - MCP setup: https://www.metricduck.com/mcp/setup - MCP tool reference: https://www.metricduck.com/docs/mcp/tools - Check a figure against its filing: https://www.metricduck.com/docs/mcp/check-a-figure - Point-in-time data and backtests: https://www.metricduck.com/docs/mcp/point-in-time - Monitoring recipe: https://www.metricduck.com/docs/mcp/monitoring - REST quickstart: https://www.metricduck.com/docs/api - OpenAPI schema: https://api.metricduck.com/openapi.json - Pricing: https://www.metricduck.com/pricing - Contact: https://www.metricduck.com/contact - Short index for agents: https://www.metricduck.com/llms.txt