Base URL
https://statorigin.org/api/v1
All endpoints are GET, return JSON, and send
Access-Control-Allow-Origin: *, so you can call them straight from a
browser without a proxy.
Quick start
curl "https://statorigin.org/api/v1/statistics?industry=electric-vehicles®ion=CN&year=2020..2026&limit=5" import requests
r = requests.get("https://statorigin.org/api/v1/statistics",
params={"industry": "electric-vehicles", "region": "CN", "limit": 100})
for row in r.json()["data"]:
print(row["period"]["start"][:4], row["value"], row["scale"],
"—", row["source"]["org"], row["source"]["locator"]) const res = await fetch(
"https://statorigin.org/api/v1/statistics?industry=electric-vehicles&limit=100"
);
const { data, meta } = await res.json();
// Every row carries its own citation, ready to use.
console.log(data[0].citation.apa);
console.log(meta.attribution); Endpoints
11 endpoints. Every one returns the same envelope and the same licence and attribution metadata.
/statistics Query data points
The main endpoint. Filters compose, so you can ask for one indicator in one region over a year range.
| Parameter | Type | Notes |
|---|---|---|
industry | string | Industry slug. Comma-separate for several. |
region | string | Region code or slug. Comma-separate for several. |
indicator | string | Indicator slug. |
year | string | A year, or an inclusive range like 2020..2026. |
value_type | enum | actual · estimate · forecast |
source_org | string | Source organisation slug. |
limit | integer | 1–500. Default 50. |
cursor | string | Opaque cursor from meta.next_cursor. |
/statistics/{id} One data point
Returns the record plus any sources that disagree with it, so a consumer sees the same conflict the page shows.
| Parameter | Type | Notes |
|---|---|---|
id | string | A stat_… identifier. |
/industries Industry tree
The full ISIC Rev.4 classification: 21 sections, 88 divisions.
| Parameter | Type | Notes |
|---|---|---|
level | integer | 1 = section, 2 = division. |
parent | string | Parent ISIC code, e.g. C. |
/industries/{slug} One industry
Detail plus a coverage summary, its indicators, regions and sources.
| Parameter | Type | Notes |
|---|---|---|
slug | string | e.g. electric-vehicles |
/indicators List indicators
Filter by industry or by a substring of the name and definition.
| Parameter | Type | Notes |
|---|---|---|
industry | string | Industry slug. |
q | string | Substring match. |
/indicators/{slug} One indicator
Definition, units, methodology note, and the regions and sources that carry it.
| Parameter | Type | Notes |
|---|---|---|
slug | string | Indicator slug. |
/indicators/{slug}/series Time series
One entry per observation, each with its own source: a series here is a set of individually sourced points, not one dataset with one citation.
| Parameter | Type | Notes |
|---|---|---|
region | string | Region code or slug. Defaults to GLOBAL. |
from | integer | Earliest year. |
to | integer | Latest year. |
/sources Source organisations
Every publisher in the database, with its tier and contribution.
| Parameter | Type | Notes |
|---|---|---|
tier | integer | 1–4. |
/sources/{slug} One organisation
Its documents and the data taken from them.
| Parameter | Type | Notes |
|---|---|---|
slug | string | Organisation slug. |
limit | integer | 1–500. Default 100. |
/regions Regions
Countries and supranational groupings.
| Parameter | Type | Notes |
|---|---|---|
type | string | world · country · bloc · subnational |
/search Full-text search
Searches indicator names, regions, industries, source organisations and the verbatim source quotes.
| Parameter | Type | Notes |
|---|---|---|
q | string | 2–120 characters. |
limit | integer | 1–100. Default 25. |
Response shape
Every list endpoint returns data plus meta. Each element
of data is a full record; provenance is never abbreviated.
| Field | Meaning |
|---|---|
id | The permanent identifier. Also the last path segment of the record's URL. |
indicator | Slug, name and definition of what is being measured. |
industry | Array: a figure can belong to more than one industry, with the ISIC code. |
region | Code, name and type (world, country, bloc). |
period | Start, end and granularity. Always explicit, never inferred from context. |
value + scale | Kept separate on purpose, so the source's own magnitude survives. 17.2 + million. |
value_type | actual, estimate or forecast, never conflated. |
source | Publisher, report, publication date, locator, the verbatim quote, access date and link status. |
citation | Pre-formatted APA and BibTeX, crediting the original publisher and linking to the record. |
is_secondhand | True when the figure was relayed rather than read from the original publication. |
Live example: /api/v1/statistics/stat_01M2HY9T64ZTD2K066E4BAY4T4
Authentication and quotas
| Tier | Requests per day | How |
|---|---|---|
| Anonymous | 1,000 | No key. Counted per IP. |
| Free key | 10,000 | Authorization: Bearer so_live_… |
| Higher quotas | 100,000 | Available on request for research and public-interest projects. |
Responses include X-RateLimit-Limit, X-RateLimit-Remaining
and X-RateLimit-Reset. Exceeding the quota returns 429 with Retry-After.
Quotas exist to stop abuse, not to sell access. If you need more than the free tier for something useful, ask: the answer is usually yes.
Errors
Errors return { "error": { "code", "message", "docs" } } with an
HTTP status that matches the code.
| Status | Code | Meaning |
|---|---|---|
| 400 | bad_request | A parameter was missing or malformed. The message says which. |
| 401 | invalid_api_key | The bearer token is not recognised or is deactivated. |
| 404 | not_found | No record matches that identifier. |
| 429 | rate_limited | Daily quota exhausted. Retry-After gives the seconds remaining. |
| 500 | internal_error | Something failed on our side. Retrying is reasonable. |
| 503 | database_unavailable | A deployment problem on our side, not yours. |
A malformed filter is rejected rather than ignored. If you pass
year=20204 you get a 400, not a result set containing
every year. A silently dropped filter is how wrong numbers get into other
people's work.
Licence and attribution
Data is published under CC BY 4.0. Attribution is required and commercial use is permitted.
Attribute the original publisher (they did the work) and link to
the permanent record so the trail stays checkable. Every response includes an
attribution string in meta and a formatted citation on
each record, so you never have to assemble one by hand.
Machine-readable resources
- OpenAPI 3.1 specification · generate a client, or import into Postman or Insomnia
- llms.txt · a plain-language brief for language models
- Sitemap index · every page, with truthful lastmod values
- Methodology · how figures are sourced and verified
Currently serving 480 published data points across 395 indicators and 47 source organisations.