Financials Normalizer
Pricing
from $10.00 / 1,000 us company-period results
Financials Normalizer
Standardises company financial statements from official filings (SEC XBRL and Companies House UK), with growth metrics, earnings-quality flags, and revenue-by-segment breakdowns -- every number linked back to its source filing.
Pricing
from $10.00 / 1,000 us company-period results
Rating
0.0
(0)
Developer
Elliot Rose
Maintained by CommunityActor stats
1
Bookmarked
2
Total users
1
Monthly active users
6 days ago
Last modified
Categories
Share
Standardises company financial statements from official filings — SEC XBRL (US) and Companies House iXBRL (UK) — into one consistent schema of ~30 line items and 8 ratios per company-period, plus growth metrics, plain-language earnings-quality flags, and (opt-in) revenue-by-segment breakdowns. Every number links back to the exact filing (accession, form, filed date, and a direct URL) it came from.
Give it tickers or CIKs (US) or company numbers (UK); it resolves them, pulls the filer's full fact history, and normalises the mess of inconsistent tagging (Revenues vs SalesRevenueNet vs RevenueFromContractWithCustomerExcludingAssessedTax; UK TurnoverRevenue vs Turnover) into one shape you can chart or diff across companies — US or UK, side by side.
Why this is different from a cheap fundamentals API
It's point-in-time correct, not just "latest number." Every US row separates standardized (the latest-filed value for that period, restatements included) from original (what was first reported, before any restatement) — and this is the one thing most low-cost fundamentals APIs get wrong or don't offer at all. Feed it a pointInTime date and it reproduces exactly what was knowable as of that date: later restatements become invisible, periods not yet filed come back null. That's the difference between a backtest with lookahead bias baked in and one without. If you're building a screener, backtester, or anything that scores historical decisions against financial data, this is the feature that matters most here.
Getting this genuinely right took real work: SEC's own fy field on an XBRL fact reflects which filing it was extracted from, not which real fiscal year the period belongs to (every 10-K reports ~3 years of comparative figures, and all of them get tagged with the current filing's year). Naively trusting it — which is what most quick XBRL parsers do — silently merges different fiscal years together. This Actor buckets by the fact's real calendar period instead, verified against real multi-year filing histories across several large-cap filers.
Input
| Field | Type | Notes |
|---|---|---|
tickers | string[] | e.g. ["AAPL", "MSFT"] |
ciks | string[] | with or without leading zeros / CIK prefix |
ukCompanyNumbers | string[] | UK companies via Companies House — see UK support below |
statements | enum[] | IS, BS, CF; default all three |
periods | enum | annual (default), quarterly, ttm |
years | integer | fiscal years of history, default 5, max 20 |
pointInTime | date string | only consider filings filed on/before this date — see "point-in-time correct" above |
includeRawTags | boolean | add a raw_facts_sample field per row |
includeSegments | boolean | add a segments field per US row with a revenue-by-product/geography breakdown, when the filer reports one. Costs 1-2 extra requests per filing — off by default. |
secUserAgent | string | required for US — "Your Company Name contact@example.com", per SEC's fair access policy |
companiesHouseApiKey | string (secret) | required for UK — get one free at developer.company-information.service.gov.uk |
maxConcurrency | integer | companies processed in parallel, default 3 |
At least one of tickers, ciks, ukCompanyNumbers is required.
Output
One dataset row per company-period (US) or per company (UK — Companies House gives one "latest accounts" snapshot, not a queryable multi-year history the way SEC does). Example (US, periods: "annual"):
{"cik": "0001234567","ticker": "ACME","entity_name": "ACME CORP","market": "us","fy": 2022,"fp": "FY","period_start": "2022-01-01","period_end": "2022-12-31","form": "10-K","filed_at": "2023-02-15","accn": "0001234567-23-000010","filing_url": "https://www.sec.gov/Archives/edgar/data/1234567/000123456723000010/","standardized": {"revenue": 1050000,"cost_of_revenue": 600000,"gross_profit": 450000,"operating_income": 350000,"net_income": 300000,"eps_basic": 3.0,"eps_diluted": 2.9,"total_assets": 5500000,"current_assets": 2200000,"cash": 1100000,"total_liabilities": 2300000,"current_liabilities": 850000,"long_term_debt": 1400000,"equity": 3200000,"operating_cash_flow": 400000,"capex": 120000,"free_cash_flow": 280000,"shares_outstanding": 105000},"original": {"revenue": 1000000},"ratios": {"gross_margin": 0.4286,"operating_margin": 0.3333,"net_margin": 0.2857,"current_ratio": 2.5882,"debt_to_equity": 0.4375,"roe": 0.09375,"roa": 0.05455,"fcf_margin": 0.2667},"growth": {"revenue_yoy": 0.3125,"net_income_yoy": 0.2,"revenue_cagr_2y": 0.2749},"red_flags": [{"flag": "restated","severity": "info","detail": "This period's figures were revised in a later filing: revenue. `standardized` shows the latest-filed value; `original` shows what was first reported."}],"raw_tag_map": {"revenue": "Revenues","cost_of_revenue": "CostOfRevenue","total_liabilities": "Liabilities"},"missing_fields": ["interest_expense", "r_and_d", "sga", "..."],"confidence": 1.0,"confidence_note": "All requested line items were found for this period.","derived_items": ["gross_profit", "free_cash_flow"],"derived": false,"segments": []}
Notes on the shape:
standardizedalways uses the value from the latest-filed accession ("restated view").originalcarries only items where the earliest-filed accession reported a different value — i.e. it only appears for items that were actually restated. In the example above, revenue was originally reported as 1,000,000 and later restated to 1,050,000 in a subsequent 10-K's comparative column.growth— YoY (annual and quarterly), QoQ (quarterly), and CAGR (annual, spanning the actual window returned) for revenue, gross profit, operating income, net income, and free cash flow.TTMrows get a real TTM-vs-year-ago-TTM YoY when 8 quarters of history are available. The first row in any series has nothing to compare against (growth: {}); a gap in fiscal-year coverage is detected and skipped rather than silently computing a multi-year change and calling it YoY.red_flags— plain rule-based earnings-quality checks, no AI/LLM involved: restatement detection (now reliable — see the point-in-time note above), receivables growing much faster than revenue (possible aggressive revenue recognition), profit not converting to operating cash flow, and sharp leverage (debt/equity) increases. Every flag names the exact numbers behind it and is worth a second look, not a verdict. An empty list means "checked, nothing found" — it's always present, never a missing key.confidence_note— a plain-language explanation of theconfidencescore: whether missing items are a real data gap (core financials absent) or just secondary items this filer doesn't separately disclose (common — most filers don't break out goodwill from intangibles). Purely algorithmic, no AI involved, same as everything else in this Actor.segments(only present whenincludeSegments: true) — revenue by product/segment/geography, parsed from the filing's own disaggregation note when it reports one.[]is an honest, valid result for single-segment filers, not a failure. Labels (member_label) are best-effort formatting of the raw XBRL member name; themember/axisfields are the authoritative, unambiguous values.raw_tag_mapshows which XBRL tag was actually used for each item that has a value, so you can audit exactly where a number came from.missing_fieldslists standardised items with no value for this period (no matching tag, or excluded bypointInTime).derived_itemslists items computed from others rather than read directly from a tag (e.g.gross_profit = revenue - cost_of_revenuewhen noGrossProfittag exists;free_cash_flow = operating_cash_flow - capex, always derived;total_liabilities = total_assets - equitywhenLiabilitiesisn't tagged).fp: "Q4"rows (inperiods: "quarterly") andfp: "TTM"rows are computed, never filed directly — flow items arederived: true; instant (balance-sheet) items are simply the fiscal-year-end (or latest-quarter-end) values, since a balance sheet has no "Q4-only" figure.pointInTimereproduces what was knowable as of a given date: only filingsfiled <= pointInTimeare considered, so later restatements are invisible and periods not yet filed come back withnullvalues andconfidence: 0.
A company that resolves but has no XBRL facts on file produces one row: {"cik": ..., "identifier": ..., "market": "us", "error": "no XBRL facts on file for this filer (pre-2009 filer or non-reporting entity)"} — every failure path returns a specific, honest reason, never a silent blank.
UK output shape
UK rows use the same standardized/ratios/confidence/confidence_note shape (so a UK and a US row are directly comparable field-by-field), but have market: "uk", company_number instead of cik/ticker, no fy/fp (Companies House gives one latest-accounts snapshot per call, not a queryable history), and an extra.employees field UK filers commonly disclose that US filers don't. growth/red_flags are empty ({}/[]) for UK rows today — no historical series to compare against yet.
Be aware of a real, structural UK data limitation (documented, not hidden): unlike SEC filings, UK company accounts aren't uniformly structured data. Micro-entity and abbreviated accounts are legally allowed to omit the profit & loss account entirely, so revenue/net_income will genuinely be unavailable for many small UK private companies — confidence_note explains this per row. Some older/small filings are plain PDF scans with no machine-readable data at all — that produces a clear error row ("...no machine-readable (iXBRL) version available..."), never a silent gap. This module targets the common FRS-102/UK-GAAP small-company taxonomy; full IFRS support for large UK-listed groups is out of scope for now.
Pricing events
| Event | Price | When |
|---|---|---|
company-period-us | $0.01 | each standardised US (SEC) company-period row pushed |
company-period-uk | $0.02 | each standardised UK (Companies House) company-period row pushed |
no-data | $0.002 | a requested company/CIK/UK number resolved but produced no rows |
MCP tools
This Actor is designed to back two MCP tools for downstream agents:
get_financials(ticker, period)— run withtickers: [ticker],periods: period(annual/quarterly/ttm), return the standardised rows.compare(tickers, metric)— run withtickers, then projectstandardized.<metric>(orratios.<metric>, orgrowth.<metric>_yoy) across companies and periods for a side-by-side comparison.
Provenance promise
Every number in standardized and original traces back to a specific filing: the row's accn + form + filed_at identify the exact filing, filing_url links straight to it, and raw_tag_map names the exact tag (US). Nothing is estimated from outside sources — items with no matching tag are null and listed in missing_fields, not guessed. The only computed values are the ones in derived_items (simple, documented arithmetic), growth (documented formulas), and red_flags (plain rule-based checks) — never third-party data, never an LLM guess.
Limitations
- Banks, insurers, and other regulated-industry filers commonly use different XBRL tags for analogous concepts (e.g.
InterestAndDividendIncomeOperatinginstead ofRevenues,Deposits-heavy balance sheets) that this actor'sTAG_MAPdoes not specifically target — expect lowerconfidenceand moremissing_fieldsfor these filers. - Pre-2009 filers / periods have no XBRL data on
data.sec.govat all (XBRL mandates phased in 2009–2011); these return ano-datarow. - UK micro-entity/abbreviated accounts can legally omit the P&L entirely, and some filings are PDF-only with no machine-readable data — see "UK output shape" above. Full IFRS-taxonomy support for large UK-listed groups is not yet built.
segmentsonly covers revenue-by-product/geography (the common ASC 606 disaggregation note); segment-level profit/assets (a different note) aren't extracted. Table layouts vary by filer — a genuinely different shape than the common case produces[], not a guess.- Fiscal-quarter
Q4andTTMfigures for flow items are derived by subtraction, not filed directly by the company; they inherit any inconsistency in the underlying quarterly/annual tags (e.g. a mid-year accounting change can make a derived Q4 look odd). confidenceis the share of core line items present after derivation — it is a completeness signal, not an accuracy guarantee.confidence_noteexplains what's actually missing and why.red_flagsare heuristic signals worth a human second look, not findings — thresholds are tuned to avoid noise (e.g. a leverage-ratio flag requires both a meaningful relative and absolute change, so a near-zero-debt company moving from "almost none" to "still almost none" doesn't trigger a false alarm) but are not a substitute for real diligence.