REST · v1

API Reference

The read-only Hachiquant API for programmatic access.

Base path
https://hachiquant.com/api/v1
Authentication

No key required — every endpoint is open. Anonymous calls are rate limited per IP.

Rate limit

60 requests per minute per IP. Over the limit returns 429 with Retry-After.

Historical figures

Each period's figures are as filed in that period's own report, so every value traces to one filing. When a later annual report restates a year, the earlier figures are not replaced; the statement endpoints (view=canonical) add the restated figures alongside, in a restatement object naming the report that restated them. With history=extended, the statement endpoints (view=canonical) and /metrics also return the years before a company’s earliest report, as printed in the five-year summary of later annual reports: headline figures only, each year labelled derived_from with the report it comes from.

Fixes we have made to the data are listed on the Data corrections page.

How our API compares with other Japanese stock data APIs

Quick start
curl https://hachiquant.com/api/v1/companies/7203
Download OpenAPI

Pricing and limits

PriceFree. There is no paid plan and no key.
REST API rate limit60 requests per minute per IP; over it returns 429 with Retry-After.
MCP server rate limit300 requests per minute per IP, separate from the REST limit.
Page sizeUp to 200 rows per list request; page with offset.
CoverageAbout 4,000 listed Japanese companies, about 10 years of statements.
FreshnessData refreshes daily; each data response carries X-Data-As-Of.

What the API does not have

  • No share prices, market capitalisation or price-based ratios (P/E, P/B).
  • No forecasts, shareholder lists or dividend data.
  • Quarterly reports end in 2024; interim data after FY2024 is semi-annual.
  • Provided as is, with no uptime or accuracy guarantee (see the terms).

Use from Claude, ChatGPT and other AI assistants

Hachiquant is also a remote MCP server, with no key and no sign-in. Add the URL below as a custom connector in Claude or ChatGPT, or in any MCP client, and the assistant can search companies, read statements and ratios, and screen the market. Every figure keeps its source filing. The MCP server has its own limit: 300 requests per minute per IP.

Connector URL
https://hachiquant.com/mcp
Claude Code
claude mcp add --transport http hachiquant https://hachiquant.com/mcp

System

Liveness and machine-readable schema.

get /api/v1/health
Liveness check

Returns 200 with a database connectivity probe and data_as_of, the newest filing date in the dataset. Open (no key).

Example request
curl https://hachiquant.com/api/v1/health
Responses
  • 200 The service and its database pool are healthy.
get /api/v1/openapi.json
This OpenAPI document

Returns the OpenAPI 3.1 schema you are reading. Open (no key).

Example request
curl https://hachiquant.com/api/v1/openapi.json
Responses
  • 200 The OpenAPI schema.
  • 304 Not Modified: the request's `If-None-Match` names the current `ETag`. No body; it repeats the `ETag` and `Cache-Control` of the `200` it stands for. This endpoint is not rate limited, so the response carries no rate-limit headers, and it carries no `X-Data-As-Of`.

Companies

Search and company identity.

get /api/v1/companies
Search companies

Free-text search over securities code and JP/EN name. Matching is Unicode-normalized on both sides (NFKC + case folding, hiragana folded to katakana, whitespace and . , ・ ' - ignored), so full-width (MINKABU), half-width katakana (トヨタ), hiragana (とよた) and ideographic-space (株式会社 極洋) spellings all match; a former English name noted on the filing cover page stays matchable. Ranking: securities-code prefix, then exact name, then name prefix (a leading or trailing 株式会社 / (株) / 有限会社 / 合同会社 is ignored, so 日立 finds 株式会社日立製作所 as a prefix), then English acronym (the initials of the English name's words, legal forms skipped: mufg finds Mitsubishi UFJ Financial Group, jt Japan Tobacco), then substring; within each tier, companies still filing rank above ones with no filing in the 18 months before the newest filing (delisted, merged), then the larger company by revenue in its newest annual report (total assets when it states no revenue; so トヨタ or 日立 lands on the group flagship; companies stating neither rank after), then the shorter matching name, then the code.

Parameters
q querystringSecurities code or name substring (JP or EN), any width. Empty q lists the universe, code-ordered. A q that normalizes to nothing (only separators) matches nothing. Longer than 200 characters returns 400.
limit queryintegerMaximum rows (default 50, max 200; larger values are capped). Non-integer values return 400.
offset queryintegerRows to skip, for paging the full universe. Non-integer values return 400.
Example request
curl https://hachiquant.com/api/v1/companies?q=toyota
Responses
  • 200 Matching companies, best match first.
  • 304 Not Modified: the request's `If-None-Match` names the current `ETag`. No body; it repeats the `ETag`, `Cache-Control` and `X-Data-As-Of` of the `200` it stands for and counts against the rate limit. Only a response that would have been `200` becomes a `304`.
  • 400 Malformed request (e.g. a non-numeric screener bound).
  • 429 Per-IP quota exceeded.
  • 503 The data this endpoint serves from memory (the search index for `/companies`; the screener universe for `/screener` and `/industries`) has not been built since the API started, and the last attempt to build it failed. Retry after `Retry-After` seconds. Once built, a failed rebuild keeps serving the previous data instead. Never cached, never `304`.
get /api/v1/companies/{ticker}
Company profile

Identity and extended profile for a single company, resolved from its ticker. The identity is the filer of the code's newest filing (ties broken by submission time, then doc_id).

Parameters
ticker requiredpathstringSecurities code without the trailing check digit, e.g. 7203 for Toyota. The 5-character securities code (72030), a .T or .JP suffix, lowercase letters and full-width characters are normalized to it. Values containing control characters (e.g. an embedded percent-encoded NUL) return 400; any other value that does not normalize to four ASCII digits or uppercase letters returns 404.
Example request
curl https://hachiquant.com/api/v1/companies/7203
Responses
  • 200 The company's identity.
  • 304 Not Modified: the request's `If-None-Match` names the current `ETag`. No body; it repeats the `ETag`, `Cache-Control` and `X-Data-As-Of` of the `200` it stands for and counts against the rate limit. Only a response that would have been `200` becomes a `304`.
  • 400 Malformed request (e.g. a non-numeric screener bound).
  • 404 No such company (or, where the operation says so, no such filing or no computable data).
  • 429 Per-IP quota exceeded.

Financials

Statements, filings, and raw XBRL facts.

get /api/v1/line-items
Canonical line-item map

Every canonical statement line in display order, with its labels, role, section and the XBRL elements that satisfy it. The layout that view=canonical statements are placed on by key: a line a filing does not report is absent from that period's lines but present here. Static data; open (no key).

Example request
curl https://hachiquant.com/api/v1/line-items
Responses
  • 200 The line-item map.
  • 304 Not Modified: the request's `If-None-Match` names the current `ETag`. No body; it repeats the `ETag` and `Cache-Control` of the `200` it stands for. This endpoint is not rate limited, so the response carries no rate-limit headers, and it carries no `X-Data-As-Of`.
get /api/v1/companies/{ticker}/income-statements
Income statements

Period-by-period income statements, newest first. Each period carries its raw XBRL records, or with view=canonical its canonical lines.

Parameters
ticker requiredpathstringSecurities code without the trailing check digit, e.g. 7203 for Toyota. The 5-character securities code (72030), a .T or .JP suffix, lowercase letters and full-width characters are normalized to it. Values containing control characters (e.g. an embedded percent-encoded NUL) return 400; any other value that does not normalize to four ASCII digits or uppercase letters returns 404.
view querycanonicalcanonical returns each period's canonical line items (lines, plus basis) in place of its raw XBRL records: the normalized statement the web financials page renders, resolved within one consolidation scope. An annual period that the next annual report restates also carries that report's figures under restatement. Any other value returns 400.
history queryextendedextended also returns the years before the company's earliest served period, as printed in the five-year summary (主要な経営指標等の推移) of its later annual reports: usually four more fiscal years (FY2012–FY2015 for a company whose first stored annual report is FY2016). They follow the served periods, newest first, and each carries derived_from naming the report it was printed in. Each year comes from the newest annual report that prints it (a later restatement of a summary figure wins), in one consolidation scope (consolidated when the summary prints consolidated figures, else parent-only), one reporting standard and one currency, decided for that year. Only the headline lines a summary prints are present (revenue or a bank's ordinary revenue, ordinary or pre-tax income, net income, comprehensive income, total assets, net assets or owners' equity, the three cash-flow totals and cash); on /metrics, only the roe, equity_ratio, eps and bvps it prints, every other metric null with five_year_summary. A derived year repeats its source report's doc_id (that report's own period is in the same response), so key periods by doc_id and period_end together, or check derived_from. Derived years exist only where the source summary facts carry their context dates (every report sampled from 2016 on does); none precede a company's first fiscal period, and a stub year under 181 days is left out. On the statement endpoints it requires view=canonical. Without it, responses are unchanged. Any other value returns 400.
Example request
curl https://hachiquant.com/api/v1/companies/7203/income-statements?view=canonical
Responses
  • 200 Income statements, one object per reporting period.
  • 304 Not Modified: the request's `If-None-Match` names the current `ETag`. No body; it repeats the `ETag`, `Cache-Control` and `X-Data-As-Of` of the `200` it stands for and counts against the rate limit. Only a response that would have been `200` becomes a `304`.
  • 400 Malformed request (e.g. a non-numeric screener bound).
  • 404 No such company (or, where the operation says so, no such filing or no computable data).
  • 429 Per-IP quota exceeded.
get /api/v1/companies/{ticker}/balance-sheets
Balance sheets

Period-by-period balance sheets, newest first.

Parameters
ticker requiredpathstringSecurities code without the trailing check digit, e.g. 7203 for Toyota. The 5-character securities code (72030), a .T or .JP suffix, lowercase letters and full-width characters are normalized to it. Values containing control characters (e.g. an embedded percent-encoded NUL) return 400; any other value that does not normalize to four ASCII digits or uppercase letters returns 404.
view querycanonicalcanonical returns each period's canonical line items (lines, plus basis) in place of its raw XBRL records: the normalized statement the web financials page renders, resolved within one consolidation scope. An annual period that the next annual report restates also carries that report's figures under restatement. Any other value returns 400.
history queryextendedextended also returns the years before the company's earliest served period, as printed in the five-year summary (主要な経営指標等の推移) of its later annual reports: usually four more fiscal years (FY2012–FY2015 for a company whose first stored annual report is FY2016). They follow the served periods, newest first, and each carries derived_from naming the report it was printed in. Each year comes from the newest annual report that prints it (a later restatement of a summary figure wins), in one consolidation scope (consolidated when the summary prints consolidated figures, else parent-only), one reporting standard and one currency, decided for that year. Only the headline lines a summary prints are present (revenue or a bank's ordinary revenue, ordinary or pre-tax income, net income, comprehensive income, total assets, net assets or owners' equity, the three cash-flow totals and cash); on /metrics, only the roe, equity_ratio, eps and bvps it prints, every other metric null with five_year_summary. A derived year repeats its source report's doc_id (that report's own period is in the same response), so key periods by doc_id and period_end together, or check derived_from. Derived years exist only where the source summary facts carry their context dates (every report sampled from 2016 on does); none precede a company's first fiscal period, and a stub year under 181 days is left out. On the statement endpoints it requires view=canonical. Without it, responses are unchanged. Any other value returns 400.
Example request
curl https://hachiquant.com/api/v1/companies/7203/balance-sheets?view=canonical
Responses
  • 200 Balance sheets, one object per reporting period.
  • 304 Not Modified: the request's `If-None-Match` names the current `ETag`. No body; it repeats the `ETag`, `Cache-Control` and `X-Data-As-Of` of the `200` it stands for and counts against the rate limit. Only a response that would have been `200` becomes a `304`.
  • 400 Malformed request (e.g. a non-numeric screener bound).
  • 404 No such company (or, where the operation says so, no such filing or no computable data).
  • 429 Per-IP quota exceeded.
get /api/v1/companies/{ticker}/cash-flow-statements
Cash flow statements

Period-by-period cash flow statements, newest first.

Parameters
ticker requiredpathstringSecurities code without the trailing check digit, e.g. 7203 for Toyota. The 5-character securities code (72030), a .T or .JP suffix, lowercase letters and full-width characters are normalized to it. Values containing control characters (e.g. an embedded percent-encoded NUL) return 400; any other value that does not normalize to four ASCII digits or uppercase letters returns 404.
view querycanonicalcanonical returns each period's canonical line items (lines, plus basis) in place of its raw XBRL records: the normalized statement the web financials page renders, resolved within one consolidation scope. An annual period that the next annual report restates also carries that report's figures under restatement. Any other value returns 400.
history queryextendedextended also returns the years before the company's earliest served period, as printed in the five-year summary (主要な経営指標等の推移) of its later annual reports: usually four more fiscal years (FY2012–FY2015 for a company whose first stored annual report is FY2016). They follow the served periods, newest first, and each carries derived_from naming the report it was printed in. Each year comes from the newest annual report that prints it (a later restatement of a summary figure wins), in one consolidation scope (consolidated when the summary prints consolidated figures, else parent-only), one reporting standard and one currency, decided for that year. Only the headline lines a summary prints are present (revenue or a bank's ordinary revenue, ordinary or pre-tax income, net income, comprehensive income, total assets, net assets or owners' equity, the three cash-flow totals and cash); on /metrics, only the roe, equity_ratio, eps and bvps it prints, every other metric null with five_year_summary. A derived year repeats its source report's doc_id (that report's own period is in the same response), so key periods by doc_id and period_end together, or check derived_from. Derived years exist only where the source summary facts carry their context dates (every report sampled from 2016 on does); none precede a company's first fiscal period, and a stub year under 181 days is left out. On the statement endpoints it requires view=canonical. Without it, responses are unchanged. Any other value returns 400.
Example request
curl https://hachiquant.com/api/v1/companies/7203/cash-flow-statements?view=canonical
Responses
  • 200 Cash flow statements, one object per reporting period.
  • 304 Not Modified: the request's `If-None-Match` names the current `ETag`. No body; it repeats the `ETag`, `Cache-Control` and `X-Data-As-Of` of the `200` it stands for and counts against the rate limit. Only a response that would have been `200` becomes a `304`.
  • 400 Malformed request (e.g. a non-numeric screener bound).
  • 404 No such company (or, where the operation says so, no such filing or no computable data).
  • 429 Per-IP quota exceeded.
get /api/v1/companies/{ticker}/filings
Filing history

Filing (document) metadata for a company, so consumers can reach the original filing (by doc_id). Also available at /documents. Newest first: by filing date, then submission time, then doc_id, so same-day filings keep a stable order. By default every stored document type is listed except quarterly-report amendments (150) that no statement serves; a 150 that is its period's served filing (the doc_id the statements and metrics cite) is listed too. doc_type selects types explicitly (including every 150). Withdrawn documents are listed with their withdrawal_status. quarter and fiscal_year place each filing in the company's own fiscal calendar, exactly as the statement endpoints do.

Parameters
ticker requiredpathstringSecurities code without the trailing check digit, e.g. 7203 for Toyota. The 5-character securities code (72030), a .T or .JP suffix, lowercase letters and full-width characters are normalized to it. Values containing control characters (e.g. an embedded percent-encoded NUL) return 400; any other value that does not normalize to four ASCII digits or uppercase letters returns 404.
doc_type querystringComma-separated document type codes to keep, e.g. 120,130. Entries that are not three digits return 400.
from querystringEarliest filing date (date), inclusive, YYYY-MM-DD. Invalid dates return 400.
to querystringLatest filing date (date), inclusive, YYYY-MM-DD. Invalid dates return 400.
limit queryintegerMaximum rows; absent returns every match. Non-integer values return 400.
offset queryintegerMatches to skip. Non-integer values return 400.
Example request
curl https://hachiquant.com/api/v1/companies/7203/filings
Responses
  • 200 Filing metadata, newest first.
  • 304 Not Modified: the request's `If-None-Match` names the current `ETag`. No body; it repeats the `ETag`, `Cache-Control` and `X-Data-As-Of` of the `200` it stands for and counts against the rate limit. Only a response that would have been `200` becomes a `304`.
  • 400 Malformed request (e.g. a non-numeric screener bound).
  • 404 No such company (or, where the operation says so, no such filing or no computable data).
  • 429 Per-IP quota exceeded.
get /api/v1/companies/{ticker}/document-data
Raw XBRL facts

Raw parsed XBRL facts (power/debug use, and the way to verify a figure against its filing). With doc_id, every fact of that one filing, whatever its document type — annual (120), semi-annual (160), amendments. Without doc_id, every fact of the company's legacy quarterly reports (140) only: quarterly reports stopped being filed in April 2024, so the default is empty for annual-only or newer filers. A filing under non-disclosure (disclosure_status 2) yields no facts (200 []): the official disclosure shows only a notice for it.

Parameters
ticker requiredpathstringSecurities code without the trailing check digit, e.g. 7203 for Toyota. The 5-character securities code (72030), a .T or .JP suffix, lowercase letters and full-width characters are normalized to it. Values containing control characters (e.g. an embedded percent-encoded NUL) return 400; any other value that does not normalize to four ASCII digits or uppercase letters returns 404.
doc_id querystringA doc_id from /filings (e.g. S100Y8NY). A doc_id that is not one of this company's filings — unknown, or another company's — returns 404.
Example request
curl https://hachiquant.com/api/v1/companies/7203/document-data?doc_id=S100Y8NY
Responses
  • 200 Raw financial data elements.
  • 304 Not Modified: the request's `If-None-Match` names the current `ETag`. No body; it repeats the `ETag`, `Cache-Control` and `X-Data-As-Of` of the `200` it stands for and counts against the rate limit. Only a response that would have been `200` becomes a `304`.
  • 400 Malformed request (e.g. a non-numeric screener bound).
  • 404 No such company (or, where the operation says so, no such filing or no computable data).
  • 429 Per-IP quota exceeded.

Metrics

Computed ratios and the fundamental valuation block.

get /api/v1/companies/{ticker}/metrics
Computed metrics

Trimmed-core fundamental metrics for every reporting period, newest first. Ratios are decimals (0.18 = 18%) and current_ratio is a multiple; eps and bvps are per-share amounts and fcf an amount in base units, all in the period's currency. A metric that cannot be computed is null, and null_reasons says why: an input not reported, a zero denominator, a change of standard, scope or currency against the prior year, and more.

Parameters
ticker requiredpathstringSecurities code without the trailing check digit, e.g. 7203 for Toyota. The 5-character securities code (72030), a .T or .JP suffix, lowercase letters and full-width characters are normalized to it. Values containing control characters (e.g. an embedded percent-encoded NUL) return 400; any other value that does not normalize to four ASCII digits or uppercase letters returns 404.
history queryextendedextended also returns the years before the company's earliest served period, as printed in the five-year summary (主要な経営指標等の推移) of its later annual reports: usually four more fiscal years (FY2012–FY2015 for a company whose first stored annual report is FY2016). They follow the served periods, newest first, and each carries derived_from naming the report it was printed in. Each year comes from the newest annual report that prints it (a later restatement of a summary figure wins), in one consolidation scope (consolidated when the summary prints consolidated figures, else parent-only), one reporting standard and one currency, decided for that year. Only the headline lines a summary prints are present (revenue or a bank's ordinary revenue, ordinary or pre-tax income, net income, comprehensive income, total assets, net assets or owners' equity, the three cash-flow totals and cash); on /metrics, only the roe, equity_ratio, eps and bvps it prints, every other metric null with five_year_summary. A derived year repeats its source report's doc_id (that report's own period is in the same response), so key periods by doc_id and period_end together, or check derived_from. Derived years exist only where the source summary facts carry their context dates (every report sampled from 2016 on does); none precede a company's first fiscal period, and a stub year under 181 days is left out. On the statement endpoints it requires view=canonical. Without it, responses are unchanged. Any other value returns 400.
Example request
curl https://hachiquant.com/api/v1/companies/7203/metrics
Responses
  • 200 One metrics object per reporting period.
  • 304 Not Modified: the request's `If-None-Match` names the current `ETag`. No body; it repeats the `ETag`, `Cache-Control` and `X-Data-As-Of` of the `200` it stands for and counts against the rate limit. Only a response that would have been `200` becomes a `304`.
  • 400 Malformed request (e.g. a non-numeric screener bound).
  • 404 No such company (or, where the operation says so, no such filing or no computable data).
  • 429 Per-IP quota exceeded.
get /api/v1/companies/{ticker}/valuation
Fundamental valuation

The fundamental valuation block (quality / return / leverage metrics) for the latest period, or the trailing-twelve-month window with ?ttm=true. The latest annual is never a stub annual shorter than 181 days (e.g. an eight-day final report); such a period stays in /metrics. Market multiples (P/E, EV/EBITDA, …) are omitted until the market-price source lands. On the latest annual, industry_percentiles ranks the company within its TSE 33 industry on eight ratios (rank, peer count n and top_pct), omitting a metric with fewer than 10 peers. The response is a single object, so a known company with no computable period is a 404 with message No financial data for ticker … (No annual data to anchor TTM for ticker … with ttm), while an unknown ticker is No company for ticker …; GET /companies/{ticker} tells the two apart.

Parameters
ticker requiredpathstringSecurities code without the trailing check digit, e.g. 7203 for Toyota. The 5-character securities code (72030), a .T or .JP suffix, lowercase letters and full-width characters are normalized to it. Values containing control characters (e.g. an embedded percent-encoded NUL) return 400; any other value that does not normalize to four ASCII digits or uppercase letters returns 404.
ttm querybooleanReturn trailing-twelve-month metrics instead of the latest period's: the latest ~12-month annual plus the next fiscal year's interim minus the same interim a year earlier. When that window cannot be formed (no newer interim yet, as for a March year-end company until its half-year report), the response is the latest annual exactly as without ttm, labelled as itself with the same values and null_reasons (until 2026-10-12 its roe/roa were recomputed on closing balances and its eps, bvps and growth were null), but never with industry_percentiles. A flow the annual reports but the interim pair does not is left out of the window, and a metric null for that reason says interim_not_reported. Values other than true/false return 400.
Example request
curl https://hachiquant.com/api/v1/companies/7203/valuation
Responses
  • 200 The latest (or TTM) fundamental valuation snapshot.
  • 304 Not Modified: the request's `If-None-Match` names the current `ETag`. No body; it repeats the `ETag`, `Cache-Control` and `X-Data-As-Of` of the `200` it stands for and counts against the rate limit. Only a response that would have been `200` becomes a `304`.
  • 400 Malformed request (e.g. a non-numeric screener bound).
  • 404 No such company (or, where the operation says so, no such filing or no computable data).
  • 429 Per-IP quota exceeded.

Screener

Rank the universe by fundamental metrics.

get /api/v1/screener
Screen the universe

Ranks companies by each company's latest annual values from the precomputed metrics (refreshed daily). Freshness: by default a company whose filing_status is no_longer_filing (no original annual, quarterly or semi-annual report for more than 548 days before the newest one in the data; the same rule as /companies) is left out; include_stale=true keeps them. Listed investment vehicles (J-REITs, ETFs and other funds filing under ordinance 030; entity_type: investment_vehicle on /companies) are always left out, since corporate ratios do not apply to them; they stay in search and on their own company pages. Before 2026-10 this was a 730-day rule on the latest annual period_end. The latest annual is the same period /valuation serves: the newest full-length annual period (a stub annual shorter than 181 days never counts), with whatever metrics it has, possibly none (the row then has empty metrics). Filters: add <metric>_min and/or <metric>_max query parameters (e.g. roe_min=0.1, equity_ratio_max=0.8). A company must report every filtered metric to match. Valid metric keys: gross_margin, operating_margin, net_margin, roe, roa, revenue_growth, eps, eps_growth, current_ratio, equity_ratio, bvps, fcf. Non-numeric (or NaN) bounds and non-integer limit/offset return 400. An unrecognized sort key falls back to ticker order, and any order other than asc sorts descending. Industry: industry=3700 or industry=transportation-equipment keeps one TSE 33 sector's companies: the rows whose industry object has that code or slug (the 33 values are listed in the Industry schema). The sector's English or Japanese name also works (Transportation Equipment, 輸送用機器); slugs and English names match in any case. total counts the matches, and the filter combines with the bounds, sort, paging and include_stale. One value per request: a repeated industry, or a value that names no sector, returns 400 listing the 33 slugs. Companies without a sector (industry: null) never match.

Parameters
roe_min querynumberExample lower bound. The same <metric>_min / <metric>_max pattern works for every metric key (see description). A bound on any other name (a misspelling such as roe_minimum, or an unserved metric such as per_min) is ignored without error, like any unknown query parameter; the response does not echo the filters it applied.
roe_max querynumberExample upper bound.
sort querygross_margin | operating_margin | net_margin | roe | roa | revenue_growth | eps | eps_growth | current_ratio | equity_ratio | bvps | fcfMetric key to order by; omit to order by ticker. A key outside this list is ignored without error and the results come back in ticker order; the response does not echo the sort it applied.
order queryasc | descSort direction. Any value other than asc sorts descending.
limit queryintegerMaximum rows (default 50, max 200; larger values are capped). Non-integer values return 400.
offset queryintegerRows to skip. Non-integer values return 400.
include_stale querybooleantrue keeps companies that are no longer filing (filing_status: no_longer_filing; see Freshness). Values other than true/false return 400.
industry querystringTSE 33 sector to keep: its four-digit code (3700), slug (transportation-equipment) or name (Transportation Equipment, 輸送用機器). Surrounding spaces are ignored; slugs and English names match in any case. The industry object serves the code and slug, and the Industry schema lists all 33. One value per request: repeating the parameter, or a value that names no sector, returns 400 listing the slugs.
Example request
curl https://hachiquant.com/api/v1/screener
Responses
  • 200 A page of matching companies plus the total match count.
  • 304 Not Modified: the request's `If-None-Match` names the current `ETag`. No body; it repeats the `ETag`, `Cache-Control` and `X-Data-As-Of` of the `200` it stands for and counts against the rate limit. Only a response that would have been `200` becomes a `304`.
  • 400 Malformed request (e.g. a non-numeric screener bound).
  • 429 Per-IP quota exceeded.
  • 503 The data this endpoint serves from memory (the search index for `/companies`; the screener universe for `/screener` and `/industries`) has not been built since the API started, and the last attempt to build it failed. Retry after `Retry-After` seconds. Once built, a failed rebuild keeps serving the previous data instead. Never cached, never `304`.
get /api/v1/industries
List industries

The 33 TSE industry sectors in sector-code order (since 2026-10-09), each with its code, slug and English and Japanese names (as in the Industry schema), the number of companies it has in the screener's default universe, and the quartiles of the eight ranking metrics across those companies. Companies: the screener's default universe: currently filing operating companies (not no_longer_filing, no investment vehicles), each on its latest full-length annual. companies equals the screener's total for industry=<code> without include_stale; a company without a sector is in no industry. A sector with no such company is still listed, with 0. Quartiles: for each of roe, roa, net_margin, operating_margin, gross_margin, equity_ratio, revenue_growth and eps_growth, the 25th percentile, median and 75th percentile of the sector's companies that have a value, by linear interpolation between the closest ranks (the method of NumPy's default and Excel's PERCENTILE.INC), with n, the companies counted. A metric with fewer than 10 values is omitted, the same rule as industry_percentiles on /valuation, whose n it matches. Computed from the daily precomputed metrics, so it changes when they do. Takes no parameters.

Example request
curl https://hachiquant.com/api/v1/industries
Responses
  • 200 The 33 sectors with company counts and metric quartiles.
  • 304 Not Modified: the request's `If-None-Match` names the current `ETag`. No body; it repeats the `ETag`, `Cache-Control` and `X-Data-As-Of` of the `200` it stands for and counts against the rate limit. Only a response that would have been `200` becomes a `304`.
  • 429 Per-IP quota exceeded.
  • 503 The data this endpoint serves from memory (the search index for `/companies`; the screener universe for `/screener` and `/industries`) has not been built since the API started, and the last attempt to build it failed. Retry after `Retry-After` seconds. Once built, a failed rebuild keeps serving the previous data instead. Never cached, never `304`.

API changelog

Changes within /api/v1 are additive; a breaking change ships under a new version.

  • A non-breaking space (&nbsp;) in a profile text now reads as a space instead of the literal reference, in business_policy_ja and in description_ja / description_en: filers pad headings and figures with it (「Vision&nbsp;2030」). No other text normalization changes.
  • GET /companies/{ticker} now also serves business_policy_ja, the annual securities report’s 「経営方針、経営環境及び対処すべき課題等」 section (where a company states its medium-term management plan), as plain text whose paragraphs are separated by a newline, with business_policy_doc_id and business_policy_period_end naming the report it was quoted from. All three are null for a company whose latest annual report carries no such section or that has not been re-extracted yet; the companions are null whenever the text is. No existing field changes.
  • /valuation?ttm=true with no trailing window to form (no newer interim yet, as for a March year-end company until its half-year report) now serves the latest annual exactly as plain /valuation does: the same period, metric values and null_reasons, average-balance roe and roa, eps, bvps and growth included, without industry_percentiles. It had been recomputed on closing balances with eps, bvps and growth null under the annual’s label (7203 FY2025 S100Y8NY: roe 0.0964, now 0.1015). Responses with a window (span TTM) are unchanged.
  • The OpenAPI document states what the screener does with names it does not know: a bound on any other name (roe_minimum, per_min) or a sort key outside the list is ignored without error, and the response echoes neither. The reference examples request view=canonical on the statement endpoints and one filing’s doc_id on /document-data. No response changes.
  • A period of a company whose current TSE 33 sector is Banks, Securities & Commodity Futures or Insurance now gets not_applicable_for_financials for a missing operating income, gross profit or current split when no filed element names the sector and the period has neither operating income nor current assets; extension_only still wins. Six companies change: 8604 (was summary_only), 8473 and 8698 (all periods), 8725, 8630’s IFRS periods and 8398’s FY2016–FY2023 annuals (were not_reported). General-format firms in those sectors (8739) and Other Financing (8591) keep their reasons. Only null_reasons change; no value does (8604’s fcf stays not_reported [capex]).
  • cost_of_sales and gross_profit are now the pair that foots with the revenue served beside them: the first pair of filed elements, in line-map order, with net_sales − cost_of_sales = gross_profit within ¥2M, else the first-filed lines. A company whose revenue line is 営業収益 is served 営業総利益 (and 営業原価 where its 売上原価 does not foot), not 売上総利益 struck from net sales alone, in statements and gross_margin alike: 9950 34.3% → 44.9%, 3382 15.3% → 30.0%, 8267 24.7% → 36.5%. Those lines are labelled Operating Gross Profit (営業総利益) and Operating Cost (営業原価). Other lines and metrics are unchanged.
  • A view=canonical net_sales line read from 営業収益 is labelled Operating Revenue (営業収益), not Revenue (売上高): the filer’s own 売上高 is a smaller figure (8267 S100Y5VH: 営業収益 ¥10.7T, 売上高 ¥9.36T). The same holds for its cover-page twin and the railway, electric-power, investment-management and commodity-futures 営業収益 totals; OperatingRevenue2 reads Operating Revenue (営業収入) and GrossOperatingRevenue Gross Operating Revenue (営業総収入). 売上高, 売上収益, 完成工事高 and other company-specific revenue elements keep Revenue (売上高); bank, insurer and broker lines keep their own labels, including Insurance Revenue (保険収益) from the company-specific InsuranceRevenueIFRS. Values, keys, metrics and /line-items are unchanged.
  • A standalone quarter_value or semiannual_value is now always the difference of one element: the earlier filing’s fact for the same element, else an element of the same line that both filings file, the later one at the line’s figure (9020’s FY Mar 2026 H2 revenue stays ¥1,621,583M through OperatingRevenueRWY); a cover-page summary element still pairs with its statement element. Otherwise the field is omitted: 9823’s FY Sep 2025 H2 revenue had been ¥101,424M, 営業収益 minus the H1 report’s 売上高. A ¥0 figure is no evidence of one element. A context naming any member past the parent-only scope, with or without the Member suffix, is a breakdown, never the total: 9021’s FY Mar 2024 Q2 quarter_value is ¥400,632M (was ¥719,442M, against a Q1 segment of ¥50,460M) and its Q1 /metrics operating_margin 0.1414 (was 1.0347). A parent-only filer’s total now outranks its segments: 9363’s raw NetSales record is its total in all 30 filings (FY2025 S100YK5Y: ¥9,212M, was the port-transportation segment’s ¥10,364M), and its canonical net_sales line keeps 営業収入 (OperatingRevenue2), the statement’s caption. 8306’s raw NoncurrentAssets balance-sheet record is the holding company’s own total (non_consolidated) instead of a business group’s segment. No fields change.
  • A retailer’s annual cost of sales tagged 商品売上原価 (CostOfGoodsSold) or 商品及び製品売上原価 (CostOfMerchandiseAndFinishedGoodsSoldCOS) instead of 売上原価 is now served as cost_of_sales, paired with gross profit like any cost element and ranked after every total cost: a filing that also tags a total (売上原価, 営業原価) serves the total when it foots or when no pair foots, and the new element only when it foots and no total does. 7512 had no annual cost line (FY2025 S100Y36L now ¥284,936M); in production 28 of 96 parent-only retailers and wholesalers lacked one. The lines are labelled Cost of Goods Sold (商品売上原価) and Cost of Merchandise and Finished Goods Sold (商品及び製品売上原価). Raw records include the two elements; on a 313-company corpus no other line and no metric changed.
  • view=canonical profit lines read from an IFRS element carry that element’s label: net_income_to_owners reads Profit Attributable to Owners of Parent (親会社の所有者に帰属する当期利益) instead of Net Income (Parent) (親会社株主に帰属する当期純利益), net_income Profit (Loss) (当期利益) and the non-controlling share Profit Attributable to Non-controlling Interests (非支配持分に帰属する当期利益), as for 7203; J-GAAP and US-GAAP lines, keys, values and /line-items are unchanged.
  • Raw statement records (no view=) of rows stored before the resolver columns, as in 9984’s amended FY2015 report S100A0D0, now carry currency, from the stored resolver currency or else the ISO 4217 unit (JPY for JPY and JPYPerShares, absent for pure), and consolidation, from the context_id (non_consolidated when it carries NonConsolidatedMember, else consolidated). A stored value is never replaced; values, consolidated_or_individual and is_dimensional are unchanged.
  • view=canonical lines of a filing not yet re-resolved (e.g. 9984’s amended FY2015 report S100A0D0) now carry currency: a line’s currency is its own fact’s, from the stored resolver currency or else its ISO 4217 unit, and is absent only when the fact names neither (never inferred from the period). Values are unchanged.
  • view=canonical lines read from an IFRS element whose concept differs from the key’s label carry that element’s label and label_ja: an IFRS filer’s inventories on merchandise_and_finished_goods read Inventories (棚卸資産), other financial assets no longer read Short-term or Investment Securities, owners’ equity no longer reads Shareholders’ Equity (株主資本); keys, values and /line-items are unchanged.
  • The OpenAPI document now matches the responses: is_ytd is true when some flow record has no standalone quarter_value (value is always cumulative from the fiscal-year start), every endpoint but /health documents ETag, Cache-Control and 304, and headquarters and description_en are documented as null for now. /filings date errors name the parameter (invalid date for from=…); status and code are unchanged.
  • history=extended now also serves parent-only summary years: companies without consolidated figures, and the parent-only early years of companies that consolidated later, get their earlier years too (9363 reaches FY2012).
  • Statements (view=canonical) and /metrics take history=extended: the years before a company’s earliest served period (usually four, e.g. FY2012–FY2015) are added as printed in the five-year summary of its later annual reports, headline figures only, each labelled derived_from with its source report; /metrics serves the printed roe, equity_ratio, eps and bvps there and null (five_year_summary) for the rest. Default responses are unchanged.
  • New GET /industries lists the 33 TSE sectors in code order with code, slug, English and Japanese names, companies (the screener’s default universe, equal to its industry= total) and quartiles {p25, median, p75, n} of ROE, ROA, net, operating and gross margin, equity ratio, revenue growth and EPS growth; a metric with fewer than 10 values is omitted.
  • /valuation carries industry_percentiles on the latest annual: for ROE, ROA, net, operating and gross margin, equity ratio, revenue growth and EPS growth, the company’s rank within its TSE 33 industry ({industry, n, rank, top_pct}; ties share the better rank), precomputed daily; a metric with fewer than 10 industry peers is omitted. MCP get_valuation returns it and names the ranks in its summary.
  • A fund report a listed asset manager files under its own securities code is no longer served as the manager’s filing: its statements, metrics, valuation, /filings, fiscal_year_end, latest_filing_date and filing_status come from its own corporate reports only, and it is typed entity_type company (7330 and 8253 changed; listed J-REITs and ETFs are unchanged).
  • MCP screen_companies takes industry (a TSE 33 sector code, slug or name, as /screener does), and errors for an unknown statement key or metric suggest the likely name (revenue → net_sales, return_on_equity → roe); metric names ignore case.
  • Statements, /metrics, /valuation and screener rows carry currency (ISO 4217, JPY for almost every company), decided separately for consolidated and parent-only figures; a filer reporting in another currency, such as 9399 in USD, is served in that currency only, never mixed with its yen translation, and growth across a currency change is null (currency_change).
  • MCP statement results keep each period’s currency in the compact form, and summaries, descriptions and output schemas state the actual currency instead of assuming yen.
  • Companies, search rows and screener rows carry an industry object (TSE 33 sector code, slug and names, or null), and /screener filters by industry=<code, slug or name>.
  • The MCP server has its own rate limit, 300 requests per minute per IP (the REST API stays at 60 and is no longer shared with it), and answers a 429 with Retry-After and a JSON-RPC error.
  • MCP results are compact by default: statement lines carry key, label, value and element_id (detail: full returns the REST rows), new keys, from_year/to_year and offset arguments narrow and page them, and every list result reports truncated and next_offset within a 36 KB budget. The REST API is unchanged.
  • A ticker path accepts the 5-character securities code (72030), a .T or .JP suffix, lowercase and full-width characters, and a 400 for a malformed query parameter names the parameter.
  • /filings lists a quarterly-report amendment (150) by default when it is the filing a period’s figures come from, and a ticker containing a control character returns 400 through hachiquant.com, as documented.
  • MCP tools return numbers identical to the REST API to the last digit, accept null for optional arguments and the same ticker forms, and search_companies refuses an empty query.
  • IFRS income statements gain their own finance income and costs, other operating income and expenses, discontinued-operations lines and equity-method placement as the filer presents it; new Japanese-GAAP extraordinary lines itemize the totals.
  • Company names drop cover-page notes and are served half-width; search matches English acronyms (mufg, jt) and hiragana.
  • Filer-specific element and member ids are served under the neutral prefix filer, and an amendment that changes no financial figure no longer replaces the filing it amends.
  • New null reasons summary_only and not_applicable_for_financials; bank, insurer and broker revenue lines carry their industry labels (e.g. Ordinary Revenue).
  • The profile’s description_ja omits a leading statement of the accounting basis, so it starts at the business description itself.
  • Each restatement object carries kind: restatement when a headline total or the reporting standard changed, reclassification when only other lines moved.
  • A line that only changed element, with every total unchanged, is no longer reported as restated.
  • A keyless, read-only MCP server at hachiquant.com/mcp offers eight tools that return the same JSON as the REST endpoints.
  • This page documents connecting AI assistants to the MCP server.
  • The placeholder ticker 0000 and its sub-routes now return 404, like an unknown ticker.
  • With view=canonical, statements add a restatement object for each annual period that the next annual report restates.
  • Data responses carry X-Data-As-Of and /api/v1/health reports data_as_of, the newest filing date in the dataset.
  • New null reason not_meaningful_for_financials for financial companies’ free cash flow; extension_only can now name operating_income.
  • Breaking: the source system’s filer code is removed from every /api/v1 response; provenance stays doc_id, source_doc_id and element_id.
  • span, basis and source_doc_id on /metrics, /valuation and screener rows.
  • The screener gains include_stale (default false), backed by a daily precompute.
  • entity_type on /companies and the profile, period_start on screener rows, and /document-data returns [] for a non-disclosed filing.
  • /filings gains doc_type, from, to, limit and offset; the profile serves fiscal_year_end as MM-DD and a canonical accounting_standard.
  • HTTP caching with weak ETag, 304 Not Modified and Cache-Control: max-age=300.
  • Search ignores full-/half-width and spacing differences, and the flagship company ranks first on group names.