# Aggre documentation (complete text) > Aggre is a data bank behind one keyed HTTP API: crypto market data, official macro series, SEC filings, Taiwan equities, statutes and name lists, health and on-chain datasets. These pages document the API, the datasets, the console and how an agent should use them. Append `.md` to any page URL for the Markdown version. Generated from https://docs.aggre.org. Each page starts with its own title. === https://docs.aggre.org === # Introduction > Aggre is one keyed HTTP API in front of market, macro, filings, legal, health and on-chain datasets, with a console to manage keys. Page: https://docs.aggre.org · Section: Get started · All pages: https://docs.aggre.org/llms.txt Aggre is a data bank. You read many kinds of data (exchange candles, official macro series, SEC filings, Taiwan equities, statutes and government name lists, health registries, DeFi figures) through **one HTTP API and one kind of API key**, and every row says where it came from, when it was read and what credit its publisher asks for. ## The pieces | Piece | Address | What it is | |---|---|---| | Data API | `https://api.aggre.org` | Read-only JSON over HTTPS. API key in a header. No cookies, no browser (CORS) access. | | Console | `https://app.aggre.org` | Sign in, create API keys, manage organizations, see usage, browse datasets. | | Accounts API | `https://accounts.aggre.org` | What the console calls (cookie session). You only need it to build your own console. | | Documentation | `https://docs.aggre.org` | This site. Every page is also available as Markdown. | ## What you can read | Family | Examples | Guide | |---|---|---| | Market data | Candles, funding rates, open interest, latest tickers by venue | [Market data](https://docs.aggre.org/datasets/market.md) | | Macro | Official series with revisions kept as versions, the release calendar | [Macro](https://docs.aggre.org/datasets/macro.md) | | Filings and trades | SEC EDGAR filings, XBRL facts, insider trades, 13F holdings, Congress trades | [Filings](https://docs.aggre.org/datasets/filings.md) | | Taiwan equities | TWSE and TPEx closes, valuation, institutional and margin data, revenue, statements | [Taiwan equities](https://docs.aggre.org/datasets/taiwan-equities.md) | | Statutes | Current text of laws from ten jurisdictions; Taiwan judgments and retrieval | [Statutes](https://docs.aggre.org/datasets/legal-statutes.md) | | Name lists and legal documents | OFAC, UN and HHS-OIG lists, Taiwan FSC news, standard-form contracts | [Regulatory and legal documents](https://docs.aggre.org/datasets/legal-regulatory.md) | | Health | openFDA, EMA, NPPES, ClinicalTrials.gov, WHO, Eurostat mortality | [Health](https://docs.aggre.org/datasets/health.md) | | On-chain | DeFi protocol TVL | [On-chain](https://docs.aggre.org/datasets/onchain.md) | The full list with dataset ids is on [Datasets](https://docs.aggre.org/datasets.md). Which datasets hold data right now is not fixed in these pages: each source is switched on only after a person has read its publisher's terms, and the API tells you the state on every response (`meta.status`, and `503 terms_unread` where a source is still gated). See [Freshness and availability](https://docs.aggre.org/concepts/freshness.md). ## Where to start 1. [Quickstart](https://docs.aggre.org/quickstart.md): get a key and make your first call in five minutes. 2. [Concepts](https://docs.aggre.org/concepts/response-format.md): the rules that hold on every route (envelope, errors, paging, attribution). 3. [Data API reference](https://docs.aggre.org/api/data.md): every route, its parameters and an example, generated from the OpenAPI file. 4. [For agents](https://docs.aggre.org/agents/overview.md): `.md` URLs, `llms.txt`, OpenAPI and the MCP compatibility routes. ## Agent friendly Every page on this site has a Markdown twin: add `.md` to the address (`/quickstart` is also `/quickstart.md`, and this page is `/index.md`), or send `Accept: text/markdown`. Links inside the Markdown are absolute and point to other `.md` pages, so an agent that follows them stays in Markdown. [`/llms.txt`](https://docs.aggre.org/llms.txt) lists every page; [`/llms-full.txt`](https://docs.aggre.org/llms-full.txt) is all of them in one file. === https://docs.aggre.org/quickstart === # Quickstart > Create an API key and read your first rows from the Aggre data API in a few minutes. Page: https://docs.aggre.org/quickstart · Section: Get started · All pages: https://docs.aggre.org/llms.txt You need an account in the console, an API key, and any HTTP client. The data API is called from a server, script or agent: it sends no CORS headers, so a browser page cannot call it directly. ## 1. Create a key {#create-a-key} 1. Open the [console](https://app.aggre.org/login) and sign in with one of the providers it offers. The first sign-in creates your personal account; there is no separate sign-up. 2. Open **API keys** in your account and create a key. Give it a name you will recognise. 3. Copy the secret. It looks like `aggre_sk_` followed by 43 characters, and **it is shown once**. Only a hash is stored, so a lost key cannot be recovered; create a new one and revoke the old one. Keep the key out of source control and logs. More on keys, quotas and revocation: [Authentication](https://docs.aggre.org/authentication.md) and [API keys in the console](https://docs.aggre.org/console/api-keys.md). ```bash export AGGRE_API_KEY="aggre_sk_..." ``` ## 2. Check the key {#check-the-key} `GET /v1/whoami` describes the key you call with (never its secret) and what it has used in its current period. ```bash curl -s https://api.aggre.org/v1/whoami \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` The answer has this shape (values are illustrative): ```json { "data": { "key_id": "6b0e0c1e-0000-0000-0000-000000000000", "key_prefix": "aggre_sk_ab12cd34", "name": "my first key", "account": "my-handle", "rate_policy": "default", "ip_allowlist_configured": false, "usage": { "period": "month", "limit": 100000, "used": 2 } } } ``` If you get `401 unauthorized`, the key is missing, mistyped or revoked. The header `X-API-Key: aggre_sk_...` is accepted as an alternative to `Authorization: Bearer`. ## 3. See what exists {#list-datasets} ```bash curl -s https://api.aggre.org/v1/datasets \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` Each entry is `{ "id", "title", "path", "store_kind" }`. `path` is where to read the dataset, for example `/v1/finance/market/candles_1d`. ## 4. Read rows {#read-rows} Daily candles of one instrument, newest first, three rows: ```bash curl -s "https://api.aggre.org/v1/finance/market/candles_1d?instrument_id=OKX:SPOT:SOL-USDC&limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` Every data route answers in the same envelope ([Response format](https://docs.aggre.org/concepts/response-format.md)): ```json { "data": [ { "instrument_id": "OKX:SPOT:SOL-USDC", "venue": "OKX", "product": "SPOT", "symbol": "SOLUSDC", "ts": 1767139200000, "open": 0, "high": 0, "low": 0, "close": 0, "volume": 0, "quote_volume": null, "version": 0 } ], "meta": { "source": "okx", "status": "ok", "fetchedAt": "2026-01-01T00:00:00Z", "dataDate": "2025-12-31T00:00:00Z", "message": null }, "next_cursor": null } ``` The numbers above are placeholders to show the shape, not data. Look at `meta.status`: `ok`, `stale` (our last read is older than the dataset's window) or `empty` (nothing matched or nothing has been read yet). The same call from code: ```python import os, requests r = requests.get( "https://api.aggre.org/v1/finance/market/candles_1d", params={"instrument_id": "OKX:SPOT:SOL-USDC", "limit": 3}, headers={"Authorization": f"Bearer {os.environ['AGGRE_API_KEY']}"}, timeout=30, ) r.raise_for_status() body = r.json() print(body["meta"]["status"], len(body["data"])) ``` ```javascript const res = await fetch( "https://api.aggre.org/v1/finance/market/candles_1d?instrument_id=OKX:SPOT:SOL-USDC&limit=3", { headers: { Authorization: `Bearer ${process.env.AGGRE_API_KEY}` } }, ); if (!res.ok) throw new Error(`${res.status} ${(await res.json()).error.code}`); const { data, meta, next_cursor } = await res.json(); ``` ## 5. Handle the common failures {#failures} | You see | Meaning | Do | |---|---|---| | `400 invalid_request` | An unknown or repeated query parameter, or a value out of range. Parameters are strict, never ignored. | Fix the request. | | `401 unauthorized` | No key, a wrong key, or a revoked key. | Check the header and the key. | | `429 rate_limited` | Too many requests from your IP. | Wait `Retry-After` seconds and retry. | | `429 usage_limit_exceeded` | The key's quota for its period is spent. | Do not retry; use another key or wait for the period to roll. | | `503 terms_unread` | The source's publisher terms have not been recorded as read yet. | Not retryable now. See [Freshness and availability](https://docs.aggre.org/concepts/freshness.md). | Every response carries `x-request-id`; quote it when you ask for help. The full list is in [Errors](https://docs.aggre.org/concepts/errors.md). ## Next - Page through results: [Pagination](https://docs.aggre.org/concepts/pagination.md). - Pick data: [Datasets](https://docs.aggre.org/datasets.md) and the [Data API reference](https://docs.aggre.org/api/data.md). - Show data to people: [Attribution](https://docs.aggre.org/concepts/attribution.md) (`credit` and `attribution` must be shown with the rows). === https://docs.aggre.org/authentication === # Authentication and API keys > How the data API authenticates requests, what an API key is, and the limits you can set on it. Page: https://docs.aggre.org/authentication · Section: Get started · All pages: https://docs.aggre.org/llms.txt The data API (`https://api.aggre.org`) accepts **API keys only**. The accounts service behind the console (`https://accounts.aggre.org`) accepts **session cookies only** and never an API key. The two never mix. ## Sending the key {#sending-the-key} ```http GET /v1/whoami HTTP/1.1 Host: api.aggre.org Authorization: Bearer aggre_sk_... ``` `X-API-Key: aggre_sk_...` is accepted instead of the `Authorization` header. Every `/v1/*` route needs a key; `GET /healthz` and `GET /readyz` do not. ## What a key is {#what-a-key-is} - The format is `aggre_sk_` followed by 43 characters of base64url (32 random bytes). - The secret is shown **once**, when you create the key, and is never returned again. Aggre stores a SHA-256 hash and the first 8 characters after `aggre_sk_` as a non-secret display prefix; listings show only that prefix. - A key belongs to an account: your personal account or an [organization](https://docs.aggre.org/console/organizations.md). Members with the right role manage the organization's keys ([roles](https://docs.aggre.org/console/organizations.md#roles)). - Never put a key in client-side code, a repository, a log or a URL. Calls to the data API belong on a server or in an agent's tool configuration. ## Limits you can set {#limits} Each key has: | Setting | Meaning | |---|---| | Quota (`usage_limit`) and period (`usage_period`: `day`, `month` or `total`) | How many requests the key may make per period. Once spent, requests answer `429 usage_limit_exceeded`. | | IP allowlist (`ip_allowlist`) | A list of CIDR ranges the key may be used from. Empty means open. Outside the list: `403 ip_not_allowed`. | | Expiry (`expires_at`) | Optional date after which the key stops working. | | Rate policy (`rate_policy`) | `default`. `exempt` exists for platform staff only. | Self-service keys have a monthly allowance (the default is shown in the console when you create a key; a `day` quota counts as up to 31 times its limit against that allowance), and an account can hold at most 20 active keys. Unlimited keys, `exempt` rate policy and quotas above the default are set by platform staff. ## Revoking and rotating {#revoking} Revoke a key in the console. Revocation reaches the API within about 30 seconds (the gateway caches keys for that long). To rotate: create the new key, deploy it, then revoke the old one. ## Usage counting {#usage} Each request made with a key is recorded as a usage event: time, method, route template (never the raw URL or query string), dataset id, HTTP status and request id. Your IP address and query text are not stored. The count in `GET /v1/whoami` and in the console is the key's counter for its current period; it can lag a few seconds because the gateway writes counters in batches. `GET /v1/whoami` itself counts as a normal request. See [Usage and audit log](https://docs.aggre.org/console/usage.md). ## Errors you will see {#errors} | Status | `error.code` | Cause | |---|---|---| | 401 | `unauthorized` | Missing, malformed, unknown or revoked key. | | 403 | `ip_not_allowed` | The key has an allowlist and the request came from elsewhere. | | 403 | `forbidden` | The account is disabled. | | 429 | `rate_limited` | Per-source-IP limit, checked before the key. Retry after `Retry-After`. | | 429 | `usage_limit_exceeded` | The key's quota is spent. Retrying will not help. | Details: [Errors](https://docs.aggre.org/concepts/errors.md) and [Rate limits and quotas](https://docs.aggre.org/concepts/rate-limits.md). === https://docs.aggre.org/concepts/response-format === # Response format > The envelope every data route returns, the meta object, strict query parameters and the rules that hold on every route. Page: https://docs.aggre.org/concepts/response-format · Section: Concepts · All pages: https://docs.aggre.org/llms.txt ## The envelope {#envelope} Every successful data answer is JSON in the same shape: ```json { "data": [ /* rows, or one object on a single-record route */ ], "meta": { "source": "okx", "status": "ok", "fetchedAt": "2026-01-01T00:00:00Z", "dataDate": "2025-12-31T00:00:00Z", "message": null }, "next_cursor": null } ``` - `data` is an array of rows (a list route) or one object (a single-record route). The shape of a row is its [JSON Schema](https://docs.aggre.org/api/schemas.md). - `meta` says where the data came from and how fresh it is ([below](#meta)). - `next_cursor` is `null` on the last page and on routes without paging; otherwise pass it back unchanged as `cursor` ([Pagination](https://docs.aggre.org/concepts/pagination.md)). A few service routes differ: `GET /v1/datasets` and `GET /v1/whoami` return `{ "data": ... }` only, and `GET /healthz` / `GET /readyz` return `{ "status": "ok" | "unavailable" }`. Errors use their own envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## The `meta` object {#meta} | Field | Meaning | |---|---| | `source` | The one source of the rows, or `aggre` when they mix several. | | `status` | `ok`, `stale` (our last read is older than the dataset's window) or `empty` (nothing matched, or nothing was ever read). Some families add other states, documented on their route. | | `fetchedAt` | When Aggre last successfully read the source. `null` where nothing has been read yet. | | `dataDate` | The newest data point returned. What it means per route (a bar's open time, a publisher's list date, the last read) is stated on the route. | | `message` | A sentence the route wants you to see, or `null`. Where a dataset has a standing caveat (name lists are not a screening verdict; Congress trades are disclosed weeks late) it is here, on every response. | Routes add keys of their own (for example `restricted`, `attribution`, `licenses` on statutes; `series` on macro observations; `dataset` on filings). **Ignore keys you do not know**: fields are added over time and never removed or renamed ([Versioning](https://docs.aggre.org/reference/versioning.md)). ## Strict query parameters {#strict} An **unknown** or **repeated** query parameter is `400 invalid_request`, never silently ignored. So is a value out of range, a malformed date, or a cursor from another route. This catches typos (`limt=5`) before they return the wrong rows; build your requests from the parameter lists in the [reference](https://docs.aggre.org/api/data.md). ## Values and units {#values} - Identifiers are strings. Measured values are JSON numbers. Money and on-chain amounts that need exact precision are **decimal strings**. - Time-series timestamps are Unix milliseconds in UTC (`ts`); times inside `meta` are RFC 3339. Calendar dates are `YYYY-MM-DD`. See [Identifiers and values](https://docs.aggre.org/concepts/identifiers.md). - Units are explicit where a value is not obvious (`unit`, `unit_multiplier`); nothing is converted on the way in, so `value × unit_multiplier` is in `unit`. - A value a publisher leaves out is absent or `null`, never `0`. ## Headers {#headers} Every response carries `x-request-id`; quote it when you report a problem. A `429 rate_limited` also carries `Retry-After`. === https://docs.aggre.org/concepts/identifiers === # Identifiers and values > How instruments, datasets, series and statutes are identified, and how times and numbers are written. Page: https://docs.aggre.org/concepts/identifiers · Section: Concepts · All pages: https://docs.aggre.org/llms.txt ## Dataset ids and paths {#datasets} A dataset id is `{domain}.{category}.{name}`, for example `finance.market.candles_1m` or `legal.statutes.tw_moj`. A route path usually follows it: `/v1/{domain}/{category}/{name}`. Two families share one route and select the dataset with `?dataset=`: the ten `legal.statutes.*` datasets and the three `legal.regulatory.*` name lists. `GET /v1/datasets` returns each dataset's `path`, so you do not have to derive it. ## Market instruments {#instruments} `instrument_id` is `{VENUE}:{PRODUCT}:{native}`: uppercase venue, a product of `SPOT`, `PERP` or `FUTURES`, and the venue's own symbol. Example: `OKX:SPOT:SOL-USDC`. `symbol` is the native symbol without separators, uppercase (`SOLUSDC`). `(venue, product, symbol)` is unique. Funding rates and open interest need a `PERP` or `FUTURES` id. ## Other identifiers {#others} | What | Form | Example | |---|---|---| | Statute | `{JURISDICTION}:{SOURCE}:{native}`; may contain `:` and `/` | `UK:LEG:ukpga/2020/1`, `TW:MOJ:A0000001:en` | | Macro series | `{source}.{code}`, lowercase | `fed.effr` | | SEC company | CIK, 1 to 10 digits (returned padded) | `0000320193` | | Taiwan security | `TWSE:{code}` or `TPEX:{code}` | `TWSE:2330` | | Clinical trial | NCT number | `NCT...` | | Drug / device record | the openFDA `key`, exactly as listed | | A statute id may be sent raw in the path or percent-encoded (`UK%3ALEG%3Aukpga%2F2020%2F1`); the server sees the same id. ## Time {#time} - Series timestamps (`ts`) are **Unix milliseconds, UTC**. For a candle, `ts` is the bar's open time. - `from` is inclusive and `to` is exclusive on the field the route names. `to` must be later than `from`. - `meta` times are RFC 3339 (`2026-01-01T00:00:00Z`). Use `Z`; a `+` in an offset must be written `%2B` in a URL. - Calendar dates (`YYYY-MM-DD`) name a UTC day; a monthly or quarterly period is its first day, a year is 1 January. - Where a publisher gives a day and not a time, the row says so (`date_only`) and nothing is invented. ## Numbers {#numbers} Prices, volumes and measurements are JSON numbers (IEEE double). Amounts that must be exact (tick size, on-chain values) are decimal strings. A publisher's missing value is `null` or absent, not zero. Do not parse a decimal string with a binary float if you need the exact value. === https://docs.aggre.org/concepts/pagination === # Pagination > How cursors, limits and ordering work across the data API. Page: https://docs.aggre.org/concepts/pagination · Section: Concepts · All pages: https://docs.aggre.org/llms.txt ## Cursor paging {#cursors} List routes that can return more rows than one page give you `next_cursor` in the envelope. Pass it back unchanged as `cursor` to get the next page; it is `null` on the last page. ```bash # first page curl -s "https://api.aggre.org/v1/finance/macro/series?limit=100" -H "Authorization: Bearer $AGGRE_API_KEY" # next page: the previous answer's next_cursor, as it came curl -s "https://api.aggre.org/v1/finance/macro/series?limit=100&cursor=$NEXT" -H "Authorization: Bearer $AGGRE_API_KEY" ``` Rules: - A cursor is **opaque**. Do not parse, build or edit it. A cursor taken from another route, or a garbled one, is `400 invalid_request`. - Keep the same filters while paging. (Statute listings tolerate a filter change by continuing after the last id, but do not rely on that elsewhere.) - `limit` is the page size. Its range is on each route (commonly 1 to 1000, default 100; statutes 1 to 200, default 50; statute provisions 1 to 1000, default 500). - A page never splits one period's versions on the macro routes (`versions=all`). Paging loop: ```python import os, requests def pages(url, params): cursor = None while True: q = dict(params, **({"cursor": cursor} if cursor else {})) r = requests.get(url, params=q, headers={"Authorization": f"Bearer {os.environ['AGGRE_API_KEY']}"}, timeout=30) r.raise_for_status() body = r.json() yield from body["data"] cursor = body.get("next_cursor") if not cursor: return ``` ## Time-window paging {#windows} Time series (candles, funding rates, open interest) do not use cursors: `next_cursor` is always `null`. Read further with `from` and `to` (Unix ms, `from` inclusive, `to` exclusive) and `order`: - `order=desc` (the default for candles) returns the newest rows first; take the oldest `ts` you got and use it as the next `to`. - `order=asc` returns the oldest first; take the newest `ts` plus one as the next `from`. ## Order {#order} Each route states its default order and which ones it allows (`order=asc|desc`). Calendars read forward (`asc`), series of bars read backward (`desc`). Name-list searches, statute lists and similar are ordered by an identifier so that paging is stable. ## Change feeds {#change-feeds} Where a route has `updated_since`, rows are ordered by `(updated_at, key)` ascending and `updated_at` moves only when the content changed, so `updated_since` plus the cursor is a change feed: store the newest `updated_at` you processed and ask for rows since then. === https://docs.aggre.org/concepts/errors === # Errors > The error envelope, every error code and what to do about each. Page: https://docs.aggre.org/concepts/errors · Section: Concepts · All pages: https://docs.aggre.org/llms.txt Every error from the data API has the same JSON shape, plus the response header `x-request-id`: ```json { "error": { "code": "invalid_request", "message": "unknown query parameter: limt", "request_id": "8f5c0c3e-..." } } ``` `code` is the stable machine code; branch on it, not on `message` (which is for people and may change). A client must tolerate codes it does not know. The JSON Schema is [`error`](https://docs.aggre.org/api/schemas.md#error). Assert on the **code**, not just the status: several different problems share a status (two kinds of `429`, several kinds of `503`). ## Codes of the data API {#data-api} | Status | `error.code` | Meaning | What to do | |---|---|---|---| | 400 | `invalid_request` | Unknown or repeated query parameter, value out of range, malformed id/date, a cursor from another route, a wrong combination of parameters. | Fix the request. Do not retry unchanged. | | 401 | `unauthorized` | No key, malformed key, unknown key or revoked key. | Check the key and header. | | 403 | `ip_not_allowed` | The key has an IP allowlist and the request came from outside it. | Call from an allowed address or edit the allowlist. | | 403 | `forbidden` | The account is not allowed to use the key (for example it is disabled). | Contact the account owner. | | 404 | `not_found` | The id is well formed but nothing is stored under it (an unknown series, statute, record), or the path has no id. | Check the id. For stored-in-stages datasets the record may not be loaded yet. | | 410 | `taken_down` | The judgment has been taken down and is hidden (judgment routes, when the deployment hides takedowns). | Do not retry. | | 429 | `rate_limited` | Too many requests from your source IP, checked before the key. | Wait `Retry-After` seconds, then retry with backoff. | | 429 | `usage_limit_exceeded` | The key's quota for its period is spent. | Do **not** retry. Use another key or wait for the period to roll. | | 501 | `corpus_not_migrated` | A judgment route whose corpus has not been loaded yet. | Try later. | | 503 | `store_unavailable` | The database behind the route is not reachable or not configured. | Retry with backoff; if it persists, report the `request_id`. | | 503 | `terms_unread` | The source's publisher terms have not been recorded as read, so the route will not serve its data. | Not a transient error. See [Freshness and availability](https://docs.aggre.org/concepts/freshness.md). | | 503 | `index_unavailable` | The search index behind a retrieval route has no index yet. | Retry later. | | 503 | `retrieval_unavailable` | The retrieval service is not reachable. | Retry with backoff. | | 500 | `internal` | Something went wrong on our side. | Retry once; if it persists, report the `request_id`. | ## Codes of the accounts API {#accounts-api} The accounts service (the console's backend) uses the same envelope and adds codes for sessions and writes: `conflict` (409), `origin_not_allowed`, `csrf_required`, `step_up_required`, `account_disabled`, `email_mismatch` (403), `validation_failed`, plus codes for platform-staff features. See the [accounts API](https://docs.aggre.org/api/accounts.md). ## Handling errors well {#handling} 1. Log `error.code` and `request_id` for every non-2xx answer. 2. Retry only what can change: `429 rate_limited` (after `Retry-After`) and `503 store_unavailable` / `500 internal` (with exponential backoff and a cap). Never retry `400`, `401`, `403`, `404`, `429 usage_limit_exceeded` or `503 terms_unread` unchanged. 3. Treat `meta.status: "empty"` on a 200 as a valid, empty answer, not an error. ## The legacy MCP routes {#mcp} `POST /v1/mcp/call` keeps the older flat error shape `{ "error": "message" }` so existing tool clients keep working. See [MCP compatibility](https://docs.aggre.org/agents/mcp.md). === https://docs.aggre.org/concepts/rate-limits === # Rate limits and quotas > The two limits on the data API, how to tell them apart, and how to stay under them. Page: https://docs.aggre.org/concepts/rate-limits · Section: Concepts · All pages: https://docs.aggre.org/llms.txt Two independent limits apply to a request. Both answer `429`; they differ by `error.code`. | | `rate_limited` | `usage_limit_exceeded` | |---|---|---| | What is limited | Request rate per source IP | Total requests per key per period | | Checked | Before the key is looked at | After the key is accepted | | Header | `Retry-After` (seconds) | none | | Retry? | Yes, after waiting | No: the quota is spent until the period rolls | ## Rate limit {#rate-limit} The gateway limits each source IP in process, as a token bucket. The standing configuration is about **20 requests per second with a burst of 40** per IP per gateway pod; because it is applied per pod, the effective ceiling for one IP can be higher when traffic is spread over several pods, and the values are deployment settings that can change. Do not depend on the exact numbers: honour `Retry-After` and back off. ## Quota {#quota} Each key has a quota and a period (`day`, `month` or `total`). The default for a self-service key is a monthly allowance shown when you create the key. The counter you see in the console and in `GET /v1/whoami` is the current period's count; it can lag a few seconds. A quota applies per key, not per account, so spreading work over several keys raises the total you can use, but an account can hold at most 20 active keys. ## Staying under the limits {#staying-under} - Use `limit` close to the maximum a route allows instead of many small pages. - Cache what does not change: instruments and series catalogues, statute text (compare `content_hash` or `updated_since` before re-reading). - Use change feeds (`updated_since`) rather than re-reading whole datasets. - Retry `429 rate_limited` with exponential backoff and jitter, and obey `Retry-After`. - Check `GET /v1/whoami` to see how much of the period a key has used. === https://docs.aggre.org/concepts/freshness === # Freshness and availability > What meta.status means, why a dataset can be empty or answer terms_unread, and how revisions are kept as versions. Page: https://docs.aggre.org/concepts/freshness · Section: Concepts · All pages: https://docs.aggre.org/llms.txt Aggre reads each source from its publisher on a schedule and serves what it stored. Three mechanisms tell you what you are looking at; none of them is hidden behind a status page you have to find. ## `meta.status` {#status} | Value | Meaning | |---|---| | `ok` | The data is within the dataset's freshness window. | | `stale` | Aggre's last successful read is older than the window for this dataset (the window is stated per route: 5 minutes for latest tickers, 24 hours for funding rates, 72 hours for several daily sets, 14 days for standard-form contracts, and so on). The rows are still the last ones read. | | `empty` | Nothing matched your filters, or nothing has ever been read for this dataset. | `stale` is judged on the newest data, and only when you did not pin the view: a request with `to`, `date` or `as_of` is a historical view and is not reported stale. `meta.fetchedAt` and `meta.dataDate` give you the dates to judge for yourself. ## The terms gate {#terms} A source is read, and served, only after a person has read the publisher's terms and recorded that (`terms_read_on`). Until then: - the collector for that source does not run, and - on families that gate at the route (health, on-chain, standard-form contracts, derived macro series over entity files), the API answers `503 terms_unread` rather than serving rows whose licence is unknown; on others, `license` and `attribution` are `null` and the response says "Terms not read". `503 terms_unread` is not transient: retrying does not help. It means the dataset exists and its route works, but its source is not yet switched on. ## Which datasets have data {#availability} Do not infer availability from the list of routes. Ask the API: - `GET /v1/datasets` lists every dataset and where to read it. - A normal call tells you the state in `meta.status` (`ok`, `stale`, `empty`) or with `503 terms_unread`. - For a dataset you depend on, store `meta.fetchedAt` and alert on `stale`. Sources are switched on one at a time as their terms are recorded, so a dataset that is empty today may hold data tomorrow. These pages describe what a dataset **is** and how it behaves when it holds data. ## Revisions are versions {#versions} Publishers revise numbers. Aggre never overwrites: a changed value is stored as the next `version` and the earlier ones are kept. - Macro observations and Taiwan monthly revenue and statements: the default (`versions=latest`) returns the highest version per period; `versions=all` returns every version; `as_of=` returns each period **as Aggre knew it then** (the highest version first seen at or before that instant), which is what you need for honest backtests. - `revision` is the publisher's own label (`advance`, `preliminary`, `revised`, `final`, ...) and is `null` when the publisher states none. It is never invented. - Candles carry a `version`; a higher version replaces a lower one, and only confirmed bars are stored. ## Removed records {#removed} When a source stops listing a record (a repealed statute, a delisted sanctions entry), Aggre keeps the last content it saw and marks it removed (`removed_on`) instead of deleting it. Lists hide removed records by default; `include_removed=true` (statutes, contracts) or `removed=include|only` (name lists) shows them, and `updated_since` plus `include_removed` lets you track both changes and disappearances. === https://docs.aggre.org/concepts/attribution === # Attribution and licensing > Why rows carry credit, attribution and license, and what whoever displays them must do. Page: https://docs.aggre.org/concepts/attribution · Section: Concepts · All pages: https://docs.aggre.org/llms.txt Aggre redistributes data that publishers own. Their terms often require a credit line, a notice, or a restriction. Aggre stores that text with the data and returns it, so the obligation travels with the rows. ## The rule {#the-rule} > **Whoever shows a row shows its credit.** The API does not compose attribution and a client must not paraphrase it. Where the field is called: | Field | Where | What to do | |---|---|---| | `credit` | Per row or per series (macro series and observations, calendar events, filings, on-chain, health, Congress trades, ...) | Display it next to the data, as returned. | | `attribution` | Statutes (per instrument and in `meta`), name lists, Taiwan equities (`meta.attribution`: `[{source_id, credit}]`) | Display it. | | `license` | Statutes, name lists, standard-form contracts, `meta.licenses` | Observe it. | | `restricted` | Statutes (`restricted: true`, and in `meta`) | The text carries use restrictions. Show the attribution and the reminder to check the latest version at the source. | `license` and `attribution` are `null` until a person has read the publisher's terms; the response then says "Terms not read" ([Freshness](https://docs.aggre.org/concepts/freshness.md#terms)). Treat that as "no permission recorded yet", not as "no restriction". ## Derived figures {#derived} Figures Aggre computes on read (macro derived series) carry the publisher's credit followed by a sentence saying Aggre computed the figure. Show both. ## What Aggre does not grant {#no-grant} Serving a row does not grant rights beyond the publisher's terms. In particular: - Market data is subject to the exchange's terms; Aggre grants nothing beyond them. - Name lists (OFAC, UN, HHS-OIG) are exact or prefix name search only. **They are not a screening verdict**; every response says so in `meta.message`. - Congress trades are disclosed weeks after the trade, give amounts as ranges, and are not a recommendation. - Statute text must be checked against the official source before you rely on it. === https://docs.aggre.org/datasets === # Datasets > Every dataset family, its dataset ids and the route that serves it. Page: https://docs.aggre.org/datasets · Section: Datasets · All pages: https://docs.aggre.org/llms.txt A **dataset** is one kind of row with one schema and one route. Datasets are grouped in families; each family has a guide that explains the data and its caveats, and a reference page with every route's parameters. `GET /v1/datasets` returns the same list from the live API, with the `path` of each. How to read the state of a dataset (`meta.status`, `503 terms_unread`) is in [Freshness and availability](https://docs.aggre.org/concepts/freshness.md). These pages do not say which datasets currently hold data, because that changes as sources are switched on. ## Families {#families} | Family | Dataset ids | Guide | Reference | |---|---|---|---| | Market data | `finance.market.candles_1m`, `candles_1h`, `candles_1d`, `instruments`, `tickers_latest`, `funding_rates`, `open_interest` | [Market data](https://docs.aggre.org/datasets/market.md) | [Market](https://docs.aggre.org/api/data/market.md) | | Macro | `finance.macro.calendar_events`, `series`, `observations`; `finance.macro_derived.series`, `observations` | [Macro](https://docs.aggre.org/datasets/macro.md) | [Macro](https://docs.aggre.org/api/data/macro.md) | | Filings and trades | `finance.filings.companies`, `filings`, `company_facts`, `fundamentals`, `insider_transactions`, `fails_to_deliver`, `holdings_13f`, `news_8k`, `congress_trades` | [Filings](https://docs.aggre.org/datasets/filings.md) | [Filings](https://docs.aggre.org/api/data/filings.md) | | Taiwan equities | `finance.equities_tw.securities`, `daily_close`, `valuation_daily`, `institutional_daily`, `margin_daily`, `monthly_revenue`, `statements`, `indices`, `sources` | [Taiwan equities](https://docs.aggre.org/datasets/taiwan-equities.md) | [Taiwan equities](https://docs.aggre.org/api/data/equities-tw.md) | | Statutes | `legal.statutes.tw_moj`, `jp_egov`, `uk_legislation`, `ca_laws`, `eu_eurlex`, `us_ecfr`, `de_gii`, `au_federal` (and `sg_sso`, `cn_flk`, see the guide) | [Statutes](https://docs.aggre.org/datasets/legal-statutes.md) | [Legal](https://docs.aggre.org/api/data/legal.md) | | Name lists and legal documents | `legal.regulatory.ofac_sdn`, `un_sanctions`, `us_exclusions`, `fsc_news`; `legal.contracts.tw_standard_forms` | [Regulatory and legal documents](https://docs.aggre.org/datasets/legal-regulatory.md) | [Legal](https://docs.aggre.org/api/data/legal.md) | | Health | `health.drugs.fda_*`, `health.devices.fda_*`, `health.drugs.ema_medicines`, `health.providers.nppes`, `health.trials.clinicaltrials_gov`, `health.statistics.who_gho`, `health.statistics.eurostat_mortality` | [Health](https://docs.aggre.org/datasets/health.md) | [openFDA](https://docs.aggre.org/api/data/health-openfda.md), [registries](https://docs.aggre.org/api/data/health-registries.md) | | On-chain | `onchain.defi.protocol_tvl` | [On-chain](https://docs.aggre.org/datasets/onchain.md) | [On-chain](https://docs.aggre.org/api/data/onchain.md) | ## Choosing a route {#choosing} - **Time series** (candles, funding, open interest, indices, prices): filter by id and a `from`/`to` window. - **Catalogues** (instruments, series, companies, securities): small lists you can cache; page with `cursor`. - **Records** (statutes, trials, medicines, filings): list with filters, then fetch one by its id. - **Search**: name lists and provider registries are *searches*, deliberately not bulk enumerations. Statute titles can be filtered by substring; there is no full-text or semantic search over statutes on the data routes (retrieval over judgments and statutes is a separate service, see [Statutes](https://docs.aggre.org/datasets/legal-statutes.md#judgments-and-retrieval)). ## What is not offered {#not-offered} - No streaming: no WebSocket or server-sent events on the data API. Everything is HTTP request/response. - No browser access to the data API (no CORS). Call it from a server or an agent. - No order books, individual trades or liquidations in the market data, only candles, tickers, funding and open interest. - Statutes are the **current** version only; old versions are not kept or served. - Sources whose publishers offer no official API or licence for redistribution are not collected (for example Singapore Statutes Online and the Chinese national law database). === https://docs.aggre.org/datasets/market === # Market data > Candles, instruments, latest tickers, funding rates and open interest from crypto venues. Page: https://docs.aggre.org/datasets/market · Section: Datasets · All pages: https://docs.aggre.org/llms.txt Exchange market data in one shape across venues. Reference: [Market data routes](https://docs.aggre.org/api/data/market.md). ## What is in it {#contents} | Dataset | Route | One row is | |---|---|---| | `finance.market.candles_1m`, `candles_1h`, `candles_1d` | `GET /v1/finance/market/candles_{1m,1h,1d}` | One confirmed OHLCV bar of one instrument | | `finance.market.instruments` | `GET /v1/finance/market/instruments` | One instrument: venue, product, base, quote, tick size, `enabled` | | `finance.market.tickers_latest` | `GET /v1/finance/market/tickers` | The latest price and rolling 24-hour figures of one enabled instrument | | `finance.market.funding_rates` | `GET /v1/finance/market/funding_rates` | One settled funding payment of a perpetual | | `finance.market.open_interest` | `GET /v1/finance/market/open_interest` | One open-interest snapshot of a perpetual | Instruments are identified as `{VENUE}:{PRODUCT}:{native}` ([Identifiers](https://docs.aggre.org/concepts/identifiers.md#instruments)). List what is available with `GET /v1/finance/market/instruments?venue=&product=`: it is the authority on which instruments exist and are `enabled`. ## Candles {#candles} - Required: `instrument_id`. Optional: `from`, `to` (Unix ms on `ts`, `from` inclusive, `to` exclusive), `limit` (1 to 1000, default 100), `order` (`asc` or `desc`, default `desc`). - `ts` is the bar's **open** time in UTC. Only **confirmed** bars are stored: a bar still forming is not served. - `version` orders updates of the same bar: a higher version replaces a lower one. - `meta.dataDate` is the open time of the newest returned bar. `meta.status` is `stale` when the newest stored bar is more than one closed bar behind now (judged only when `to` is not set). - There is no cursor: `next_cursor` is always `null`. Read further with `from`/`to` ([Pagination](https://docs.aggre.org/concepts/pagination.md#windows)). ## Latest tickers {#tickers} One row per **enabled** instrument, the latest only: no history, no `from`/`to`, no cursor. - `price` is the last traded price (`price_basis: "last"`) or, where a venue publishes no last price in its bulk answer (Hyperliquid), its mark price (`"mark"`). Check `price_basis`. - `open_24h`, `high_24h`, `low_24h`, `volume_24h`, `quote_volume_24h` are the venue's **rolling** 24 hours ending at `ts` (not a UTC day) and are `null` where the venue does not send them. The API never computes them. - `ts` is the venue's timestamp, or Aggre's clock when the venue sends none. `meta.status` is `stale` when the newest row is more than 5 minutes old; judge each row's own `ts` for per-instrument freshness. - Filters are optional and exact: `venue`, `product`, `instrument_id` (which must agree with the other two when given). ## Funding rates and open interest {#derivatives} Perpetuals (`PERP`) and futures only. - A funding row is one settled payment. `rate` is that period's fraction **as the venue reports it**: not annualised, and the period differs by venue and instrument. `meta.status` is `stale` after 24 hours. - Open interest is a **snapshot**: venues publish only the current value, so history starts the day Aggre began collecting. Values are in base-asset units; `open_interest_usd` appears only where the venue states it. `meta.status` is `stale` after 30 minutes. ## Caveats {#caveats} - Market data is subject to each venue's terms. Aggre grants nothing beyond them ([Attribution](https://docs.aggre.org/concepts/attribution.md#no-grant)). - Aggre reads public endpoints on a schedule; it is not a streaming feed and not an execution venue. Do not use it for latency-sensitive trading. === https://docs.aggre.org/datasets/macro === # Macro data > Official macroeconomic series, their revisions as versions, the release calendar and computed series. Page: https://docs.aggre.org/datasets/macro · Section: Datasets · All pages: https://docs.aggre.org/llms.txt Official macroeconomic data read from the **publishers themselves** (central banks, statistics agencies, ministries), never from an aggregator. Reference: [Macro routes](https://docs.aggre.org/api/data/macro.md). ## Series and observations {#series} `GET /v1/finance/macro/series` is the catalogue (ordered by `series_id`; filters `source`, `economy`, `frequency`). `GET /v1/finance/macro/observations?series_id=...` returns the values of one series. An unknown `series_id` is `404 not_found`. A series has a `series_id` of the form `{source}.{code}` (for example `fed.effr`), an `economy` (two uppercase letters, `EU` for the euro area), a `frequency` (`daily`, `weekly`, `monthly`, `quarterly`, `annual`, `irregular`), a `unit`, a `unit_multiplier`, an optional seasonal adjustment, its `credit` and `terms_read_on`. ### Units {#units} `unit` says what the number is (`percent`, `index`, `usd`, ...) and `unit_multiplier` how many of that unit one stored value is, so **`value × unit_multiplier` is in `unit`**. Nothing is converted on the way in: a publisher that states "millions of dollars" is stored as unit `usd`, multiplier `1000000`, value as published. Once a series has observations its unit, multiplier, currency, frequency, adjustment, economy and source never change; a series whose meaning changes gets a new id. ### Periods {#periods} `period` is a date: a month or a quarter is its first day, a year is 1 January, a week is the day the publisher assigns, a day is itself. A value the publisher leaves out (`ND`, `-`, empty) is absent, never zero. ### Revisions {#revisions} A revision is a **new version**, never an overwrite. An observation is identified by `(series_id, period, version)`; the first value read for a period is version 1, and a later read that returns a different value or label stores the next version. | Parameter | Result | |---|---| | `versions=latest` (default) | The highest version per period | | `versions=all` | Every version (a page never splits one period's versions) | | `as_of=` | Each period as Aggre knew it then: the highest version first seen at or before that instant; periods first read later are absent. An `as_of` view is never reported stale | `revision` (`advance`, `preliminary`, `revised`, `final`, ...) and `published_on` are the publisher's own words, `null` when it states none. Use `as_of` for backtests that must not see later revisions. ### Freshness {#freshness} `meta.dataDate` on observations is Aggre's last successful read of the publisher (`last_read_at`), not an observation period. `meta.status` is `stale` when the series has a freshness window and the last read is older than it, not judged for `as_of` views or for a series with `discontinued_on`. ## Attribution {#attribution} `credit` is the text the publisher's terms ask for, stored once per series and returned on every observation row. **Whoever shows a value shows its `credit`** ([Attribution](https://docs.aggre.org/concepts/attribution.md)). `terms_read_on` is the day a person last read the publisher's terms; `null` means nobody has. ## Publishers {#publishers} The macro collector is built to read official sources including the Federal Reserve, BLS, BEA, the Census Bureau, the New York Fed, the US Treasury, CFTC, EIA, FHFA and OFR in the United States; the ECB, the Bank of England, Eurostat, ONS and OECD in Europe; the Ministry of Finance, Japan Customs, the Cabinet Office and e-Stat in Japan; Hong Kong's Census and Statistics Department; Taiwan's DGBAS, NDC, Central Bank, Ministry of Finance, FSC and Ministry of the Interior; and the BIS, IMF and World Bank. A source is served only after its terms are recorded as read ([Freshness](https://docs.aggre.org/concepts/freshness.md#terms)); a publisher whose terms forbid redistribution is not read. The catalogue (`/series`) is the authoritative list of what is served. ## Computed series {#derived} `GET /v1/finance/macro_derived/series` and `/observations` serve values **Aggre computes on read**: nothing is stored and none appears in `macro/series`. All rows have `kind: computed`. 1. The year-over-year change of stored series (the derived id is the input's plus `_yoy`): `value = (input at period / input at compared_with − 1) × 100`, from the newest stored version of both; no row where the earlier value is absent or zero. 2. Sums and ratios over the rows of Taiwan FSC Banking Bureau files (cards, deposits, loans, non-performing ratios). 3. Counts and median prices per ping over Taiwan Ministry of the Interior actual-price deals, nationally and for six cities, by month. 4. Sums, counts and medians over the exchange's monthly revenue file for listed companies. These medians are computed from amounts and can differ slightly from medians of published percentages. A row is `{series_id, period, value, unit, unit_multiplier, compared_with, rows_used, provisional, credit}`. A revised input revises the value on the next read. The series `credit` is the publisher's followed by a sentence saying Aggre computed the figure. A derived series over an entity dataset is listed only while its terms are read; `/observations` of one whose terms are unread is `503 terms_unread`. ## Economic calendar {#calendar} `GET /v1/finance/macro/calendar_events` lists scheduled releases: **the schedule only**, no estimates and no actual or previous values. - Filters (all optional; unknown or repeated ones are 400): `from`, `to` (Unix ms on `ts`), `source` (`BLS`, `BEA`, `CENSUS`, `FOMC`, `ECB`, `ONS`, `EUROSTAT`), `economy`, `limit`, `order` (default `asc`: a calendar reads forward). - `ts` is the release instant (UTC). Where the publisher gives the day and not the time, `date_only` is `true` and `ts` is the start of that UTC day; no time is made up. - `impact` is Aggre's own grading (`impact_basis` is always `editorial`), not the publisher's. - `origin` is `feed` (read from the publisher's machine-readable schedule) or `manual` (a hand-kept table a person checked against the publisher on `verified_on`); a manual row without a verification date is never served. - A schedule is replaced as a whole per source, so a moved or withdrawn release disappears from the future while past events stay. === https://docs.aggre.org/datasets/filings === # Filings and trades > SEC EDGAR companies, filings, XBRL facts, fundamentals, insider transactions, fails-to-deliver, 13F holdings and 8-K news, plus US Congress stock trades. Page: https://docs.aggre.org/datasets/filings · Section: Datasets · All pages: https://docs.aggre.org/llms.txt US public-company disclosures from the SEC's EDGAR system and members of Congress's stock-trade disclosures. Reference: [Filings routes](https://docs.aggre.org/api/data/filings.md). All routes share the standard envelope, strict query parameters, opaque cursors and a per-row `credit`. A CIK is one to ten digits, with or without leading zeros (returned padded). ## SEC EDGAR {#edgar} | Dataset | Route | Notes | |---|---|---| | `finance.filings.companies` | `/v1/finance/filings/companies` | The companies on the coverage list, ordered by `cik`. Filters `cik`, `ticker`, `sic`. | | `finance.filings.filings` | `/v1/finance/filings/filings` | `cik` required; `form`, `from`, `to`, `order`. | | `finance.filings.company_facts` | `/v1/finance/filings/company_facts` | As-filed XBRL facts, never overwritten; `value` is a decimal string. `cik` required; `concept`, `unit`, `period_from`, `period_to`, `fiscal_year`, `fiscal_period`, `latest`. | | `finance.filings.fundamentals` | `/v1/finance/filings/fundamentals` | Normalized fundamentals per fiscal period, **computed by Aggre** from the as-filed facts and not published by the SEC (`meta.message` says how). `cik` required; `fiscal_period` (`FY` or `Q`); `limit` default 12; no cursor. | | `finance.filings.insider_transactions` | `/v1/finance/filings/insider_transactions` | Form 4. `cik` is the **issuer's**, required; `from`, `to` on `transaction_date`, `code`, `amendments` (`collapse` default, or `all`). | | `finance.filings.fails_to_deliver` | `/v1/finance/filings/fails_to_deliver` | `symbol` required; `from`, `to` on `settlement_date`, `order`. The CUSIP column is never stored. | | `finance.filings.holdings_13f` | `/v1/finance/filings/holdings_13f` | One institution's holding of a company in one quarter, from the SEC's Form 13F data sets. Give `ticker` **or** `issuer_cik`. **Matched by the issuer's name** (the CUSIP is neither read nor stored), so a row may include another class of the same issuer and a differently spelled one may be missing; `meta.message` always says so. `consistent` is `false` for a row whose price (`value_usd / shares`) is more than 5 times from that quarter's median for the stock; such rows are hidden unless `consistent=all`. | | `finance.filings.news_8k` | `/v1/finance/filings/news_8k` | The company's 8-K and 8-K/A reports, newest first, with their items and, where a press release came with it, the Exhibit 99 **file names** and short descriptions. **No text of any release or filing is stored or served**: open `url` (the report on EDGAR). Give `cik` or `ticker`; `from`, `to` on `filed_on`; `item`. `exhibits_complete` is `false` while the report may carry a release and its EDGAR header page has not been read yet. | Ordering, `meta` and the two clocks (when a filing was filed and when Aggre read it) are described on each route in the [reference](https://docs.aggre.org/api/data/filings.md). ## US Congress stock trades {#congress} `GET /v1/finance/filings/congress_trades` lists trades that members of Congress reported under the STOCK Act, newest trade first. - Filters: `politician` (name substring), `ticker`, `chamber` (`Senate` or `House`), `type` (`buy`, `sell`, `exchange`), `from`/`to` (on `transaction_date`), `disclosed_from`/`disclosed_to` (on `disclosure_date`). - **Disclosed weeks after the trade**: `transaction_date` is the trade, `disclosure_date` the day it was reported. - **Amounts are ranges** the report uses, not exact values. `owner` may be a spouse or child. - `meta.source` is the rows' source when they share one, else `aggre`; `meta.dataset.sources` lists each source's terms. `meta.message` always carries the standing caveats: not a recommendation, use restrictions on financial-disclosure reports, and "Terms not read" while a source's terms are unread. - The only source built is a community aggregate (`senate_stock_watcher`), which is **not** the Senate's own record. Check `source` on each row. - Freshness window 72 hours. === https://docs.aggre.org/datasets/taiwan-equities === # Taiwan equities > Taiwan listed (TWSE) and OTC (TPEx) after-hours data: closes, valuation, institutional and margin data, revenue, statements and indices. Page: https://docs.aggre.org/datasets/taiwan-equities · Section: Datasets · All pages: https://docs.aggre.org/llms.txt Taiwan Stock Exchange (TWSE, listed) and Taipei Exchange (TPEx, OTC) after-hours data. Reference: [Taiwan equities routes](https://docs.aggre.org/api/data/equities-tw.md). ## Datasets {#datasets} All routes are `GET /v1/finance/equities_tw/{name}`. | Name | One row is | Notes | |---|---|---| | `securities` | A listed or OTC security | Code, name, industry, shares outstanding. Filters `market`, `q`, `industry_code`. | | `daily_close` | One security's trading day | Open, high, low, close, volume, value. | | `valuation_daily` | Valuation ratios of a trading day | P/E, dividend yield, P/B. | | `institutional_daily` | Foreign, investment-trust and dealer net trades | **TPEx only**; the TWSE file is not read. | | `margin_daily` | Margin and short balances | **TPEx only**; the TWSE margin file names no day and is excluded. | | `monthly_revenue` | A company's revenue for one month | A revision is a new `version`. | | `statements` | Quarterly income statement or balance sheet | Six industry formats; a revision is a new `version`. Amounts in **thousand NT$**, as published. | | `indices` | Close of an exchange index on a trading day | | | `sources` | The upstream files, their licence, terms state and last read | | ## Using them {#using} - `security_id` is `TWSE:2330` or `TPEX:6488`. Dates are ISO (`YYYY-MM-DD`); the exchanges' Republic-of-China calendar dates are converted. - Read a **history** with `security_id` (newest first by default) or a one-day **cross-section** with `date` (ascending `security_id` by default). The day routes take one or the other, not both. - Statement and revenue amounts are in thousand NT$ and are not converted. - `monthly_revenue` and `statements` take `versions` and `as_of` like [macro observations](https://docs.aggre.org/datasets/macro.md#revisions). - Staleness is judged only for unpinned views: a request with `date=` or `as_of=` is never `stale`. `meta.fetchedAt` is `null` for a view nothing has read yet. ## Attribution {#attribution} Every response carries `meta.attribution`: the Open Government Data License credit for the sources of the rows returned, as `[{source_id, credit}]`. Show it with the data ([Attribution](https://docs.aggre.org/concepts/attribution.md)). Every source is switched on only after its terms are recorded as read. === https://docs.aggre.org/datasets/legal-statutes === # Statutes > The current text of laws from official sources, how to find and read them, and the Taiwan judgments and retrieval routes. Page: https://docs.aggre.org/datasets/legal-statutes · Section: Datasets · All pages: https://docs.aggre.org/llms.txt Statutes and regulations as the official sources publish them: **current version only**, with provisions, attachments, licence and attribution. Reference: [Legal routes](https://docs.aggre.org/api/data/legal.md). ## Datasets {#datasets} | Dataset | `instrument_id` prefix | Publisher | |---|---|---| | `legal.statutes.tw_moj` | `TW:MOJ:` | Ministry of Justice, Laws & Regulations Database (Traditional Chinese and English; laws and orders, each language a separate record) | | `legal.statutes.jp_egov` | `JP:EGOV:` | e-Gov Laws and Regulations Search | | `legal.statutes.uk_legislation` | `UK:LEG:` | legislation.gov.uk | | `legal.statutes.ca_laws` | `CA:JUSTICE:` | Justice Laws Website | | `legal.statutes.eu_eurlex` | `EU:EURLEX:` | EUR-Lex (regulations, directives, decisions) | | `legal.statutes.us_ecfr` | `US:ECFR:` | Electronic Code of Federal Regulations (federal regulations, not acts of Congress) | | `legal.statutes.de_gii` | `DE:GII:` | Gesetze im Internet (federal law) | | `legal.statutes.au_federal` | `AU:FEDERAL:` | Federal Register of Legislation | | `legal.statutes.sg_sso` | `SG:SSO:` | Singapore Statutes Online. **Not collected**: no official API or open-data licence. Where such text is ever served it is `restricted` and must carry attribution. | | `legal.statutes.cn_flk` | `CN:FLK:` | National Database of Laws and Regulations. **Not collected**: no published API and terms not reviewed. | An instrument id may contain `:` and `/`, for example `UK:LEG:ukpga/2020/1` or `TW:MOJ:A0000001:en`. ## Routes {#routes} All need an API key and are strict about parameters. | Route | Returns | |---|---| | `GET /v1/legal/statutes/instruments` | A list of instruments without provisions or foreword | | `GET /v1/legal/statutes/instruments/{instrument_id}` | One instrument with foreword, provisions and attachments (up to 5000 provisions per call) | | `GET /v1/legal/statutes/instruments/{instrument_id}/provisions` | Only the provisions, paged | The id goes in the path raw or percent-encoded. A path ending in `/provisions` is always the provisions route, so no source id ends that way. A malformed id is `400`, a well-formed id that does not exist is `404`. ### Listing {#listing} Filters combine with AND: `dataset`, `jurisdiction` (two uppercase letters), `language` (`zh-Hant`, `en`, `ja`, ...), `kind` (`act`, `regulation`, `order`, `treaty`, `other`), `status` (`in_force`, `repealed`, `abandoned`, `withdrawn`), `q` (title **contains**, case-insensitive, 1 to 200 characters; a directory filter, not full-text search), `updated_since` (`YYYY-MM-DD` or RFC 3339), `include_removed`. Order is fixed by `instrument_id`; `limit` is 1 to 200, default 50. The cursor is the last `instrument_id`. To follow changes, combine `updated_since` with `include_removed=true`: marking an instrument as gone from its source updates `updated_at`. ### Reading provisions {#provisions} The detail route returns at most 5000 provisions; for a longer instrument `provisions_truncated` is `true` and `next_from_seq` says where to continue with the provisions route. The provisions route takes `from_seq` (default 0) or `cursor` (not both), `number` and `limit` (1 to 1000, default 500). `number` finds an article. Write it as the original (`第 184 條`, `Article 15-1`), or as an article key: `184`, `184-1`, `184之1`, `第184條之1`, `Article 184` and leading zeros all mean the same key, and `184` does not match `184-1` or `1840`. The returned `number` is always the original text. A provision with no numbering (such as `附則`) matches only its exact text. A `from_seq` past the last provision returns `200` with an empty array. ## Licence, attribution and restrictions {#licence} Each instrument has `license`, `attribution` and `restricted`; the response `meta` repeats them de-duplicated (`licenses`, `attribution`, `restricted` when any instrument is restricted). Provision rows carry none of these: use `meta`. If an instrument is restricted you must show its attribution and the reminder to check the latest version at the source. Licence and attribution strings come from each publisher's terms ([Attribution](https://docs.aggre.org/concepts/attribution.md)). An instrument its source stopped listing is still served (`removed_on` set, with a message saying the content is the last version seen). ## Judgments and retrieval {#judgments-and-retrieval} Taiwan judgments and semantic retrieval are served by a separate set of routes, registered in the same API: | Route | Purpose | |---|---| | `GET /v1/legal/judgments/lookup` | Find a judgment by its citation | | `GET /v1/legal/judgments/{jid}` | Read a judgment | | `POST /v1/legal/judgments/{jid}/search` | Find where in one judgment a question is answered | | `GET`/`POST /v1/legal/judgments/{jid}/outline` | The map of one judgment | | `POST /v1/legal/judgments/search` | Search case law by the court's own reasoning | | `POST /v1/legal/retrieve`, `POST /v1/legal/retrieve/batch` | Retrieval over the legal corpora | Judgment routes can answer `501 corpus_not_migrated` while a corpus is not loaded, `410 taken_down`, `503 index_unavailable` and `503 retrieval_unavailable` ([Errors](https://docs.aggre.org/concepts/errors.md)). The per-route reference for these is not generated on this site yet; the argument lists of the [MCP compatibility tools](https://docs.aggre.org/agents/mcp.md) (`retrieve`, `search_judgments`, `lookup_judgment`, `get_judgment`, `search_in_judgment`, `judgment_outline`) describe the same operations. Retrieval is a ranked search over a bounded index, and its responses carry a `coverage` object that says how the ranking was done (for example `coverage.rerank=bm25_fallback` when the reranker was unavailable and results are in lexical order). Read `coverage` before treating an empty result as proof that nothing matches. === https://docs.aggre.org/datasets/legal-regulatory === # Regulatory lists and legal documents > Government sanctions and exclusion lists, the Taiwan FSC news feed and Taiwan standard-form contracts. Page: https://docs.aggre.org/datasets/legal-regulatory · Section: Datasets · All pages: https://docs.aggre.org/llms.txt Official lists and documents that sit next to statutes. Reference: [Legal routes](https://docs.aggre.org/api/data/legal.md). Statutes have [their own guide](https://docs.aggre.org/datasets/legal-statutes.md). ## Name lists {#name-lists} | Dataset | What a row is | Publisher | Stale after | |---|---|---|---| | `legal.regulatory.ofac_sdn` | One SDN entry (person, entity, vessel, aircraft) | US Treasury OFAC | 48 hours | | `legal.regulatory.un_sanctions` | One entry of the UN Security Council consolidated list | UN Security Council | 72 hours | | `legal.regulatory.us_exclusions` | One entry of the List of Excluded Individuals/Entities | HHS Office of Inspector General | 10 days | Routes: - `GET /v1/legal/regulatory/entries?dataset=...` — `dataset` is required. Optional: `q` with `match=prefix` or `exact`, `kind`, `listed_from`, `removed=exclude|include|only`, `cursor`, `limit` (1 to 200, default 50). - `GET /v1/legal/regulatory/entry?dataset=...&entry_id=...` — one entry with its names and attributes. A delisted entry is still found and carries `removed_on`. Rules that matter: - **Name search is exact or prefix only and is never a screening verdict.** Every response says so in `meta.message`. Do not use these routes as a compliance screening engine: they do not do fuzzy matching, transliteration or alias resolution. - Entries are served as the publisher publishes them; removals are kept as history (`removed=include` or `only`). - The HHS-OIG list carries no entry id, so Aggre derives one and says so on each row. - `license` and `attribution` are `null` until a person has read the list's terms; the API then says "Terms not read". - `meta.dataDate` is the publisher's list date and `meta.lastReadAt` is Aggre's last successful full read. - Usage records the list you asked for, never the query or the entry id. ## Taiwan FSC news {#fsc-news} `GET /v1/legal/regulatory/fsc_news` serves items from the Financial Supervisory Commission's five official RSS feeds: press releases, penalty cases, announcements, draft-regulation notices and law interpretations. - Filters: `category`, `published_from`, `published_to`; `include=text` adds the plain-text description (then `limit` is at most 100); `cursor`, `limit`. - Newest first (undated last), then category, then guid. Titles, links and publication days are as published. Items that left a feed are kept. - This is not the articles behind the links, and there is no search. `meta.dataset` carries the item count and per-category counts; `meta.message` says "Terms not read" while nobody has read the FSC's terms. Stale after 48 hours. ## Taiwan standard-form contracts {#contracts} Model contracts (範本) and the terms a contract must and must not contain (應記載及不得記載事項), from the Executive Yuan's website, with machine-extracted text of each attached file. - `GET /v1/legal/contracts/tw_standard_forms` lists forms without text (filters `kind`, `q`, `issuer`, `published_from`, `published_to`, `updated_since`, `include_removed`; ordered by `form_id`). - `GET /v1/legal/contracts/tw_standard_forms/{form_id}` returns the form, every version (oldest first) and the files of one version with their text (`version` picks an older one; `text=false` leaves the text out). - Extracted text is machine output and may contain errors. Stale after 14 days. `503 terms_unread` until the publisher's terms are recorded as read. === https://docs.aggre.org/datasets/health === # Health > openFDA drug and device records, EMA medicines, NPPES providers, ClinicalTrials.gov, WHO indicators and Eurostat mortality. Page: https://docs.aggre.org/datasets/health · Section: Datasets · All pages: https://docs.aggre.org/llms.txt Health datasets from public registries and agencies. Reference: [openFDA routes](https://docs.aggre.org/api/data/health-openfda.md) and [registries and statistics](https://docs.aggre.org/api/data/health-registries.md). Every route answers **`503 terms_unread`** until the publisher's terms are recorded as read ([Freshness](https://docs.aggre.org/concepts/freshness.md#terms)). ## Common behaviour {#common} - **Change feeds**: list routes are ordered by `(updated_at, key)` ascending, and `updated_at` moves only when a record's content changed. Store the newest `updated_at` you handled and pass it back as `updated_since`. - **Prose and payload are opt-in** where they are large: EMA `include=text`, ClinicalTrials.gov `include=prose` (page capped at 100), FDA 510(k) summaries `include=content` (page capped at 25). - **Loading in stages**: a `404 not_found` can mean "not loaded yet", and `meta.status` can be `backfilling` (a first full read is still running), `degraded` (some partitions are stuck) or `not_loaded` (NPPES, before a baseline has been applied). `meta` says how far the load has got. - Single-record routes take no query parameters. ## openFDA {#openfda} Nineteen openFDA datasets, each with a list route and a record route: | Category | Datasets (`fda_{name}`) | |---|---| | Drugs (`/v1/health/drugs/`) | `label`, `ndc`, `drugsfda`, `orangebook`, `shortages`, `nsde`, `unii`, `substance`, `historicaldocument`, `enforcement`, `crl` | | Devices (`/v1/health/devices/`) | `510k`, `pma`, `classification`, `udi`, `registrationlisting`, `covid19serology`, `recall`, `device_enforcement` | Rows keep the upstream openFDA record **whole** in `payload` (nothing renamed or flattened). The list takes `key_prefix` (match on the start of the key), `updated_since`, `cursor` and `limit`; there are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload), so a page can be shorter than `limit` and still have a `next_cursor`: that is normal. A key containing `/` can be sent raw or as `%2F`. `meta` says which export the rows come from and how many partitions are imported, pending or failed. ## FDA 510(k) summaries {#510k} `GET /v1/health/devices/fda_510k_summary` serves the **extracted text** of 510(k) summary documents, one row per clearance (only those whose document produced text). Filters `k_number` (start of the number), `decision_date_from`/`decision_date_to`, `product_code`, `updated_since`. `content` is left out unless `include=content`. ## EMA medicines {#ema} `GET /v1/health/drugs/ema_medicines` lists centrally authorised human and veterinary medicines, one row per EMA product number, withdrawn and refused ones included (`in_latest_report: false` when the newest report no longer contains one). Filters include `category`, `status`, `active_substance`, `atc_code`, `therapeutic_area` and several flags (`biosimilar`, `generic`, `conditional_approval`, ...). `GET .../ema_medicines/{product_number}` returns every column. ## NPPES providers {#nppes} `GET /v1/health/providers/nppes` searches the NPI Registry (practice location only; no mailing address and no phone numbers). These are records about named individuals, so it is a **search, not an enumeration**: give `npi` (up to 20, comma-separated), or `state` together with `last_name`, `organization_name` (a prefix of at least 3 characters) or `taxonomy`; anything less is `400`. At most 100 per page (default 25), ordered by NPI. No change feed and no bulk route. ## ClinicalTrials.gov {#trials} `GET /v1/health/trials/clinicaltrials_gov` lists studies, one row per NCT id. Filters `overall_status`, `study_type`, `phase`, `sponsor`, `condition`, `country`, `has_results`, `first_post_since`, `updated_since`. The array filters (`phase`, `condition`, `country`) match one element exactly as published (case-sensitive). `GET .../clinicaltrials_gov/{nct_id}` returns the whole study. ## WHO Global Health Observatory {#who} `GET /v1/health/statistics/who_gho?indicator=...` serves one **curated** indicator at a time (the whole table is too large to page), within one `spatial_dim_type` (default `COUNTRY`; regions and the world are other types). Rows the indicator's last complete read no longer contained are returned with `in_latest_read: false`. `value_display` is WHO's own formatted string. `GET .../who_gho/indicators` is the catalogue. An indicator outside it is `404`. ## Eurostat causes of death {#eurostat} `GET /v1/health/statistics/eurostat_mortality?icd10=...` returns the cells of one cause code (`icd10` is required: without it the list would be a dump of about 600,000 cells). `GET .../eurostat_mortality/{year}/{geo}/{icd10}` is one cell; `.../causes` and `.../places` list the cause and place codes. `value` is `null` for a status-only cell. ## Caveats {#caveats} These are public records processed by Aggre: they are not medical advice and not a substitute for the regulator's own record. Check `license`, `attribution` and `credit` on the rows, and treat `meta.status` seriously on staged loads. === https://docs.aggre.org/datasets/onchain === # On-chain data > DeFi protocol total value locked by day. Page: https://docs.aggre.org/datasets/onchain · Section: Datasets · All pages: https://docs.aggre.org/llms.txt On-chain and DeFi figures. Reference: [On-chain route](https://docs.aggre.org/api/data/onchain.md). ## Protocol TVL {#protocol-tvl} `GET /v1/onchain/defi/protocol_tvl` serves DeFi protocol total value locked (TVL) from DefiLlama's protocol list: one row per protocol per UTC day, identified by `(slug, as_of)`. The dataset is `onchain.defi.protocol_tvl` and it is also listed under `finance.market`. Fields include `tvl_usd` (a JSON number), `mcap_usd`, `change_1h`, `change_1d`, `change_7d`, `category`, `chain`, `chains`, `chain_tvls` and `tvl_rank` (Aggre's own: 1 is the largest TVL of the day). A figure the source leaves out is `null`, never zero. Two shapes, chosen by `slug`: | Shape | Parameters | Result | |---|---|---| | **A day** (no `slug`) | `as_of`, `category` (exact, case-sensitive), `chain` (one element of `chains`, exact) | Every protocol of one day ordered by TVL rank. The newest stored day unless `as_of` names one. `from`, `to` and `order` are `400` here. | | **A history** (`slug`) | `from` (inclusive), `to` (exclusive), both `YYYY-MM-DD`, `order` | One protocol's rows over time, newest first unless `order=asc`. `as_of`, `category` and `chain` are `400` here. | A cursor pins its day. ## Behaviour to know {#behaviour} - `as_of` is the day Aggre **read** the figure. History starts the day collection started; nothing is backfilled. - `meta.status` is `empty` for no rows and `stale` when the answer follows the newest data and Aggre's last successful read is more than 3 days old. It is never `stale` for a view pinned to a date. - **Whoever shows a row shows `meta.dataset.credit`.** - The route answers `503 terms_unread` until the publisher's terms are recorded as read, and then reads no row ([Freshness](https://docs.aggre.org/concepts/freshness.md#terms)). === https://docs.aggre.org/api/data === # Data API > Every read route of https://api.aggre.org: what each does, its parameters and an example. Page: https://docs.aggre.org/api/data · Section: API reference · All pages: https://docs.aggre.org/llms.txt The data API is served at `https://api.aggre.org`. It is read-only, takes an API key in `Authorization: Bearer aggre_sk_...` (or `X-API-Key`), sets no cookies and allows no browser (CORS) access; call it from a server, a script or an agent. New to it? Start with the [quickstart](https://docs.aggre.org/quickstart.md). This reference is generated from the OpenAPI file ([`/openapi/data.yaml`](https://docs.aggre.org/openapi/data.yaml), also as [JSON](https://docs.aggre.org/openapi/data.json)), so it lists exactly the routes the service registers. Row shapes are the JSON Schemas in the [schema reference](https://docs.aggre.org/api/schemas.md). Rules that apply to every route are in [Concepts](https://docs.aggre.org/concepts/response-format.md): the response envelope, strict query parameters, opaque cursors, freshness (`meta.status`), attribution (`credit`) and the shared error codes. ## Pages | Page | Routes | Covers | |---|---|---| | [Service routes](https://docs.aggre.org/api/data/service.md) | 4 | Health checks, the dataset list and the calling key. | | [Market data](https://docs.aggre.org/api/data/market.md) | 7 | Candles, funding rates, open interest, instruments and the latest tickers. | | [Macro data](https://docs.aggre.org/api/data/macro.md) | 5 | The economic calendar, official macro series and their observations, and derived series. | | [Filings and trades (SEC EDGAR, US Congress)](https://docs.aggre.org/api/data/filings.md) | 9 | Companies, filings, XBRL facts, fundamentals, insider transactions, fails-to-deliver, 13F holdings, 8-K news and Congress trades. | | [Taiwan equities](https://docs.aggre.org/api/data/equities-tw.md) | 9 | TWSE and TPEx securities, daily closes, valuation, institutional and margin data, revenue, statements and indices. | | [Legal data](https://docs.aggre.org/api/data/legal.md) | 8 | Statutes, sanctions and exclusion lists, the Taiwan FSC news feed and Taiwan standard-form contracts. | | [Health: openFDA](https://docs.aggre.org/api/data/health-openfda.md) | 40 | The 19 openFDA datasets (drug labels, NDC, approvals, shortages, recalls, device clearances and more). | | [Health: registries and statistics](https://docs.aggre.org/api/data/health-registries.md) | 12 | EMA medicines, NPPES providers, ClinicalTrials.gov, FDA 510(k) summaries, WHO GHO and Eurostat mortality. | | [On-chain data](https://docs.aggre.org/api/data/onchain.md) | 1 | Total value locked in DeFi protocols, by protocol and chain. | ## All routes | Method | Path | Summary | |---|---|---| | `GET` | `/healthz` | [Liveness](https://docs.aggre.org/api/data/service.md#healthz) | | `GET` | `/readyz` | [Readiness](https://docs.aggre.org/api/data/service.md#readyz) | | `GET` | `/v1/datasets` | [The datasets and where to read them](https://docs.aggre.org/api/data/service.md#listDatasets) | | `GET` | `/v1/whoami` | [The calling key and its usage](https://docs.aggre.org/api/data/service.md#whoami) | | `GET` | `/v1/finance/market/candles_1m` | [Confirmed one-minute candles of one instrument](https://docs.aggre.org/api/data/market.md#candles1M) | | `GET` | `/v1/finance/market/candles_1h` | [Confirmed one-hour candles of one instrument](https://docs.aggre.org/api/data/market.md#candles1H) | | `GET` | `/v1/finance/market/candles_1d` | [Confirmed one-day candles of one instrument](https://docs.aggre.org/api/data/market.md#candles1D) | | `GET` | `/v1/finance/market/funding_rates` | [Settled funding payments of a perpetual](https://docs.aggre.org/api/data/market.md#fundingRates) | | `GET` | `/v1/finance/market/open_interest` | [Open-interest snapshots of a perpetual](https://docs.aggre.org/api/data/market.md#openInterest) | | `GET` | `/v1/finance/market/instruments` | [The instrument list](https://docs.aggre.org/api/data/market.md#listInstruments) | | `GET` | `/v1/finance/market/tickers` | [The latest ticker of every enabled instrument](https://docs.aggre.org/api/data/market.md#listTickers) | | `GET` | `/v1/finance/macro/calendar_events` | [Scheduled economic releases](https://docs.aggre.org/api/data/macro.md#listCalendarEvents) | | `GET` | `/v1/finance/macro/series` | [The macro series catalogue](https://docs.aggre.org/api/data/macro.md#listMacroSeries) | | `GET` | `/v1/finance/macro/observations` | [Observations of one series](https://docs.aggre.org/api/data/macro.md#listMacroObservations) | | `GET` | `/v1/finance/macro_derived/series` | [The computed macro series catalogue](https://docs.aggre.org/api/data/macro.md#listMacroDerivedSeries) | | `GET` | `/v1/finance/macro_derived/observations` | [Computed values of one series](https://docs.aggre.org/api/data/macro.md#listMacroDerivedObservations) | | `GET` | `/v1/finance/filings/companies` | [SEC companies on the coverage list](https://docs.aggre.org/api/data/filings.md#listFilingsCompanies) | | `GET` | `/v1/finance/filings/filings` | [A company's filings](https://docs.aggre.org/api/data/filings.md#listFilings) | | `GET` | `/v1/finance/filings/company_facts` | [As-filed XBRL facts of a company](https://docs.aggre.org/api/data/filings.md#listFilingsCompanyFacts) | | `GET` | `/v1/finance/filings/fundamentals` | [Normalized fundamentals per fiscal period](https://docs.aggre.org/api/data/filings.md#listFilingsFundamentals) | | `GET` | `/v1/finance/filings/insider_transactions` | [Form 4 insider transactions of an issuer](https://docs.aggre.org/api/data/filings.md#listFilingsInsiderTransactions) | | `GET` | `/v1/finance/filings/fails_to_deliver` | [SEC fails-to-deliver balances of a symbol](https://docs.aggre.org/api/data/filings.md#listFilingsFailsToDeliver) | | `GET` | `/v1/finance/filings/holdings_13f` | [SEC Form 13F holdings of a covered company](https://docs.aggre.org/api/data/filings.md#listFilingsHoldings13f) | | `GET` | `/v1/finance/filings/news_8k` | [SEC 8-K current reports of a covered company, with the file names of their press releases](https://docs.aggre.org/api/data/filings.md#listFilingsNews8k) | | `GET` | `/v1/finance/filings/congress_trades` | [Stock trades of US members of Congress (Periodic Transaction Reports)](https://docs.aggre.org/api/data/filings.md#listFilingsCongressTrades) | | `GET` | `/v1/finance/equities_tw/securities` | [Taiwan listed and OTC securities](https://docs.aggre.org/api/data/equities-tw.md#listEquitiesTwSecurities) | | `GET` | `/v1/finance/equities_tw/daily_close` | [Daily close of Taiwan securities](https://docs.aggre.org/api/data/equities-tw.md#listEquitiesTwDailyClose) | | `GET` | `/v1/finance/equities_tw/valuation_daily` | [Daily valuation ratios of Taiwan securities](https://docs.aggre.org/api/data/equities-tw.md#listEquitiesTwValuationDaily) | | `GET` | `/v1/finance/equities_tw/institutional_daily` | [Institutional trades of TPEx securities](https://docs.aggre.org/api/data/equities-tw.md#listEquitiesTwInstitutionalDaily) | | `GET` | `/v1/finance/equities_tw/margin_daily` | [Margin balances of TPEx securities](https://docs.aggre.org/api/data/equities-tw.md#listEquitiesTwMarginDaily) | | `GET` | `/v1/finance/equities_tw/monthly_revenue` | [Monthly revenue of Taiwan companies](https://docs.aggre.org/api/data/equities-tw.md#listEquitiesTwMonthlyRevenue) | | `GET` | `/v1/finance/equities_tw/statements` | [Quarterly statements of Taiwan companies](https://docs.aggre.org/api/data/equities-tw.md#listEquitiesTwStatements) | | `GET` | `/v1/finance/equities_tw/indices` | [Index closes of Taiwan exchanges](https://docs.aggre.org/api/data/equities-tw.md#listEquitiesTwIndices) | | `GET` | `/v1/finance/equities_tw/sources` | [Registered upstream files of the Taiwan datasets](https://docs.aggre.org/api/data/equities-tw.md#listEquitiesTwSources) | | `GET` | `/v1/legal/statutes/instruments` | [Statutes across the ten statute datasets](https://docs.aggre.org/api/data/legal.md#listStatuteInstruments) | | `GET` | `/v1/legal/statutes/instruments/{instrument_id}` | [One statute with its provisions](https://docs.aggre.org/api/data/legal.md#getStatuteInstrument) | | `GET` | `/v1/legal/statutes/instruments/{instrument_id}/provisions` | [The provisions of one statute, paged](https://docs.aggre.org/api/data/legal.md#listStatuteProvisions) | | `GET` | `/v1/legal/regulatory/entries` | [Entries of a sanctions or exclusion list](https://docs.aggre.org/api/data/legal.md#listRegulatoryEntries) | | `GET` | `/v1/legal/regulatory/entry` | [One entry of a sanctions or exclusion list](https://docs.aggre.org/api/data/legal.md#getRegulatoryEntry) | | `GET` | `/v1/legal/regulatory/fsc_news` | [Taiwan FSC news (five RSS feeds)](https://docs.aggre.org/api/data/legal.md#listFscNews) | | `GET` | `/v1/onchain/defi/protocol_tvl` | [DeFi protocol total value locked](https://docs.aggre.org/api/data/onchain.md#listOnchainProtocolTvl) | | `GET` | `/v1/legal/contracts/tw_standard_forms` | [Taiwan standard-form contracts (定型化契約), without text](https://docs.aggre.org/api/data/legal.md#listContractForms) | | `GET` | `/v1/legal/contracts/tw_standard_forms/{form_id}` | [One standard form with its versions and the text of its files](https://docs.aggre.org/api/data/legal.md#getContractForm) | | `GET` | `/v1/health/drugs/ema_medicines` | [EMA medicines register](https://docs.aggre.org/api/data/health-registries.md#listEmaMedicines) | | `GET` | `/v1/health/drugs/ema_medicines/{product_number}` | [One EMA medicine, with its text and source row](https://docs.aggre.org/api/data/health-registries.md#getEmaMedicine) | | `GET` | `/v1/health/providers/nppes` | [Search the NPPES NPI Registry](https://docs.aggre.org/api/data/health-registries.md#searchNppesProviders) | | `GET` | `/v1/health/providers/nppes/{npi}` | [One NPPES provider by NPI](https://docs.aggre.org/api/data/health-registries.md#getNppesProvider) | | `GET` | `/v1/health/trials/clinicaltrials_gov` | [ClinicalTrials.gov studies](https://docs.aggre.org/api/data/health-registries.md#listTrialsStudies) | | `GET` | `/v1/health/trials/clinicaltrials_gov/{nct_id}` | [One ClinicalTrials.gov study, with its prose](https://docs.aggre.org/api/data/health-registries.md#getTrialsStudy) | | `GET` | `/v1/health/devices/fda_510k_summary` | [FDA 510(k) summary documents (extracted text)](https://docs.aggre.org/api/data/health-openfda.md#listFdaSummaries) | | `GET` | `/v1/health/devices/fda_510k_summary/{k_number}` | [One 510(k) summary, with its text](https://docs.aggre.org/api/data/health-openfda.md#getFdaSummary) | | `GET` | `/v1/health/drugs/fda_label` | [openFDA drug labels (prescribing information)](https://docs.aggre.org/api/data/health-openfda.md#listFdaLabel) | | `GET` | `/v1/health/drugs/fda_label/{key}` | [One record of: openFDA drug labels (prescribing information)](https://docs.aggre.org/api/data/health-openfda.md#getFdaLabel) | | `GET` | `/v1/health/drugs/fda_ndc` | [openFDA National Drug Code directory](https://docs.aggre.org/api/data/health-openfda.md#listFdaNdc) | | `GET` | `/v1/health/drugs/fda_ndc/{key}` | [One record of: openFDA National Drug Code directory](https://docs.aggre.org/api/data/health-openfda.md#getFdaNdc) | | `GET` | `/v1/health/drugs/fda_drugsfda` | [openFDA Drugs@FDA approvals](https://docs.aggre.org/api/data/health-openfda.md#listFdaDrugsfda) | | `GET` | `/v1/health/drugs/fda_drugsfda/{key}` | [One record of: openFDA Drugs@FDA approvals](https://docs.aggre.org/api/data/health-openfda.md#getFdaDrugsfda) | | `GET` | `/v1/health/drugs/fda_orangebook` | [openFDA Orange Book](https://docs.aggre.org/api/data/health-openfda.md#listFdaOrangebook) | | `GET` | `/v1/health/drugs/fda_orangebook/{key}` | [One record of: openFDA Orange Book](https://docs.aggre.org/api/data/health-openfda.md#getFdaOrangebook) | | `GET` | `/v1/health/drugs/fda_shortages` | [openFDA drug shortages](https://docs.aggre.org/api/data/health-openfda.md#listFdaShortages) | | `GET` | `/v1/health/drugs/fda_shortages/{key}` | [One record of: openFDA drug shortages](https://docs.aggre.org/api/data/health-openfda.md#getFdaShortages) | | `GET` | `/v1/health/drugs/fda_nsde` | [openFDA NDC SPL data elements (NSDE)](https://docs.aggre.org/api/data/health-openfda.md#listFdaNsde) | | `GET` | `/v1/health/drugs/fda_nsde/{key}` | [One record of: openFDA NDC SPL data elements (NSDE)](https://docs.aggre.org/api/data/health-openfda.md#getFdaNsde) | | `GET` | `/v1/health/drugs/fda_unii` | [openFDA UNII substance identifiers](https://docs.aggre.org/api/data/health-openfda.md#listFdaUnii) | | `GET` | `/v1/health/drugs/fda_unii/{key}` | [One record of: openFDA UNII substance identifiers](https://docs.aggre.org/api/data/health-openfda.md#getFdaUnii) | | `GET` | `/v1/health/drugs/fda_substance` | [openFDA substance data](https://docs.aggre.org/api/data/health-openfda.md#listFdaSubstance) | | `GET` | `/v1/health/drugs/fda_substance/{key}` | [One record of: openFDA substance data](https://docs.aggre.org/api/data/health-openfda.md#getFdaSubstance) | | `GET` | `/v1/health/drugs/fda_historicaldocument` | [openFDA historical documents](https://docs.aggre.org/api/data/health-openfda.md#listFdaHistoricaldocument) | | `GET` | `/v1/health/drugs/fda_historicaldocument/{key}` | [One record of: openFDA historical documents](https://docs.aggre.org/api/data/health-openfda.md#getFdaHistoricaldocument) | | `GET` | `/v1/health/drugs/fda_enforcement` | [openFDA drug enforcement reports (recalls)](https://docs.aggre.org/api/data/health-openfda.md#listFdaEnforcement) | | `GET` | `/v1/health/drugs/fda_enforcement/{key}` | [One record of: openFDA drug enforcement reports (recalls)](https://docs.aggre.org/api/data/health-openfda.md#getFdaEnforcement) | | `GET` | `/v1/health/drugs/fda_crl` | [openFDA complete response letters](https://docs.aggre.org/api/data/health-openfda.md#listFdaCrl) | | `GET` | `/v1/health/drugs/fda_crl/{key}` | [One record of: openFDA complete response letters](https://docs.aggre.org/api/data/health-openfda.md#getFdaCrl) | | `GET` | `/v1/health/devices/fda_510k` | [openFDA 510(k) clearances](https://docs.aggre.org/api/data/health-openfda.md#listFda510k) | | `GET` | `/v1/health/devices/fda_510k/{key}` | [One record of: openFDA 510(k) clearances](https://docs.aggre.org/api/data/health-openfda.md#getFda510k) | | `GET` | `/v1/health/devices/fda_pma` | [openFDA premarket approvals (PMA)](https://docs.aggre.org/api/data/health-openfda.md#listFdaPma) | | `GET` | `/v1/health/devices/fda_pma/{key}` | [One record of: openFDA premarket approvals (PMA)](https://docs.aggre.org/api/data/health-openfda.md#getFdaPma) | | `GET` | `/v1/health/devices/fda_classification` | [openFDA device classification](https://docs.aggre.org/api/data/health-openfda.md#listFdaClassification) | | `GET` | `/v1/health/devices/fda_classification/{key}` | [One record of: openFDA device classification](https://docs.aggre.org/api/data/health-openfda.md#getFdaClassification) | | `GET` | `/v1/health/devices/fda_udi` | [openFDA unique device identifiers (UDI)](https://docs.aggre.org/api/data/health-openfda.md#listFdaUdi) | | `GET` | `/v1/health/devices/fda_udi/{key}` | [One record of: openFDA unique device identifiers (UDI)](https://docs.aggre.org/api/data/health-openfda.md#getFdaUdi) | | `GET` | `/v1/health/devices/fda_registrationlisting` | [openFDA device registration and listing](https://docs.aggre.org/api/data/health-openfda.md#listFdaRegistrationlisting) | | `GET` | `/v1/health/devices/fda_registrationlisting/{key}` | [One record of: openFDA device registration and listing](https://docs.aggre.org/api/data/health-openfda.md#getFdaRegistrationlisting) | | `GET` | `/v1/health/devices/fda_covid19serology` | [openFDA COVID-19 serology tests](https://docs.aggre.org/api/data/health-openfda.md#listFdaCovid19serology) | | `GET` | `/v1/health/devices/fda_covid19serology/{key}` | [One record of: openFDA COVID-19 serology tests](https://docs.aggre.org/api/data/health-openfda.md#getFdaCovid19serology) | | `GET` | `/v1/health/devices/fda_recall` | [openFDA device recalls](https://docs.aggre.org/api/data/health-openfda.md#listFdaRecall) | | `GET` | `/v1/health/devices/fda_recall/{key}` | [One record of: openFDA device recalls](https://docs.aggre.org/api/data/health-openfda.md#getFdaRecall) | | `GET` | `/v1/health/devices/fda_device_enforcement` | [openFDA device enforcement reports](https://docs.aggre.org/api/data/health-openfda.md#listFdaDeviceEnforcement) | | `GET` | `/v1/health/devices/fda_device_enforcement/{key}` | [One record of: openFDA device enforcement reports](https://docs.aggre.org/api/data/health-openfda.md#getFdaDeviceEnforcement) | | `GET` | `/v1/health/statistics/who_gho` | [WHO Global Health Observatory observations of one indicator](https://docs.aggre.org/api/data/health-registries.md#listWhoObservations) | | `GET` | `/v1/health/statistics/who_gho/indicators` | [The curated WHO GHO indicators](https://docs.aggre.org/api/data/health-registries.md#listWhoIndicators) | | `GET` | `/v1/health/statistics/eurostat_mortality` | [Eurostat causes of death, cells of one cause](https://docs.aggre.org/api/data/health-registries.md#listEurostatMortality) | | `GET` | `/v1/health/statistics/eurostat_mortality/causes` | [Cause codes in the Eurostat table](https://docs.aggre.org/api/data/health-registries.md#listEurostatCauses) | | `GET` | `/v1/health/statistics/eurostat_mortality/places` | [Place codes in the Eurostat table](https://docs.aggre.org/api/data/health-registries.md#listEurostatPlaces) | | `GET` | `/v1/health/statistics/eurostat_mortality/{year}/{geo}/{icd10}` | [One Eurostat cell](https://docs.aggre.org/api/data/health-registries.md#getEurostatMortality) | === https://docs.aggre.org/api/data/service === # Service routes > Health checks, the dataset list and the calling key. Page: https://docs.aggre.org/api/data/service · Section: API reference · All pages: https://docs.aggre.org/llms.txt Routes about the service itself. `/healthz` and `/readyz` need no key; `/v1/datasets` lists every dataset with the path to read it, and `/v1/whoami` describes the key you call with (never its secret) and what it has used. On this page: - [Liveness](#healthz): `GET /healthz` - [Readiness](#readyz): `GET /readyz` - [The datasets and where to read them](#listDatasets): `GET /v1/datasets` - [The calling key and its usage](#whoami): `GET /v1/whoami` ## Liveness {#healthz} `GET /healthz` No auth. The process is up; nothing is checked. **Example** ```bash curl -s "https://api.aggre.org/healthz" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: `HealthResponse`. | Field | Type | Required | Description | |---|---|---|---| | `status` | `ok` \| `unavailable` | yes | | | `checks` | object | no | readyz: postgres, clickhouse, and finance_db / legal_db when configured. | ## Readiness {#readyz} `GET /readyz` No auth. Postgres and ClickHouse answer (and `finance_db` / `legal_db` when configured). `503` with the same body shape when one does not. **Example** ```bash curl -s "https://api.aggre.org/readyz" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: `HealthResponse`. | Field | Type | Required | Description | |---|---|---|---| | `status` | `ok` \| `unavailable` | yes | | | `checks` | object | no | readyz: postgres, clickhouse, and finance_db / legal_db when configured. | **Errors**: `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## The datasets and where to read them {#listDatasets} `GET /v1/datasets` **Example** ```bash curl -s "https://api.aggre.org/v1/datasets" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: `DatasetsResponse`. | Field | Type | Required | Description | |---|---|---|---| | `data` | array of `Dataset` | yes | | **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## The calling key and its usage {#whoami} `GET /v1/whoami` Never returns the secret. Counts as a normal request against the key. **Example** ```bash curl -s "https://api.aggre.org/v1/whoami" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: `WhoAmIResponse`. | Field | Type | Required | Description | |---|---|---|---| | `data` | `WhoAmI` | yes | | **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). === https://docs.aggre.org/api/accounts === # Accounts API > The control-plane API behind the console: browser contract, sessions, login flow, roles and handles. Page: https://docs.aggre.org/api/accounts · Section: API reference · All pages: https://docs.aggre.org/llms.txt `https://accounts.aggre.org` is the **control plane**: sign-in, personal accounts and organizations, invitations, API-key management and usage views. It is what the [console](https://docs.aggre.org/console/overview.md) calls. You do not need it to read data (that is the [data API](https://docs.aggre.org/api/data.md), which takes API keys); you need it only if you build your own console or automate account management from a browser session. | | Data API | Accounts API | |---|---|---| | Host | `api.aggre.org` | `accounts.aggre.org` | | Credential | API key (`Authorization: Bearer aggre_sk_...`) | Session cookie | | Browser access (CORS) | none | only `https://app.aggre.org` and `https://admin.aggre.org` | | Accepts the other credential? | no | no: it never accepts an API key | The route list with parameters is generated in the [Accounts API reference](https://docs.aggre.org/api/accounts/reference.md); the OpenAPI file is [`/openapi/accounts.yaml`](https://docs.aggre.org/openapi/accounts.yaml). Platform-staff routes (`/v1/admin/*`) are not documented here. ## Browser contract {#browser-contract} 1. Every call is `fetch(url, { credentials: "include" })` from the browser. The cookies belong to `accounts.aggre.org`, so a server on another host never sees them: logged-in data is fetched in the browser, not server-rendered. 2. Every non-GET request needs all three: the `Origin` the browser sends (it must be exactly an allowed app origin), the header `X-Aggre-CSRF: 1` (any non-empty value), and `Content-Type: application/json` when there is a body. Missing or wrong: `403 csrf_required` or `403 origin_not_allowed`. 3. Every authenticated request, GET included, must carry an allowed `Origin`; one without is treated as unauthenticated (`401`). 4. CORS: exact match on the configured origins, `Access-Control-Allow-Credentials: true`, allowed headers `Content-Type, X-Aggre-CSRF`, methods `GET, POST, PATCH, DELETE, OPTIONS`. No wildcard. Responses carry `Vary: Origin` and `Cache-Control: no-store`. 5. Cookies are `HttpOnly; Secure; SameSite=Lax`, host-only, with the `__Host-` prefix: `__Host-aggre_app` for the app audience and `__Host-aggre_admin` for the admin audience. They are never interchangeable. 6. Success bodies are `{ "data": ... }`; a secret or token is a sibling key (`secret`, `token`) and appears **once**. Errors use the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). 7. Times are RFC 3339 UTC, ids are UUID strings, handles are lowercase. ## Signing in {#login} Login is a **full-page navigation**, not `fetch`: ```text https://accounts.aggre.org/login/{provider}?audience=app&return_to=https%3A%2F%2Fapp.aggre.org%2F ``` `provider` is one of the ids returned by `GET /v1/config` (for example `google`, `github`, `orbbit`). `return_to` must be an absolute URL on the audience's own origin; anything else is replaced by that origin's root. The browser comes back to `return_to` with the session cookie set, or to `{origin}/login?error=` with one of: | `error` | Meaning | |---|---| | `access_denied` | The person cancelled at the provider. | | `invalid_state` | The login state is missing, expired, reused, or the browser finishing the login is not the one that started it. | | `provider_error` | The provider rejected the code, returned an invalid token or was unreachable. | | `account_disabled` | The account is suspended. | | `not_staff` | The admin audience was requested by a user who is not platform staff. | | `identity_in_use` | Linking a provider identity that already belongs to another user. | | `session_required` | Linking without a valid session. | | `internal` | Anything else. | OIDC providers use authorization code with PKCE, `state` and `nonce`, and verify the id token's signature and claims. GitHub uses OAuth 2 with PKCE. ### Who you become {#identity} An identity is `(provider, subject)`, never the e-mail address. A known identity logs you in as the same user. For a new identity, if the provider reports an e-mail it vouches for (a verified address) and an existing user's verified primary e-mail equals it, the identity is **linked to that user** (auto-merge); otherwise a new user and personal account are created. An unverified or absent e-mail never merges anything, and a later change of e-mail at the provider never moves an identity. You can link another provider while signed in (`link=1`) and unlink one as long as another remains. ## Sessions {#sessions} A session is an opaque random token in the cookie; only its hash is stored. App sessions live 30 days from login (not sliding) and die after 14 days without use; admin sessions live 8 hours. At most 20 live sessions per user and audience: a login beyond that revokes the oldest. `POST /v1/auth/logout` revokes the current session and `POST /v1/auth/logout-all` all of them. A suspended account cannot sign in and all its sessions stop working. ## Roles {#roles} On a personal account you are the owner. An organization has `owner`, `admin` and `member`, always with at least one owner. Details of who can do what are in [Organizations](https://docs.aggre.org/console/organizations.md#roles). A caller with no relation to an account gets `404 not_found` (existence is not leaked); one with a relation but too little role gets `403 forbidden`. ## Handles {#handles} Users and organizations share one namespace of handles: 3 to 39 characters of `a-z`, `0-9` and `-`, not starting or ending with `-`, no `--`. Reserved words (`admin`, `api`, `app`, `docs`, `login`, `settings`, ...) are refused. The first rename of an account is free; after that, once per 30 days (`409 conflict` with the next date). `GET /v1/handles/{handle}` checks availability. ## Rate limits {#rate-limits} Besides the per-IP limit on every route, the login routes share a tighter per-IP limit; over it the answer is `429 rate_limited` with `Retry-After`. === https://docs.aggre.org/api/accounts/reference === # Accounts API reference > Login, sessions, accounts, organizations, invitations and API-key management routes. Page: https://docs.aggre.org/api/accounts/reference · Section: API reference · All pages: https://docs.aggre.org/llms.txt Every route of the accounts service at `https://accounts.aggre.org` that a signed-in person's browser uses. Read the [accounts API overview](https://docs.aggre.org/api/accounts.md) first: these routes take a **session cookie** (not an API key), an allowed `Origin` and, for anything but GET, the header `X-Aggre-CSRF: 1`. The OpenAPI file is [`/openapi/accounts.yaml`](https://docs.aggre.org/openapi/accounts.yaml) (also [JSON](https://docs.aggre.org/openapi/accounts.json)). The platform-staff routes under `/v1/admin/*` are not part of this reference. | Group | Route | Summary | |---|---|---| | Configuration | `GET /v1/config` | [Public console configuration (login buttons, limits, defaults)](#getConfig) | | Login and sessions | `GET /login/{provider}` | [Start a login (full-page navigation, answers 302 to the provider)](#loginStart) | | Login and sessions | `GET /login/callback/{provider}` | [OAuth redirect URI. Sets the session cookie and answers 302 to return_to or {origin}/login?error=](#loginCallback) | | Login and sessions | `POST /v1/auth/logout` | [Revoke the current session and clear its cookie](#logout) | | Login and sessions | `POST /v1/auth/logout-all` | [Revoke every session of the user (both audiences)](#logoutAll) | | The signed-in user | `GET /v1/me` | [The signed-in user, identities, memberships and session](#getMe) | | The signed-in user | `DELETE /v1/me` | [Delete the personal account (keys revoked, identities and sessions removed, handle stays reserved)](#deleteMe) | | The signed-in user | `DELETE /v1/me/identities/{identity_id}` | [Unlink a login method (409 if it is the last one)](#unlinkIdentity) | | Accounts and usage | `GET /v1/handles/{handle}` | [Is this handle usable? (signed-in users only)](#checkHandle) | | Accounts and usage | `GET /v1/accounts/{handle}` | [One account you can see (self, member, or staff)](#getAccount) | | Accounts and usage | `PATCH /v1/accounts/{handle}` | [Change display_name and/or handle (user: self; org: owner). First rename free, then once per 30 days.](#updateAccount) | | Accounts and usage | `GET /v1/accounts/{handle}/usage` | [Request counts per UTC day and per key over the last N days](#getUsage) | | Accounts and usage | `GET /v1/accounts/{handle}/audit` | [Audit log of the account (owner/admin/staff), newest first](#listAudit) | | API keys | `GET /v1/accounts/{handle}/api-keys` | [Keys of the account, newest first, revoked ones included (max 200). Never contains secrets.](#listApiKeys) | | API keys | `POST /v1/accounts/{handle}/api-keys` | [Create a key. The secret is in the response once and never again.](#createApiKey) | | API keys | `PATCH /v1/accounts/{handle}/api-keys/{key_id}` | [Rename a key or replace its ip_allowlist](#updateApiKey) | | API keys | `DELETE /v1/accounts/{handle}/api-keys/{key_id}` | [Revoke a key (takes effect on the gateway within ~30 s)](#revokeApiKey) | | Organizations and members | `POST /v1/orgs` | [Create an org; the caller becomes its owner](#createOrg) | | Organizations and members | `DELETE /v1/orgs/{handle}` | [Delete an org (owner). Keys are revoked, memberships removed, the handle stays reserved.](#deleteOrg) | | Organizations and members | `GET /v1/orgs/{handle}/members` | [Members of the org (any member, or staff)](#listMembers) | | Organizations and members | `PATCH /v1/orgs/{handle}/members/{user_handle}` | [Change a member's role (owner). 409 if it would leave no owner.](#updateMember) | | Organizations and members | `DELETE /v1/orgs/{handle}/members/{user_handle}` | [Remove a member, or leave (user_handle = yourself). 409 for the last owner.](#removeMember) | | Invitations | `GET /v1/orgs/{handle}/invitations` | [Pending invitations (owner/admin)](#listInvitations) | | Invitations | `POST /v1/orgs/{handle}/invitations` | [Invite an e-mail address. Re-inviting the same address replaces the pending invitation. No e-mail is sent; share the link.](#createInvitation) | | Invitations | `DELETE /v1/orgs/{handle}/invitations/{invitation_id}` | [Revoke a pending invitation](#revokeInvitation) | | Invitations | `GET /v1/invitations/{token}` | [What an invitation link is for (no session needed, so the page can ask the visitor to sign in first)](#previewInvitation) | | Invitations | `POST /v1/invitations/{token}/accept` | [Join the org. The caller's verified primary e-mail must equal the invited address (403 email_mismatch).](#acceptInvitation) | ## Public console configuration (login buttons, limits, defaults) {#getConfig} `GET /v1/config` **Response** `200` | Field | Type | Required | Description | |---|---|---|---| | `data` | `Config` | yes | | ## Start a login (full-page navigation, answers 302 to the provider) {#loginStart} `GET /login/{provider}` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `provider` | path | yes | string | | | `audience` | query | no | `app` \| `admin` (default `app`) | | | `return_to` | query | no | string, uri | Absolute URL on the audience origin; otherwise ignored. | | `link` | query | no | `1` | Attach this provider to the signed-in user. | **Errors**: `302`, `400`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## OAuth redirect URI. Sets the session cookie and answers 302 to return_to or {origin}/login?error= {#loginCallback} `GET /login/callback/{provider}` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `provider` | path | yes | string | | | `code` | query | no | string | | | `state` | query | no | string | | | `error` | query | no | string | | **Errors**: `302`, `400`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Revoke the current session and clear its cookie {#logout} `POST /v1/auth/logout` **Response** `204`. ## Revoke every session of the user (both audiences) {#logoutAll} `POST /v1/auth/logout-all` **Response** `204`. ## The signed-in user, identities, memberships and session {#getMe} `GET /v1/me` **Response** `200` | Field | Type | Required | Description | |---|---|---|---| | `data` | `Me` | yes | | **Errors**: `401`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Delete the personal account (keys revoked, identities and sessions removed, handle stays reserved) {#deleteMe} `DELETE /v1/me` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `confirm` | query | yes | string | Must equal the user's handle. | **Response** `204`. **Errors**: `401`, `409`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Unlink a login method (409 if it is the last one) {#unlinkIdentity} `DELETE /v1/me/identities/{identity_id}` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `identity_id` | path | yes | string, uuid | | **Response** `204`. **Errors**: `404`, `409`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Is this handle usable? (signed-in users only) {#checkHandle} `GET /v1/handles/{handle}` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `handle` | path | yes | string | | **Response** `200` | Field | Type | Required | Description | |---|---|---|---| | `data` | object | yes | | | `data.handle` | string | yes | | | `data.available` | boolean | yes | | | `data.reason` | `invalid` \| `reserved` \| `taken` \| `null` | no | | ## One account you can see (self, member, or staff) {#getAccount} `GET /v1/accounts/{handle}` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `handle` | path | yes | string | | **Response** `200` | Field | Type | Required | Description | |---|---|---|---| | `data` | `Account` | yes | | **Errors**: `404`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Change display_name and/or handle (user: self; org: owner). First rename free, then once per 30 days. {#updateAccount} `PATCH /v1/accounts/{handle}` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `handle` | path | yes | string | | **Request body** (JSON) | Field | Type | Required | Description | |---|---|---|---| | `display_name` | nullable, string | no | | | `handle` | string | no | | **Response** `200` | Field | Type | Required | Description | |---|---|---|---| | `data` | `Account` | yes | | **Errors**: `403`, `404`, `409`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Request counts per UTC day and per key over the last N days {#getUsage} `GET /v1/accounts/{handle}/usage` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `handle` | path | yes | string | | | `days` | query | no | integer, 1–90, default `30` | | **Response** `200` | Field | Type | Required | Description | |---|---|---|---| | `data` | `Usage` | yes | | **Errors**: `404`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Audit log of the account (owner/admin/staff), newest first {#listAudit} `GET /v1/accounts/{handle}/audit` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `handle` | path | yes | string | | | `limit` | query | no | integer, 1–100, default `50` | | | `before` | query | no | integer, int64 | Return entries with id < before. | **Response** `200` | Field | Type | Required | Description | |---|---|---|---| | `data` | array of `AuditEntry` | yes | | | `next_before` | nullable, integer, int64 | yes | | **Errors**: `403`, `404`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Keys of the account, newest first, revoked ones included (max 200). Never contains secrets. {#listApiKeys} `GET /v1/accounts/{handle}/api-keys` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `handle` | path | yes | string | | **Response** `200` | Field | Type | Required | Description | |---|---|---|---| | `data` | array of `ApiKey` | yes | | **Errors**: `404`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Create a key. The secret is in the response once and never again. {#createApiKey} `POST /v1/accounts/{handle}/api-keys` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `handle` | path | yes | string | | **Request body** (JSON) | Field | Type | Required | Description | |---|---|---|---| | `name` | string | yes | | | `usage_limit` | nullable, integer, int64 | no | Omit = server default. null (Unlimited) and values above the default: staff only. | | `usage_period` | `day` \| `month` \| `total` | no | | | `rate_policy` | `default` \| `exempt` | no | exempt: staff only. | | `internal` | boolean, default `false` | no | true gives the key the `internal` scope (the data API's `/v1/internal/*` per-row routes). Platform staff on an admin session, freshly signed in; anyone else gets 403. | | `ip_allowlist` | array of string | no | | | `expires_at` | nullable, string, date-time | no | | **Response** `201` | Field | Type | Required | Description | |---|---|---|---| | `data` | `ApiKey` | yes | | | `secret` | string | yes | | **Errors**: `400`, `403`, `404`, `409`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Rename a key or replace its ip_allowlist {#updateApiKey} `PATCH /v1/accounts/{handle}/api-keys/{key_id}` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `handle` | path | yes | string | | | `key_id` | path | yes | string, uuid | | **Request body** (JSON) | Field | Type | Required | Description | |---|---|---|---| | `name` | string | no | | | `ip_allowlist` | array of string | no | CIDRs or bare addresses; [] = open. | **Response** `200` | Field | Type | Required | Description | |---|---|---|---| | `data` | `ApiKey` | yes | | **Errors**: `400`, `403`, `404`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Revoke a key (takes effect on the gateway within ~30 s) {#revokeApiKey} `DELETE /v1/accounts/{handle}/api-keys/{key_id}` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `handle` | path | yes | string | | | `key_id` | path | yes | string, uuid | | **Response** `204`. **Errors**: `403`, `404`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Create an org; the caller becomes its owner {#createOrg} `POST /v1/orgs` **Request body** (JSON) | Field | Type | Required | Description | |---|---|---|---| | `handle` | string | yes | | | `display_name` | string | no | | **Response** `201` | Field | Type | Required | Description | |---|---|---|---| | `data` | `Account` | yes | | **Errors**: `400`, `409`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Delete an org (owner). Keys are revoked, memberships removed, the handle stays reserved. {#deleteOrg} `DELETE /v1/orgs/{handle}` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `handle` | path | yes | string | | | `confirm` | query | yes | string | Must equal the org handle. | **Response** `204`. **Errors**: `403`, `404`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Members of the org (any member, or staff) {#listMembers} `GET /v1/orgs/{handle}/members` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `handle` | path | yes | string | | **Response** `200` | Field | Type | Required | Description | |---|---|---|---| | `data` | array of `Member` | yes | | **Errors**: `404`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Change a member's role (owner). 409 if it would leave no owner. {#updateMember} `PATCH /v1/orgs/{handle}/members/{user_handle}` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `handle` | path | yes | string | | | `user_handle` | path | yes | string | | **Request body** (JSON) | Field | Type | Required | Description | |---|---|---|---| | `role` | `Role` | yes | | **Response** `200` | Field | Type | Required | Description | |---|---|---|---| | `data` | `Member` | yes | | **Errors**: `403`, `404`, `409`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Remove a member, or leave (user_handle = yourself). 409 for the last owner. {#removeMember} `DELETE /v1/orgs/{handle}/members/{user_handle}` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `handle` | path | yes | string | | | `user_handle` | path | yes | string | | **Response** `204`. **Errors**: `403`, `404`, `409`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Pending invitations (owner/admin) {#listInvitations} `GET /v1/orgs/{handle}/invitations` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `handle` | path | yes | string | | **Response** `200` | Field | Type | Required | Description | |---|---|---|---| | `data` | array of `Invitation` | yes | | **Errors**: `403`, `404`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Invite an e-mail address. Re-inviting the same address replaces the pending invitation. No e-mail is sent; share the link. {#createInvitation} `POST /v1/orgs/{handle}/invitations` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `handle` | path | yes | string | | **Request body** (JSON) | Field | Type | Required | Description | |---|---|---|---| | `email` | string, email | yes | | | `role` | `Role` | no | | **Response** `201` | Field | Type | Required | Description | |---|---|---|---| | `data` | `Invitation` | yes | | | `token` | string | yes | One-time secret; the console links to {app}/invitations/{token}. | **Errors**: `400`, `403`, `404`, `409`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Revoke a pending invitation {#revokeInvitation} `DELETE /v1/orgs/{handle}/invitations/{invitation_id}` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `handle` | path | yes | string | | | `invitation_id` | path | yes | string, uuid | | **Response** `204`. **Errors**: `403`, `404`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## What an invitation link is for (no session needed, so the page can ask the visitor to sign in first) {#previewInvitation} `GET /v1/invitations/{token}` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `token` | path | yes | string | | **Response** `200` | Field | Type | Required | Description | |---|---|---|---| | `data` | object | yes | | | `data.org` | object | yes | | | `data.role` | `Role` | yes | | | `data.email_hint` | string | yes | | | `data.expires_at` | string, date-time | yes | | **Errors**: `404`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Join the org. The caller's verified primary e-mail must equal the invited address (403 email_mismatch). {#acceptInvitation} `POST /v1/invitations/{token}/accept` **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `token` | path | yes | string | | **Response** `200` | Field | Type | Required | Description | |---|---|---|---| | `data` | object | yes | | | `data.org` | `Account` | yes | | | `data.role` | `Role` | yes | | **Errors**: `401`, `403`, `404`, `409`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). === https://docs.aggre.org/api/data/market === # Market data > Candles, funding rates, open interest, instruments and the latest tickers. Page: https://docs.aggre.org/api/data/market · Section: API reference · All pages: https://docs.aggre.org/llms.txt Crypto market data by venue. Concepts and caveats are in the [market data guide](https://docs.aggre.org/datasets/market.md). Instruments are identified as `{VENUE}:{PRODUCT}:{native}`, for example `OKX:SPOT:SOL-USDC`. On this page: - [Confirmed one-minute candles of one instrument](#candles1M): `GET /v1/finance/market/candles_1m` - [Confirmed one-hour candles of one instrument](#candles1H): `GET /v1/finance/market/candles_1h` - [Confirmed one-day candles of one instrument](#candles1D): `GET /v1/finance/market/candles_1d` - [Settled funding payments of a perpetual](#fundingRates): `GET /v1/finance/market/funding_rates` - [Open-interest snapshots of a perpetual](#openInterest): `GET /v1/finance/market/open_interest` - [The instrument list](#listInstruments): `GET /v1/finance/market/instruments` - [The latest ticker of every enabled instrument](#listTickers): `GET /v1/finance/market/tickers` ## Confirmed one-minute candles of one instrument {#candles1M} `GET /v1/finance/market/candles_1m` Only confirmed bars. `ts` is the bar open (Unix ms UTC). **No cursor paging yet:** `next_cursor` is always null; read further with `from`/`to`. Dataset `finance.market.candles_1m`; semantics in [the dataset guide](https://docs.aggre.org/datasets.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `instrument_id` | query | yes | string | `{VENUE}:{PRODUCT}:{native}`, e.g. OKX:SPOT:SOL-USDC. Funding and open interest need a PERP or FUTURES id. | | `from` | query | no | integer, int64 | Unix ms, inclusive (on `ts`). | | `to` | query | no | integer, int64 | Unix ms, exclusive (on `ts`). Must be later than `from`. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | | `order` | query | no | `asc` \| `desc` (default `desc`) | Sort direction (default newest first). | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/market/candles_1m?instrument_id=OKX:SPOT:SOL-USDC&limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`candles`](https://docs.aggre.org/api/schemas.md#candles). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Confirmed one-hour candles of one instrument {#candles1H} `GET /v1/finance/market/candles_1h` Only confirmed bars. `ts` is the bar open (Unix ms UTC). **No cursor paging yet:** `next_cursor` is always null; read further with `from`/`to`. Dataset `finance.market.candles_1h`; semantics in [the dataset guide](https://docs.aggre.org/datasets.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `instrument_id` | query | yes | string | `{VENUE}:{PRODUCT}:{native}`, e.g. OKX:SPOT:SOL-USDC. Funding and open interest need a PERP or FUTURES id. | | `from` | query | no | integer, int64 | Unix ms, inclusive (on `ts`). | | `to` | query | no | integer, int64 | Unix ms, exclusive (on `ts`). Must be later than `from`. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | | `order` | query | no | `asc` \| `desc` (default `desc`) | Sort direction (default newest first). | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/market/candles_1h?instrument_id=OKX:SPOT:SOL-USDC&limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`candles`](https://docs.aggre.org/api/schemas.md#candles). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Confirmed one-day candles of one instrument {#candles1D} `GET /v1/finance/market/candles_1d` Only confirmed bars. `ts` is the bar open (Unix ms UTC). **No cursor paging yet:** `next_cursor` is always null; read further with `from`/`to`. Dataset `finance.market.candles_1d`; semantics in [the dataset guide](https://docs.aggre.org/datasets.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `instrument_id` | query | yes | string | `{VENUE}:{PRODUCT}:{native}`, e.g. OKX:SPOT:SOL-USDC. Funding and open interest need a PERP or FUTURES id. | | `from` | query | no | integer, int64 | Unix ms, inclusive (on `ts`). | | `to` | query | no | integer, int64 | Unix ms, exclusive (on `ts`). Must be later than `from`. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | | `order` | query | no | `asc` \| `desc` (default `desc`) | Sort direction (default newest first). | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/market/candles_1d?instrument_id=OKX:SPOT:SOL-USDC&limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`candles`](https://docs.aggre.org/api/schemas.md#candles). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Settled funding payments of a perpetual {#fundingRates} `GET /v1/finance/market/funding_rates` `instrument_id` must be a PERP or FUTURES id. `rate` is that period's fraction as the venue reports it, not annualised. `next_cursor` is always null. Stale after 24 h. Dataset `finance.market.funding_rates`. **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `instrument_id` | query | yes | string | `{VENUE}:{PRODUCT}:{native}`, e.g. OKX:SPOT:SOL-USDC. Funding and open interest need a PERP or FUTURES id. | | `from` | query | no | integer, int64 | Unix ms, inclusive (on `ts`). | | `to` | query | no | integer, int64 | Unix ms, exclusive (on `ts`). Must be later than `from`. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | | `order` | query | no | `asc` \| `desc` (default `desc`) | Sort direction (default newest first). | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/market/funding_rates?instrument_id=OKX:SPOT:SOL-USDC&limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`funding_rates`](https://docs.aggre.org/api/schemas.md#funding_rates). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Open-interest snapshots of a perpetual {#openInterest} `GET /v1/finance/market/open_interest` `instrument_id` must be a PERP or FUTURES id. A snapshot in base-asset units; history starts the day collection starts. `next_cursor` is always null. Stale after 30 min. Dataset `finance.market.open_interest`. **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `instrument_id` | query | yes | string | `{VENUE}:{PRODUCT}:{native}`, e.g. OKX:SPOT:SOL-USDC. Funding and open interest need a PERP or FUTURES id. | | `from` | query | no | integer, int64 | Unix ms, inclusive (on `ts`). | | `to` | query | no | integer, int64 | Unix ms, exclusive (on `ts`). Must be later than `from`. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | | `order` | query | no | `asc` \| `desc` (default `desc`) | Sort direction (default newest first). | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/market/open_interest?instrument_id=OKX:SPOT:SOL-USDC&limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`open_interest`](https://docs.aggre.org/api/schemas.md#open_interest). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## The instrument list {#listInstruments} `GET /v1/finance/market/instruments` Dataset `finance.market.instruments` (Postgres). No cursor. 503 `store_unavailable` when `finance_db` is not configured. **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `venue` | query | no | string, pattern `^[A-Z0-9]+$` | Exact venue code: uppercase letters and digits (OKX, BITGET, HYPERLIQUID ...). | | `product` | query | no | `SPOT` \| `PERP` \| `FUTURES` | | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/market/instruments" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`instruments`](https://docs.aggre.org/api/schemas.md#instruments). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## The latest ticker of every enabled instrument {#listTickers} `GET /v1/finance/market/tickers` One row per enabled instrument, latest only: no history, no cursor. The 24 h figures are the venue's rolling 24 hours and null where the venue does not send them. Dataset `finance.market.tickers_latest`. **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `venue` | query | no | string, pattern `^[A-Z0-9]+$` | Exact venue code: uppercase letters and digits (OKX, BITGET, HYPERLIQUID ...). | | `product` | query | no | `SPOT` \| `PERP` \| `FUTURES` | | | `instrument_id` | query | no | string | Exact; must agree with `venue`/`product` when they are given. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/market/tickers" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`tickers_latest`](https://docs.aggre.org/api/schemas.md#tickers_latest). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). === https://docs.aggre.org/api/data/macro === # Macro data > The economic calendar, official macro series and their observations, and derived series. Page: https://docs.aggre.org/api/data/macro · Section: API reference · All pages: https://docs.aggre.org/llms.txt Official macroeconomic series and the release calendar. Read the [macro guide](https://docs.aggre.org/datasets/macro.md) first for versions (revisions), units and the attribution rule. On this page: - [Scheduled economic releases](#listCalendarEvents): `GET /v1/finance/macro/calendar_events` - [The macro series catalogue](#listMacroSeries): `GET /v1/finance/macro/series` - [Observations of one series](#listMacroObservations): `GET /v1/finance/macro/observations` - [The computed macro series catalogue](#listMacroDerivedSeries): `GET /v1/finance/macro_derived/series` - [Computed values of one series](#listMacroDerivedObservations): `GET /v1/finance/macro_derived/observations` ## Scheduled economic releases {#listCalendarEvents} `GET /v1/finance/macro/calendar_events` The schedule only: no estimates, no actual or previous values. `impact` is Aggre's own grading. Whoever shows an event shows its `credit`. `next_cursor` is always null. Dataset `finance.macro.calendar_events`. **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `from` | query | no | integer, int64 | Unix ms, inclusive (on `ts`). | | `to` | query | no | integer, int64 | Unix ms, exclusive (on `ts`). Must be later than `from`. | | `source` | query | no | `BLS` \| `BEA` \| `CENSUS` \| `FOMC` \| `ECB` \| `ONS` \| `EUROSTAT` | | | `economy` | query | no | string, pattern `^[A-Z]{2}$` | Two uppercase letters; EU = euro area. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | | `order` | query | no | `asc` \| `desc` (default `asc`) | Sort direction (default oldest first). | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/macro/calendar_events?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`calendar_events`](https://docs.aggre.org/api/schemas.md#calendar_events). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## The macro series catalogue {#listMacroSeries} `GET /v1/finance/macro/series` Ordered by `series_id`. Dataset `finance.macro.series`. **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `source` | query | no | string | Lowercase letters, digits and underscores. | | `economy` | query | no | string, pattern `^[A-Z]{2}$` | Two uppercase letters; EU = euro area. | | `frequency` | query | no | `daily` \| `weekly` \| `monthly` \| `quarterly` \| `annual` \| `irregular` | | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/macro/series?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`macro_series`](https://docs.aggre.org/api/schemas.md#macro_series). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Observations of one series {#listMacroObservations} `GET /v1/finance/macro/observations` A revision is a new `version`, never an overwrite. `value x unit_multiplier` is in `unit`. Whoever shows a value shows its `credit`. `meta.series` is the series row. Dataset `finance.macro.observations`. **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `series_id` | query | yes | string | e.g. fed.effr; list them at /v1/finance/macro/series. An unknown id is 404. | | `from` | query | no | string, date | YYYY-MM-DD on `period`, inclusive. | | `to` | query | no | string, date | YYYY-MM-DD on `period`, exclusive. | | `as_of` | query | no | integer, int64 | Unix ms: each period as Aggre knew it then (the highest version first seen at or before it). | | `versions` | query | no | `latest` \| `all` (default `latest`) | `latest` = highest version per period; `all` = every revision. | | `order` | query | no | `asc` \| `desc` (default `asc`) | Sort direction (default oldest first). | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/macro/observations?series_id=fed&limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`macro_observation`](https://docs.aggre.org/api/schemas.md#macro_observation). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## The computed macro series catalogue {#listMacroDerivedSeries} `GET /v1/finance/macro_derived/series` Series Aggre computes on read; nothing is stored: the year-over-year change of 30 stored series (`twtrade`, `twdgbas`), ten sums and ratios over the rows of the FSC Banking Bureau's issuer and bank files, five sums, counts and medians over the exchange's monthly revenue file (`twfsc.*`), fourteen monthly series of counted deals and median price per ping from the Ministry of the Interior's actual-price registry (`twrealprice.*`), the Treasury's monthly interest expense on public issues (`fiscal.interest_expense_public`, the sum of the 29 stored `fiscal.ie_*` lines; `rows_used` counts the lines present) and, for every CFTC contract whose long, short and open-interest series are stored, the net position (long - short, `cftc._net`) and its share of open interest in percent (`cftc.`). Listed only while what it is computed from exists, and, for rows of an entity dataset, only once somebody has read the publisher's terms. Same filters as the stored catalogue; `inputs` and `formula` say what each is computed from. Ordered by `series_id`. Dataset `finance.macro_derived.series`. **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `source` | query | no | string | Lowercase letters, digits and underscores. | | `economy` | query | no | string, pattern `^[A-Z]{2}$` | Two uppercase letters; EU = euro area. | | `frequency` | query | no | `daily` \| `weekly` \| `monthly` \| `quarterly` \| `annual` \| `irregular` | | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/macro_derived/series?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`macro_derived_series`](https://docs.aggre.org/api/schemas.md#macro_derived_series). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Computed values of one series {#listMacroDerivedObservations} `GET /v1/finance/macro_derived/observations` `value x unit_multiplier` is in `unit`. A year-over-year value (percent) is the input's change against the same period one year earlier (`compared_with`), from the newest stored version of both; a value over rows carries `rows_used`, how many issuers, banks, companies or deals it is computed from; a `twrealprice` value carries `provisional`, true for the latest three months published. A revised input revises the value on the next read. A period with nothing to compute from has no row. Whoever shows a value shows its `credit`. `meta.series` is the computed series row; `meta.status` follows what it is computed from. 404 `not_found` for an id that is not computed from anything read yet; 503 `terms_unread` for one over an entity dataset whose publisher terms nobody has read. Dataset `finance.macro_derived.observations`. **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `series_id` | query | yes | string | e.g. twtrade.exports_yoy; list them at /v1/finance/macro_derived/series. An unknown id is 404. | | `from` | query | no | string, date | YYYY-MM-DD on `period`, inclusive. | | `to` | query | no | string, date | YYYY-MM-DD on `period`, exclusive. | | `order` | query | no | `asc` \| `desc` (default `asc`) | Sort direction (default oldest first). | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/macro_derived/observations?series_id=twtrade&limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`macro_derived_observation`](https://docs.aggre.org/api/schemas.md#macro_derived_observation). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). === https://docs.aggre.org/api/schemas === # Schema reference > JSON Schemas of every row and of the error envelope. Page: https://docs.aggre.org/api/schemas · Section: API reference · All pages: https://docs.aggre.org/llms.txt The shape of every row the data API returns, as [JSON Schema](https://json-schema.org/) (draft 2020-12). Each schema is served as a file at `/schemas/{name}.json` on this site; the `$id` inside a schema is its canonical identifier. A response is always the envelope `{ "data": ..., "meta": ..., "next_cursor": ... }` ([Response format](https://docs.aggre.org/concepts/response-format.md)); the schemas below describe the rows inside `data`, plus the error envelope. Clients must ignore properties they do not know: fields are added over time, never removed or renamed. On this page: [calendar_events](#calendar_events) · [candles](#candles) · [equities_tw_daily_close](#equities_tw_daily_close) · [equities_tw_indices](#equities_tw_indices) · [equities_tw_institutional_daily](#equities_tw_institutional_daily) · [equities_tw_margin_daily](#equities_tw_margin_daily) · [equities_tw_monthly_revenue](#equities_tw_monthly_revenue) · [equities_tw_securities](#equities_tw_securities) · [equities_tw_sources](#equities_tw_sources) · [equities_tw_statements](#equities_tw_statements) · [equities_tw_valuation_daily](#equities_tw_valuation_daily) · [error](#error) · [filings_company](#filings_company) · [filings_congress_trade](#filings_congress_trade) · [filings_fact](#filings_fact) · [filings_filing](#filings_filing) · [filings_ftd](#filings_ftd) · [filings_fundamental](#filings_fundamental) · [filings_holding_13f](#filings_holding_13f) · [filings_insider_transaction](#filings_insider_transaction) · [filings_news_8k](#filings_news_8k) · [funding_rates](#funding_rates) · [health_ema_medicine](#health_ema_medicine) · [health_eurostat_cause](#health_eurostat_cause) · [health_eurostat_mortality](#health_eurostat_mortality) · [health_eurostat_place](#health_eurostat_place) · [health_fda_record](#health_fda_record) · [health_fda_summary](#health_fda_summary) · [health_nppes_provider](#health_nppes_provider) · [health_trials_study](#health_trials_study) · [health_who_indicator](#health_who_indicator) · [health_who_observation](#health_who_observation) · [instruments](#instruments) · [legal_contract_form](#legal_contract_form) · [legal_federal_register_document](#legal_federal_register_document) · [legal_fsc_news_item](#legal_fsc_news_item) · [legal_regulatory_entry](#legal_regulatory_entry) · [macro_derived_observation](#macro_derived_observation) · [macro_derived_series](#macro_derived_series) · [macro_observation](#macro_observation) · [macro_series](#macro_series) · [mcp_call](#mcp_call) · [onchain_protocol_tvl](#onchain_protocol_tvl) · [open_interest](#open_interest) · [tickers_latest](#tickers_latest) ## calendar_events {#calendar_events} **CalendarEvent**. [`calendar_events.json`](https://docs.aggre.org/schemas/calendar_events.json) One scheduled economic release (a CPI print, an FOMC decision day, a euro indicator). Only rows read from a publisher's machine-readable schedule, or hand-kept rows that a person verified against the publisher, are served. The impact grade is Aggre's own (editorial), not the publisher's. | Field | Type | Required | Description | |---|---|---|---| | `event_id` | string | yes | {SOURCE}:{release_key}:{reference_period, or the UTC day when there is none}. | | `source` | `BLS` \| `BEA` \| `CENSUS` \| `FOMC` \| `ECB` \| `ONS` \| `EUROSTAT` | yes | The publisher whose schedule lists the release. | | `economy` | string, pattern `^[A-Z]{2}$` | yes | ISO 3166-1 alpha-2 country, or EU for the euro area. | | `currency` | string or null, pattern `^[A-Z]{3}$` | no | | | `title` | string | yes | | | `release_key` | string, pattern `^[a-z0-9_]+$` | yes | Stable id of the kind of release, e.g. cpi, fomc_decision. | | `reference_period` | string or null, pattern `^[0-9]{4}-(0[1-9]\|1[0-2]\|Q[1-4])$` | no | The period the release reports on (YYYY-MM or YYYY-Qn); null when the publisher does not say. Never guessed. | | `ts` | integer | yes | The release instant, Unix ms (UTC). When date_only, the start of that day in UTC: the publisher gave the day, not the time. | | `date_only` | boolean | yes | True when the publisher gives the day and not the time; no time is implied. | | `impact` | `high` \| `medium` \| `low` | yes | Aggre's own grading of how market-moving the release is. Editorial: not the publisher's. | | `impact_basis` | `"editorial"` | yes | | | `source_url` | string, pattern `^https://` | yes | The publisher's own page for the schedule or the release. | | `credit` | string | yes | The attribution text the publisher's terms ask for, stored with the row. Whoever shows the row shows this text. | | `origin` | `feed` \| `manual` | yes | feed: read from the publisher's machine-readable schedule. manual: a hand-kept table, verified by a person on verified_on. | | `retrieved_at` | integer or null | no | Feed rows: Unix ms of the worker's last successful read of the schedule. Null for manual rows. | | `verified_on` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | no | Manual rows: the day a person checked the date against the publisher. Null for feed rows. | ## candles {#candles} **Candle row (finance.market.candles_1m | _1h | _1d)**. [`candles.json`](https://docs.aggre.org/schemas/candles.json) | Field | Type | Required | Description | |---|---|---|---| | `instrument_id` | string, pattern `^[A-Z0-9]+:(SPOT\|PERP\|FUTURES):\S+$` | yes | | | `venue` | string, pattern `^[A-Z0-9]+$` | yes | | | `product` | `SPOT` \| `PERP` \| `FUTURES` | yes | | | `symbol` | string | yes | Normalised symbol, FirstFa style: native without separators, uppercase. | | `ts` | integer | yes | Bar open time, Unix milliseconds UTC. | | `open` | number | yes | | | `high` | number | yes | | | `low` | number | yes | | | `close` | number | yes | | | `volume` | number | yes | Base-asset volume. | | `quote_volume` | number or null | no | | | `version` | integer | yes | Exchange update time in ms; higher version replaces lower (ReplacingMergeTree). | ## equities_tw_daily_close {#equities_tw_daily_close} **EquitiesTwDailyClose**. [`equities_tw_daily_close.json`](https://docs.aggre.org/schemas/equities_tw_daily_close.json) One security's after-hours quote of one trading day. A security that did not trade (no positive close) has no row. Overwritten when the exchange remakes the day's file. | Field | Type | Required | Description | |---|---|---|---| | `security_id` | string, pattern `^(TWSE\|TPEX):[0-9A-Z]{4,6}$` | yes | {MARKET}:{code}, e.g. TWSE:2330, TPEX:6488. | | `trade_date` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The trading day the file names (converted from the ROC date). | | `open` | number or null | yes | NT$ | | `high` | number or null | yes | NT$ | | `low` | number or null | yes | NT$ | | `close` | number | yes | NT$ | | `change` | number or null | yes | NT$ from the day before, signed, as published. | | `volume` | integer or null | yes | Shares traded. | | `value` | integer or null | yes | NT$ traded. | | `trades` | integer or null | yes | Number of transactions. | | `source_id` | string, pattern `^(twse\|tpex)_[a-z0-9_]+$` | yes | The registered upstream file the row was read from (see the sources dataset). The response's meta.attribution carries its credit text. | ## equities_tw_indices {#equities_tw_indices} **EquitiesTwIndexDaily**. [`equities_tw_indices.json`](https://docs.aggre.org/schemas/equities_tw_indices.json) One Taiwan index's close on one trading day (TWSE's MI_INDEX lists every index of the day; TPEx's month file gives the OTC index and its total-return index per day). | Field | Type | Required | Description | |---|---|---|---| | `market` | `TWSE` \| `TPEX` | yes | | | `index_name` | string | yes | As published (Chinese), e.g. 發行量加權股價指數, 櫃買指數. | | `trade_date` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The trading day. | | `close` | number | yes | Index points. | | `change` | number or null | yes | Points, signed; null where the answer gives none (TPEx's month file). | | `source_id` | string, pattern `^(twse\|tpex)_[a-z0-9_]+$` | yes | The registered upstream file the row was read from (see the sources dataset). The response's meta.attribution carries its credit text. | ## equities_tw_institutional_daily {#equities_tw_institutional_daily} **EquitiesTwInstitutionalDaily**. [`equities_tw_institutional_daily.json`](https://docs.aggre.org/schemas/equities_tw_institutional_daily.json) Net shares bought (positive) or sold (negative) by the three institutional investor groups, one OTC (TPEx) security, one trading day. TWSE (listed) securities have no open-licensed dataset and are not covered. | Field | Type | Required | Description | |---|---|---|---| | `security_id` | string, pattern `^TPEX:[0-9A-Z]{4,6}$` | yes | | | `trade_date` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The trading day the file names. | | `foreign_net` | integer or null | yes | Foreign investors, foreign dealers and mainland investors, net shares. | | `trust_net` | integer or null | yes | Securities investment trust companies, net shares. | | `dealer_net` | integer or null | yes | Dealers, net shares. | | `total_net` | integer or null | yes | All three together, net shares, as published. | | `source_id` | string, pattern `^(twse\|tpex)_[a-z0-9_]+$` | yes | The registered upstream file the row was read from (see the sources dataset). The response's meta.attribution carries its credit text. | ## equities_tw_margin_daily {#equities_tw_margin_daily} **EquitiesTwMarginDaily**. [`equities_tw_margin_daily.json`](https://docs.aggre.org/schemas/equities_tw_margin_daily.json) Margin purchase and short sale balances of one OTC (TPEx) security on one trading day, in lots as FirstFa documents it (not re-checked against the file). TWSE's margin file (data.gov.tw 11680) names no day and is excluded. | Field | Type | Required | Description | |---|---|---|---| | `security_id` | string, pattern `^TPEX:[0-9A-Z]{4,6}$` | yes | | | `trade_date` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The trading day the file names. | | `margin_balance` | integer or null | yes | Margin purchase balance, lots. | | `margin_previous` | integer or null | yes | Previous day's margin purchase balance, lots. | | `short_balance` | integer or null | yes | Short sale balance, lots. | | `short_previous` | integer or null | yes | Previous day's short sale balance, lots. | | `source_id` | string, pattern `^(twse\|tpex)_[a-z0-9_]+$` | yes | The registered upstream file the row was read from (see the sources dataset). The response's meta.attribution carries its credit text. | ## equities_tw_monthly_revenue {#equities_tw_monthly_revenue} **EquitiesTwMonthlyRevenue**. [`equities_tw_monthly_revenue.json`](https://docs.aggre.org/schemas/equities_tw_monthly_revenue.json) A company's operating revenue for one month, as it filed it, in thousands of NT$ (unit_multiplier 1000, not converted). A re-read with different figures is the next version; older versions are kept. | Field | Type | Required | Description | |---|---|---|---| | `security_id` | string, pattern `^(TWSE\|TPEX):[0-9A-Z]{4,6}$` | yes | {MARKET}:{code}, e.g. TWSE:2330, TPEX:6488. | | `month` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The revenue month, as its first day. | | `version` | integer, 1– | yes | | | `revenue` | integer or null | yes | Thousand NT$, the month's revenue (營業收入-當月營收). | | `previous_month` | integer or null | yes | Thousand NT$, the month before as the company reports it. | | `year_ago` | integer or null | yes | Thousand NT$, the same month a year before as the company reports it. | | `unit` | `"twd"` | yes | | | `unit_multiplier` | `1000` | yes | | | `table_date` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The table's 出表日期 the version was read from. | | `first_seen_at` | integer | yes | Unix ms when WE first read this version. | | `source_id` | string, pattern `^(twse\|tpex)_[a-z0-9_]+$` | yes | The registered upstream file the row was read from (see the sources dataset). The response's meta.attribution carries its credit text. | ## equities_tw_securities {#equities_tw_securities} **EquitiesTwSecurity**. [`equities_tw_securities.json`](https://docs.aggre.org/schemas/equities_tw_securities.json) A Taiwan listed (TWSE) or OTC (TPEx) security as last seen in the exchanges' after-hours files. The company list contributes industry, share count and English short name; its people and contact fields are never read into this dataset. | Field | Type | Required | Description | |---|---|---|---| | `security_id` | string, pattern `^(TWSE\|TPEX):[0-9A-Z]{4,6}$` | yes | {MARKET}:{code}, e.g. TWSE:2330, TPEX:6488. | | `market` | `TWSE` \| `TPEX` | yes | | | `code` | string, pattern `^[0-9A-Z]{4,6}$` | yes | | | `name` | string | yes | As published (Chinese), from the newest row that carried one. | | `name_en` | string or null | yes | 英文簡稱 from the company list when it is plain printable ASCII; else null. | | `industry_code` | string or null, pattern `^[0-9]{2}$` | yes | The exchange's two-digit industry code; null until the company list was read. | | `industry_name` | string or null | yes | Chinese name of industry_code in this market's table; null when the code is not in it. | | `industry_name_en` | string or null | yes | Our English name for the industry. | | `shares_issued` | integer or null, 1– | yes | 已發行普通股數或TDR原股發行股數; null when absent or not positive. | | `profile_table_date` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The company list's 出表日期 that gave industry and shares; null until read. | | `first_seen_on` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | First trading day or table date any dataset listed it. | | `last_seen_on` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | Newest trading day or table date any dataset listed it. | | `updated_at` | integer | yes | Unix ms of the last write to this row. | ## equities_tw_sources {#equities_tw_sources} **EquitiesTwSource**. [`equities_tw_sources.json`](https://docs.aggre.org/schemas/equities_tw_sources.json) One registered upstream file (a data.gov.tw dataset) with its licence and terms state. terms_read_on is the gate: nothing is read from a source whose terms nobody has read. | Field | Type | Required | Description | |---|---|---|---| | `source_id` | string, pattern `^(twse\|tpex)_[a-z0-9_]+$` | yes | The registered upstream file the row was read from (see the sources dataset). The response's meta.attribution carries its credit text. | | `market` | `TWSE` \| `TPEX` | yes | | | `kind` | `valuation` \| `institutional` \| `margin` \| `close` \| `index` \| `revenue` \| `income` \| `balance` \| `profile` | yes | | | `format` | `ci` \| `basi` \| `bd` \| `fh` \| `ins` \| `mim` \| `null` | yes | Statement format; null for every other kind. | | `data_gov_tw_id` | integer | yes | https://data.gov.tw/dataset/{id} | | `title` | string | yes | As data.gov.tw lists it (Chinese). | | `registered_url` | string, pattern `^https://` | yes | The download data.gov.tw registers for the dataset. | | `licence_path_unconfirmed` | boolean | yes | True when what is read is the exchange's OpenAPI path of the same data and not the registered download. | | `license` | string | yes | Open Government Data License, version 1.0 -- carried over from FirstFa, not re-read. | | `credit_template` | string | yes | The attribution statement with {year}; the API fills the year and returns the result in meta.attribution. | | `terms_url` | string, pattern `^https://` | yes | | | `terms_read_on` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The day a person last read the licence terms for this source; null = nobody has and the worker will not read it. | | `last_read_at` | integer or null | yes | Unix ms of the worker's last successful read. | | `data_date` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | Newest data day or table date the last successful read named. | | `paused_until` | integer or null | yes | Unix ms; a 403/429 pauses the source for 24 h. | | `last_error` | string or null | yes | A short fixed message (never a URL) for the last failed read. | ## equities_tw_statements {#equities_tw_statements} **EquitiesTwStatement**. [`equities_tw_statements.json`](https://docs.aggre.org/schemas/equities_tw_statements.json) One quarterly income statement or balance sheet of a company in its industry format. lines is a closed vocabulary ([the Taiwan equities guide](https://docs.aggre.org/datasets/taiwan-equities.md)): amounts in thousand NT$, eps and book_value_per_share in NT$; the income statement is cumulative for the year to date. Nothing is added up and a blank line is absent. A re-read with different figures is the next version. | Field | Type | Required | Description | |---|---|---|---| | `security_id` | string, pattern `^(TWSE\|TPEX):[0-9A-Z]{4,6}$` | yes | {MARKET}:{code}, e.g. TWSE:2330, TPEX:6488. | | `fiscal_year` | integer, 2000–2100 | yes | Western year (ROC year + 1911). | | `quarter` | integer, 1–4 | yes | | | `statement` | `income` \| `balance` | yes | | | `format` | `ci` \| `basi` \| `bd` \| `fh` \| `ins` \| `mim` | yes | ci general industry, basi banks, bd securities and futures, fh financial holding, ins insurers, mim other industries. | | `version` | integer, 1– | yes | | | `lines` | object | yes | Our key -> number. Keys: revenue, gross_profit, operating_income, net_interest_income, non_interest_income, net_revenue, insurance_service_result, insurance_finance_result, net_income, net_income_parent, eps (income); total_assets, total_liabilities, total_equity, parent_equity, book_value_per_share (balance). | | `unit` | `"twd"` | yes | | | `unit_multiplier` | `1000` | yes | | | `table_date` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The table's 出表日期 the version was read from. | | `first_seen_at` | integer | yes | Unix ms when WE first read this version. | | `source_id` | string, pattern `^(twse\|tpex)_[a-z0-9_]+$` | yes | The registered upstream file the row was read from (see the sources dataset). The response's meta.attribution carries its credit text. | ## equities_tw_valuation_daily {#equities_tw_valuation_daily} **EquitiesTwValuationDaily**. [`equities_tw_valuation_daily.json`](https://docs.aggre.org/schemas/equities_tw_valuation_daily.json) P/E, dividend yield and P/B of one security on one trading day, as the exchange publishes them. A figure the exchange leaves out is null, never zero. | Field | Type | Required | Description | |---|---|---|---| | `security_id` | string, pattern `^(TWSE\|TPEX):[0-9A-Z]{4,6}$` | yes | {MARKET}:{code}, e.g. TWSE:2330, TPEX:6488. | | `trade_date` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The trading day the file names. | | `pe` | number or null | yes | Price-to-earnings ratio; null when the exchange gives none (a loss, for instance). | | `dividend_yield` | number or null | yes | Percent. | | `pb` | number or null | yes | Price-to-book ratio. | | `source_id` | string, pattern `^(twse\|tpex)_[a-z0-9_]+$` | yes | The registered upstream file the row was read from (see the sources dataset). The response's meta.attribution carries its credit text. | ## error {#error} **Error envelope**. [`error.json`](https://docs.aggre.org/schemas/error.json) | Field | Type | Required | Description | |---|---|---|---| | `error` | object | yes | | | `error.code` | `unauthorized` \| `forbidden` \| `ip_not_allowed` \| `not_found` \| `invalid_request` \| `rate_limited` \| `usage_limit_exceeded` \| `store_unavailable` \| `internal` \| `conflict` \| `origin_not_allowed` \| `csrf_required` \| `step_up_required` \| `account_disabled` \| `email_mismatch` \| `provider_read_only` \| `validation_failed` \| `secrets_key_missing` \| `bootstrap_invalid` \| `bootstrap_disabled` \| `credentials_key_missing` \| `taken_down` \| `index_unavailable` \| `retrieval_unavailable` \| `corpus_not_migrated` \| `terms_unread` | yes | Stable machine code. | | `error.message` | string | yes | | | `error.request_id` | string | yes | | ## filings_company {#filings_company} **FilingsCompany**. [`filings_company.json`](https://docs.aggre.org/schemas/filings_company.json) One company known to SEC EDGAR, as the worker last read it. Dataset finance.filings.companies. [the filings guide](https://docs.aggre.org/datasets/filings.md). | Field | Type | Required | Description | |---|---|---|---| | `cik` | string, pattern `^[0-9]{10}$` | yes | Central Index Key, zero-padded to 10 digits. | | `name` | string | yes | dei:EntityRegistrantName of the latest periodic report when there is one, else the EDGAR name. | | `tickers` | array of string | yes | | | `exchanges` | array of string | yes | | | `sic` | integer or null, 100–9999 | yes | | | `sic_description` | string or null | yes | | | `fiscal_year_end` | string or null, pattern `^[0-9]{4}$` | yes | MMDD. | | `state_of_incorporation` | string or null | yes | | | `entity_type` | string or null | yes | | | `share_classes` | array of object | yes | Cover-page shares outstanding, one entry per class. | | `share_classes[].label` | string or null | yes | | | `share_classes[].shares` | integer, 0– | yes | | | `shares_total` | integer or null, 0– | yes | Every class summed. | | `shares_as_of` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | | | `shares_form` | `10-Q` \| `10-K` \| `20-F` \| `40-F` \| `10-Q/A` \| `10-K/A` \| `20-F/A` \| `40-F/A` \| `null` | yes | | | `shares_accession` | string or null, pattern `^[0-9]{10}-[0-9]{2}-[0-9]{6}$` | yes | | | `last_refreshed_at` | integer | yes | Unix ms: when the worker last read this company successfully. | | `credit` | string | yes | Attribution text. Whoever shows the row shows this text; the API does not compose it. | ## filings_congress_trade {#filings_congress_trade} **FilingsCongressTrade**. [`filings_congress_trade.json`](https://docs.aggre.org/schemas/filings_congress_trade.json) One stock trade of a US member of Congress from a Periodic Transaction Report (STOCK Act). Disclosed weeks after the trade; amounts are value ranges, not trade sizes. Dataset finance.filings.congress_trades. [the filings guide](https://docs.aggre.org/datasets/filings.md). | Field | Type | Required | Description | |---|---|---|---| | `trade_id` | string, pattern `^[0-9a-f]{64}$` | yes | Content id ([the filings guide](https://docs.aggre.org/datasets/filings.md)): SHA-256 of the report's own fields, so a re-read of the same report is the same row. | | `source` | `senate_stock_watcher` \| `senate_efd` \| `house_clerk` | yes | Where the row was read from. senate_stock_watcher is a community aggregate, not the Senate. | | `chamber` | `Senate` \| `House` | yes | | | `politician` | string | yes | The member's name as the source gives it. | | `owner` | string or null | yes | Who owns the asset, as filed (typically Self, Spouse, Child, Joint); null when the report gives none. | | `transaction_date` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The day of the transaction. | | `disclosure_date` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The day the report was filed; null when the source gives none. | | `ticker` | string or null, pattern `^[A-Z0-9][A-Z0-9.-]{0,11}$` | yes | Upper-case ticker symbol; null when the report gives none (bonds, funds, private assets). | | `asset_description` | string or null | yes | | | `asset_type` | string or null | yes | The report's asset type text. | | `transaction_type` | `buy` \| `sell` \| `exchange` \| `null` | yes | Null when the report's text is none of the three; type_text keeps the text. | | `type_text` | string or null | yes | The report's own transaction text (Purchase, Sale (Full), Sale (Partial), Exchange). | | `amount_text` | string or null | yes | The amount range exactly as filed. | | `amount_low` | integer or null, 0– | yes | Lower bound in dollars of the range. A range, never a trade size. | | `amount_high` | integer or null, 0– | yes | Upper bound in dollars; null for an open-ended range (Over $50,000,000) or when the text is not a range. | | `comment` | string or null | yes | | | `source_url` | string or null, pattern `^https://` | yes | The report on the publisher's site. | | `source_doc_id` | string or null | yes | The report's id from the last path segment of source_url. | | `first_seen_at` | integer | yes | When this repository first stored the row (Unix ms): our clock, not the publisher's. | | `credit` | string | yes | Attribution of the row's source (filings.source_terms.credit); whoever shows the row shows it. | ## filings_fact {#filings_fact} **FilingsFact**. [`filings_fact.json`](https://docs.aggre.org/schemas/filings_fact.json) One as-filed XBRL fact of a whitelisted concept. A later filing that reports the same period is a new row, never an overwrite. Dataset finance.filings.company_facts. [the filings guide](https://docs.aggre.org/datasets/filings.md). | Field | Type | Required | Description | |---|---|---|---| | `cik` | string, pattern `^[0-9]{10}$` | yes | Central Index Key, zero-padded to 10 digits. | | `taxonomy` | `us-gaap` \| `ifrs-full` \| `dei` | yes | | | `concept` | string, pattern `^[A-Za-z0-9]+$` | yes | | | `unit` | string | yes | | | `period_start` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | | | `period_end` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | | | `value` | string, pattern `^-?[0-9]+(\.[0-9]+)?$` | yes | Decimal string: money and share counts are never floats. | | `fiscal_year` | integer or null | yes | As the FILING states it, not the fact's own period. | | `fiscal_period` | `FY` \| `Q1` \| `Q2` \| `Q3` \| `Q4` \| `null` | yes | | | `form` | string | yes | | | `filed_on` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | | | `accession` | string, pattern `^[0-9]{10}-[0-9]{2}-[0-9]{6}$` | yes | EDGAR accession number. | | `credit` | string | yes | Attribution text. Whoever shows the row shows this text; the API does not compose it. | ## filings_filing {#filings_filing} **FilingsFiling**. [`filings_filing.json`](https://docs.aggre.org/schemas/filings_filing.json) One filing in a company's EDGAR index. Dataset finance.filings.filings. [the filings guide](https://docs.aggre.org/datasets/filings.md). | Field | Type | Required | Description | |---|---|---|---| | `accession` | string, pattern `^[0-9]{10}-[0-9]{2}-[0-9]{6}$` | yes | EDGAR accession number. | | `cik` | string, pattern `^[0-9]{10}$` | yes | Central Index Key, zero-padded to 10 digits. | | `form` | string | yes | | | `filed_on` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | | | `accepted_at` | integer or null | yes | Unix ms, EDGAR acceptance time. | | `report_date` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | | | `items` | array of string, pattern `^[0-9]{1,2}\.[0-9]{2}$` | yes | 8-K item numbers as the index lists them. | | `primary_document` | string or null, pattern `^[A-Za-z0-9._-]{1,200}$` | yes | | | `primary_description` | string or null | yes | | | `is_xbrl` | boolean or null | yes | | | `size` | integer or null, 0– | yes | | | `url` | string or null, pattern `^https://www\.sec\.gov/Archives/edgar/data/` | yes | | | `credit` | string | yes | Attribution text. Whoever shows the row shows this text; the API does not compose it. | ## filings_ftd {#filings_ftd} **FilingsFailToDeliver**. [`filings_ftd.json`](https://docs.aggre.org/schemas/filings_ftd.json) The aggregate net balance of shares that failed to be delivered for a symbol on a settlement date. There is no CUSIP column. Dataset finance.filings.fails_to_deliver. [the filings guide](https://docs.aggre.org/datasets/filings.md). | Field | Type | Required | Description | |---|---|---|---| | `symbol` | string, pattern `^[A-Z0-9.-]{1,15}$` | yes | | | `settlement_date` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | | | `quantity` | integer, 0– | yes | | | `price` | string or null, pattern `^-?[0-9]+(\.[0-9]+)?$` | yes | The SEC's previous-day closing price as a decimal string; null when the file gives none. | | `description` | string or null | yes | | | `file` | string, pattern `^cnsfails[0-9]{6}[ab]\.zip$` | yes | | | `credit` | string | yes | Attribution text. Whoever shows the row shows this text; the API does not compose it. | ## filings_fundamental {#filings_fundamental} **FilingsFundamental**. [`filings_fundamental.json`](https://docs.aggre.org/schemas/filings_fundamental.json) One fiscal period of a company's standard metrics, computed from the stored facts by the normalizer. Dataset finance.filings.fundamentals. [the filings guide](https://docs.aggre.org/datasets/filings.md). | Field | Type | Required | Description | |---|---|---|---| | `cik` | string, pattern `^[0-9]{10}$` | yes | Central Index Key, zero-padded to 10 digits. | | `fiscal_year` | integer | yes | | | `fiscal_period` | `Q1` \| `Q2` \| `Q3` \| `Q4` \| `FY` | yes | | | `period_start` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | | | `period_end` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | | | `currency` | string or null, pattern `^[A-Z]{3}$` | yes | | | `metrics` | object | yes | revenue, net_income, eps_diluted, operating_cash_flow, total_assets, total_liabilities and the extras of section 6.3 where present; a metric the filings do not give is null. | | `normalizer` | integer, 1– | yes | | | `credit` | string | yes | Attribution text. Whoever shows the row shows this text; the API does not compose it. | ## filings_holding_13f {#filings_holding_13f} **FilingsHolding13F**. [`filings_holding_13f.json`](https://docs.aggre.org/schemas/filings_holding_13f.json) One institution's holding of a covered issuer in one quarter, summed per filing and matched by the issuer's name (no CUSIP). Dataset finance.filings.holdings_13f. [the filings guide](https://docs.aggre.org/datasets/filings.md). | Field | Type | Required | Description | |---|---|---|---| | `period` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | | | `issuer_cik` | string, pattern `^[0-9]{10}$` | yes | Central Index Key, zero-padded to 10 digits. | | `ticker` | string | yes | | | `accession` | string, pattern `^[0-9]{10}-[0-9]{2}-[0-9]{6}$` | yes | EDGAR accession number. | | `manager_cik` | string or null, pattern `^[0-9]{10}$` | yes | | | `manager_name` | string | yes | | | `shares` | integer, 0– | yes | | | `value_usd` | integer, 0– | yes | | | `data_set` | string | yes | | | `consistent` | boolean | yes | False when the reported price is more than 5x from the quarter's median for the stock; the row is flagged, not repaired. | | `match_basis` | `issuer_name` | yes | | | `credit` | string | yes | Attribution text. Whoever shows the row shows this text; the API does not compose it. | ## filings_insider_transaction {#filings_insider_transaction} **FilingsInsiderTransaction**. [`filings_insider_transaction.json`](https://docs.aggre.org/schemas/filings_insider_transaction.json) One transaction line of a Form 4 or 4/A, with its filing. Names of people are served as filed. Dataset finance.filings.insider_transactions. [the filings guide](https://docs.aggre.org/datasets/filings.md). | Field | Type | Required | Description | |---|---|---|---| | `issuer_cik` | string, pattern `^[0-9]{10}$` | yes | Central Index Key, zero-padded to 10 digits. | | `accession` | string, pattern `^[0-9]{10}-[0-9]{2}-[0-9]{6}$` | yes | EDGAR accession number. | | `form` | `4` \| `4/A` | yes | | | `filed_on` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | | | `owners` | array of object | yes | | | `owners[].cik` | string or null, pattern `^[0-9]{10}$` | yes | | | `owners[].name` | string | yes | | | `owners[].is_director` | boolean or null | yes | | | `owners[].is_officer` | boolean or null | yes | | | `owners[].is_ten_percent_owner` | boolean or null | yes | | | `owners[].is_other` | boolean or null | yes | | | `owners[].officer_title` | string or null | yes | | | `rule_10b5_1` | boolean or null | yes | | | `seq` | integer, 0– | yes | | | `derivative` | boolean | yes | | | `security_title` | string | yes | | | `transaction_date` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | | | `code` | string, pattern `^[A-Z]$` | yes | | | `shares` | number or null | yes | | | `price` | string or null, pattern `^-?[0-9]+(\.[0-9]+)?$` | yes | USD per share as a decimal string; null when the filing gives none. | | `acquired_disposed` | `A` \| `D` \| `null` | yes | | | `owned_after` | number or null | yes | | | `ownership` | `D` \| `I` \| `null` | yes | | | `credit` | string | yes | Attribution text. Whoever shows the row shows this text; the API does not compose it. | ## filings_news_8k {#filings_news_8k} **FilingsNews8K**. [`filings_news_8k.json`](https://docs.aggre.org/schemas/filings_news_8k.json) One current report (8-K, 8-K/A) with its items and Exhibit 99 file names. No filing text is stored. Dataset finance.filings.news_8k. [the filings guide](https://docs.aggre.org/datasets/filings.md). | Field | Type | Required | Description | |---|---|---|---| | `accession` | string, pattern `^[0-9]{10}-[0-9]{2}-[0-9]{6}$` | yes | EDGAR accession number. | | `cik` | string, pattern `^[0-9]{10}$` | yes | Central Index Key, zero-padded to 10 digits. | | `form` | `8-K` \| `8-K/A` | yes | | | `filed_on` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | | | `accepted_at` | integer or null | yes | | | `items` | array of string, pattern `^[0-9]{1,2}\.[0-9]{2}$` | yes | | | `exhibits` | array of object | yes | | | `exhibits[].type` | string, pattern `^EX-99(\.[0-9]{1,2})?$` | yes | | | `exhibits[].document` | string, pattern `^[A-Za-z0-9._-]{1,200}$` | yes | | | `exhibits[].description` | string or null | yes | | | `exhibits_complete` | boolean | yes | | | `url` | string or null, pattern `^https://www\.sec\.gov/Archives/edgar/data/` | yes | | | `credit` | string | yes | Attribution text. Whoever shows the row shows this text; the API does not compose it. | ## funding_rates {#funding_rates} **Funding rate row (finance.market.funding_rates)**. [`funding_rates.json`](https://docs.aggre.org/schemas/funding_rates.json) | Field | Type | Required | Description | |---|---|---|---| | `instrument_id` | string, pattern `^[A-Z0-9]+:(PERP\|FUTURES):\S+$` | yes | | | `venue` | string, pattern `^[A-Z0-9]+$` | yes | | | `product` | `PERP` \| `FUTURES` | yes | | | `symbol` | string | yes | Normalised symbol: native without separators, uppercase. | | `ts` | integer | yes | Settlement time as the venue reports it, Unix milliseconds UTC. Not grid-aligned (Hyperliquid's drifts by milliseconds around the hour). | | `rate` | number | yes | That period's funding rate as a fraction (0.0001 is 0.01%), as the venue reports it: not annualised, not normalised to a common period. The period differs by venue and instrument (8 h on OKX and Bitget unless the venue says otherwise; 1 h on Hyperliquid) and the history endpoints do not state it. | | `version` | integer | yes | ReplacingMergeTree version; equal to ts (a settled rate does not change). | ## health_ema_medicine {#health_ema_medicine} **HealthEmaMedicine**. [`health_ema_medicine.json`](https://docs.aggre.org/schemas/health_ema_medicine.json) One medicine of the EMA Medicines report. Served by GET /v1/health/drugs/ema_medicines[/{product_number}]. Contract: [the health guide](https://docs.aggre.org/datasets/health.md). The list omits therapeutic_indication and raw unless include=text. | Field | Type | Required | Description | |---|---|---|---| | `dataset_id` | `"health.drugs.ema_medicines"` | yes | | | `product_number` | string | yes | EMA product number as published; opaque. | | `name` | string | yes | | | `category` | string or null | yes | | | `status` | string or null | yes | | | `opinion_status` | string or null | yes | | | `inn_common_name` | string or null | yes | | | `active_substance` | string or null | yes | | | `therapeutic_area` | string or null | yes | | | `atc_code` | string or null | yes | | | `atcvet_code` | string or null | yes | | | `authorisation_holder` | string or null | yes | | | `medicine_url` | string or null | yes | | | `therapeutic_indication` | string or null | no | Omitted from the list unless include=text. | | `accelerated_assessment` | boolean or null | yes | Tri-state: null means the report left the cell blank (or wrote something other than Yes or No), which is not the same statement as false. | | `additional_monitoring` | boolean or null | yes | Tri-state: null means the report left the cell blank (or wrote something other than Yes or No), which is not the same statement as false. | | `advanced_therapy` | boolean or null | yes | Tri-state: null means the report left the cell blank (or wrote something other than Yes or No), which is not the same statement as false. | | `biosimilar` | boolean or null | yes | Tri-state: null means the report left the cell blank (or wrote something other than Yes or No), which is not the same statement as false. | | `conditional_approval` | boolean or null | yes | Tri-state: null means the report left the cell blank (or wrote something other than Yes or No), which is not the same statement as false. | | `exceptional_circumstances` | boolean or null | yes | Tri-state: null means the report left the cell blank (or wrote something other than Yes or No), which is not the same statement as false. | | `generic` | boolean or null | yes | Tri-state: null means the report left the cell blank (or wrote something other than Yes or No), which is not the same statement as false. | | `orphan` | boolean or null | yes | Tri-state: null means the report left the cell blank (or wrote something other than Yes or No), which is not the same statement as false. | | `prime` | boolean or null | yes | Tri-state: null means the report left the cell blank (or wrote something other than Yes or No), which is not the same statement as false. | | `decision_date` | string or null, date | yes | | | `authorisation_date` | string or null, date | yes | | | `withdrawal_date` | string or null, date | yes | | | `first_published_date` | string or null, date | yes | | | `last_updated_date` | string or null, date | yes | | | `raw` | object | no | Every header of the report mapped to the trimmed text of this row's cell, including headers we do not know. Omitted from the list unless include=text. | | `in_latest_report` | boolean | yes | false: the newest complete report did not contain this medicine (a row is never deleted). | | `first_seen_at` | string, date-time | yes | | | `fetched_at` | string, date-time | yes | When the row's content was last written. | | `updated_at` | string, date-time | yes | Moves only when a stored column changes; the change cursor. | | `license` | string or null | yes | As recorded by a person after reading EMA's terms; null until then. | | `attribution` | string or null | yes | As recorded by a person after reading EMA's terms; null until then. | ## health_eurostat_cause {#health_eurostat_cause} **HealthEurostatCause**. [`health_eurostat_cause.json`](https://docs.aggre.org/schemas/health_eurostat_cause.json) A cause code in the table with its label. Served by GET /v1/health/statistics/eurostat_mortality/causes. | Field | Type | Required | Description | |---|---|---|---| | `dataset_id` | `"health.statistics.eurostat_mortality"` | yes | | | `icd10` | string | yes | | | `label` | string or null | yes | | | `license` | string or null | yes | | | `attribution` | string or null | yes | | ## health_eurostat_mortality {#health_eurostat_mortality} **HealthEurostatMortality**. [`health_eurostat_mortality.json`](https://docs.aggre.org/schemas/health_eurostat_mortality.json) One cell of Eurostat's causes-of-death table (hlth_cd_asdr2): year, place and cause. Served by GET /v1/health/statistics/eurostat_mortality[/{year}/{geo}/{icd10}]. Contract: [the health guide](https://docs.aggre.org/datasets/health.md). | Field | Type | Required | Description | |---|---|---|---| | `dataset_id` | `"health.statistics.eurostat_mortality"` | yes | | | `year` | integer, 1900–2100 | yes | | | `geo` | string | yes | Eurostat code as published (DE, DE21, EU27_2020, …). | | `geo_name` | string or null | yes | Label as published. | | `geo_kind` | `country` \| `nuts2` \| `aggregate` \| `other` | yes | Derived by Aggre from the shape of the geo code, not taken from Eurostat. | | `icd10` | string | yes | Cause code as published (C33_C34, A-R_V-Y, …). | | `icd10_label` | string or null | yes | | | `sex` | `"T"` | yes | | | `age` | `"TOTAL"` | yes | | | `unit` | `"RT"` | yes | Rate per 100 000 (age-standardised), as Eurostat's RT. | | `value` | number or null | yes | Null for a cell that carries only a status flag. | | `status` | string or null | yes | Eurostat's flag, as published; never interpreted here. | | `in_latest_read` | boolean | yes | false: the last complete read of this year did not contain the cell (kept, never deleted). | | `first_seen_at` | string, date-time | yes | | | `fetched_at` | string, date-time | yes | | | `updated_at` | string, date-time | yes | | | `license` | string or null | yes | | | `attribution` | string or null | yes | | ## health_eurostat_place {#health_eurostat_place} **HealthEurostatPlace**. [`health_eurostat_place.json`](https://docs.aggre.org/schemas/health_eurostat_place.json) A place code in the table with its label and our derived kind. Served by GET /v1/health/statistics/eurostat_mortality/places. | Field | Type | Required | Description | |---|---|---|---| | `dataset_id` | `"health.statistics.eurostat_mortality"` | yes | | | `geo` | string | yes | | | `geo_kind` | `country` \| `nuts2` \| `aggregate` \| `other` | yes | | | `name` | string or null | yes | | | `license` | string or null | yes | | | `attribution` | string or null | yes | | ## health_fda_record {#health_fda_record} **HealthFdaRecord**. [`health_fda_record.json`](https://docs.aggre.org/schemas/health_fda_record.json) One openFDA record, stored as the publisher exported it. Served by GET /v1/health/{drugs|devices}/fda_*[/{key}]. Contract: [the health guide](https://docs.aggre.org/datasets/health.md). | Field | Type | Required | Description | |---|---|---|---| | `dataset_id` | string, pattern `^health\.(drugs\|devices)\.fda_[a-z0-9_]+$` | yes | | | `endpoint` | string, pattern `^[a-z]+/[a-z0-9]+$` | yes | The openFDA endpoint as the manifest spells it, e.g. drug/ndc, device/pma. | | `key` | string | yes | The natural key (a composite key's parts joined by '/', a trailing part may be empty: 'P140004/'), or the sha256 hex of the record when key_kind is content_hash. | | `key_kind` | `natural` \| `content_hash` | yes | content_hash: no verified natural key (or the key field was missing); an edited record is a new row. | | `payload` | object | yes | The record exactly as published. Nothing renamed or flattened. | | `content_hash` | string, pattern `^[0-9a-f]{64}$` | yes | | | `export_date` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | export_date of the partition this row was last seen in. | | `in_latest_export` | boolean | yes | false when the newest export we have imported for the endpoint is newer than this row's export_date, i.e. the row was not in it. The row is not deleted. true when no export is known. | | `first_seen_at` | string, date-time | yes | | | `fetched_at` | string, date-time | yes | When we last read this record, changed or not. | | `updated_at` | string, date-time | yes | When the record's content last changed (a re-import of identical content does not move it). The order of the list and its change feed. | | `license` | string or null | yes | Copied from the terms once a person has read them; null until then. | | `attribution` | string or null | yes | null until the terms were read. | ## health_fda_summary {#health_fda_summary} **HealthFdaSummary**. [`health_fda_summary.json`](https://docs.aggre.org/schemas/health_fda_summary.json) The text of one FDA 510(k) summary document as the worker extracted it. Served by GET /v1/health/devices/fda_510k_summary[/{k_number}]. Contract: [the health guide](https://docs.aggre.org/datasets/health.md). Only rows whose extraction produced text are served (status is always ok). `content` is omitted from the list unless include=content; the one-summary route always returns it. The worker's error text and attempt counter are never served. | Field | Type | Required | Description | |---|---|---|---| | `dataset_id` | `"health.devices.fda_510k_summary"` | yes | | | `k_number` | string, pattern `^[A-Z]+[0-9]{6}$` | yes | The clearance number, upper-case (K232060, DEN250040). | | `status` | `"ok"` | yes | | | `device_name` | string or null | no | From the 510(k) record, when the worker read it. | | `applicant` | string or null | no | | | `product_code` | string or null | no | | | `decision_date` | string or null, date | no | | | `content` | string | no | The extracted text. Omitted from list rows unless include=content. | | `content_chars` | integer, 1– | yes | | | `content_hash` | string, pattern `^[0-9a-f]{64}$` | yes | sha256 of `content`; changes exactly when the text changes. | | `truncated` | boolean | yes | true when the text hit the 2,000,000-character cap. | | `extractor` | string, pattern `^pdf-text/[0-9]+$` | yes | Which version of the extractor produced `content`. | | `source_url` | string or null, uri | yes | The document the text came from. | | `first_seen_at` | string, date-time | yes | | | `fetched_at` | string, date-time | yes | | | `updated_at` | string, date-time | yes | Moves only when the status or the text changes; the change-feed cursor. | | `license` | string or null | yes | null until a person has read the terms. | | `attribution` | string or null | yes | null until the terms were read. | ## health_nppes_provider {#health_nppes_provider} **HealthNppesProvider**. [`health_nppes_provider.json`](https://docs.aggre.org/schemas/health_nppes_provider.json) One provider of the NPPES NPI Registry as the worker projected it. Served by GET /v1/health/providers/nppes[/{npi}]. Contract: [the health guide](https://docs.aggre.org/datasets/health.md). Records about named individuals: the list answers a selective search only. | Field | Type | Required | Description | |---|---|---|---| | `dataset_id` | `"health.providers.nppes"` | yes | | | `npi` | string, pattern `^[0-9]{10}$` | yes | The National Provider Identifier. | | `entity_type` | string or null | yes | `individual` or `organization` (from the registry's entity type code 1 or 2); null for anything else, and for a deactivation tombstone of an NPI we never saw. | | `organization_name` | string or null | yes | Legal business name; null for an individual. | | `last_name` | string or null | yes | Legal last name, as published (the registry's case); null for an organisation. | | `first_name` | string or null | yes | As published. | | `middle_name` | string or null | yes | As published. | | `name_prefix` | string or null | yes | As published. | | `name_suffix` | string or null | yes | As published. | | `credential` | string or null | yes | As published. | | `practice_address_1` | string or null | yes | The practice location, not the mailing address. | | `practice_address_2` | string or null | yes | The practice location, not the mailing address. | | `practice_city` | string or null | yes | As published. | | `practice_state` | string or null | yes | As published (two-letter code for US locations). | | `practice_postal_code` | string or null | yes | As published. | | `practice_country` | string or null | yes | As published; the registry gives it outside the U.S. | | `sex` | string or null | yes | Code as published. | | `sole_proprietor` | string or null | yes | Code as published. | | `organization_subpart` | string or null | yes | Code as published. | | `primary_taxonomy_code` | string or null | yes | The raw NUCC taxonomy code (e.g. 207Q00000X); not joined to a description table. | | `enumeration_date` | string or null | yes | Text exactly as published; the format is not assumed. | | `last_update_date` | string or null | yes | Text exactly as published. | | `deactivation_date` | string or null | yes | Text exactly as published. A row can carry only this and the reason: the registry's weekly file says 'deactivated' that way, and the worker keeps the name and address already stored. | | `reactivation_date` | string or null | yes | Text exactly as published. | | `deactivation_reason_code` | string or null | yes | Code as published. | | `first_seen_at` | string, date-time | yes | When we first stored the NPI. | | `fetched_at` | string, date-time | yes | The last time the row changed (an identical re-read writes nothing). | | `updated_at` | string, date-time | yes | Moves only when a stored column changes. | | `license` | string or null | yes | As recorded by a person after reading the publisher's terms; null until then. | | `attribution` | string or null | yes | As recorded by a person after reading the publisher's terms; null until then. | ## health_trials_study {#health_trials_study} **HealthTrialsStudy**. [`health_trials_study.json`](https://docs.aggre.org/schemas/health_trials_study.json) One ClinicalTrials.gov study as projected by the worker. Served by GET /v1/health/trials/clinicaltrials_gov[/{nct_id}]. Contract: [the health guide](https://docs.aggre.org/datasets/health.md). The three prose fields are omitted from the list unless include=prose. The worker's content hash is never served. | Field | Type | Required | Description | |---|---|---|---| | `dataset_id` | `"health.trials.clinicaltrials_gov"` | yes | | | `nct_id` | string, pattern `^[A-Za-z0-9_-]+$` | yes | | | `brief_title` | string | yes | | | `official_title` | string or null | no | | | `acronym` | string or null | no | | | `overall_status` | string or null | no | As published (e.g. COMPLETED, RECRUITING); not enumerated by this contract. | | `why_stopped` | string or null | no | | | `study_type` | string or null | no | | | `phases` | array of string | yes | | | `enrollment` | integer or null | no | | | `enrollment_type` | string or null | no | | | `lead_sponsor` | string or null | no | | | `lead_sponsor_class` | string or null | no | | | `conditions` | array of string | yes | | | `keywords` | array of string | yes | | | `mesh_terms` | array of string | yes | | | `interventions` | array of string | yes | 'TYPE: name' labels. | | `primary_outcomes` | array of string | yes | | | `brief_summary` | string or null | no | | | `detailed_description` | string or null | no | | | `eligibility_criteria` | string or null | no | | | `sex` | string or null | no | | | `minimum_age` | string or null | no | | | `maximum_age` | string or null | no | | | `healthy_volunteers` | boolean or null | no | null = not stated. | | `location_countries` | array of string | yes | | | `location_count` | integer, 0– | yes | | | `start_date` | string or null, pattern `^[0-9]{4}-[0-9]{2}(-[0-9]{2})?$` | no | As published; month precision occurs. | | `completion_date` | string or null, pattern `^[0-9]{4}-[0-9]{2}(-[0-9]{2})?$` | no | | | `first_post_date` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | no | | | `last_update_post_date` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | no | | | `has_results` | boolean | yes | | | `source_url` | string, uri | yes | | | `first_seen_at` | string, date-time | yes | | | `fetched_at` | string, date-time | yes | | | `updated_at` | string, date-time | yes | | | `license` | string or null | yes | null until a person has read the terms. | | `attribution` | string or null | yes | null until the terms were read. | ## health_who_indicator {#health_who_indicator} **HealthWhoIndicator**. [`health_who_indicator.json`](https://docs.aggre.org/schemas/health_who_indicator.json) One curated WHO GHO indicator. Served by GET /v1/health/statistics/who_gho/indicators. Contract: [the health guide](https://docs.aggre.org/datasets/health.md). | Field | Type | Required | Description | |---|---|---|---| | `dataset_id` | `"health.statistics.who_gho"` | yes | | | `indicator_id` | string | yes | | | `code` | string | yes | The GHO code. | | `category` | string | yes | | | `ord` | integer | yes | Position in the curated list; a pass reads in this order. | | `paged` | boolean | yes | Read page by page upstream (large indicators). | | `description` | string | yes | Aggre's own words, not WHO's label. | | `enabled` | boolean | yes | | | `last_read_at` | string or null, date-time | yes | End of the last complete read of this indicator. | | `last_read_rows` | integer or null | yes | | | `license` | string or null | yes | | | `attribution` | string or null | yes | | ## health_who_observation {#health_who_observation} **HealthWhoObservation**. [`health_who_observation.json`](https://docs.aggre.org/schemas/health_who_observation.json) One WHO Global Health Observatory record. Served by GET /v1/health/statistics/who_gho. Contract: [the health guide](https://docs.aggre.org/datasets/health.md). Country names are not in these rows (only the place code and the parent region). | Field | Type | Required | Description | |---|---|---|---| | `dataset_id` | `"health.statistics.who_gho"` | yes | | | `indicator_id` | string | yes | Our id of the indicator (the catalogue's `indicator_id`). | | `indicator_code` | string | yes | The GHO code. | | `spatial_dim_type` | string | yes | COUNTRY, GLOBAL, REGION, UNSDGREGION, … as published. | | `spatial_dim` | string | yes | The place code as published (an ISO country code for COUNTRY). | | `year` | integer, 1900–2100 | yes | | | `breakdown` | object | yes | Dim1..3 as {type: value}. | | `breakdown_key` | string | yes | Canonical form of `breakdown`: keys sorted, `type=value` joined by `;`. | | `parent_location` | string or null | yes | | | `parent_location_code` | string or null | yes | | | `value_display` | string or null | yes | WHO's own formatted string. | | `numeric_value` | number or null | yes | | | `low` | number or null | yes | | | `high` | number or null | yes | | | `in_latest_read` | boolean | yes | false: the last complete read of the indicator did not contain this row (kept, never deleted). | | `first_seen_at` | string, date-time | yes | | | `fetched_at` | string, date-time | yes | | | `updated_at` | string, date-time | yes | | | `license` | string or null | yes | | | `attribution` | string or null | yes | | ## instruments {#instruments} **Instrument**. [`instruments.json`](https://docs.aggre.org/schemas/instruments.json) | Field | Type | Required | Description | |---|---|---|---| | `instrument_id` | string | yes | | | `venue` | string | yes | | | `product` | `SPOT` \| `PERP` \| `FUTURES` | yes | | | `symbol` | string | yes | | | `native` | string | yes | | | `base` | string | yes | | | `quote` | string | yes | | | `kind` | string or null | no | | | `tick_size` | string or null | no | Decimal string. | | `display_name` | string or null | no | | | `enabled` | boolean | yes | | ## legal_contract_form {#legal_contract_form} **LegalContractForm**. [`legal_contract_form.json`](https://docs.aggre.org/schemas/legal_contract_form.json) One Taiwan standard-form contract (定型化契約): a model contract (範本) or the terms a contract must and must not contain (應記載及不得記載事項), as the worker read it from the Executive Yuan's lists. Served by GET /v1/legal/[the dataset guide](https://docs.aggre.org/datasets.md) (without versions and attachments) and GET /v1/legal/[the dataset guide](https://docs.aggre.org/datasets.md){form_id} (with them). Contract: [the regulatory guide](https://docs.aggre.org/datasets/legal-regulatory.md). Nothing is served until a person has read the publisher's terms (503 terms_unread). The text of an attachment is machine-extracted and may contain extraction errors; file_url is the authoritative document. | Field | Type | Required | Description | |---|---|---|---| | `form_id` | string, pattern `^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$` | yes | The GUID of the form's detail page on the publisher's site, lower case. | | `dataset_id` | `"legal.contracts.tw_standard_forms"` | yes | | | `kind` | `template` \| `required_terms` | yes | template = 定型化契約範本; required_terms = 定型化契約應記載及不得記載事項. | | `title` | string | yes | As published. | | `issuer` | string or null | yes | The issuing ministry, only when the detail page labelled one; null otherwise. Never inferred. | | `published_on` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The date the detail page states, as a calendar day; null when it states none or it is not a real day. | | `published_on_roc` | string or null | yes | The same date as published, ROC calendar (115-04-29). | | `order_refs` | array of string | yes | Issuing-order numbers (…字第…號) found on the page, as published, sorted. | | `source_url` | string, pattern `^https://` | yes | The form's detail page on the publisher's site. | | `current_version` | integer, 1– | yes | A new version is added when the title or any attached file changes; the old one stays (versions). | | `content_hash` | string, pattern `^[0-9a-f]{64}$` | yes | Hash of the current version's content (kind, title, each file's id and sha256). | | `attachment_count` | integer, 0– | yes | | | `text_chars` | integer, 0– | yes | Characters of extracted text in the current version. | | `first_seen_at` | string, date-time | yes | | | `fetched_at` | string, date-time | yes | | | `updated_at` | string, date-time | yes | | | `removed_on` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The day a complete, accepted read no longer listed the form. null = still listed. | | `license` | string or null | yes | The dataset's licence, copied from its terms. null until a person has read the terms. | | `attribution` | string or null | yes | The attribution text the terms ask for. null until the terms were read. | | `version` | integer, 1– | no | Only on the single-form route: the version whose files are shown (the current one unless `version` was asked for). | | `shown_version` | object | no | Only on the single-form route: the shown version. | | `shown_version.version` | integer, 1– | yes | | | `shown_version.content_hash` | string, pattern `^[0-9a-f]{64}$` | yes | | | `shown_version.title` | string | yes | | | `shown_version.fetched_at` | string, date-time | yes | | | `versions` | array of object | no | Only on the single-form route: every version, oldest first. | | `versions[].version` | integer, 1– | yes | | | `versions[].content_hash` | string, pattern `^[0-9a-f]{64}$` | yes | | | `versions[].title` | string | yes | | | `versions[].fetched_at` | string, date-time | yes | | | `attachments` | array of object | no | Only on the single-form route: the files of the shown version, in the order the page lists them. | | `attachments[].seq` | integer, 0– | yes | | | `attachments[].file_id` | string, pattern `^[0-9A-Fa-f]+$` | yes | The publisher's file id. | | `attachments[].file_url` | string, pattern `^https://` | yes | The file on the publisher's site: the authoritative document. | | `attachments[].media_type` | `pdf` \| `docx` \| `odt` \| `doc` \| `other` | yes | Sniffed from the file's first bytes. doc is the legacy binary Word format: recognised, not read. | | `attachments[].bytes` | integer or null, 0– | yes | null only when the file is absent. | | `attachments[].file_sha256` | string or null, pattern `^[0-9a-f]{64}$` | yes | null only when the file is absent. | | `attachments[].text_status` | `ok` \| `scanned` \| `empty` \| `unsupported` \| `timeout` \| `absent` | yes | ok = text read; scanned = a PDF with no text layer (no OCR); empty = a text layer but under 200 characters, or no paragraphs; unsupported = a format this worker cannot read; timeout = extraction ran out of time; absent = the publisher no longer serves the file. | | `attachments[].text_chars` | integer, 0– | yes | | | `attachments[].text_truncated` | boolean | yes | true when the text hit the 2,000,000-character cap. | | `attachments[].text_sha256` | string or null, pattern `^[0-9a-f]{64}$` | yes | | | `attachments[].extractor` | string or null | yes | The logic that produced the text (pdf-text/1, zip-xml/1); null when there is no text. | | `attachments[].text` | string or null | yes | The extracted text; null when the request said text=false. | ## legal_federal_register_document {#legal_federal_register_document} **LegalFederalRegisterDocument**. [`legal_federal_register_document.json`](https://docs.aggre.org/schemas/legal_federal_register_document.json) One Federal Register document (metadata and abstract only, no full text), as the Office of the Federal Register published it. Served by GET /v1/legal/regulatory/federal_register and GET /v1/legal/regulatory/federal_register/{document_number}. Contract: [the regulatory guide](https://docs.aggre.org/datasets/legal-regulatory.md). | Field | Type | Required | Description | |---|---|---|---| | `dataset_id` | `"legal.regulatory.federal_register"` | yes | | | `document_number` | string | yes | The publisher's document number, e.g. 2024-05678, E9-12345. | | `doc_type` | string or null | yes | As published (Rule, Proposed Rule, Notice, Presidential Document were seen). Not an enum: the publisher may add types. | | `title` | string | yes | | | `abstract` | string or null | yes | The publisher's abstract; null when it gives none (about one document in five). | | `action` | string or null | yes | | | `dates_text` | string or null | yes | The publisher's free-text DATES paragraph (comment and effective dates in words). | | `publication_date` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | | | `effective_on` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | | | `comments_close_on` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The comment deadline; null when the document has none. | | `significant` | boolean or null | yes | Tri-state: null means the source does not say (documents that predate the flag), not 'not significant'. | | `page_length` | integer or null, 0– | yes | | | `start_page` | integer or null, 0– | yes | | | `end_page` | integer or null, 0– | yes | | | `volume` | integer or null, 0– | yes | | | `agencies` | array of object | yes | The publisher's agency objects, as published (name, raw_name, slug, id, parent_id, ...). | | `agency_slugs` | array of string | yes | Each agencies[].slug verbatim; what the agency filter matches. | | `cfr_references` | array of object | yes | The publisher's CFR references, as published (title, part, ...). | | `cfr_labels` | array of string, pattern `^[^ ]+ CFR .+$` | yes | '{title} CFR {part}' for each reference with a title, e.g. '21 CFR 820'; what cfr_title/cfr_part match. | | `docket_ids` | array of string | yes | | | `regulation_id_numbers` | array of string | yes | | | `html_url` | string or null, pattern `^https://` | yes | | | `raw_text_url` | string or null, pattern `^https://` | yes | Plain-text full text; kept so a full-text slice is a join, not a re-crawl. | | `pdf_url` | string or null, pattern `^https://` | yes | | | `ecfr_instruments` | array of string, pattern `^US:ECFR:[0-9]+-.+$` | yes | Derived at read time, never stored: instrument ids of legal.statutes.us_ecfr (US:ECFR:{title}-{part}) for the CFR references of titles 21, 42, 45 whose part is stored. Empty otherwise. | | `content_hash` | string, pattern `^[0-9a-f]{64}$` | yes | | | `first_seen_at` | string, date-time | yes | | | `fetched_at` | string, date-time | yes | | | `license` | string or null | yes | The dataset's licence, copied from its terms. null until a person has read the terms: the API then says 'terms not read' and states nothing. | | `attribution` | string or null | yes | The attribution text the terms ask for. null until the terms were read. | ## legal_fsc_news_item {#legal_fsc_news_item} **LegalFscNewsItem**. [`legal_fsc_news_item.json`](https://docs.aggre.org/schemas/legal_fsc_news_item.json) One item of the five official RSS feeds of Taiwan's Financial Supervisory Commission (金融監督管理委員會): press releases, penalty cases, announcements, draft-regulation notices, law interpretations. Title, link and publication day as the FSC published them; the description (plain text reduced from the RSS description, never HTML) only with include=text. Not the article behind the link. Items that left a feed are kept. Served by GET /v1/legal/regulatory/fsc_news. See [the regulatory guide](https://docs.aggre.org/datasets/legal-regulatory.md). | Field | Type | Required | Description | |---|---|---|---| | `category` | `news` \| `penalty` \| `announcement` \| `draft_law` \| `law_interp` | yes | Which of the five feeds the item came from. | | `category_label` | string | yes | The Chinese name of the feed: 新聞稿, 裁罰案件, 重要公告, 法規草案預告, 最新法令函釋. | | `guid` | string | yes | The item's (a full URL carrying a dataserno), else its . With category it identifies the item. | | `title` | string | yes | As published. | | `link` | string or null, pattern `^https?://` | yes | The FSC's own page for the item, as published; null when the feed gave none or not an http(s) address. | | `published_on` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The calendar day written in , in the offset the publisher wrote; null when absent or unreadable. The time of day is not kept. | | `description` | string or null | no | Only with include=text. Plain text reduced from the RSS description (line breaks at block ends, entities decoded); null when the item had none. Text, not HTML: a consumer that puts it in a page must escape it. | | `content_hash` | string, pattern `^[0-9a-f]{64}$` | yes | | | `first_seen_at` | string, date-time | yes | | | `fetched_at` | string, date-time | yes | The read that last wrote the row. | | `license` | string or null | yes | The dataset's licence, copied from the FSC's terms. null until a person has read the terms: the API then says 'Terms not read' and states nothing. | | `attribution` | string or null | yes | The attribution text the terms ask for. null until the terms were read. | ## legal_regulatory_entry {#legal_regulatory_entry} **LegalRegulatoryEntry**. [`legal_regulatory_entry.json`](https://docs.aggre.org/schemas/legal_regulatory_entry.json) One entry of an official name list (OFAC SDN, UN Security Council consolidated list, HHS-OIG exclusions), exactly as the publisher published it. Served by GET /v1/legal/regulatory/entries (without names and attributes) and GET /v1/legal/regulatory/entry (with them). Name search is exact or prefix on a normalised name and is never a screening verdict: every response says so in meta.message. | Field | Type | Required | Description | |---|---|---|---| | `dataset_id` | `legal.regulatory.ofac_sdn` \| `legal.regulatory.un_sanctions` \| `legal.regulatory.us_exclusions` | yes | | | `entry_id` | string | yes | The publisher's own id (SDN uid, UN reference number). For the HHS-OIG list, which has none, an id the worker built from name, birth date, state and exclusion date (id_derived true). | | `id_derived` | boolean | yes | True when the publisher has no id and entry_id was built by the worker. | | `kind` | `person` \| `entity` \| `vessel` \| `aircraft` \| `other` | yes | | | `primary_name` | string | yes | As published. | | `matched_name` | string or null | yes | The stored name (primary or alias) the q filter matched; null when the request had no q. | | `listed_on` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The day the publisher says the entry was listed; null when it says none. | | `removed_on` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The day a complete, accepted read no longer contained the entry (delisted). null = still listed. Set only by a complete read that was not shrunk. | | `program` | string or null | yes | Sanctions programme or exclusion basis, as published. | | `remarks` | string or null | yes | The publisher's free text, as published. | | `url` | string or null, pattern `^https://` | yes | The publisher's own page for the entry. | | `extra` | object | yes | Publisher fields that have no column, as published. | | `content_hash` | string, pattern `^[0-9a-f]{64}$` | yes | | | `first_seen_at` | string, date-time | yes | | | `fetched_at` | string, date-time | yes | | | `license` | string or null | yes | The list's licence, copied from its terms. null until a person has read the terms: the API then says 'terms not read' and states nothing. | | `attribution` | string or null | yes | The attribution text the terms ask for. null until the terms were read. | | `names` | array of object | no | Only on the single-entry route. Every name, the primary one included as seq 0. | | `names[].seq` | integer, 0– | yes | | | `names[].name` | string | yes | | | `names[].name_type` | `primary` \| `alias` \| `weak_alias` \| `transliteration` | yes | | | `attributes` | array of object | no | Only on the single-entry route. Birth dates, places, nationalities, identifiers, addresses, each as published (a birth date may be only a year, an address only a country). Personal data: served exactly as published. | | `attributes[].seq` | integer, 0– | yes | | | `attributes[].attr_type` | `birth_date` \| `birth_place` \| `nationality` \| `citizenship` \| `identifier` \| `address` \| `npi` \| `other` | yes | | | `attributes[].value` | string | yes | | | `attributes[].country` | string or null | yes | | | `attributes[].note` | string or null | yes | | ## macro_derived_observation {#macro_derived_observation} **MacroDerivedObservation**. [`macro_derived_observation.json`](https://docs.aggre.org/schemas/macro_derived_observation.json) One computed value for one period. A year-over-year value compares the input's newest stored version with the same period one year earlier; a value over rows is computed from the newest version of each issuer's, bank's or company's row. Not versioned and not stored: a revised input revises the value on the next read. Each row repeats its series' unit, multiplier and credit. | Field | Type | Required | Description | |---|---|---|---| | `series_id` | string, pattern `^[a-z0-9_]+\.[a-z0-9_]+$` | yes | | | `period` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The period, as in macro_observation.json: a month is its first day. | | `value` | number | yes | In unit x unit_multiplier. Always finite; a period with nothing to compute from (a year-over-year base absent or zero, no row stating the figure) has no row. | | `unit` | string | yes | percent. | | `unit_multiplier` | integer, 1– | yes | 1. | | `compared_with` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | Year over year: the input's period 12 months earlier, the base of the change; null for a value over rows. | | `credit` | string | yes | The series' attribution text. Whoever shows the value shows this text. | | `rows_used` | integer or null, 1– | yes | A value over rows: how many issuers, banks, companies or counted deals it is computed from, so a jump caused by an issuer entering the file can be told from a real one; null for a year-over-year value. | | `provisional` | boolean or null | yes | twrealprice series only: true for the latest three months of the all-Taiwan series (the newest seasons are still being filed and revised; the figure moves). false for every other month; null for every other kind of series. | ## macro_derived_series {#macro_derived_series} **MacroDerivedSeries**. [`macro_derived_series.json`](https://docs.aggre.org/schemas/macro_derived_series.json) A series Aggre computes on read; nothing is stored and it is not in macro_series.json's catalogue. Four kinds exist today: the year-over-year change of 30 stored series (twtrade, twdgbas), sums and ratios over the rows of the FSC Banking Bureau's issuer and bank files (twfsc), and sums, counts and medians over the companies of the exchange's monthly revenue file (twfsc.revenue*; the medians are computed from the amounts, so they differ slightly from FirstFa's, which takes the median of the printed percentages), and the counted deals and the median price per ping of the Ministry of the Interior's actual-price registry, by month, for Taiwan and six cities (twrealprice.*; monthly over a quarterly dataset, the exact median differs slightly from FirstFa's histogram median). Economy, frequency, source, terms and read state are those of what it is computed from. `credit` is the publisher's credit followed by a sentence saying Aggre computed the figure. A series computed over an entity dataset is listed only while somebody has read the publisher's terms. | Field | Type | Required | Description | |---|---|---|---| | `series_id` | string, pattern `^[a-z0-9_]+\.[a-z0-9_]+$` | yes | The input's series_id followed by _yoy (e.g. twtrade.exports_yoy), or twfsc.. | | `source` | string, pattern `^[a-z0-9_]+$` | yes | The publisher, as the prefix of series_id. | | `economy` | string or null, pattern `^[A-Z]{2}$` | yes | ISO 3166-1 alpha-2 country, or EU for the euro area; null for a world or multi-country aggregate. | | `title` | string | yes | | | `description` | string or null | yes | | | `unit` | string | yes | percent for a change or a ratio; twd, cards or companies for an amount or a count; deals for counted deals; twd_per_ping for the median price per ping. | | `unit_multiplier` | integer, 1– | yes | One stored value is this many units (NT$ million: twd and 1000000). | | `currency` | string or null, pattern `^[A-Z]{3}$` | yes | ISO 4217 when the unit is money, else null. | | `frequency` | `daily` \| `weekly` \| `monthly` \| `quarterly` \| `annual` \| `irregular` | yes | | | `seasonal_adjustment` | `sa` \| `nsa` \| `na` | yes | sa, nsa or na of what it is computed from; nsa for a figure computed over rows. | | `source_url` | string, pattern `^https://` | yes | The publisher's own page for the series. | | `terms_url` | string, pattern `^https://` | yes | The publisher's terms of use or licence page. | | `terms_read_on` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The day a person last read those terms for this series; null = nobody has. | | `credit` | string | yes | The attribution text the publisher's terms ask for, stored with the series and repeated on every observation. Whoever shows a value shows this text. | | `last_read_at` | integer or null | yes | Unix ms of the worker's last successful read of the publisher (also when nothing changed); null = never read. | | `stale_after_secs` | integer or null, 1– | yes | How old last_read_at may get before /observations reports meta.status stale; null = not judged. | | `discontinued_on` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The day the publisher stopped the series; null = still published. | | `kind` | `"computed"` | yes | The value is computed by Aggre, not published by the agency. | | `inputs` | array of string, pattern `^[a-z0-9_]+\.[a-z0-9_]+$` | yes | What it is computed from: stored series ids (macro_series.json), macro.dataset ids (twfsc.cards, twfsc.banks) or equities_tw.monthly_revenue. | | `formula` | string | yes | In words: what is computed from the inputs and when a period has no value. | ## macro_observation {#macro_observation} **MacroObservation**. [`macro_observation.json`](https://docs.aggre.org/schemas/macro_observation.json) One value of an official macro series for one period, as one read of the publisher gave it. A revised value is a new version of the same period: earlier versions are kept and can be asked for, never overwritten. Each row repeats its series' unit, multiplier and credit. | Field | Type | Required | Description | |---|---|---|---| | `series_id` | string, pattern `^[a-z0-9_]+\.[a-z0-9_]+$` | yes | | | `period` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The period the value is for, as a date: a day is itself, a month its first day, a quarter its first day, a year January 1st; a week the day the publisher dates it by. The series' frequency says which. Never the release day (that is published_on). | | `value` | number | yes | As stored: value x unit_multiplier is in unit. Always finite: a value the publisher leaves out ('ND', '-', empty) is absent, never zero. | | `unit` | string | yes | The series' unit. | | `unit_multiplier` | integer, 1– | yes | The series' multiplier: value x unit_multiplier is in unit. | | `version` | integer, 1– | yes | 1 for the first value read for the period; +1 each time a later read returned a different value or revision label. The default view returns the highest version per period. | | `revision` | string or null, pattern `^[a-z0-9_]+$` | yes | The publisher's own label for this vintage (advance, second, third, preliminary, final ...); null when it states none. Never invented. | | `published_on` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The release day the publisher states for this value; null when it states none. | | `first_seen_at` | integer | yes | Unix ms: when Aggre first read this value. as_of= filters on it: what we knew then, not what the publisher knew. | | `credit` | string | yes | The series' attribution text. Whoever shows the value shows this text. | ## macro_series {#macro_series} **MacroSeries**. [`macro_series.json`](https://docs.aggre.org/schemas/macro_series.json) One official macro series (a policy rate, a price index, a GDP table line) as a publisher defines it. The catalogue row carries what a value means: its unit, multiplier, frequency and seasonal adjustment never change once the series has observations. Values live in macro_observation.json. | Field | Type | Required | Description | |---|---|---|---| | `series_id` | string, pattern `^[a-z0-9_]+\.[a-z0-9_]+$` | yes | {source}.{name}, e.g. fed.effr. Stable: a series whose meaning changes gets a new id. | | `source` | string, pattern `^[a-z0-9_]+$` | yes | The publisher, as the prefix of series_id. | | `economy` | string or null, pattern `^[A-Z]{2}$` | yes | ISO 3166-1 alpha-2 country, or EU for the euro area; null for a world or multi-country aggregate. | | `title` | string | yes | | | `description` | string or null | yes | | | `unit` | string | yes | What one stored unit is: percent, index, usd, eur, persons, barrels ... Explicit, never implied by the title. | | `unit_multiplier` | integer, 1– | yes | One stored value is this many units: billions of dollars = unit usd, unit_multiplier 1000000000. value x unit_multiplier is in unit. | | `currency` | string or null, pattern `^[A-Z]{3}$` | yes | ISO 4217 when the unit is money, else null. | | `frequency` | `daily` \| `weekly` \| `monthly` \| `quarterly` \| `annual` \| `irregular` | yes | | | `seasonal_adjustment` | `sa` \| `nsa` \| `na` | yes | sa seasonally adjusted, nsa not adjusted, na not applicable (a policy rate). | | `source_url` | string, pattern `^https://` | yes | The publisher's own page for the series. | | `terms_url` | string, pattern `^https://` | yes | The publisher's terms of use or licence page. | | `terms_read_on` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The day a person last read those terms for this series; null = nobody has. | | `credit` | string | yes | The attribution text the publisher's terms ask for, stored with the series and repeated on every observation. Whoever shows a value shows this text. | | `last_read_at` | integer or null | yes | Unix ms of the worker's last successful read of the publisher (also when nothing changed); null = never read. | | `stale_after_secs` | integer or null, 1– | yes | How old last_read_at may get before /observations reports meta.status stale; null = not judged. | | `discontinued_on` | string or null, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The day the publisher stopped the series; null = still published. | ## mcp_call {#mcp_call} **POST /v1/mcp/call and GET /v1/mcp/tools envelopes ([the judgments notes](https://docs.aggre.org/datasets/legal-statutes.md#judgments-and-retrieval))**. [`mcp_call.json`](https://docs.aggre.org/schemas/mcp_call.json) Frozen legacy envelope. Errors on /v1/mcp/call are the flat legacy `{error: string}`, NOT the structured envelope of error.json. **request** | Field | Type | Required | Description | |---|---|---|---| | `name` | `retrieve` \| `retrieve_batch` \| `search_judgments` \| `get_judgment` \| `lookup_judgment` \| `search_in_judgment` \| `judgment_outline` | yes | The seven judgment-related tools. Other legacy tool names are listed by GET /v1/mcp/tools with available=false and answer 501 until their work package lands; an unknown name is 400 before authentication. | | `arguments` | object | no | The tool's arguments, exactly the legacy input schema (additionalProperties false). | **response** | Field | Type | Required | Description | |---|---|---|---| | `name` | string | yes | | | `result` | object | yes | The same JSON the native route returns as `data` ([the judgments notes](https://docs.aggre.org/datasets/legal-statutes.md#judgments-and-retrieval)), with the same additive fields. | **error** | Field | Type | Required | Description | |---|---|---|---| | `error` | string | yes | | **tools** | Field | Type | Required | Description | |---|---|---|---| | `tools` | array of object | yes | | | `tools[].name` | string | yes | | | `tools[].description` | string | yes | Frozen text (an LLM reads it). Takedown sentences are generated from the active policy. | | `tools[].input_schema` | object | yes | | | `tools[].permission` | `search_read` \| `dataset_read` \| `export_write` | yes | Legacy permission strings (crates/mcp tool_specs); the seven judgment tools are search_read. | | `tools[].available` | boolean | no | Additive. false = listed, not served yet. | ## onchain_protocol_tvl {#onchain_protocol_tvl} **OnchainProtocolTvl**. [`onchain_protocol_tvl.json`](https://docs.aggre.org/schemas/onchain_protocol_tvl.json) One DeFi protocol's total value locked on one UTC day, as the source stated it when we read it. `as_of` is the day WE read the figure, not a date the source states. A second read of the same day replaces that day's row only when a value changed. A figure the source leaves out is null, never zero. | Field | Type | Required | Description | |---|---|---|---| | `slug` | string, pattern `^[a-z0-9][a-z0-9._-]{0,127}$` | yes | The source's own stable identifier of the protocol, e.g. aave-v3. | | `as_of` | string, pattern `^[0-9]{4}-[0-9]{2}-[0-9]{2}$` | yes | The UTC day this row is for: the day Aggre read the figure. | | `source` | string | yes | The source id, today `defillama`. | | `name` | string | yes | The protocol's display name as the source states it. | | `symbol` | string or null | yes | The protocol token's ticker as the source states it; null when it has none (the source writes a dash). | | `category` | string or null | yes | The source's category label, e.g. Lending, Dexs. Free text, not an enum: the source adds categories. | | `chain` | string or null | yes | The source's summary chain label (often Multi-Chain); `chains` is the list. | | `chains` | array of string | yes | Every chain the protocol is deployed on, as the source names them. | | `tvl_usd` | number, 0– | yes | Total value locked in US dollars, a JSON number (IEEE double). Not an integer, not rounded. | | `mcap_usd` | number or null, 0– | yes | The protocol token's market capitalisation in US dollars when the source states one. | | `change_1h` | number or null | yes | Percent change of TVL over one hour, as the source states it. | | `change_1d` | number or null | yes | Percent change of TVL over one day, as the source states it. | | `change_7d` | number or null | yes | Percent change of TVL over seven days, as the source states it. | | `tvl_rank` | integer, 1– | yes | 1 is the largest TVL among the protocols stored for that day (ties by slug). Computed by us, not the source's. | | `url` | string or null | yes | The protocol's own website as the source states it. Informational; never fetched. | | `chain_tvls` | object | yes | Chain (or chain-and-kind) label to TVL in US dollars, the numeric entries only, as the source states them. | | `source_url` | string | yes | The exact endpoint this row was read from. | | `updated_at` | integer, int64 | yes | Unix ms of the last time this row's content was written. An identical re-read writes nothing. | ## open_interest {#open_interest} **Open interest snapshot (finance.market.open_interest)**. [`open_interest.json`](https://docs.aggre.org/schemas/open_interest.json) | Field | Type | Required | Description | |---|---|---|---| | `instrument_id` | string, pattern `^[A-Z0-9]+:(PERP\|FUTURES):\S+$` | yes | | | `venue` | string, pattern `^[A-Z0-9]+$` | yes | | | `product` | `PERP` \| `FUTURES` | yes | | | `symbol` | string | yes | Normalised symbol: native without separators, uppercase. | | `ts` | integer | yes | The venue's own timestamp of the reading when it gives one, else the collector's clock; Unix milliseconds UTC. | | `open_interest` | number | yes | Open interest in the base asset (coins, not contracts). | | `open_interest_usd` | number | no | Open interest in USD, present only where the venue states it; never computed by Aggre. | | `version` | integer | yes | ReplacingMergeTree version; equal to ts. | ## tickers_latest {#tickers_latest} **Ticker**. [`tickers_latest.json`](https://docs.aggre.org/schemas/tickers_latest.json) The latest ticker of one instrument. One row per instrument, overwritten in place; no history is kept. | Field | Type | Required | Description | |---|---|---|---| | `instrument_id` | string | yes | {VENUE}:{PRODUCT}:{native}, e.g. OKX:SPOT:BTC-USDT. | | `venue` | string | yes | | | `product` | `SPOT` \| `PERP` \| `FUTURES` | yes | | | `symbol` | string | yes | | | `ts` | integer | yes | Unix ms of the figures: the venue's own timestamp, or the worker's clock when the venue sends none. | | `price` | number | yes | | | `price_basis` | `last` \| `mark` | yes | last: the last traded price. mark: the venue's mark price, used where the venue publishes no last price in its bulk answer (Hyperliquid). | | `open_24h` | number or null | no | Price at the start of the venue's rolling 24 hours (not a UTC day); null where the venue does not send it. | | `high_24h` | number or null | no | Highest price in the rolling 24 hours; null where the venue does not send it. | | `low_24h` | number or null | no | Lowest price in the rolling 24 hours; null where the venue does not send it. | | `volume_24h` | number or null | no | Base-asset units traded in the rolling 24 hours. | | `quote_volume_24h` | number or null | no | Quote-currency units traded in the rolling 24 hours. | === https://docs.aggre.org/api/data/filings === # Filings and trades (SEC EDGAR, US Congress) > Companies, filings, XBRL facts, fundamentals, insider transactions, fails-to-deliver, 13F holdings, 8-K news and Congress trades. Page: https://docs.aggre.org/api/data/filings · Section: API reference · All pages: https://docs.aggre.org/llms.txt SEC EDGAR datasets and US Congress stock-trade disclosures. See the [filings guide](https://docs.aggre.org/datasets/filings.md). On this page: - [SEC companies on the coverage list](#listFilingsCompanies): `GET /v1/finance/filings/companies` - [A company's filings](#listFilings): `GET /v1/finance/filings/filings` - [As-filed XBRL facts of a company](#listFilingsCompanyFacts): `GET /v1/finance/filings/company_facts` - [Normalized fundamentals per fiscal period](#listFilingsFundamentals): `GET /v1/finance/filings/fundamentals` - [Form 4 insider transactions of an issuer](#listFilingsInsiderTransactions): `GET /v1/finance/filings/insider_transactions` - [SEC fails-to-deliver balances of a symbol](#listFilingsFailsToDeliver): `GET /v1/finance/filings/fails_to_deliver` - [SEC Form 13F holdings of a covered company](#listFilingsHoldings13f): `GET /v1/finance/filings/holdings_13f` - [SEC 8-K current reports of a covered company, with the file names of their press releases](#listFilingsNews8k): `GET /v1/finance/filings/news_8k` - [Stock trades of US members of Congress (Periodic Transaction Reports)](#listFilingsCongressTrades): `GET /v1/finance/filings/congress_trades` ## SEC companies on the coverage list {#listFilingsCompanies} `GET /v1/finance/filings/companies` Ordered by `cik`. [the filings guide](https://docs.aggre.org/datasets/filings.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `cik` | query | no | string, pattern `^[0-9]{1,10}$` | SEC CIK, one to ten digits, with or without leading zeros (returned padded). | | `ticker` | query | no | string | Letters, digits, `.` or `-`, at most 12; case-insensitive. | | `sic` | query | no | integer | Standard Industrial Classification code. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/filings/companies?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`filings_company`](https://docs.aggre.org/api/schemas.md#filings_company). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## A company's filings {#listFilings} `GET /v1/finance/filings/filings` Ordered by `filed_on`, `accession`. [the filings guide](https://docs.aggre.org/datasets/filings.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `cik` | query | yes | string, pattern `^[0-9]{1,10}$` | SEC CIK, one to ten digits, with or without leading zeros (returned padded). | | `form` | query | no | string | Comma list of at most 20 form names, e.g. 10-K,8-K. | | `from` | query | no | string, date | YYYY-MM-DD on `filed_on`, inclusive. | | `to` | query | no | string, date | YYYY-MM-DD on `filed_on`, exclusive. | | `order` | query | no | `asc` \| `desc` (default `desc`) | Sort direction (default newest first). | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/filings/filings?cik=&limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`filings_filing`](https://docs.aggre.org/api/schemas.md#filings_filing). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## As-filed XBRL facts of a company {#listFilingsCompanyFacts} `GET /v1/finance/filings/company_facts` Facts are as filed, never overwritten; `value` is a decimal string. [the filings guide](https://docs.aggre.org/datasets/filings.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `cik` | query | yes | string, pattern `^[0-9]{1,10}$` | SEC CIK, one to ten digits, with or without leading zeros (returned padded). | | `concept` | query | no | string | Comma list of at most 20 concept names, e.g. Revenues,Assets. | | `unit` | query | no | string | | | `period_from` | query | no | string, date | YYYY-MM-DD on the period end, inclusive. | | `period_to` | query | no | string, date | YYYY-MM-DD on the period end, exclusive. | | `fiscal_year` | query | no | integer | The filing's own label. | | `fiscal_period` | query | no | `FY` \| `Q1` \| `Q2` \| `Q3` \| `Q4` | | | `latest` | query | no | boolean, default `true` | `true` (default): the latest-filed value of each period; `false`: every filed value. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/filings/company_facts?cik=&limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`filings_fact`](https://docs.aggre.org/api/schemas.md#filings_fact). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Normalized fundamentals per fiscal period {#listFilingsFundamentals} `GET /v1/finance/filings/fundamentals` Computed by Aggre's normalizer from as-filed facts, not published by the SEC (`meta.message` says how). No cursor. [the filings guide](https://docs.aggre.org/datasets/filings.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `cik` | query | yes | string, pattern `^[0-9]{1,10}$` | SEC CIK, one to ten digits, with or without leading zeros (returned padded). | | `fiscal_period` | query | no | `FY` \| `Q` | `FY` or `Q` (any quarter). | | `limit` | query | no | integer, 1–1000, default `12` | Periods returned, newest first. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/filings/fundamentals?cik=&limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`filings_fundamental`](https://docs.aggre.org/api/schemas.md#filings_fundamental). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Form 4 insider transactions of an issuer {#listFilingsInsiderTransactions} `GET /v1/finance/filings/insider_transactions` `cik` is the ISSUER's. Newest transaction first. `price` is a decimal string, `shares` and `owned_after` are numbers; names of people are served as filed. [the filings guide](https://docs.aggre.org/datasets/filings.md) (and section 6.5 for the caveats). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `cik` | query | yes | string, pattern `^[0-9]{1,10}$` | SEC CIK, one to ten digits, with or without leading zeros (returned padded). | | `from` | query | no | string, date | YYYY-MM-DD on `transaction_date`, inclusive. | | `to` | query | no | string, date | YYYY-MM-DD on `transaction_date`, exclusive. | | `code` | query | no | string, pattern `^[A-Z]$` | One capital letter: the Form 4 transaction code, e.g. P (purchase) or S (sale). | | `amendments` | query | no | `collapse` \| `all` (default `collapse`) | `collapse`: a line a later 4/A of the same filer restates unchanged is shown once; `all`: every line. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/filings/insider_transactions?cik=&limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`filings_insider_transaction`](https://docs.aggre.org/api/schemas.md#filings_insider_transaction). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## SEC fails-to-deliver balances of a symbol {#listFilingsFailsToDeliver} `GET /v1/finance/filings/fails_to_deliver` The aggregate net balance of shares that failed to be delivered, by settlement date; a fail can arise on a long or a short sale and is not evidence of abusive or naked short selling (`meta.message` says so). `quantity` is an integer, `price` the SEC's previous-day close as a decimal string. No CUSIP is stored or served. [the filings guide](https://docs.aggre.org/datasets/filings.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `symbol` | query | yes | string, pattern `^[A-Za-z0-9.-]{1,15}$` | The ticker symbol, upper-cased by the API: 1 to 15 of letters, digits, `.` and `-`. | | `from` | query | no | string, date | YYYY-MM-DD on `settlement_date`, inclusive. | | `to` | query | no | string, date | YYYY-MM-DD on `settlement_date`, exclusive. | | `order` | query | no | `asc` \| `desc` (default `desc`) | Sort direction (default newest first). | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/filings/fails_to_deliver?symbol=&limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`filings_ftd`](https://docs.aggre.org/api/schemas.md#filings_ftd). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## SEC Form 13F holdings of a covered company {#listFilingsHoldings13f} `GET /v1/finance/filings/holdings_13f` One institution's holding of the company in one quarter, from the SEC's Form 13F data sets (originals and combination reports; options and bonds left out; the lines of one filing for one issuer summed). **Matched by the issuer's name** (the CUSIP is neither read nor stored), so a row may include another class of the same issuer and a differently spelled one may be missing: `meta.message` always says so. Newest quarter first, the largest holding first within a quarter. `consistent` is false when the reported price (`value_usd` / `shares`) is more than 5 times away from that quarter's median for the stock; such rows are hidden unless `consistent=all`. Give `ticker` or `issuer_cik`, not both. [the filings guide](https://docs.aggre.org/datasets/filings.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `ticker` | query | no | string, pattern `^[A-Za-z0-9.-]{1,12}$` | A coverage ticker, upper-cased by the API: letters, digits, `.` and `-`, at most 12. Give this or `issuer_cik`. | | `issuer_cik` | query | no | string, pattern `^[0-9]{1,10}$` | The issuer's CIK, with or without leading zeros; returned padded to ten digits. Give this or `ticker`. | | `period` | query | no | string, date | A quarter end, YYYY-MM-DD. | | `consistent` | query | no | `true` \| `all` (default `true`) | `true` (default) hides rows whose price is out of line; `all` shows them too. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/filings/holdings_13f?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`filings_holding_13f`](https://docs.aggre.org/api/schemas.md#filings_holding_13f). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## SEC 8-K current reports of a covered company, with the file names of their press releases {#listFilingsNews8k} `GET /v1/finance/filings/news_8k` The company's 8-K and 8-K/A reports, newest first, with their items and, where the report came with a press release, the Exhibit 99 documents' file names and the company's own short descriptions (an `EX-99.1` description that only repeats the type is `null`). **No text of a release or of any filing is stored or served**: open `url` (the report on EDGAR) or the exhibit's file in the same EDGAR folder. `exhibits_complete` is false while the report may carry a release (items 2.02, 7.01, 8.01) and its EDGAR header page has not been read yet (the worker reads at most 5 per company per day and 200 per hour, and gives up on a page after 5 tries); a report that cannot carry one is complete with no exhibits. Reports filed before the worker's window (90 days by default) are listed but were never asked about. Give `cik` or `ticker`, not both. [the filings guide](https://docs.aggre.org/datasets/filings.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `cik` | query | no | string, pattern `^[0-9]{1,10}$` | The company's CIK, with or without leading zeros; returned padded to ten digits. Give this or `ticker`. | | `ticker` | query | no | string, pattern `^[A-Za-z0-9.-]{1,12}$` | A coverage ticker, upper-cased by the API: letters, digits, `.` and `-`, at most 12. Give this or `cik`. | | `from` | query | no | string, date | First filing day (inclusive), YYYY-MM-DD. | | `to` | query | no | string, date | Last filing day (exclusive), YYYY-MM-DD; must be after `from`. | | `item` | query | no | string, pattern `^[0-9]{1,2}\.[0-9]{2}$` | Only reports that list this 8-K item number, e.g. `2.02` (results of operations), `7.01` (Regulation FD), `8.01` (other events). | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/filings/news_8k?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`filings_news_8k`](https://docs.aggre.org/api/schemas.md#filings_news_8k). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Stock trades of US members of Congress (Periodic Transaction Reports) {#listFilingsCongressTrades} `GET /v1/finance/filings/congress_trades` Stock trades that members of Congress reported under the STOCK Act, newest trade first. **Disclosed weeks after the trade**: `transaction_date` is the trade, `disclosure_date` the day it was reported. **Amounts are the value ranges the report uses** (`amount_low`, `amount_high`, and the text as filed), never the size of a trade; `owner` says whose trade it is (a spouse's or a child's too). Rows with `source` `senate_stock_watcher` are a community aggregate's reading of the Senate's reports, not the Senate's own data. Use of financial disclosure reports is restricted by law and whether that bears on this service has not been reviewed; the dataset is off until a person has read its source's terms, and `meta.message` says so while they are unread. Not a recommendation. `meta.source` is the rows' source when they share one, else `aggre`; `meta.dataset.sources` lists the terms of each source in the page. The API records the dataset asked for, never the query. [the filings guide](https://docs.aggre.org/datasets/filings.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `politician` | query | no | string | Case-insensitive substring of the member's name, 2 to 100 characters; percent, underscore and backslash are literal. | | `ticker` | query | no | string, pattern `^[A-Za-z0-9.-]{1,12}$` | Exact ticker, upper-cased by the API: letters, digits, `.` and `-`, at most 12. | | `chamber` | query | no | `Senate` \| `House` | Only this chamber. | | `type` | query | no | `buy` \| `sell` \| `exchange` | Only this kind of transaction (`transaction_type`). | | `from` | query | no | string, date | First transaction day (inclusive), YYYY-MM-DD. | | `to` | query | no | string, date | Last transaction day (exclusive), YYYY-MM-DD; must be after `from`. | | `disclosed_from` | query | no | string, date | First disclosure day (inclusive), YYYY-MM-DD; rows without a disclosure date never match. | | `disclosed_to` | query | no | string, date | Last disclosure day (exclusive), YYYY-MM-DD; must be after `disclosed_from`. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/filings/congress_trades?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`filings_congress_trade`](https://docs.aggre.org/api/schemas.md#filings_congress_trade). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). === https://docs.aggre.org/api/openapi === # OpenAPI and schema files > Download the machine-readable API description and JSON Schemas. Page: https://docs.aggre.org/api/openapi · Section: API reference · All pages: https://docs.aggre.org/llms.txt Everything in the [reference](https://docs.aggre.org/api/data.md) is generated from files you can download and feed to a client generator, a validator or an agent. ## OpenAPI {#openapi} | File | Describes | Formats | |---|---|---| | Data API | Every read route of `https://api.aggre.org` | [`/openapi/data.yaml`](https://docs.aggre.org/openapi/data.yaml), [`/openapi/data.json`](https://docs.aggre.org/openapi/data.json) | | Accounts API | The console's control-plane routes (platform-staff routes left out) | [`/openapi/accounts.yaml`](https://docs.aggre.org/openapi/accounts.yaml), [`/openapi/accounts.json`](https://docs.aggre.org/openapi/accounts.json) | Both are OpenAPI 3. In the data API file, row schemas are `$ref`s to the JSON Schema files below, as absolute URLs on this site, so a tool resolves them without extra configuration. The files are served with `Access-Control-Allow-Origin: *`. The data API file is kept equal to the service's own router by a contract test: every registered route is in the spec and every operation in the spec is registered, and the query parameters match what each route's parser accepts. ## JSON Schemas {#schemas} One file per row type at `/schemas/{name}.json`, for example [`/schemas/candles.json`](https://docs.aggre.org/schemas/candles.json). They are JSON Schema draft 2020-12. The [schema reference](https://docs.aggre.org/api/schemas.md) lists the fields of each and the file names. The `$id` inside a schema is the schema's canonical identifier and may name `aggre.org`; the copy served here is the same file. ## Using them {#using} ```bash # validate a row against its schema curl -s https://docs.aggre.org/schemas/candles.json -o candles.schema.json # generate a typed client (any OpenAPI 3 generator works) curl -s https://docs.aggre.org/openapi/data.yaml -o aggre-data.openapi.yaml ``` Ignore properties a schema does not list: fields are added over time ([Versioning](https://docs.aggre.org/reference/versioning.md)). === https://docs.aggre.org/api/data/equities-tw === # Taiwan equities > TWSE and TPEx securities, daily closes, valuation, institutional and margin data, revenue, statements and indices. Page: https://docs.aggre.org/api/data/equities-tw · Section: API reference · All pages: https://docs.aggre.org/llms.txt Taiwan listed (TWSE) and OTC (TPEx) after-hours data. See the [Taiwan equities guide](https://docs.aggre.org/datasets/taiwan-equities.md). On this page: - [Taiwan listed and OTC securities](#listEquitiesTwSecurities): `GET /v1/finance/equities_tw/securities` - [Daily close of Taiwan securities](#listEquitiesTwDailyClose): `GET /v1/finance/equities_tw/daily_close` - [Daily valuation ratios of Taiwan securities](#listEquitiesTwValuationDaily): `GET /v1/finance/equities_tw/valuation_daily` - [Institutional trades of TPEx securities](#listEquitiesTwInstitutionalDaily): `GET /v1/finance/equities_tw/institutional_daily` - [Margin balances of TPEx securities](#listEquitiesTwMarginDaily): `GET /v1/finance/equities_tw/margin_daily` - [Monthly revenue of Taiwan companies](#listEquitiesTwMonthlyRevenue): `GET /v1/finance/equities_tw/monthly_revenue` - [Quarterly statements of Taiwan companies](#listEquitiesTwStatements): `GET /v1/finance/equities_tw/statements` - [Index closes of Taiwan exchanges](#listEquitiesTwIndices): `GET /v1/finance/equities_tw/indices` - [Registered upstream files of the Taiwan datasets](#listEquitiesTwSources): `GET /v1/finance/equities_tw/sources` ## Taiwan listed and OTC securities {#listEquitiesTwSecurities} `GET /v1/finance/equities_tw/securities` The catalogue of TWSE and TPEx securities, ordered by `security_id`. `q` matches a code prefix or a name substring (at most 20 characters; `%`, `_` and `\` are literal). Every response carries `meta.attribution` (`[{source_id, credit}]`): whoever shows a row shows its credit. [the Taiwan equities guide](https://docs.aggre.org/datasets/taiwan-equities.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `market` | query | no | `TWSE` \| `TPEX` | Only this exchange. | | `q` | query | no | string | Code prefix or name substring. | | `industry_code` | query | no | string, pattern `^[0-9]{2}$` | Two-digit industry code, e.g. 24. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/equities_tw/securities?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`equities_tw_securities`](https://docs.aggre.org/api/schemas.md#equities_tw_securities). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Daily close of Taiwan securities {#listEquitiesTwDailyClose} `GET /v1/finance/equities_tw/daily_close` Open, high, low, close, volume and value of a trading day. Either `security_id` (one security's history) or `date` (every security of the day), not both. Every response carries `meta.attribution` (`[{source_id, credit}]`): whoever shows a row shows its credit. [the Taiwan equities guide](https://docs.aggre.org/datasets/taiwan-equities.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `security_id` | query | no | string, pattern `^(TWSE\|TPEX):[0-9A-Z]+$` | One security's history, e.g. TWSE:2330. Give this or `date`. | | `date` | query | no | string, date | Every security of this trading day, YYYY-MM-DD. Give this or `security_id`. | | `market` | query | no | `TWSE` \| `TPEX` | Narrows a `date` query to one exchange. | | `from` | query | no | string, date | First trading day (inclusive) of a history. | | `to` | query | no | string, date | Last trading day (exclusive) of a history; must be after `from`. | | `order` | query | no | `asc` \| `desc` | Sort direction (default: newest first for a history, `security_id` order for a day). | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/equities_tw/daily_close?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`equities_tw_daily_close`](https://docs.aggre.org/api/schemas.md#equities_tw_daily_close). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Daily valuation ratios of Taiwan securities {#listEquitiesTwValuationDaily} `GET /v1/finance/equities_tw/valuation_daily` P/E, dividend yield and P/B of a trading day. Either `security_id` (one security's history) or `date` (every security of the day), not both. Every response carries `meta.attribution` (`[{source_id, credit}]`): whoever shows a row shows its credit. [the Taiwan equities guide](https://docs.aggre.org/datasets/taiwan-equities.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `security_id` | query | no | string, pattern `^(TWSE\|TPEX):[0-9A-Z]+$` | One security's history, e.g. TWSE:2330. Give this or `date`. | | `date` | query | no | string, date | Every security of this trading day, YYYY-MM-DD. Give this or `security_id`. | | `market` | query | no | `TWSE` \| `TPEX` | Narrows a `date` query to one exchange. | | `from` | query | no | string, date | First trading day (inclusive) of a history. | | `to` | query | no | string, date | Last trading day (exclusive) of a history; must be after `from`. | | `order` | query | no | `asc` \| `desc` | Sort direction (default: newest first for a history, `security_id` order for a day). | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/equities_tw/valuation_daily?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`equities_tw_valuation_daily`](https://docs.aggre.org/api/schemas.md#equities_tw_valuation_daily). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Institutional trades of TPEx securities {#listEquitiesTwInstitutionalDaily} `GET /v1/finance/equities_tw/institutional_daily` Foreign, investment-trust and dealer net trades of a trading day. **TPEx securities only**: the TWSE file is not read. Either `security_id` (one security's history) or `date` (every security of the day), not both. Every response carries `meta.attribution` (`[{source_id, credit}]`): whoever shows a row shows its credit. [the Taiwan equities guide](https://docs.aggre.org/datasets/taiwan-equities.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `security_id` | query | no | string, pattern `^(TWSE\|TPEX):[0-9A-Z]+$` | One security's history, e.g. TWSE:2330. Give this or `date`. | | `date` | query | no | string, date | Every security of this trading day, YYYY-MM-DD. Give this or `security_id`. | | `market` | query | no | `TWSE` \| `TPEX` | Narrows a `date` query to one exchange. | | `from` | query | no | string, date | First trading day (inclusive) of a history. | | `to` | query | no | string, date | Last trading day (exclusive) of a history; must be after `from`. | | `order` | query | no | `asc` \| `desc` | Sort direction (default: newest first for a history, `security_id` order for a day). | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/equities_tw/institutional_daily?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`equities_tw_institutional_daily`](https://docs.aggre.org/api/schemas.md#equities_tw_institutional_daily). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Margin balances of TPEx securities {#listEquitiesTwMarginDaily} `GET /v1/finance/equities_tw/margin_daily` Margin and short balances of a trading day, in lots as published. **TPEx securities only**: the TWSE file (11680) is not read. Either `security_id` (one security's history) or `date` (every security of the day), not both. Every response carries `meta.attribution` (`[{source_id, credit}]`): whoever shows a row shows its credit. [the Taiwan equities guide](https://docs.aggre.org/datasets/taiwan-equities.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `security_id` | query | no | string, pattern `^(TWSE\|TPEX):[0-9A-Z]+$` | One security's history, e.g. TWSE:2330. Give this or `date`. | | `date` | query | no | string, date | Every security of this trading day, YYYY-MM-DD. Give this or `security_id`. | | `market` | query | no | `TWSE` \| `TPEX` | Narrows a `date` query to one exchange. | | `from` | query | no | string, date | First trading day (inclusive) of a history. | | `to` | query | no | string, date | Last trading day (exclusive) of a history; must be after `from`. | | `order` | query | no | `asc` \| `desc` | Sort direction (default: newest first for a history, `security_id` order for a day). | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/equities_tw/margin_daily?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`equities_tw_margin_daily`](https://docs.aggre.org/api/schemas.md#equities_tw_margin_daily). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Monthly revenue of Taiwan companies {#listEquitiesTwMonthlyRevenue} `GET /v1/finance/equities_tw/monthly_revenue` A company's revenue for one month, in thousand NT$ as published. A revised figure is a new version; `versions=all` and `as_of` serve the history. Every response carries `meta.attribution` (`[{source_id, credit}]`): whoever shows a row shows its credit. [the Taiwan equities guide](https://docs.aggre.org/datasets/taiwan-equities.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `security_id` | query | no | string, pattern `^(TWSE\|TPEX):[0-9A-Z]+$` | One security's history. Give this or `month`. | | `month` | query | no | string, date | Every security of this month, the first day, YYYY-MM-01. Give this or `security_id`. | | `from` | query | no | string, date | First month (inclusive) of a history. | | `to` | query | no | string, date | Last month (exclusive) of a history. | | `versions` | query | no | `latest` \| `all` | `latest` (default) or every stored version. | | `as_of` | query | no | integer, int64 | What Aggre knew at this Unix time in milliseconds. | | `order` | query | no | `asc` \| `desc` | Sort direction (default: newest first for a history, `security_id` order for a day). | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/equities_tw/monthly_revenue?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`equities_tw_monthly_revenue`](https://docs.aggre.org/api/schemas.md#equities_tw_monthly_revenue). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Quarterly statements of Taiwan companies {#listEquitiesTwStatements} `GET /v1/finance/equities_tw/statements` Income statements and balance sheets in the six industry formats, amounts in thousand NT$ as published. A revised figure is a new version. Every response carries `meta.attribution` (`[{source_id, credit}]`): whoever shows a row shows its credit. [the Taiwan equities guide](https://docs.aggre.org/datasets/taiwan-equities.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `security_id` | query | no | string, pattern `^(TWSE\|TPEX):[0-9A-Z]+$` | One security's history. Give this or `fiscal_year` with `quarter`. | | `fiscal_year` | query | no | integer, 1990– | With `quarter`: every security of that quarter. | | `quarter` | query | no | integer, 1–4 | With `fiscal_year`. | | `statement` | query | no | `income` \| `balance` | Only this statement. | | `format` | query | no | `ci` \| `basi` \| `bd` \| `fh` \| `ins` \| `mim` | Only this industry format. | | `from` | query | no | string, date | First period (inclusive) of a history. | | `to` | query | no | string, date | Last period (exclusive) of a history. | | `versions` | query | no | `latest` \| `all` | `latest` (default) or every stored version. | | `as_of` | query | no | integer, int64 | What Aggre knew at this Unix time in milliseconds. | | `order` | query | no | `asc` \| `desc` | Sort direction (default: newest first for a history, `security_id` order for a day). | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/equities_tw/statements?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`equities_tw_statements`](https://docs.aggre.org/api/schemas.md#equities_tw_statements). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Index closes of Taiwan exchanges {#listEquitiesTwIndices} `GET /v1/finance/equities_tw/indices` Close of each exchange index of a trading day. Give `market` or `index_name` (or both). Every response carries `meta.attribution` (`[{source_id, credit}]`): whoever shows a row shows its credit. [the Taiwan equities guide](https://docs.aggre.org/datasets/taiwan-equities.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `market` | query | no | `TWSE` \| `TPEX` | Only this exchange. Give this or `index_name`. | | `index_name` | query | no | string | Exact index name. Give this or `market`. | | `from` | query | no | string, date | First trading day (inclusive). | | `to` | query | no | string, date | Last trading day (exclusive). | | `order` | query | no | `asc` \| `desc` | Sort direction (default: newest first for a history, `security_id` order for a day). | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/equities_tw/indices?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`equities_tw_indices`](https://docs.aggre.org/api/schemas.md#equities_tw_indices). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Registered upstream files of the Taiwan datasets {#listEquitiesTwSources} `GET /v1/finance/equities_tw/sources` The registered files with their licence, the terms state (`terms_read_on`) and when each was last read. Every response carries `meta.attribution` (`[{source_id, credit}]`): whoever shows a row shows its credit. [the Taiwan equities guide](https://docs.aggre.org/datasets/taiwan-equities.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `market` | query | no | `TWSE` \| `TPEX` | Only this exchange. | | `kind` | query | no | `valuation` \| `institutional` \| `margin` \| `close` \| `index` \| `revenue` \| `income` \| `balance` \| `profile` | Only this kind of file. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/finance/equities_tw/sources?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`equities_tw_sources`](https://docs.aggre.org/api/schemas.md#equities_tw_sources). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). === https://docs.aggre.org/api/data/legal === # Legal data > Statutes, sanctions and exclusion lists, the Taiwan FSC news feed and Taiwan standard-form contracts. Page: https://docs.aggre.org/api/data/legal · Section: API reference · All pages: https://docs.aggre.org/llms.txt Statutes ([statutes guide](https://docs.aggre.org/datasets/legal-statutes.md)), government name lists, the FSC news feed and standard-form contracts ([regulatory guide](https://docs.aggre.org/datasets/legal-regulatory.md)). The Taiwan judgments routes are described in the [statutes guide](https://docs.aggre.org/datasets/legal-statutes.md#judgments-and-retrieval). On this page: - [Statutes across the ten statute datasets](#listStatuteInstruments): `GET /v1/legal/statutes/instruments` - [One statute with its provisions](#getStatuteInstrument): `GET /v1/legal/statutes/instruments/{instrument_id}` - [The provisions of one statute, paged](#listStatuteProvisions): `GET /v1/legal/statutes/instruments/{instrument_id}/provisions` - [Entries of a sanctions or exclusion list](#listRegulatoryEntries): `GET /v1/legal/regulatory/entries` - [One entry of a sanctions or exclusion list](#getRegulatoryEntry): `GET /v1/legal/regulatory/entry` - [Taiwan FSC news (five RSS feeds)](#listFscNews): `GET /v1/legal/regulatory/fsc_news` - [Taiwan standard-form contracts (定型化契約), without text](#listContractForms): `GET /v1/legal/contracts/tw_standard_forms` - [One standard form with its versions and the text of its files](#getContractForm): `GET /v1/legal/contracts/tw_standard_forms/{form_id}` ## Statutes across the ten statute datasets {#listStatuteInstruments} `GET /v1/legal/statutes/instruments` Ordered by `instrument_id`; the list has no provisions and no foreword. `meta.restricted` / `attribution` / `licenses` carry the terms the data comes with. [the statutes guide](https://docs.aggre.org/datasets/legal-statutes.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `dataset` | query | no | `legal.statutes.tw_moj` \| `legal.statutes.jp_egov` \| `legal.statutes.uk_legislation` \| `legal.statutes.ca_laws` \| `legal.statutes.eu_eurlex` \| `legal.statutes.us_ecfr` \| `legal.statutes.de_gii` \| `legal.statutes.au_federal` \| `legal.statutes.cn_flk` \| `legal.statutes.sg_sso` | One of the ten statute dataset ids. | | `jurisdiction` | query | no | string, pattern `^[A-Z]{2}$` | Two uppercase letters, e.g. TW, EU. | | `language` | query | no | string | Exact, e.g. zh-Hant, en, ja. | | `kind` | query | no | `act` \| `regulation` \| `order` \| `treaty` \| `other` | | | `status` | query | no | `in_force` \| `repealed` \| `abandoned` \| `withdrawn` | | | `q` | query | no | string | Title contains this text (case-insensitive, 1-200 characters). A catalogue filter, not full-text search. | | `updated_since` | query | no | string | YYYY-MM-DD (00:00 UTC) or RFC 3339; `updated_at >=` this. | | `include_removed` | query | no | boolean, default `false` | `true` also returns instruments the source stopped listing. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–200, default `50` | | **Example** ```bash curl -s "https://api.aggre.org/v1/legal/statutes/instruments?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: `StatuteInstrumentsResponse`. | Field | Type | Required | Description | |---|---|---|---| | `data` | array of `StatuteInstrument` | yes | | | `meta` | `Meta` | yes | Where the data came from and how fresh it is. Routes add a few keys of their own (listed); clients must ignore keys they do not know. | | `next_cursor` | string or null | yes | | **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One statute with its provisions {#getStatuteInstrument} `GET /v1/legal/statutes/instruments/{instrument_id}` At most 5000 provisions; longer ones set `provisions_truncated` and `next_from_seq`, continue with the provisions route. A removed instrument still answers 200 with `removed_on`. Takes no query parameters. [the statutes guide](https://docs.aggre.org/datasets/legal-statutes.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `instrument_id` | path | yes | string | A statute `instrument_id` such as `UK:LEG:ukpga/2020/1` or `TW:MOJ:A0000001:en`. It can contain `/` and `:`; the server accepts them literally or percent-encoded and sees the same id. A path ending `/provisions` is always the provisions route. | **Example** ```bash curl -s "https://api.aggre.org/v1/legal/statutes/instruments/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: `StatuteDetailResponse`. | Field | Type | Required | Description | |---|---|---|---| | `data` | `StatuteDetail` | yes | An instrument with its foreword, provisions (at most 5000 per answer) and attachments. | | `meta` | `Meta` | yes | Where the data came from and how fresh it is. Routes add a few keys of their own (listed); clients must ignore keys they do not know. | | `next_cursor` | null | yes | | **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## The provisions of one statute, paged {#listStatuteProvisions} `GET /v1/legal/statutes/instruments/{instrument_id}/provisions` [the statutes guide](https://docs.aggre.org/datasets/legal-statutes.md). A `from_seq` past the last provision answers 200 with an empty list. **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `instrument_id` | path | yes | string | A statute `instrument_id` such as `UK:LEG:ukpga/2020/1` or `TW:MOJ:A0000001:en`. It can contain `/` and `:`; the server accepts them literally or percent-encoded and sees the same id. A path ending `/provisions` is always the provisions route. | | `version` | query | no | integer, 1– | Read this version of the text (see `versions` on the instrument). Repeat it on the next page. Not with `as_of`. 404 when there is no such version. | | `as_of` | query | no | string | Read the text Aggre held at this date or RFC 3339 time (encode `+` as %2B). Not with `version`. 404 before the history begins. | | `from_seq` | query | no | integer, 0– | Start at this `seq` (default 0). Give this or `cursor`, not both. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `number` | query | no | string | An article number: the raw text as stored (`第 184 條`, `Article 15-1`, matched exactly) or its article key (`184`, `184-1`, `184之1`, `第184條之1`, `Article 184`; leading zeros ignored), which matches every provision whose number has the same key. `184` does not match `184-1`. The returned `number` is the raw text. [the statutes guide](https://docs.aggre.org/datasets/legal-statutes.md). | | `limit` | query | no | integer, 1–1000, default `500` | | **Example** ```bash curl -s "https://api.aggre.org/v1/legal/statutes/instruments//provisions?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: `StatuteProvisionsResponse`. | Field | Type | Required | Description | |---|---|---|---| | `data` | array of `StatuteProvision` | yes | | | `meta` | `Meta` | yes | Where the data came from and how fresh it is. Routes add a few keys of their own (listed); clients must ignore keys they do not know. | | `next_cursor` | string or null | yes | | | `next_from_seq` | integer or null | no | seq of the next page's first provision; set together with next_cursor. | **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Entries of a sanctions or exclusion list {#listRegulatoryEntries} `GET /v1/legal/regulatory/entries` Served as published. [the regulatory guide](https://docs.aggre.org/datasets/legal-regulatory.md); `meta.message` carries the terms status. **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `dataset` | query | yes | `legal.regulatory.ofac_sdn` \| `legal.regulatory.un_sanctions` \| `legal.regulatory.us_exclusions` | The name list. | | `q` | query | no | string | Name search on the normalized name key (letters and digits). | | `match` | query | no | `prefix` \| `exact` (default `prefix`) | Only with `q`. | | `kind` | query | no | `person` \| `entity` \| `vessel` \| `aircraft` \| `other` | | | `listed_from` | query | no | string, date | YYYY-MM-DD on `listed_on`. | | `removed` | query | no | `exclude` \| `include` \| `only` (default `exclude`) | Entries the publisher removed: left out (default), included, or only those. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | | **Example** ```bash curl -s "https://api.aggre.org/v1/legal/regulatory/entries?dataset=legal.regulatory.ofac_sdn&limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`legal_regulatory_entry`](https://docs.aggre.org/api/schemas.md#legal_regulatory_entry). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One entry of a sanctions or exclusion list {#getRegulatoryEntry} `GET /v1/legal/regulatory/entry` An entry the publisher removed is still found: it carries `removed_on`. **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `dataset` | query | yes | `legal.regulatory.ofac_sdn` \| `legal.regulatory.un_sanctions` \| `legal.regulatory.us_exclusions` | The name list. | | `entry_id` | query | yes | string | The entry id as published (1-256 bytes, no control characters). | **Example** ```bash curl -s "https://api.aggre.org/v1/legal/regulatory/entry?dataset=legal.regulatory.ofac_sdn&entry_id=" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`legal_regulatory_entry`](https://docs.aggre.org/api/schemas.md#legal_regulatory_entry). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Taiwan FSC news (five RSS feeds) {#listFscNews} `GET /v1/legal/regulatory/fsc_news` Items of the Financial Supervisory Commission's five official RSS feeds (press releases, penalty cases, announcements, draft-regulation notices, law interpretations), newest first (undated last), then category, then guid. Titles, links and publication days as published; the plain-text `description` only with `include=text` (then `limit` is at most 100). Not the articles behind the links; items that left a feed are kept; no search in V0. `meta.dataset` carries the item count and the per-category counts, `meta.dataDate` the newest publication day, `meta.lastReadAt` our newest successful run; `meta.message` says "Terms not read" while nobody has read the FSC's terms. [the regulatory guide](https://docs.aggre.org/datasets/legal-regulatory.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `category` | query | no | `news` \| `penalty` \| `announcement` \| `draft_law` \| `law_interp` | | | `published_from` | query | no | string, date | YYYY-MM-DD on `published_on`, inclusive; an undated item matches neither bound. | | `published_to` | query | no | string, date | YYYY-MM-DD on `published_on`, inclusive. | | `include` | query | no | `text` | `text` adds the plain-text `description`. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–200, default `50` | At most 100 with `include=text`. | **Example** ```bash curl -s "https://api.aggre.org/v1/legal/regulatory/fsc_news?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`legal_fsc_news_item`](https://docs.aggre.org/api/schemas.md#legal_fsc_news_item). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Taiwan standard-form contracts (定型化契約), without text {#listContractForms} `GET /v1/legal/contracts/tw_standard_forms` Model contracts (範本) and the terms a contract must and must not contain (應記載及不得記載事項), as the worker read them from the Executive Yuan's lists, ordered by `form_id`. No text and no attachments here: the single-form route has them. `q` is a literal, case-insensitive title substring. `issuer` is null on a form whose page named no ministry and matches exactly as stored. A form the publisher stopped listing is left out unless `include_removed=true` (it carries `removed_on`). 503 `terms_unread` until a person has read the publisher's terms. [the regulatory guide](https://docs.aggre.org/datasets/legal-regulatory.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `kind` | query | no | `template` \| `required_terms` | `template` = 範本, `required_terms` = 應記載及不得記載事項. | | `q` | query | no | string | Title contains this text (1-200 characters). | | `issuer` | query | no | string | Exactly the stored issuer (1-200 characters). | | `published_from` | query | no | string, date | YYYY-MM-DD, inclusive, on `published_on`. | | `published_to` | query | no | string, date | YYYY-MM-DD, inclusive. Not before `published_from`. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `include_removed` | query | no | boolean, default `false` | Also forms the publisher stopped listing. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–200, default `50` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/legal/contracts/tw_standard_forms?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`legal_contract_form`](https://docs.aggre.org/api/schemas.md#legal_contract_form). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One standard form with its versions and the text of its files {#getContractForm} `GET /v1/legal/contracts/tw_standard_forms/{form_id}` The form, every version (oldest first) and the files of one version with the text extracted from each. `version` picks an older version (default the current one); `text=false` leaves the text out. The text is machine-extracted and may contain errors, and a scanned file has none (`text_status`): `file_url` is the authoritative document. A removed form is still found (`removed_on`). 404 for an unknown form or version, 400 for an id that is not a GUID, 503 `terms_unread` until a person has read the publisher's terms. **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `form_id` | path | yes | string, pattern `^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$` | The GUID of a standard form as listed by the collection route (36 characters; upper or lower case). | | `version` | query | no | integer, 1– | A version number from `versions` (default the current one). | | `text` | query | no | boolean, default `true` | `false` leaves the attachments' text out (default true). | **Example** ```bash curl -s "https://api.aggre.org/v1/legal/contracts/tw_standard_forms/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`legal_contract_form`](https://docs.aggre.org/api/schemas.md#legal_contract_form). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). === https://docs.aggre.org/api/data/health-openfda === # Health: openFDA > The 19 openFDA datasets (drug labels, NDC, approvals, shortages, recalls, device clearances and more). Page: https://docs.aggre.org/api/data/health-openfda · Section: API reference · All pages: https://docs.aggre.org/llms.txt Each openFDA dataset has the same two routes: a list (`/v1/health/{drugs|devices}/fda_{name}`) and a record (`.../fda_{name}/{key}`). Rows keep the upstream record whole in `payload`. See the [health guide](https://docs.aggre.org/datasets/health.md). On this page: - [FDA 510(k) summary documents (extracted text)](#listFdaSummaries): `GET /v1/health/devices/fda_510k_summary` - [One 510(k) summary, with its text](#getFdaSummary): `GET /v1/health/devices/fda_510k_summary/{k_number}` - [openFDA drug labels (prescribing information)](#listFdaLabel): `GET /v1/health/drugs/fda_label` - [One record of: openFDA drug labels (prescribing information)](#getFdaLabel): `GET /v1/health/drugs/fda_label/{key}` - [openFDA National Drug Code directory](#listFdaNdc): `GET /v1/health/drugs/fda_ndc` - [One record of: openFDA National Drug Code directory](#getFdaNdc): `GET /v1/health/drugs/fda_ndc/{key}` - [openFDA Drugs@FDA approvals](#listFdaDrugsfda): `GET /v1/health/drugs/fda_drugsfda` - [One record of: openFDA Drugs@FDA approvals](#getFdaDrugsfda): `GET /v1/health/drugs/fda_drugsfda/{key}` - [openFDA Orange Book](#listFdaOrangebook): `GET /v1/health/drugs/fda_orangebook` - [One record of: openFDA Orange Book](#getFdaOrangebook): `GET /v1/health/drugs/fda_orangebook/{key}` - [openFDA drug shortages](#listFdaShortages): `GET /v1/health/drugs/fda_shortages` - [One record of: openFDA drug shortages](#getFdaShortages): `GET /v1/health/drugs/fda_shortages/{key}` - [openFDA NDC SPL data elements (NSDE)](#listFdaNsde): `GET /v1/health/drugs/fda_nsde` - [One record of: openFDA NDC SPL data elements (NSDE)](#getFdaNsde): `GET /v1/health/drugs/fda_nsde/{key}` - [openFDA UNII substance identifiers](#listFdaUnii): `GET /v1/health/drugs/fda_unii` - [One record of: openFDA UNII substance identifiers](#getFdaUnii): `GET /v1/health/drugs/fda_unii/{key}` - [openFDA substance data](#listFdaSubstance): `GET /v1/health/drugs/fda_substance` - [One record of: openFDA substance data](#getFdaSubstance): `GET /v1/health/drugs/fda_substance/{key}` - [openFDA historical documents](#listFdaHistoricaldocument): `GET /v1/health/drugs/fda_historicaldocument` - [One record of: openFDA historical documents](#getFdaHistoricaldocument): `GET /v1/health/drugs/fda_historicaldocument/{key}` - [openFDA drug enforcement reports (recalls)](#listFdaEnforcement): `GET /v1/health/drugs/fda_enforcement` - [One record of: openFDA drug enforcement reports (recalls)](#getFdaEnforcement): `GET /v1/health/drugs/fda_enforcement/{key}` - [openFDA complete response letters](#listFdaCrl): `GET /v1/health/drugs/fda_crl` - [One record of: openFDA complete response letters](#getFdaCrl): `GET /v1/health/drugs/fda_crl/{key}` - [openFDA 510(k) clearances](#listFda510k): `GET /v1/health/devices/fda_510k` - [One record of: openFDA 510(k) clearances](#getFda510k): `GET /v1/health/devices/fda_510k/{key}` - [openFDA premarket approvals (PMA)](#listFdaPma): `GET /v1/health/devices/fda_pma` - [One record of: openFDA premarket approvals (PMA)](#getFdaPma): `GET /v1/health/devices/fda_pma/{key}` - [openFDA device classification](#listFdaClassification): `GET /v1/health/devices/fda_classification` - [One record of: openFDA device classification](#getFdaClassification): `GET /v1/health/devices/fda_classification/{key}` - [openFDA unique device identifiers (UDI)](#listFdaUdi): `GET /v1/health/devices/fda_udi` - [One record of: openFDA unique device identifiers (UDI)](#getFdaUdi): `GET /v1/health/devices/fda_udi/{key}` - [openFDA device registration and listing](#listFdaRegistrationlisting): `GET /v1/health/devices/fda_registrationlisting` - [One record of: openFDA device registration and listing](#getFdaRegistrationlisting): `GET /v1/health/devices/fda_registrationlisting/{key}` - [openFDA COVID-19 serology tests](#listFdaCovid19serology): `GET /v1/health/devices/fda_covid19serology` - [One record of: openFDA COVID-19 serology tests](#getFdaCovid19serology): `GET /v1/health/devices/fda_covid19serology/{key}` - [openFDA device recalls](#listFdaRecall): `GET /v1/health/devices/fda_recall` - [One record of: openFDA device recalls](#getFdaRecall): `GET /v1/health/devices/fda_recall/{key}` - [openFDA device enforcement reports](#listFdaDeviceEnforcement): `GET /v1/health/devices/fda_device_enforcement` - [One record of: openFDA device enforcement reports](#getFdaDeviceEnforcement): `GET /v1/health/devices/fda_device_enforcement/{key}` ## FDA 510(k) summary documents (extracted text) {#listFdaSummaries} `GET /v1/health/devices/fda_510k_summary` The text of 510(k) summary documents, one row per clearance, as the worker extracted it from the PDF. Only clearances whose document produced text are listed. Ordered by `(updated_at, k_number)` ascending; `updated_at` moves only when the text changes, so `updated_since` plus the cursor is a change feed. `k_number` matches the start of the number. `content` is left out unless `include=content`, and the page is then capped at 25 rows (a single summary can be two million characters). `meta.status` is `backfilling` while the first fill has clearances left; `meta.run` says how many. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `k_number` | query | no | string, pattern `^[A-Za-z0-9]{1,9}$` | A prefix of the clearance number: 1-9 letters or digits, upper-cased (`K23`, `DEN25`). | | `decision_date_from` | query | no | string, date | YYYY-MM-DD, inclusive, on the FDA decision date. | | `decision_date_to` | query | no | string, date | YYYY-MM-DD, inclusive. Not before `decision_date_from`. | | `product_code` | query | no | string, pattern `^[A-Za-z0-9]{1,10}$` | Exact FDA product code, upper-cased. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `include` | query | no | `content` | `content` adds the extracted text (page cap 25). | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000, or 1-25 with `include=content` (the default then is 25). | **Example** ```bash curl -s "https://api.aggre.org/v1/health/devices/fda_510k_summary?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_summary`](https://docs.aggre.org/api/schemas.md#health_fda_summary). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One 510(k) summary, with its text {#getFdaSummary} `GET /v1/health/devices/fda_510k_summary/{k_number}` The row with its `content`. Takes no query parameters. 404 for a clearance with no extracted text (the document has not been read yet, is not on the publisher's site, or has no text layer): the other states are the worker's bookkeeping and are not served. 400 for a number that is not letters then six digits. 503 `terms_unread` until a person has read the publisher's terms. **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `k_number` | path | yes | string, pattern `^[A-Za-z]+[0-9]{6}$` | A 510(k) clearance number: letters then six digits (`K232060`, `DEN250040`); lower case is accepted. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/devices/fda_510k_summary/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_summary`](https://docs.aggre.org/api/schemas.md#health_fda_summary). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## openFDA drug labels (prescribing information) {#listFdaLabel} `GET /v1/health/drugs/fda_label` Records of the openFDA endpoint `drug/label` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000 (a page can be shorter, see above). | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_label?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One record of: openFDA drug labels (prescribing information) {#getFdaLabel} `GET /v1/health/drugs/fda_label/{key}` One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_label/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## openFDA National Drug Code directory {#listFdaNdc} `GET /v1/health/drugs/fda_ndc` Records of the openFDA endpoint `drug/ndc` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000 (a page can be shorter, see above). | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_ndc?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One record of: openFDA National Drug Code directory {#getFdaNdc} `GET /v1/health/drugs/fda_ndc/{key}` One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_ndc/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## openFDA Drugs@FDA approvals {#listFdaDrugsfda} `GET /v1/health/drugs/fda_drugsfda` Records of the openFDA endpoint `drug/drugsfda` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000 (a page can be shorter, see above). | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_drugsfda?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One record of: openFDA Drugs@FDA approvals {#getFdaDrugsfda} `GET /v1/health/drugs/fda_drugsfda/{key}` One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_drugsfda/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## openFDA Orange Book {#listFdaOrangebook} `GET /v1/health/drugs/fda_orangebook` Records of the openFDA endpoint `drug/orangebook` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000 (a page can be shorter, see above). | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_orangebook?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One record of: openFDA Orange Book {#getFdaOrangebook} `GET /v1/health/drugs/fda_orangebook/{key}` One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_orangebook/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## openFDA drug shortages {#listFdaShortages} `GET /v1/health/drugs/fda_shortages` Records of the openFDA endpoint `drug/shortages` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000 (a page can be shorter, see above). | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_shortages?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One record of: openFDA drug shortages {#getFdaShortages} `GET /v1/health/drugs/fda_shortages/{key}` One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_shortages/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## openFDA NDC SPL data elements (NSDE) {#listFdaNsde} `GET /v1/health/drugs/fda_nsde` Records of the openFDA endpoint `other/nsde` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000 (a page can be shorter, see above). | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_nsde?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One record of: openFDA NDC SPL data elements (NSDE) {#getFdaNsde} `GET /v1/health/drugs/fda_nsde/{key}` One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_nsde/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## openFDA UNII substance identifiers {#listFdaUnii} `GET /v1/health/drugs/fda_unii` Records of the openFDA endpoint `other/unii` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000 (a page can be shorter, see above). | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_unii?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One record of: openFDA UNII substance identifiers {#getFdaUnii} `GET /v1/health/drugs/fda_unii/{key}` One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_unii/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## openFDA substance data {#listFdaSubstance} `GET /v1/health/drugs/fda_substance` Records of the openFDA endpoint `other/substance` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000 (a page can be shorter, see above). | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_substance?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One record of: openFDA substance data {#getFdaSubstance} `GET /v1/health/drugs/fda_substance/{key}` One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_substance/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## openFDA historical documents {#listFdaHistoricaldocument} `GET /v1/health/drugs/fda_historicaldocument` Records of the openFDA endpoint `other/historicaldocument` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000 (a page can be shorter, see above). | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_historicaldocument?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One record of: openFDA historical documents {#getFdaHistoricaldocument} `GET /v1/health/drugs/fda_historicaldocument/{key}` One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_historicaldocument/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## openFDA drug enforcement reports (recalls) {#listFdaEnforcement} `GET /v1/health/drugs/fda_enforcement` Records of the openFDA endpoint `drug/enforcement` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000 (a page can be shorter, see above). | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_enforcement?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One record of: openFDA drug enforcement reports (recalls) {#getFdaEnforcement} `GET /v1/health/drugs/fda_enforcement/{key}` One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_enforcement/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## openFDA complete response letters {#listFdaCrl} `GET /v1/health/drugs/fda_crl` Records of the openFDA endpoint `transparency/crl` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000 (a page can be shorter, see above). | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_crl?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One record of: openFDA complete response letters {#getFdaCrl} `GET /v1/health/drugs/fda_crl/{key}` One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/fda_crl/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## openFDA 510(k) clearances {#listFda510k} `GET /v1/health/devices/fda_510k` Records of the openFDA endpoint `device/510k` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000 (a page can be shorter, see above). | **Example** ```bash curl -s "https://api.aggre.org/v1/health/devices/fda_510k?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One record of: openFDA 510(k) clearances {#getFda510k} `GET /v1/health/devices/fda_510k/{key}` One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/devices/fda_510k/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## openFDA premarket approvals (PMA) {#listFdaPma} `GET /v1/health/devices/fda_pma` Records of the openFDA endpoint `device/pma` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000 (a page can be shorter, see above). | **Example** ```bash curl -s "https://api.aggre.org/v1/health/devices/fda_pma?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One record of: openFDA premarket approvals (PMA) {#getFdaPma} `GET /v1/health/devices/fda_pma/{key}` One record by its `key` exactly as listed. A key with a `/` (a composite one, such as `P140004/S092` or `P140004/`) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/devices/fda_pma/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## openFDA device classification {#listFdaClassification} `GET /v1/health/devices/fda_classification` Records of the openFDA endpoint `device/classification` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000 (a page can be shorter, see above). | **Example** ```bash curl -s "https://api.aggre.org/v1/health/devices/fda_classification?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One record of: openFDA device classification {#getFdaClassification} `GET /v1/health/devices/fda_classification/{key}` One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/devices/fda_classification/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## openFDA unique device identifiers (UDI) {#listFdaUdi} `GET /v1/health/devices/fda_udi` Records of the openFDA endpoint `device/udi` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000 (a page can be shorter, see above). | **Example** ```bash curl -s "https://api.aggre.org/v1/health/devices/fda_udi?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One record of: openFDA unique device identifiers (UDI) {#getFdaUdi} `GET /v1/health/devices/fda_udi/{key}` One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/devices/fda_udi/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## openFDA device registration and listing {#listFdaRegistrationlisting} `GET /v1/health/devices/fda_registrationlisting` Records of the openFDA endpoint `device/registrationlisting` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000 (a page can be shorter, see above). | **Example** ```bash curl -s "https://api.aggre.org/v1/health/devices/fda_registrationlisting?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One record of: openFDA device registration and listing {#getFdaRegistrationlisting} `GET /v1/health/devices/fda_registrationlisting/{key}` One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/devices/fda_registrationlisting/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## openFDA COVID-19 serology tests {#listFdaCovid19serology} `GET /v1/health/devices/fda_covid19serology` Records of the openFDA endpoint `device/covid19serology` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000 (a page can be shorter, see above). | **Example** ```bash curl -s "https://api.aggre.org/v1/health/devices/fda_covid19serology?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One record of: openFDA COVID-19 serology tests {#getFdaCovid19serology} `GET /v1/health/devices/fda_covid19serology/{key}` One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/devices/fda_covid19serology/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## openFDA device recalls {#listFdaRecall} `GET /v1/health/devices/fda_recall` Records of the openFDA endpoint `device/recall` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000 (a page can be shorter, see above). | **Example** ```bash curl -s "https://api.aggre.org/v1/health/devices/fda_recall?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One record of: openFDA device recalls {#getFdaRecall} `GET /v1/health/devices/fda_recall/{key}` One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/devices/fda_recall/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## openFDA device enforcement reports {#listFdaDeviceEnforcement} `GET /v1/health/devices/fda_device_enforcement` Records of the openFDA endpoint `device/enforcement` as the worker stored them, whole, as `payload` (nothing renamed or flattened). Ordered by `(updated_at, key)` ascending; `updated_at` moves only when the record's content changed, so `updated_since` plus the cursor is a change feed. `key_prefix` matches the start of the key. There are no per-field filters. A page is cut to a stored-size budget (4 MiB of payload): it can be shorter than `limit` and still have a `next_cursor`, which is normal. `meta` says which export the rows come from and how many partitions of the endpoint are imported, pending or failed; `meta.status` is `backfilling` while partitions are pending and `degraded` when some are stuck. 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key_prefix` | query | no | string | The key starts with this text (case-sensitive; `%`, `_` and `\` are literal). A composite key is `part1/part2`: `P140004/` is that PMA's original application and all its supplements. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000 (a page can be shorter, see above). | **Example** ```bash curl -s "https://api.aggre.org/v1/health/devices/fda_device_enforcement?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One record of: openFDA device enforcement reports {#getFdaDeviceEnforcement} `GET /v1/health/devices/fda_device_enforcement/{key}` One record by its `key` exactly as listed. A key with a `/` (a composite one) may be sent raw or with `%2F`. Found whether or not the latest export held it (`in_latest_export`). Takes no query parameters. 404 for a record we do not hold (the worker imports the export in stages; `meta.partitions` says how far). 503 `terms_unread` until a person has read the publisher's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `key` | path | yes | string | An openFDA record's `key` exactly as listed (1-1000 characters). A composite key keeps its `/` (`P140004/S092`, or `P140004/` for an original application); send it raw or as `%2F`. For content-hash datasets it is the 64-hex hash. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/devices/fda_device_enforcement/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_fda_record`](https://docs.aggre.org/api/schemas.md#health_fda_record). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). === https://docs.aggre.org/api/data/health-registries === # Health: registries and statistics > EMA medicines, NPPES providers, ClinicalTrials.gov, FDA 510(k) summaries, WHO GHO and Eurostat mortality. Page: https://docs.aggre.org/api/data/health-registries · Section: API reference · All pages: https://docs.aggre.org/llms.txt Registries and statistics from health authorities. See the [health guide](https://docs.aggre.org/datasets/health.md). On this page: - [EMA medicines register](#listEmaMedicines): `GET /v1/health/drugs/ema_medicines` - [One EMA medicine, with its text and source row](#getEmaMedicine): `GET /v1/health/drugs/ema_medicines/{product_number}` - [Search the NPPES NPI Registry](#searchNppesProviders): `GET /v1/health/providers/nppes` - [One NPPES provider by NPI](#getNppesProvider): `GET /v1/health/providers/nppes/{npi}` - [ClinicalTrials.gov studies](#listTrialsStudies): `GET /v1/health/trials/clinicaltrials_gov` - [One ClinicalTrials.gov study, with its prose](#getTrialsStudy): `GET /v1/health/trials/clinicaltrials_gov/{nct_id}` - [WHO Global Health Observatory observations of one indicator](#listWhoObservations): `GET /v1/health/statistics/who_gho` - [The curated WHO GHO indicators](#listWhoIndicators): `GET /v1/health/statistics/who_gho/indicators` - [Eurostat causes of death, cells of one cause](#listEurostatMortality): `GET /v1/health/statistics/eurostat_mortality` - [Cause codes in the Eurostat table](#listEurostatCauses): `GET /v1/health/statistics/eurostat_mortality/causes` - [Place codes in the Eurostat table](#listEurostatPlaces): `GET /v1/health/statistics/eurostat_mortality/places` - [One Eurostat cell](#getEurostatMortality): `GET /v1/health/statistics/eurostat_mortality/{year}/{geo}/{icd10}` ## EMA medicines register {#listEmaMedicines} `GET /v1/health/drugs/ema_medicines` Centrally authorised human and veterinary medicines, one row per EMA product number, withdrawn and refused ones included; a medicine the newest report no longer contains has `in_latest_report: false`. Ordered by `(updated_at, product_number)` ascending, so `updated_since` plus the cursor is a change feed. The list leaves out `therapeutic_indication` and `raw` unless `include=text`. 503 `terms_unread` until a person has read EMA's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `category` | query | no | string | Exact, as published (human or veterinary). | | `status` | query | no | string | Exact, as published (e.g. Authorised, Withdrawn). | | `active_substance` | query | no | string | Exact, as published. | | `atc_code` | query | no | string, pattern `^[A-Za-z0-9]{1,7}$` | Prefix of the ATC code, 1-7 letters or digits (case-insensitive). | | `therapeutic_area` | query | no | string | Exact, as published. | | `accelerated_assessment` | query | no | boolean | Tri-state flag: `true` or `false` matches only rows where the report said Yes or No; blank cells match neither. | | `additional_monitoring` | query | no | boolean | Tri-state flag: `true` or `false` matches only rows where the report said Yes or No; blank cells match neither. | | `advanced_therapy` | query | no | boolean | Tri-state flag: `true` or `false` matches only rows where the report said Yes or No; blank cells match neither. | | `biosimilar` | query | no | boolean | Tri-state flag: `true` or `false` matches only rows where the report said Yes or No; blank cells match neither. | | `conditional_approval` | query | no | boolean | Tri-state flag: `true` or `false` matches only rows where the report said Yes or No; blank cells match neither. | | `exceptional_circumstances` | query | no | boolean | Tri-state flag: `true` or `false` matches only rows where the report said Yes or No; blank cells match neither. | | `generic` | query | no | boolean | Tri-state flag: `true` or `false` matches only rows where the report said Yes or No; blank cells match neither. | | `orphan` | query | no | boolean | Tri-state flag: `true` or `false` matches only rows where the report said Yes or No; blank cells match neither. | | `prime` | query | no | boolean | Tri-state flag: `true` or `false` matches only rows where the report said Yes or No; blank cells match neither. | | `authorised_since` | query | no | string, date | YYYY-MM-DD on `authorisation_date`. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `include` | query | no | `text` | `text` adds the long fields the list leaves out (smaller page cap). | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000, or 1-200 with `include=text`. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/ema_medicines?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_ema_medicine`](https://docs.aggre.org/api/schemas.md#health_ema_medicine). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One EMA medicine, with its text and source row {#getEmaMedicine} `GET /v1/health/drugs/ema_medicines/{product_number}` Every column, `therapeutic_indication` and `raw` (every cell of the report row) included. A withdrawn medicine is still found. Takes no query parameters. 503 `terms_unread` until a person has read EMA's terms. **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `product_number` | path | yes | string | EMA product number as published (opaque, 1-64 characters). | **Example** ```bash curl -s "https://api.aggre.org/v1/health/drugs/ema_medicines/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_ema_medicine`](https://docs.aggre.org/api/schemas.md#health_ema_medicine). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Search the NPPES NPI Registry {#searchNppesProviders} `GET /v1/health/providers/nppes` Providers of the NPPES NPI Registry, one row per NPI, as the worker projected them (practice location, no mailing address, no phone numbers). These are records about named individuals, so this is a **search, not an enumeration**: give `npi` (up to 20, comma-separated), or `state` together with `last_name`, `organization_name` (a prefix of at least 3 characters) or `taxonomy`; anything less is 400. Ordered by NPI, at most 100 a page (default 25); there is no change feed and no bulk route. Names match case-insensitively, `state` and `taxonomy` exactly. `meta.status` is `not_loaded` until a monthly baseline has been applied and `degraded` while a gap in the weekly files is unrepaired; `meta.load` says what has been applied. 503 `terms_unread` until a person has read CMS's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `npi` | query | no | string | One or more NPIs, comma-separated (at most 20), each exactly 10 digits. | | `last_name` | query | no | string | Legal last name, case-insensitive exact. Needs `state`. | | `first_name` | query | no | string | Legal first name, case-insensitive exact. Narrows `last_name`; not allowed without it. | | `organization_name` | query | no | string | Prefix of the legal business name, case-insensitive, at least 3 characters. Needs `state`. | | `taxonomy` | query | no | string, pattern `^[A-Za-z0-9]{10}$` | The 10-character NUCC taxonomy code of the primary taxonomy (case-insensitive). Needs `state`. | | `state` | query | no | string, pattern `^[A-Za-z]{2}$` | Two-letter practice-location state code (case-insensitive). | | `deactivated` | query | no | boolean | `true`: only NPIs with a deactivation date; `false`: only those without. Narrows a search; it is not one by itself. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–100, default `25` | Rows per page: 1-100. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/providers/nppes?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_nppes_provider`](https://docs.aggre.org/api/schemas.md#health_nppes_provider). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One NPPES provider by NPI {#getNppesProvider} `GET /v1/health/providers/nppes/{npi}` Every stored column. Takes no query parameters. 404 for an NPI we do not hold (`meta.load` says what has been applied). 503 `terms_unread` until a person has read CMS's terms. **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `npi` | path | yes | string, pattern `^[0-9]{10}$` | A National Provider Identifier: exactly 10 digits. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/providers/nppes/" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_nppes_provider`](https://docs.aggre.org/api/schemas.md#health_nppes_provider). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## ClinicalTrials.gov studies {#listTrialsStudies} `GET /v1/health/trials/clinicaltrials_gov` Studies of the ClinicalTrials.gov registry as the worker projected them, one row per NCT id. Ordered by `(updated_at, nct_id)` ascending, so `updated_since` plus the cursor is a change feed. The three prose fields (`brief_summary`, `detailed_description`, `eligibility_criteria`) are left out unless `include=prose`, and the page is then capped at 100. List filters (`phase`, `condition`, `country`) match one element of the study's array exactly as published (case-sensitive). `meta.status` is `backfilling` until the first full read of the registry has completed. 503 `terms_unread` until a person has read the registry's terms. [the health guide](https://docs.aggre.org/datasets/health.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `overall_status` | query | no | string | Exact, as published (e.g. RECRUITING, COMPLETED). | | `study_type` | query | no | string | Exact, as published (e.g. INTERVENTIONAL). | | `phase` | query | no | string | One phase as published (e.g. PHASE2); a study of two phases matches either. | | `sponsor` | query | no | string | Exact `lead_sponsor`, as published. | | `condition` | query | no | string | One element of `conditions`, exactly as published. | | `country` | query | no | string | One element of `location_countries`, exactly as published (e.g. France). | | `has_results` | query | no | boolean | Whether the registry holds results for the study. | | `first_post_since` | query | no | string, date | YYYY-MM-DD on `first_post_date` (inclusive). | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `include` | query | no | `prose` | `prose` adds the three long text fields the list leaves out (page cap 100). | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000, or 1-100 with `include=prose`. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/trials/clinicaltrials_gov?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_trials_study`](https://docs.aggre.org/api/schemas.md#health_trials_study). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One ClinicalTrials.gov study, with its prose {#getTrialsStudy} `GET /v1/health/trials/clinicaltrials_gov/{nct_id}` Every column but the worker's own hash, the prose fields included. Takes no query parameters. 404 for a study we do not hold (the worker reads the registry in stages; `meta.walk` says how far). 503 `terms_unread` until a person has read the registry's terms. **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `nct_id` | path | yes | string, pattern `^[A-Za-z0-9_-]{1,32}$` | ClinicalTrials.gov study id as published (letters, digits, `_` and `-`, at most 32 characters), e.g. `NCT00000102`. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/trials/clinicaltrials_gov/NCT00000102" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_trials_study`](https://docs.aggre.org/api/schemas.md#health_trials_study). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## WHO Global Health Observatory observations of one indicator {#listWhoObservations} `GET /v1/health/statistics/who_gho` Observations of one curated indicator (the whole table is far too large to page as one), ordered by `(spatial_dim, year, breakdown_key)` within one `spatial_dim_type` (default `COUNTRY`; regions and the world are other types). Rows the indicator's last complete read no longer contained are returned with `in_latest_read: false`. `value_display` is WHO's own formatted string. 404 `not_found` for an indicator not in the catalogue; 503 `terms_unread` until a person has read WHO's terms. **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `indicator` | query | yes | string, pattern `^[A-Za-z0-9_.-]{1,64}$` | Our indicator id (`life_expectancy`) or its GHO code (`WHOSIS_000001`); see the catalogue. | | `spatial_dim_type` | query | no | string, pattern `^[A-Za-z0-9_.-]{1,64}$`, default `COUNTRY` | COUNTRY (default), GLOBAL, REGION, UNSDGREGION, … as published. | | `spatial_dim` | query | no | string, pattern `^[A-Za-z0-9_.-]{1,64}$` | One place code as published (an ISO country code for COUNTRY). | | `breakdown` | query | no | string | Dimension filter, `TYPE:value` pairs separated by commas, at most three, e.g. `SEX:SEX_MLE`. A row matches when its `breakdown` contains every pair. | | `year_from` | query | no | integer, 1900–2100 | First year, 1900-2100. | | `year_to` | query | no | integer, 1900–2100 | Last year, 1900-2100. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/statistics/who_gho?indicator=&limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_who_observation`](https://docs.aggre.org/api/schemas.md#health_who_observation). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## The curated WHO GHO indicators {#listWhoIndicators} `GET /v1/health/statistics/who_gho/indicators` The catalogue: id, GHO code, category, Aggre's own description, whether the indicator is read page by page, and when its last complete read ended and how many rows it held. Takes no query parameters. 503 `terms_unread` until a person has read WHO's terms. **Example** ```bash curl -s "https://api.aggre.org/v1/health/statistics/who_gho/indicators" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_who_indicator`](https://docs.aggre.org/api/schemas.md#health_who_indicator). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Eurostat causes of death, cells of one cause {#listEurostatMortality} `GET /v1/health/statistics/eurostat_mortality` Cells of one cause code (`icd10` is required: without it the list would be a dump of ~600k cells), ordered by `(updated_at, year, geo)`, so `updated_since` plus the cursor is a change feed. A cell the last complete read of its year no longer held has `in_latest_read: false`. `value` is null for a status-only cell. `meta.years` carries the dataset's own `updated` text per year read. 503 `terms_unread` until a person has read Eurostat's terms. **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `icd10` | query | yes | string, pattern `^[A-Za-z0-9_-]{1,32}$` | One cause code as published (`C33_C34`, `A-R_V-Y`, …); the causes route lists them. | | `geo` | query | no | string | Exact Eurostat place codes, comma-separated, at most 20 (`DE,DE21,EU27_2020`). | | `geo_kind` | query | no | `country` \| `nuts2` \| `aggregate` \| `other` | Our derived kind of place: country (two letters), nuts2 (two letters plus two characters), aggregate (EU…, EA…, EFTA…) or other. Derived by Aggre from the code's shape, not by Eurostat. | | `year` | query | no | integer, 1900–2100 | One year; cannot be combined with year_from or year_to. | | `year_from` | query | no | integer, 1900–2100 | | | `year_to` | query | no | integer, 1900–2100 | | | `status` | query | no | string, pattern `^[A-Za-z0-9_]{1,32}$` | Eurostat's flag, exactly as published. | | `has_value` | query | no | boolean | `true`: only cells with a value; `false`: only status-only cells. | | `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page: 1-1000. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/statistics/eurostat_mortality?icd10=&limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_eurostat_mortality`](https://docs.aggre.org/api/schemas.md#health_eurostat_mortality). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Cause codes in the Eurostat table {#listEurostatCauses} `GET /v1/health/statistics/eurostat_mortality/causes` The cause codes present in the table with their labels, derived from the table. Takes no query parameters. 503 `terms_unread` until a person has read Eurostat's terms. **Example** ```bash curl -s "https://api.aggre.org/v1/health/statistics/eurostat_mortality/causes" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_eurostat_cause`](https://docs.aggre.org/api/schemas.md#health_eurostat_cause). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## Place codes in the Eurostat table {#listEurostatPlaces} `GET /v1/health/statistics/eurostat_mortality/places` The place codes present in the table with their labels and our derived `geo_kind`. 503 `terms_unread` until a person has read Eurostat's terms. **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `geo_kind` | query | no | `country` \| `nuts2` \| `aggregate` \| `other` | Our derived kind of place: country (two letters), nuts2 (two letters plus two characters), aggregate (EU…, EA…, EFTA…) or other. Derived by Aggre from the code's shape, not by Eurostat. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/statistics/eurostat_mortality/places" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_eurostat_place`](https://docs.aggre.org/api/schemas.md#health_eurostat_place). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). ## One Eurostat cell {#getEurostatMortality} `GET /v1/health/statistics/eurostat_mortality/{year}/{geo}/{icd10}` The cell of one year, place and cause. Takes no query parameters. 503 `terms_unread` until a person has read Eurostat's terms. **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `year` | path | yes | integer, 1900–2100 | | | `geo` | path | yes | string | Eurostat place code. | | `icd10` | path | yes | string | Cause code. | **Example** ```bash curl -s "https://api.aggre.org/v1/health/statistics/eurostat_mortality/1//" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`health_eurostat_mortality`](https://docs.aggre.org/api/schemas.md#health_eurostat_mortality). **Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). === https://docs.aggre.org/api/data/onchain === # On-chain data > Total value locked in DeFi protocols, by protocol and chain. Page: https://docs.aggre.org/api/data/onchain · Section: API reference · All pages: https://docs.aggre.org/llms.txt On-chain datasets. See the [on-chain guide](https://docs.aggre.org/datasets/onchain.md). On this page: - [DeFi protocol total value locked](#listOnchainProtocolTvl): `GET /v1/onchain/defi/protocol_tvl` ## DeFi protocol total value locked {#listOnchainProtocolTvl} `GET /v1/onchain/defi/protocol_tvl` One row per protocol per UTC day (`as_of` is the day Aggre read the figure; history starts the day the worker first ran, nothing is backfilled). Two shapes, chosen by `slug`. **A day** (no `slug`): every protocol of one day ordered by TVL rank (1 is the largest), the newest stored day unless `as_of` names one; `category` (exact, case-sensitive) and `chain` (one element of `chains`, exact) narrow it; `from`, `to` and `order` are 400 here. **A history** (`slug`): that protocol's rows over time, newest first unless `order=asc`; `from` is inclusive and `to` exclusive, both `YYYY-MM-DD`; `as_of`, `category` and `chain` are 400 there. A cursor pins its day. `tvl_usd` is a JSON number (a double), a figure the source leaves out is `null`, never zero. Whoever shows a row shows `meta.dataset.credit`. `meta.status`: `empty` for no rows, `stale` when the answer follows the newest data and our newest successful read is more than 3 days old, otherwise `ok`. 503 `terms_unread` until a person has read the publisher's terms; the route then reads no row. Dataset `onchain.defi.protocol_tvl`, also listed under `finance.market`. [the on-chain guide](https://docs.aggre.org/datasets/onchain.md). **Parameters** | Name | In | Required | Type | Description | |---|---|---|---|---| | `slug` | query | no | string, pattern `^[a-z0-9][a-z0-9._-]{0,127}$` | One protocol's history, as listed in `slug`: lower-case letters, digits, `.`, `_`, `-`. | | `as_of` | query | no | string, date | A day: the UTC day to list, YYYY-MM-DD. Default the newest stored day. Not with `slug`. | | `from` | query | no | string, date | A history: first day (inclusive), YYYY-MM-DD. Needs `slug`. | | `to` | query | no | string, date | A history: last day (exclusive), YYYY-MM-DD, after `from`. Needs `slug`. | | `category` | query | no | string | A day: only this category, exact as the source writes it (1-100 characters). Not with `slug`. | | `chain` | query | no | string | A day: only protocols deployed on this chain, exact as the source writes it (1-100 characters). Not with `slug`. | | `order` | query | no | `asc` \| `desc` (default `desc`) | A history: sort direction (default newest first). Needs `slug`; a day is always by rank. | | `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. | | `limit` | query | no | integer, 1–1000, default `100` | Rows per page. | **Example** ```bash curl -s "https://api.aggre.org/v1/onchain/defi/protocol_tvl?limit=3" \ -H "Authorization: Bearer $AGGRE_API_KEY" ``` **Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`onchain_protocol_tvl`](https://docs.aggre.org/api/schemas.md#onchain_protocol_tvl). **Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)). === https://docs.aggre.org/console/overview === # The console > What the Aggre console at app.aggre.org does: sign in, accounts and organizations, API keys, usage, and a browser for the datasets. Page: https://docs.aggre.org/console/overview · Section: Console and accounts · All pages: https://docs.aggre.org/llms.txt The console is the web app at [`app.aggre.org`](https://app.aggre.org). It is where people sign in, create API keys and organizations, watch usage, and look at the data before writing code. ## Signing in {#sign-in} Open the [sign-in page](https://app.aggre.org/login) and choose a provider. The providers on offer are Google, GitHub and Orbbit SSO, as configured for the deployment (the page shows exactly those). There is no password to create and no separate sign-up: your first sign-in creates your account. - If you sign in with a second provider whose **verified** e-mail address matches your account, it is linked to the same account automatically. Providers that do not vouch for an address never merge anything. - Under **Settings** you can link another sign-in method or unlink one (one must remain), and delete your account. - An app session lasts up to 30 days and ends sooner after 14 days without use. ## Accounts and handles {#accounts} Like a code-hosting site, everyone has a **personal account**, and can create or join **organizations**. Both live in one namespace of handles, and each is addressed by its handle: `app.aggre.org/{handle}`. Each account has its own API keys, usage and audit log. See [Organizations](https://docs.aggre.org/console/organizations.md). ## Pages {#pages} | Page | What you do there | |---|---| | `/{handle}` | See an overview of a personal account or an organization. | | `/{handle}/keys` | Create, list and revoke API keys: [API keys](https://docs.aggre.org/console/api-keys.md). | | `/{handle}/usage` | See requests per day and per key against the limits: [Usage and audit log](https://docs.aggre.org/console/usage.md). | | `/{handle}/members` | Organizations: members, roles and invitations: [Organizations](https://docs.aggre.org/console/organizations.md). | | `/{handle}/activity` | The audit log (owners and admins). | | `/{handle}/settings` | Display name, handle rename, leave or delete an organization. | | `/settings` | Your sign-in methods and deleting your account. | | `/orgs/new` | Create an organization. | | `/datasets`, `/datasets/{id}` | Browse the catalogue and read candles and instruments: [Browsing the data](https://docs.aggre.org/console/browsing-data.md). | | `/legal`, `/legal/{instrument_id}` | Browse statutes with their provisions, licence and attribution. | | `/docs/api`, `/docs/playground` | An in-app API reference and a playground that sends real requests with your key. | ## Platform administration {#admin} `admin.aggre.org` is a separate dashboard for Aggre's platform staff (dataset health, source credentials, login providers, staff, audit). It is not part of the customer console and is not documented here. ## Building your own client {#own-client} The console is a plain client of the [accounts API](https://docs.aggre.org/api/accounts.md) and the [data API](https://docs.aggre.org/api/data.md). Anything it does for a signed-in person can be done by a program that holds a browser session; reading data does not need the console at all, only a key. === https://docs.aggre.org/console/api-keys === # API keys in the console > Create, limit, inspect and revoke API keys from the console. Page: https://docs.aggre.org/console/api-keys · Section: Console and accounts · All pages: https://docs.aggre.org/llms.txt API keys authenticate calls to the [data API](https://docs.aggre.org/api/data.md). Manage them under **API keys** in an account (`app.aggre.org/{handle}/keys`). How a key is sent is in [Authentication](https://docs.aggre.org/authentication.md). ## Creating a key {#create} Choose a name (1 to 80 characters), optionally a quota and its period, an IP allowlist and an expiry. The secret appears **once** in the confirmation; copy it then. Afterwards the list shows only the name, the 8-character prefix, the limits, `last used`, and the usage of the current period. | Option | Notes | |---|---| | Name | Shown in the list, the usage page and the audit log. | | Quota and period | `day`, `month` or `total`. The default is a monthly allowance shown on the form. You can lower it. | | IP allowlist | CIDR ranges the key may be used from. Empty means any address. | | Expiry | The key stops working at this time. | Self-service limits: the quota cannot exceed the default allowance (a daily quota counts as up to 31 times its limit against it), it cannot be unlimited, the rate policy is `default`, and an account holds at most 20 active keys. Higher limits and unlimited keys are set by platform staff. ## Who can manage keys {#roles} On your personal account you do. In an organization, **owners and admins** create, edit and revoke keys; members can see them. Every creation and revocation is written to the audit log ([Usage and audit log](https://docs.aggre.org/console/usage.md)). ## Revoking {#revoke} Revoke from the list. The key stops working within about 30 seconds. Revocation cannot be undone; create a new key instead. ## Good practice {#practice} - One key per application or environment, named for it, so usage and revocation are precise. - Prefer an IP allowlist for servers with fixed addresses. - Store keys in a secret manager, not in source control. If a key leaks, create a new one, deploy it, then revoke the old one. - The console itself reads data for the data browser with a short-lived key of its own, created under your personal account. It is listed with your keys (named "Console browsing"), lasts 24 hours and is revoked when you sign out; it is not meant for your code. === https://docs.aggre.org/console/organizations === # Organizations and members > Create an organization, invite people, and what each role can do. Page: https://docs.aggre.org/console/organizations · Section: Console and accounts · All pages: https://docs.aggre.org/llms.txt An organization is a shared account with its own API keys, usage and audit log. Create one at [`/orgs/new`](https://app.aggre.org/orgs/new); you become its owner. ## Roles {#roles} An organization has `owner`, `admin` and `member`, and always at least one owner. | Action | owner | admin | member | |---|---|---|---| | View the account, members, keys and usage | yes | yes | yes | | View the audit log | yes | yes | no | | Create, edit and revoke API keys | yes | yes | no | | Rename the organization, edit its display name, delete it | yes | no | no | | Invite as `member`, revoke an invitation, remove a `member` | yes | yes | no | | Invite as `admin` or `owner`, change roles, remove anyone | yes | no | no | | Leave the organization | yes (unless last owner) | yes | yes | ## Invitations {#invitations} On the **Members** page an owner or admin invites someone with a role. **No e-mail is sent**: the console shows a one-time link (`app.aggre.org/invitations/{token}`) once, and you pass it on. The invitee opens it, signs in and accepts. The invitee must sign in with a method whose **verified** e-mail equals the invited address; otherwise the invitation is refused (`email_mismatch`). Invitations expire after the number of days `GET /v1/config` reports (`invitation_ttl_days`), and the preview works while signed out. ## Handles {#handles} An organization is addressed by its handle, in the same namespace as users. Only owners rename it; the first rename is free, later ones are limited to one per 30 days. Reserved words are refused. See [Accounts API: handles](https://docs.aggre.org/api/accounts.md#handles). ## Deleting {#delete} Deleting an organization is permanent and only an owner can do it; you confirm by typing its handle. Leaving an organization is available to everyone except the last owner. === https://docs.aggre.org/console/usage === # Usage and audit log > See how many requests each key has made and who changed what in an account. Page: https://docs.aggre.org/console/usage · Section: Console and accounts · All pages: https://docs.aggre.org/llms.txt ## Usage {#usage} `app.aggre.org/{handle}/usage` shows, for an account: - requests **per day** over a period you choose (zero-filled, UTC days), and the total; - consumption **per key**: its name, prefix and count over the period, set against its quota. The same numbers are available to a program through the [accounts API](https://docs.aggre.org/api/accounts/reference.md) (`GET /v1/accounts/{handle}/usage?days=`) and, for the calling key only, through the data API (`GET /v1/whoami`). Counters are written in batches, so a figure can lag a few seconds. What is recorded for each request is the time, method, matched route template, dataset id, HTTP status and request id. The query string, the row you looked at and your IP address are not recorded. ## Audit log {#audit} `app.aggre.org/{handle}/activity` is the account's audit log, visible to **owners and admins**: key creation and revocation and organization changes. Each entry has the actor, the action, a short detail and the time. === https://docs.aggre.org/console/browsing-data === # Browsing the data > The console's dataset browser, statute reader, API reference and playground. Page: https://docs.aggre.org/console/browsing-data · Section: Console and accounts · All pages: https://docs.aggre.org/llms.txt The console lets you look at data before you write code. Being signed in is all it needs: you do not paste a key. ## Datasets {#datasets} `/datasets` is the catalogue of datasets. Open a dataset to read it: candle datasets show a chart and a table, instruments and the other families show tables with the filters their routes accept. What you see is what the data API returns, including `meta.status` and the `credit` text. ## Statutes {#statutes} `/legal` lists statutes with the route's filters (jurisdiction, language, kind, status, title contains). Opening one shows its provisions, licence, attribution and restricted flag. Where attribution is required, the page shows it. ## API reference and playground {#reference} `/docs/api` is an in-console API reference, and `/docs/playground` lets you choose a route, fill the parameters, send the request with your key and copy the equivalent code. This documentation site is the full reference; the playground is the quickest way to try a call. ## How it reads data {#how} The data API allows no browser access, so the console's server forwards a read-only, allow-listed set of requests. Because the data API takes only API keys, the console makes a short-lived key of its own under your personal account ("Console browsing", 24 hours, read-only), reuses it between tabs and revokes it when you sign out. Browsing therefore counts toward that key's usage. A key you create yourself is never used for browsing. === https://docs.aggre.org/agents/overview === # Agent-friendly documentation > How an AI agent or script can read these docs as Markdown, discover every page, and call the API. Page: https://docs.aggre.org/agents/overview · Section: For agents · All pages: https://docs.aggre.org/llms.txt These docs are built to be read by programs as well as people. Nothing here needs a special client. ## Markdown for every page {#markdown} Append `.md` to any page address: | Page | Markdown | |---|---| | `https://docs.aggre.org/quickstart` | `https://docs.aggre.org/quickstart.md` | | `https://docs.aggre.org/api/data/market` | `https://docs.aggre.org/api/data/market.md` | | `https://docs.aggre.org/` | `https://docs.aggre.org/index.md` | The Markdown version has the title as `# heading`, a one-line summary, the page's canonical address, then the body. **Links inside it are absolute and point to other `.md` pages**, so an agent can follow them without leaving Markdown. Code blocks are fenced with their language. The response is `text/markdown; charset=utf-8`, with a `Link: ; rel="canonical"` header and `X-Robots-Tag: noindex` so search engines index the HTML. You can also ask for Markdown at the page's own address with an `Accept` header: ```bash curl -s -H "Accept: text/markdown" https://docs.aggre.org/concepts/errors ``` Every HTML page advertises its twin with ``, and has a **Copy page** button that puts the Markdown on the clipboard. ## Discovering pages {#discovery} | URL | What | |---|---| | [`/llms.txt`](https://docs.aggre.org/llms.txt) | An index in the [llms.txt](https://llmstxt.org/) format: every page with its description and `.md` link, grouped by section. Start here. | | [`/llms-full.txt`](https://docs.aggre.org/llms-full.txt) | The complete text of every page in one file, for loading into a context window or an index. | | [`/sitemap.xml`](https://docs.aggre.org/sitemap.xml) | The HTML pages. | | [`/search-index.json`](https://docs.aggre.org/search-index.json) | The search index: one entry per section with a short excerpt. | ## Machine-readable API description {#machine-readable} - [`/openapi/data.yaml`](https://docs.aggre.org/openapi/data.yaml) (and `.json`): every route of the data API with parameters, and `$ref`s to the row schemas. - [`/openapi/accounts.yaml`](https://docs.aggre.org/openapi/accounts.yaml): the console's control-plane routes. - [`/schemas/{name}.json`](https://docs.aggre.org/api/schemas.md): the JSON Schema of every row. The reference pages are generated from these files, so the prose and the files cannot drift apart. ## Calling the API from an agent {#calling} 1. Give the agent an API key through its tool configuration or environment, never in a prompt or a repository ([Authentication](https://docs.aggre.org/authentication.md)). 2. Start from `GET /v1/datasets` to see what exists, and read `meta.status` on every answer. 3. Follow the rules in [Best practices for agents](https://docs.aggre.org/agents/best-practices.md): strict parameters, `credit` shown with data, `terms_unread` is not retryable. 4. For legal retrieval and judgments there is also an MCP-style tool interface: [MCP compatibility](https://docs.aggre.org/agents/mcp.md). === https://docs.aggre.org/agents/best-practices === # Best practices for agents > How to use the Aggre API reliably and honestly from an AI agent or automated pipeline. Page: https://docs.aggre.org/agents/best-practices · Section: For agents · All pages: https://docs.aggre.org/llms.txt Rules that keep an agent correct, cheap and within the data's terms. Each links to the page that explains it. ## Build requests from the reference, not from memory {#requests} Parameters are **strict**: an unknown or repeated query parameter is `400 invalid_request`. Take names, types and ranges from the [reference](https://docs.aggre.org/api/data.md) or the [OpenAPI file](https://docs.aggre.org/openapi/data.yaml). A `400` is a bug in the request; fix it, do not retry it unchanged. See [Response format](https://docs.aggre.org/concepts/response-format.md#strict). ## Read the state, not just the rows {#state} Always read `meta.status` and `meta.message`: - `empty` is a valid answer. Do not invent rows or conclude "nothing exists" without checking `meta.message` and `meta.fetchedAt`. - `stale` means the last read is old; say so if you report the data. - `503 terms_unread` means the source is not switched on. It is not transient and retrying wastes quota ([Freshness](https://docs.aggre.org/concepts/freshness.md)). ## Show attribution {#attribution} If your output shows a row to a person, include its `credit` / `attribution` exactly as returned, and keep `restricted` notices. Do not paraphrase them ([Attribution](https://docs.aggre.org/concepts/attribution.md)). ## Do not over-claim {#claims} - Name lists are exact or prefix name search only. **Never present a result, or the absence of one, as a sanctions screening.** - Congress trades are disclosed weeks late and in ranges; Taiwan statements are in thousand NT$; funding rates are per the venue's own period. Read the field definitions before computing with them ([Datasets](https://docs.aggre.org/datasets.md)). - For revisions use `as_of` to see what was known at a time; do not mix versions silently ([Macro](https://docs.aggre.org/datasets/macro.md#revisions)). - Statute text is the current version; verify against the official source for anything that matters. ## Handle errors {#errors} Log `error.code` and `request_id`. Retry only `429 rate_limited` (after `Retry-After`) and transient `503 store_unavailable` / `500` with backoff. Never retry `usage_limit_exceeded` ([Errors](https://docs.aggre.org/concepts/errors.md#handling)). ## Be economical {#economy} - Use the largest sensible `limit`, follow `next_cursor`, and cache catalogues. - Use `updated_since` change feeds instead of re-reading datasets. - Read `/llms.txt` once and fetch only the `.md` pages you need instead of crawling the HTML. - Check `GET /v1/whoami` before a large job to see how much quota is left. ## Protect the key {#key} Keep the key in the tool's secret store. Never echo it, log it, put it in a URL or send it to a model as text. If it leaks, revoke it in the console and create a new one ([API keys](https://docs.aggre.org/console/api-keys.md)). === https://docs.aggre.org/agents/mcp === # MCP compatibility > The legacy MCP tool table served by GET /v1/mcp/tools and POST /v1/mcp/call, with each tool's arguments. Page: https://docs.aggre.org/agents/mcp · Section: For agents · All pages: https://docs.aggre.org/llms.txt Aggre serves a **compatibility interface** for clients written against the older Aggre MCP tool table. It is a plain HTTP API, not an MCP server process: your MCP client or agent framework calls it. | Route | Purpose | |---|---| | `GET /v1/mcp/tools` | The frozen tool table: name, description, input schema and permission of each tool. Tools that are not served have `available: false`. | | `POST /v1/mcp/call` | Call a tool: `{ "name": "", "arguments": { ... } }` answers `{ "name": "", "result": { ... } }`. | Both need an API key like every other `/v1` route. `result` is the same JSON the native route returns as `data`, with the same additive fields. ## What is served {#served} The table lists 17 tools. The **seven judgment and retrieval tools** are served by the Data Bank: `retrieve`, `retrieve_batch`, `search_judgments`, `get_judgment`, `lookup_judgment`, `search_in_judgment` and `judgment_outline`. The others are listed by `GET /v1/mcp/tools` with `available: false` and answer `501` unless a deployment forwards them to a legacy host. An unknown tool name is `400`. Use the [native routes](https://docs.aggre.org/api/data.md) for everything else: they are the supported interface. ## Errors are flat {#errors} On `POST /v1/mcp/call`, errors keep the legacy flat shape `{ "error": "message" }`, **not** the structured envelope of the rest of the API, so existing tool clients keep working. ```bash curl -s https://api.aggre.org/v1/mcp/call \ -H "Authorization: Bearer $AGGRE_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"lookup_judgment","arguments":{"citation":"憲法法庭112年憲判字第8號判決"}}' ``` ## Tool table {#tools} The table is frozen: it changes only through a reviewed contract change. | Tool | What it does | Permission | |---|---|---| | `list_datasets` | List datasets visible to the current API key. | `dataset_read` | | `search_dataset` | Search records inside a dataset with query and limit guards. | `search_read` | | `get_record` | Fetch a single record by ID with sensitive field masking, or by dataset_id (slug or id) + external_id at the dataset's current version (a 大法官解釋's full record: dataset_id taiwan-constitutional-interpretations, external_id | `dataset_read` | | `get_dataset_schema` | Return a dataset schema and version metadata. | `dataset_read` | | `export_sample` | Export a small governed sample from a dataset. | `export_write` | | `export_dataset` | Page through an entire dataset's records (limit + offset), for building a local mirror rather than a sample. | `export_write` | | `retrieve` | Semantic retrieval (RAG): two-stage recall (lexical, plus dense on the Taiwan statute corpora) + cross-encoder rerank. Search statutes only (corpus=laws), case law only (corpus=judgments), or both. English statutes: Sing | `search_read` | | `retrieve_batch` | Run 1-3 independent semantic retrieval queries under one bounded request. Each query keeps its own recall, rerank order, results and diagnostics; failures are isolated. Optional caching is org-scoped and invalidated by c | `search_read` | | `search_judgments` | Taiwan case law by the court's own reasoning: passages from 理由 and 主文 across the judgment corpus, grouped by judgment, each with a verbatim excerpt, its role (court_reasoning, mixed_facts_and_reasoning, holding) and offs | `search_read` | | `get_judgment` | Read a judgment, or a 大法官解釋 (doc_id JYIN,…, with changed_by, supplemented_by, changes and standing), from the passage index in pages by doc_id (the JID search_judgments returns), with the parts it is divided into, the st | `search_read` | | `lookup_judgment` | Find a judgment by its citation — 最高法院49年台上字第1730號, 臺灣高等法院112年度上字第123號, 憲法法庭112年憲判字第8號判決, a 大法官解釋 (釋字第380號, 司法院釋字第380號解釋, 大法官解釋第380號, 釋字第三八〇號), Chinese numerals or a JID (a 大法官解釋 match carries changed_by, supplemented_by | `search_read` | | `search_in_judgment` | Find where in ONE judgment a question is answered: ranks the passages of the judgment doc_id names (15,000-100,000 characters, of which get_judgment shows 3,000 at a time) for a query, across every part of it -- party cl | `search_read` | | `judgment_outline` | The map of one judgment by doc_id (for a 大法官解釋: its 解釋爭點 as issue, 解釋文 as holding, 理由書 as reasoning, and their numbered paragraphs): where 主文, the facts, each party's case (party_claim), what the court below held (lower_ | `search_read` | | `get_politician_trades` | US Congress (Senate + House) STOCK Act trades, filterable by politician name, ticker, and chamber. | `search_read` | | `get_investor_holdings` | A famous investor's latest 13F holdings (e.g. Buffett, Burry, Ackman, ARK), largest position first. | `search_read` | | `get_insider_trades` | Famous corporate insiders' SEC Form 4 trades (e.g. Musk, Cook, Zuckerberg), filterable by person and ticker. | `search_read` | | `who_traded` | Everyone on the watch-lists (politicians + insiders) who traded a given ticker. | `search_read` | ## Arguments {#arguments} ### list_datasets {#tool-list_datasets} List datasets visible to the current API key. | Argument | Type | Required | Description | |---|---|---|---| | `category` | `legal` \| `healthcare` \| `markets` | no | Canonical domain. legal = statutes/case law/contract templates; healthcare = drug labels, approvals, recalls, biotech company disclosure; markets = quotes, economic indicators, positions & trades. | | `query` | string | no | Substring match against slug/name/description. | | `tags` | array of string | no | Namespaced facets, ALL of which must match (AND). Vocabulary: jurisdiction:TW\|CN\|US\|SG\|global, lang:zh-Hant\|zh-Hans\|en, type:statute\|regulation\|case-law\|contract-template\|drug-label\|approval\|recall\|adverse-event\|filing\|filing-index\|filing-passage\|company-profile\|registry\|regulatory-filing\|sanction-list\|quote\|indicator\|holding\|trade, modality:fulltext\|structured, asset:crypto\|equity, derived: for materialised subsets, source:…, sector:…, and rag:retrievable for datasets that `retrieve` can semantically search. This list is the live vocabulary, not a closed set -- read the `facets` map in a response to see what actually survived your filter. Example: ["jurisdiction:TW","lang:zh-Hant","type:case-law"] | ### search_dataset {#tool-search_dataset} Search records inside a dataset with query and limit guards. | Argument | Type | Required | Description | |---|---|---|---| | `dataset_id` | string | yes | Dataset UUID | | `limit` | integer, 1–50 | no | | | `query` | string | yes | | ### get_record {#tool-get_record} Fetch a single record by ID with sensitive field masking, or by dataset_id (slug or id) + external_id at the dataset's current version (a 大法官解釋's full record: dataset_id taiwan-constitutional-interpretations, external_id its doc_id). | Argument | Type | Required | Description | |---|---|---|---| | `dataset_id` | string | no | With external_id instead of id: the dataset's slug or UUID, e.g. "taiwan-constitutional-interpretations". | | `external_id` | string | no | With dataset_id: the record's external id at the dataset's current version, e.g. a doc_id "JYIN,84,釋字,380,19950526". | | `id` | string | no | Record UUID | | `record_id` | string | no | Record UUID alias | ### get_dataset_schema {#tool-get_dataset_schema} Return a dataset schema and version metadata. | Argument | Type | Required | Description | |---|---|---|---| | `dataset_id` | string | yes | Dataset UUID or slug (e.g. "fund-holdings") | | `limit` | integer, 1–100 | no | | ### export_sample {#tool-export_sample} Export a small governed sample from a dataset. | Argument | Type | Required | Description | |---|---|---|---| | `dataset_id` | string | yes | Dataset UUID or slug (e.g. "fund-holdings") | | `limit` | integer, 1–100 | no | | ### export_dataset {#tool-export_dataset} Page through an entire dataset's records (limit + offset), for building a local mirror rather than a sample. | Argument | Type | Required | Description | |---|---|---|---| | `dataset_id` | string | yes | Dataset UUID or slug (e.g. "china-national-laws") | | `limit` | integer, 1–2000 | no | Records per page (default 500). | | `offset` | integer, 0– | no | Row offset to resume from; feed the previous response's next_offset back here to page through the whole dataset, and stop when it comes back null. That is the only stop condition -- total_estimate is an hourly approximation and bounding the walk with it truncates the copy. | ### retrieve {#tool-retrieve} Semantic retrieval (RAG): two-stage recall (lexical, plus dense on the Taiwan statute corpora) + cross-encoder rerank. Search statutes only (corpus=laws), case law only (corpus=judgments), or both. English statutes: Singapore's Acts (jurisdiction=SG), Canada's federal Acts (jurisdiction=CA) and Taiwan's laws and orders in English (jurisdiction=TW, language=en), one hit per section with law_name, article_no and heading. Japanese statutes (jurisdiction=JP, query in Japanese): one hit per article, article_no as e-Gov labels it (第709条), with the e-Gov credit in attribution. Also covers openFDA: drug labeling full text (corpus=drug-labels -- indications, dosage, warnings, adverse reactions) and recalls/safety actions (corpus=fda-safety). Returns ranked passages with citations for a natural-language query. A Taiwan judgment on the Judicial Yuan's takedown list carries takedown (labelled, not hidden). | Argument | Type | Required | Description | |---|---|---|---| | `agency` | string or array | no | Only with corpus "rulings": search only these ministries' rulings. 勞動部, 經濟部, 法務部, 財政部, 個資會籌備處, 公平會, 金管會 (or an alias: 勞委會, MOL, MOEA, MOJ, MOF, 國發會, FTC, FSC); a list searches each. Absent, all of them. An unknown agency is an error that lists the ones held, not an empty result. | | `article_no` | string | no | Exact article number, e.g. 184 or 184-1; also as written in a judgment or a statute (第184條之1, 一八四, 第一百八十四條之一). Requires law_name. For the English statute corpora also as written in English: "s 157", "section 5A", "Article 15-1", "Art. 3". For Japan (JP): 第709条, 709, 第3条の2, 3-2 or 附則第1条 (Arabic figures). | | `as_of` | string, date | no | Return only statute article versions current on this date. Applied to lexical and dense candidate generation before top_k. Datasets without explicit article version windows fail closed with complete:false and as_of_unavailable. | | `candidates` | integer, 10–32 | no | First-stage recall pool size before reranking. Overrides `depth`. Hard-capped at 32 (the reranker's max batch). | | `corpus` | `laws` \| `judgments` \| `both` \| `medical` \| `medical-laws` \| `medical-judgments` \| `rulings` \| `drug-labels` \| `fda-safety` \| `sec-filings` \| `510k` \| `device-summaries` \| `device-classification` | no | Which body to search. "laws" = statutes/regulations only, "judgments" = case law only (default), "both" = laws+judgments merged and ranked together. "medical-laws"/"medical-judgments" are the medical slices of those two, and "medical" is both (TW: 醫療法 plus the judgments that applied it; CN and US resolve to regulation alone — US is 21/42/45 CFR). "rulings" = the ministries' administrative rulings (函釋), Taiwan only (ignores `jurisdiction`): 財政部 (the tax acts), 勞動部 (labor acts), 經濟部 (公司法, 商業登記法), 法務部 (legal affairs), 個資會籌備處 (個人資料保護法; the 國家發展委員會 before it), 公平會 (公平交易法) and 金管會 (banking, securities, insurance); `agency` narrows it to some of them. One hit per ruling with `title`, `case_number` (發文字號), `date` (發文日期) and `source_url`, and a `ruling` object: `agency` (發文機關), `doc_number`, `doc_date`, `subject` (主旨), `related_articles` (相關法條: law, article_no, citation; `related_articles_source` says whether the site filed them or they were read off the text), `status` (現行 / 停止適用 / 已廢止) with `status_date` and `status_note`. 財政部 hits also carry `law_name` (稅目) and `article_no` (Arabic, e.g. "14"). A ruling is an agency's reading, not law, and the licence requires citing the source. "drug-labels" = openFDA drug labeling (SPL) full text -- indications, dosage, contraindications, warnings, adverse reactions. "fda-safety" = openFDA recalls/enforcement reports + Complete Response Letters. "510k" (alias "device-summaries") = the narrative text of FDA 510(k) summary documents; "device-classification" = device classes and their regulation definitions. "sec-filings" = SEC EDGAR healthcare/biotech filing PASSAGES (10-K/20-F/S-1/8-K), chunked from Item 1 Business and Item 1A Risk Factors — drug pipelines, clinical programs, regulatory and IP risk, in the company's own words. Hits carry `form`, `section` and `source_url`. The FDA and SEC corpora are US-only and ignore `jurisdiction`. Corpora are separate datasets, so "laws" can never return case law, and neither FDA corpus can return legal text. | | `dataset` | string | no | Explicit dataset slug; overrides corpus/jurisdiction/language. e.g. "taiwan-moj-laws-ch-law", "taiwan-judgments", "taiwan-moj-laws-en-law", "ca-law", "fda-drug-labels", "fda-safety" | | `depth` | `fast` \| `standard` \| `thorough` | no | How hard to search, trading latency for recall+precision. "fast" = small pool, strict threshold, short reranked text (interactive paths). "standard" (default) is the balanced setting. "thorough" = biggest pool TEI accepts, looser threshold, longer reranked text, and double the stage-1 time budget — use when the answer matters more than the wait. The individual arguments below override whichever fields you set. | | `explain` | boolean | no | Attach a `diagnostics` object describing how the answer was reached: the stage-1 probes actually run, per-corpus candidate counts and best lexical score for each probe, and the FULL reranked pool with an `admitted` flag saying which entries reached `top_k`. Use it when a passage you expected is missing from `results` -- it is the only way to tell "never recalled by stage 1" (fix the query, or the corpus has no such provision) from "recalled but out-ranked" (raise `top_k`, `candidates`, or `rerank_chars`). Off by default; the response is unchanged when absent. | | `jurisdiction` | `TW` \| `CN` \| `US` \| `SG` \| `CA` \| `JP` | no | TW (default), CN, US, SG, CA, or JP. Combines with `corpus` (and `language`) to pick the datasets. SG is Singapore: its current Acts (corpus "laws", one hit per section); every SG hit carries the `attribution` its source requires. CA is Canada: the consolidated federal Acts (corpus "laws", one hit per section, Justice Laws). SG and CA are English: write the query in English. JP is Japan: the statutes in force (corpus "laws", one hit per article, from e-Gov), in Japanese: write the query in Japanese, in the statute's own words (e.g. 不法行為による損害賠償); every JP hit carries the e-Gov credit (`attribution`) its licence requires. US is meaningful only for the medical corpora, where it resolves to 21/42/45 CFR — there is no US case law or statute corpus here, and asking for one returns an explanatory error rather than silently handing you Taiwanese material; so does any other jurisdiction. Ignored entirely by the FDA and SEC corpora, which are US-only already. | | `language` | `en` \| `zh` | no | Optional; omitted, every corpus is its jurisdiction's own language (TW and CN Chinese, SG and CA English). "en" with jurisdiction TW and corpus "laws" searches the Ministry of Justice's English translations of Taiwan's laws and orders (taiwan-moj-laws-en-law, taiwan-moj-orders-en-order) instead of the Chinese originals: write the query in English; hits carry the English act name in `law_name` and "Article N" in `article_no`. A language a jurisdiction is not held in is an error. | | `law_name` | string | no | Exact act name; requires article_no. Returns the complete matching article with strategy=exact, without similarity ranking. Taiwanese acts in Chinese, by the name or a short one (勞基法 for 勞動基準法; 中華民國 may be left off; 台 is read as 臺). A query that is nothing but one article of a Taiwanese act (民法第184條, 民法184, 民法第一八四條, 勞基法第11條第5款) is looked up the same way, with matched_from_query: true in the answer, and searched as usual if the lookup finds nothing; for the English statute corpora (TW with language en, SG, CA) the English title, with or without its year ("Companies Act 1967" or "Companies Act"), or the act's code. For Japan (JP) the law's e-Gov title, e.g. 民法 or 会社法. | | `pcode` | array of string | no | Search ONLY inside these acts, by MOJ pcode (e.g. ["G0380050"] for 票據法). Applied during first-stage recall, not to the results, so `top_k` still means `top_k` hits from inside these acts. Use it when you already know which statutes govern -- writing the act's NAME in `query` does not do this and never has: only article BODIES are matched, so the name contributes nothing to the score and, on the semantic arm, dilutes the query. Every hit carries the `pcode` to pass back here. Taiwanese statute corpora only (taiwan-moj-laws-ch-law, taiwan-moj-orders-ch-order, taiwan-medical-laws); anything else is an error rather than an empty result. | | `query` | string | yes | Natural-language legal query, e.g. "公務員收賄罪的量刑" or "正当防卫的认定" | | `rerank_chars` | integer, 64–1024 | no | How many characters of each candidate the cross-encoder reads. The single biggest latency lever (attention is O(n²) in length). Overrides `depth`. | | `stage1_timeout_secs` | integer, 3–120 | no | Hard cap on first-stage retrieval per corpus. By default each corpus gets its own size-appropriate budget (small statutes vs 22M-row TW judgments) scaled by `depth`; set this to force one flat budget. | | `threshold` | number, 0.05–0.9 | no | First-stage lexical similarity cutoff (pg_trgm word_similarity, 0-1). Lower = more permissive recall, more candidates for the reranker to sort out. Overrides `depth`. | | `top_k` | integer, 1–30 | no | Number of passages to return (default 8) | ### retrieve_batch {#tool-retrieve_batch} Run 1-3 independent semantic retrieval queries under one bounded request. Each query keeps its own recall, rerank order, results and diagnostics; failures are isolated. Optional caching is org-scoped and invalidated by corpus and reranker versions. | Argument | Type | Required | Description | |---|---|---|---| | `agency` | string or array | no | | | `article_no` | string | no | | | `as_of` | string, date | no | | | `cache_control` | object | no | | | `candidates` | integer, 10–32 | no | | | `corpus` | `laws` \| `judgments` \| `both` \| `medical` \| `medical-laws` \| `medical-judgments` \| `rulings` \| `drug-labels` \| `fda-safety` \| `sec-filings` \| `510k` \| `device-summaries` \| `device-classification` | no | | | `dataset` | string | no | | | `depth` | `fast` \| `standard` \| `thorough` | no | | | `explain` | boolean | no | | | `jurisdiction` | `TW` \| `CN` \| `US` \| `SG` \| `CA` \| `JP` | no | | | `language` | `en` \| `zh` | no | | | `law_name` | string | no | | | `pcode` | array of string | no | | | `queries` | array of object | yes | | | `rerank_chars` | integer, 64–1024 | no | | | `stage1_timeout_secs` | integer, 3–120 | no | | | `threshold` | number, 0.05–0.9 | no | | | `top_k` | integer, 1–30 | no | | ### search_judgments {#tool-search_judgments} Taiwan case law by the court's own reasoning: passages from 理由 and 主文 across the judgment corpus, grouped by judgment, each with a verbatim excerpt, its role (court_reasoning, mixed_facts_and_reasoning, holding) and offsets into the full text. Each result also carries case_cause (案由, e.g. 損害賠償, read from the judgment's own record; absent when the record has none) and cited_articles (the statute articles that judgment's own reasoning cites, each with law, article_no and article, at most 30, with cited_articles_total when there are more; the top-level cited_articles is a different thing, the articles most cited across the batch). No 裁判要旨 (headnote) is returned: the Judicial Yuan feed this corpus is built from does not carry one. max_results is 1–20 (default 5). Write the question in Traditional Chinese; filters for court level (court_level: supreme, high, district, constitutional — decided by the court code in the JID; 憲法法庭 is constitutional), case type and decision date. corpus picks what is searched: judgments (the default; no 大法官解釋), interpretations (司法院大法官解釋 釋字第1–813號 only, case_type 釋字, with their 解釋爭點 as role issue, 解釋文 as holding and 理由書 as court_reasoning; opinions are not indexed), constitutional (the interpretations and 憲法法庭's judgments and rulings) or all. A 大法官解釋 result carries changed_by, supplemented_by and changes (from the taiwan-constitutional-interpretations record) and standing (changed, supplemented or none); absent means unknown. cites_article (「民法第184條」, 「勞基法第11條」, 「土地法第34條之1」; one or a list) keeps judgments whose reasoning cites that article. cites_judgment (「最高法院110年度台上字第1432號」 or a doc_id; one or a list) keeps judgments whose reasoning cites that judgment; without a query it lists them, highest court and newest first. One result per case: a case's judgments at other courts and its rulings are grouped, and case.status says where the one shown stands (final, affirmed, reversed, remanded). Administrative rulings (支付命令, 本票裁定, 補費) are not indexed. court_only searches only the court's own reasoning and 主文. Results carry cited_by_count (other cases' judgments citing it, as of cited_by_as_of; see cited_by_note) and order_by cited_by orders by it; lookup_judgment of a 字號 returns cited_by_citation even when no judgment of it is in the index. synonyms (default true) also covers the other spelling of a character (僱/雇, 臺/台, 占/佔) and an article number written any way; query_expansion says what it added. flags keeps the judgments the courts set apart (grand_chamber 大法庭裁定, supreme_reference and high_reference 具參考價值之裁判, former_precedent 原判例) and every result lists its flags; by the 最高法院 own account a 具參考價值 judgment is not its unified view unless it went through 大法庭 or 徵詢程序 (flags_note). A judgment on the Judicial Yuan's takedown list (Delete-Infor) carries takedown (deleted_on, still_published_on_judicial_api, note): labelled, not hidden. | Argument | Type | Required | Description | |---|---|---|---| | `case_type` | array of `民事` \| `刑事` \| `行政` \| `家事` \| `懲戒` \| `其他` | no | Only these case types, written exactly as the Chinese label (民事, 刑事, 行政, 家事, 懲戒, 其他). A list matches any of them; a single string is read as a list of one. 大法官解釋 (case_type 釋字) are chosen with corpus, not here. | | `cited_by_weight` | number, 0–1 | no | With order_by relevance_and_cited_by: the most the count can add to a result's relevance (relevance is 0 to 1 against the best of the pool). Not tuned against judged results. | | `cites_article` | string or array | no | Keep judgments whose reasoning cites this article (all of them, when a list): write the act and the article, e.g. "民法第184條", "勞基法第11條", "土地法第34條之1". | | `cites_judgment` | string or array | no | Keep judgments whose reasoning cites this judgment: a case number with its court ("最高法院110年度台上字第1432號") or a doc_id. With no query, lists the citing judgments, highest court and newest first. | | `corpus` | `judgments` \| `interpretations` \| `constitutional` \| `all` | no | What is searched: judgments (default; no 大法官解釋), interpretations (司法院大法官解釋 釋字 only), constitutional (釋字 and 憲法法庭) or all. | | `court_level` | array of `supreme` \| `high` \| `district` \| `constitutional` | no | Only these court levels, decided by the court code in the JID (constitutional: 憲法法庭 and 大法官解釋). A list matches any of them; a single string is read as a list of one. | | `court_only` | boolean | no | Search only what the court itself wrote: 理由 (court_reasoning) and 主文 (holding), not a 事實及理由 that could not be divided into facts and reasoning (mixed_facts_and_reasoning), which may hold a party's argument. Measured, 24% of judgments (mostly 簡易判決) have no other reasoning than that, and are not found with this set. Default false; roles names passages more exactly. | | `date_from` | string, date, pattern `^[0-9]{4}-?[0-9]{2}-?[0-9]{2}$` | no | Decision date, Gregorian calendar, written YYYY-MM-DD (YYYYMMDD is read too; a 民國 year is not). Inclusive: decided on or after this day. Either bound may be given alone. | | `date_to` | string, date, pattern `^[0-9]{4}-?[0-9]{2}-?[0-9]{2}$` | no | Decision date, Gregorian calendar, written YYYY-MM-DD. Inclusive: decided on or before this day. | | `depth` | `fast` \| `standard` \| `thorough` | no | fast: lexical order, no reranker, quickest. standard (default): the best 150 passages reranked, within about 10 s. thorough: 320 reranked, within about 25 s. When the reranker is unavailable or over its budget the answer goes out in lexical order and says so (reranked: false). | | `excerpt_chars` | integer, 80–600 | no | Longest excerpt per passage (default 300). | | `flags` | array of `grand_chamber` \| `supreme_reference` \| `high_reference` \| `former_precedent` | no | Keep only judgments the courts themselves set apart; one flag or a list (any of them). grand_chamber: 大法庭裁定 (最高法院 case word 台上大, 最高行政法院 大). supreme_reference: 最高法院「具有參考價值之裁判」; high_reference: 高等法院暨所屬法院具參考價值/足資討論之裁判; former_precedent: 原判例. A flag whose list is not loaded on this deployment is refused, not answered empty. Every result carries its flags (a list, empty when none) when the lookup is enabled; absent means unknown. flags_note says that, by the 最高法院 own account, a 具參考價值 judgment is not the court's unified view unless it went through 大法庭 or 徵詢程序. | | `max_results` | integer, 1–20 | no | Cases to return, one result per case (default 5, at most 20); each carries up to three passages. | | `order_by` | `relevance` \| `cited_by` \| `relevance_and_cited_by` | no | relevance (default): the order of the search. cited_by: gather the most relevant judgments (four times max_results, at least 20, at most 60, one per case), then order them by how many other judgments cite each (cited_by_count), most first, relevance breaking ties. relevance_and_cited_by: relevance plus cited_by_weight times the count (log-scaled against the most cited of the pool). Every result carries cited_by_count and cited_by_levels when the lookup is enabled; absent means unknown. Ordering by the count is refused when it is not enabled. | | `query` | string | no | The legal question or the proposition a court would write, in Traditional Chinese, e.g. "相當於租金之不當得利 請求權時效" or "承租人請求出租人返還押租金". Required, except that cites_judgment alone (no query) lists the judgments citing it. | | `roles` | array of `court_reasoning` \| `mixed_facts_and_reasoning` \| `mixed` \| `holding` \| `issue` | no | Passage roles to search (default the first four, and issue — a 大法官解釋's 解釋爭點 — when corpus is not judgments). | | `synonyms` | boolean | no | Widen the question: statutory words for everyday ones (押金 → 押租金, 加班費 → 延長工作時間之工資); the other spelling of a character courts write both ways (僱/雇, 臺/台, 占/佔, 裡/裏, 啟/啓, 敘/敍, 鑑/鑒, 證/証, 污/汙, 溫/温); and an article number in any of its spellings (民法184, 民法第184條, 民法第一八四條 and 民法第一百八十四條 are one article, found by the articles each judgment cites). What was added is listed in query_expansion. Default true. | ### get_judgment {#tool-get_judgment} Read a judgment, or a 大法官解釋 (doc_id JYIN,…, with changed_by, supplemented_by, changes and standing), from the passage index in pages by doc_id (the JID search_judgments returns), with the parts it is divided into, the statute articles it cites and the judgments it cites (cited_judgments; search_judgments with cites_judgment finds the judgments citing this one), and case_history: the judgments that reviewed it (upper), that it reviewed (lower), and its case's final judgment. Offsets are Unicode code points; a judgment has been read in full only when next_offset is null. A judgment on the Judicial Yuan's takedown list (Delete-Infor) carries takedown (deleted_on, still_published_on_judicial_api, note): labelled, not hidden. | Argument | Type | Required | Description | |---|---|---|---| | `around` | integer, 0– | no | Start a quarter page before this code-point offset, e.g. a hit's excerpt_start. Not with offset. | | `doc_id` | string | yes | The JID from search_judgments or lookup_judgment, e.g. "CHDV,98,重訴,24,20090714,1". | | `max_chars` | integer, 200–20000 | no | Page length in characters (default 3000). | | `offset` | integer, 0– | no | Code-point offset to start at; pass the previous page's next_offset. | ### lookup_judgment {#tool-lookup_judgment} Find a judgment by its citation — 最高法院49年台上字第1730號, 臺灣高等法院112年度上字第123號, 憲法法庭112年憲判字第8號判決, a 大法官解釋 (釋字第380號, 司法院釋字第380號解釋, 大法官解釋第380號, 釋字第三八〇號), Chinese numerals or a JID (a 大法官解釋 match carries changed_by, supplemented_by, changes and standing) — to check that a cited case exists in the index before relying on it. The same 年度字號 can be a 民事 and a 刑事 case at one court: say which (…民事判決) or read ambiguous; when the named court has no such case, other_courts lists the courts that do. Each match has total_chars (its length) and, when a court is named, court_exact (臺灣高等法院臺中分院's citation also reaches 臺灣高等法院's own case under the same number, marked false and listed after the court's own). No match does not mean the judgment does not exist. A judgment on the Judicial Yuan's takedown list (Delete-Infor) carries takedown (deleted_on, still_published_on_judicial_api, note): labelled, not hidden. | Argument | Type | Required | Description | |---|---|---|---| | `citation` | string | yes | A case citation or JID, e.g. "最高法院49年台上字第1730號", "憲法法庭112年憲判字第8號" or "釋字第380號". | | `court` | string | no | Court to match when the citation names none. | ### search_in_judgment {#tool-search_in_judgment} Find where in ONE judgment a question is answered: ranks the passages of the judgment doc_id names (15,000-100,000 characters, of which get_judgment shows 3,000 at a time) for a query, across every part of it -- party claims and appendices as well as the reasoning. Each passage has its role (holding, facts, mixed_facts_and_reasoning, court_reasoning, party_claim, attachment, tail_boilerplate, unlabelled; a 大法官解釋's issue, holding and court_reasoning are its 解釋爭點, 解釋文 and 理由書), certifiable_as_court, offsets and an excerpt; excerpt_start goes to get_judgment as around. Also returns the 主文 (disposition). A party_claim passage is a party's argument, not the court's view. Write the query in the judgment's words, Traditional Chinese. A judgment on the Judicial Yuan's takedown list carries takedown (labelled, not hidden). | Argument | Type | Required | Description | |---|---|---|---| | `doc_id` | string | yes | The JID of the judgment to search inside, from search_judgments or lookup_judgment, e.g. "CHDV,98,重訴,24,20090714,1". | | `excerpt_chars` | integer, 80–600 | no | Longest excerpt per passage (default 240). | | `max_results` | integer, 1–10 | no | Passages to return (default 5). | | `query` | string | yes | What to find in this judgment, in Traditional Chinese, in the judgment's own words: the issue, the party, the amount, e.g. "抵銷抗辯 債權不存在". | | `roles` | array of `caption` \| `issue` \| `holding` \| `facts` \| `mixed_facts_and_reasoning` \| `mixed` \| `court_reasoning` \| `party_claim` \| `attachment` \| `tail_boilerplate` \| `unlabelled` | no | Only passages in these parts (default every part). | ### judgment_outline {#tool-judgment_outline} The map of one judgment by doc_id (for a 大法官解釋: its 解釋爭點 as issue, 解釋文 as holding, 理由書 as reasoning, and their numbered paragraphs): where 主文, the facts, each party's case (party_claim), what the court below held (lower_court), the court's own assessment (court_view), the closing (conclusion), the signature and the first appendix begin, and its numbered headings (item), with code-point offsets get_judgment takes as offset. Cut from the judgment's own headings and numbering, not parsed: a judgment with few headings has a short outline. With a query, also returns the passages that answer it (as search_in_judgment). A judgment on the Judicial Yuan's takedown list carries takedown (labelled, not hidden). | Argument | Type | Required | Description | |---|---|---|---| | `doc_id` | string | yes | The JID of the judgment, from search_judgments or lookup_judgment. | | `excerpt_chars` | integer, 80–600 | no | Longest excerpt per passage (default 240). | | `max_results` | integer, 1–5 | no | Passages to return with a query (default 3). | | `query` | string | no | Optional: also return the passages of this judgment that answer it. | ### get_politician_trades {#tool-get_politician_trades} US Congress (Senate + House) STOCK Act trades, filterable by politician name, ticker, and chamber. | Argument | Type | Required | Description | |---|---|---|---| | `chamber` | `Senate` \| `House` | no | | | `limit` | integer, 1–200 | no | | | `politician` | string | no | Politician name substring, e.g. "Pelosi" | | `ticker` | string | no | Stock ticker, exact, e.g. "NVDA" | ### get_investor_holdings {#tool-get_investor_holdings} A famous investor's latest 13F holdings (e.g. Buffett, Burry, Ackman, ARK), largest position first. | Argument | Type | Required | Description | |---|---|---|---| | `investor` | string | yes | Investor or fund name substring, e.g. "Buffett" or "ARK" | | `limit` | integer, 1–500 | no | | ### get_insider_trades {#tool-get_insider_trades} Famous corporate insiders' SEC Form 4 trades (e.g. Musk, Cook, Zuckerberg), filterable by person and ticker. | Argument | Type | Required | Description | |---|---|---|---| | `limit` | integer, 1–200 | no | | | `person` | string | no | Insider name substring, e.g. "Musk" | | `ticker` | string | no | Issuer ticker, exact, e.g. "TSLA" | ### who_traded {#tool-who_traded} Everyone on the watch-lists (politicians + insiders) who traded a given ticker. | Argument | Type | Required | Description | |---|---|---|---| | `limit` | integer, 1–300 | no | | | `ticker` | string | yes | Stock ticker, exact, e.g. "AAPL" | === https://docs.aggre.org/reference/versioning === # Versioning and compatibility > What changes the API makes without notice, and what it promises not to change. Page: https://docs.aggre.org/reference/versioning · Section: Reference · All pages: https://docs.aggre.org/llms.txt ## The promise {#promise} The data API is `/v1`. Within `/v1`, changes are **additive**: - New routes, new optional query parameters and new fields in responses can appear at any time. - Existing routes, parameters and fields are not removed or renamed, and their meaning does not change. A series whose meaning would change gets a new id. - New `error.code` values can be added; clients must tolerate codes they do not know. - New values can appear in documented enums such as `meta.status`; handle unknown values gracefully. Write clients that **ignore unknown fields** and tolerate unknown codes. The `meta` object in particular grows keys per family. ## What can change without notice {#changes} | Change | Example | |---|---| | A dataset starts or stops holding data | A source is switched on after its terms are read; a source is paused. Read `meta.status`. | | Rows change content | A publisher revises a number, a statute is amended, a record is delisted. Revisions are kept as versions or marked removed; see [Freshness](https://docs.aggre.org/concepts/freshness.md). | | Limits are adjusted | Rate limits, default key quotas and freshness windows are deployment settings. | | Attribution text changes | `credit` is the publisher's current wording. | ## Contract files {#contract-files} The OpenAPI files and JSON Schemas on this site are generated from the same contract the service is tested against. The data API file is checked against the service's router in the service's own tests, so a route cannot exist without being in the spec. If you find the docs and the API disagreeing, the API's behaviour is what you observed; please report it with the `x-request-id`. ## This documentation {#docs} Pages are rebuilt from the contract when it changes. Anything on a generated page ("Generated from ...") follows the contract exactly; authored guides are written to match it. The Markdown and `llms.txt` outputs are rebuilt with them. === https://docs.aggre.org/reference/glossary === # Glossary > Terms used across the Aggre documentation. Page: https://docs.aggre.org/reference/glossary · Section: Reference · All pages: https://docs.aggre.org/llms.txt **Account**: a personal account or an organization, addressed by a handle. Owns API keys. **API key**: a secret beginning `aggre_sk_` that authenticates data API calls. Shown once. **As of (`as_of`)**: a query that returns each period as Aggre knew it at a given instant, ignoring later revisions. **Attribution / credit**: text a publisher's terms ask to be shown with its data. Returned with the rows; display it as returned. **Cursor**: an opaque string (`next_cursor`) you pass back as `cursor` to get the next page. **Dataset**: one kind of row with one schema and one route, identified as `{domain}.{category}.{name}`. **Envelope**: the `{ "data", "meta", "next_cursor" }` shape of a data answer. **Handle**: the lowercase name of an account or organization, shared namespace. **Instrument**: a market product identified as `{VENUE}:{PRODUCT}:{native}`. **Meta (`meta`)**: the object that says where data came from and how fresh it is (`source`, `status`, `fetchedAt`, `dataDate`, `message`). **Restricted**: a statute flag meaning the text carries use restrictions; attribution must be shown. **Stale**: `meta.status` when Aggre's last successful read is older than the dataset's freshness window. **Terms gate**: the rule that a source is read and served only after a person has read the publisher's terms. Until then routes answer `503 terms_unread` or carry no licence. **Version**: a revision of one observation or record. A changed value is stored as the next version; earlier ones are kept. **Whoami**: `GET /v1/whoami`, which describes the calling key and its usage.