# Commodity price history
Source: https://developer.hayinsights.com/api-reference/commodities/commodity-price-history
/openapi.yaml get /openapi/v1/commodities/{id}/history
Historical closing prices for a single commodity. Use the `id` slug returned
by the list endpoint (e.g. `gold`, `wti-crude`).
# Featured commodities
Source: https://developer.hayinsights.com/api-reference/commodities/featured-commodities
/openapi.yaml get /openapi/v1/commodities/featured
A curated set of headline commodities (gold, crude oil, copper, …) with the
latest close, 1-day change and a short price sparkline.
# Gold vs DXY correlation
Source: https://developer.hayinsights.com/api-reference/commodities/gold-vs-dxy-correlation
/openapi.yaml get /openapi/v1/commodities/gold-dxy
Rebased gold price and US Dollar Index (DXY) series over the requested
window, for visualising their (typically inverse) correlation.
# List commodity prices
Source: https://developer.hayinsights.com/api-reference/commodities/list-commodity-prices
/openapi.yaml get /openapi/v1/commodities
Latest price snapshot for every tracked commodity across energy, metals,
agriculture and macro categories — including 1-day / MTD / YTD changes, the
50-period moving average, a trend classification and a sparkline.
# Top movers
Source: https://developer.hayinsights.com/api-reference/commodities/top-movers
/openapi.yaml get /openapi/v1/commodities/movers
The biggest gaining and losing commodities over the requested period.
# Crypto bubble map
Source: https://developer.hayinsights.com/api-reference/crypto/crypto-bubble-map
/openapi.yaml get /openapi/v1/crypto/bubble-map
Top coins by market capitalisation with their price change over a selected
timeframe and a normalised bubble size, for a bubble-map visualisation.
# Crypto derivatives metrics
Source: https://developer.hayinsights.com/api-reference/crypto/crypto-derivatives-metrics
/openapi.yaml get /openapi/v1/crypto/derivatives
Derivatives-market metrics — open interest, funding rates, 24h liquidations
and the options put/call ratio for the major coins.
# Crypto market dominance
Source: https://developer.hayinsights.com/api-reference/crypto/crypto-market-dominance
/openapi.yaml get /openapi/v1/crypto/dominance
Market-cap dominance breakdown — total market cap and each major coin's
share of it, with the freshness of the underlying source data.
# Crypto market overview
Source: https://developer.hayinsights.com/api-reference/crypto/crypto-market-overview
/openapi.yaml get /openapi/v1/crypto
Snapshot of the crypto market — total market capitalisation, 24h volume,
major-coin dominance split, the Fear & Greed index and trending coins.
# Crypto on-chain metrics
Source: https://developer.hayinsights.com/api-reference/crypto/crypto-on-chain-metrics
/openapi.yaml get /openapi/v1/crypto/onchain
On-chain network metrics — Ethereum gas prices, Bitcoin hashrate and active
addresses, whale transaction count and the MVRV / NUPL valuation indicators.
# Compare fund composition
Source: https://developer.hayinsights.com/api-reference/etf/compare-fund-composition
/openapi.yaml get /openapi/v1/etf/compare/fund-composition
Side-by-side composition for two to five Vietnamese funds — asset allocation,
the equity portfolio and the sector breakdown — for direct comparison. Pass
the VN fund codes (e.g. `VESAF`) as a comma-separated `codes` list.
# Compare NAV growth
Source: https://developer.hayinsights.com/api-reference/etf/compare-nav-growth
/openapi.yaml get /openapi/v1/etf/compare/nav-growth
NAV-growth series for two Vietnamese funds, benchmarked against the VN-Index,
across the available period windows. Pass the two VN fund codes (e.g. `VESAF`)
as `code1` and `code2`.
# ETF detail
Source: https://developer.hayinsights.com/api-reference/etf/etf-detail
/openapi.yaml get /openapi/v1/etf/{code}/detail
Full detail view for a single ETF — descriptive metadata, latest price, top
holdings, valuation ratios, sector weights, net-flow history and
cumulative-return performance by period. Use the exchange ticker (e.g. a TSE
code like `1306`) as the `{code}` path param.
# ETF / fund composition
Source: https://developer.hayinsights.com/api-reference/etf/etf-fund-composition
/openapi.yaml get /openapi/v1/etf/{code}/composition
Full composition of a single Vietnamese fund certificate — asset allocation,
the equity portfolio and the sector breakdown. Use the VN fund code (e.g.
`VESAF`) as the `{code}` path param.
# ETF holdings
Source: https://developer.hayinsights.com/api-reference/etf/etf-holdings
/openapi.yaml get /openapi/v1/etf/{code}/holdings
The underlying constituent holdings of an ETF's basket — ticker, name, shares
held and position value, as of the latest fund snapshot. Use the exchange
ticker (e.g. a TSE code like `1306`) as the `{code}` path param.
# ETF info
Source: https://developer.hayinsights.com/api-reference/etf/etf-info
/openapi.yaml get /openapi/v1/etf/{code}/info
Core descriptive metadata for a single ETF — manager, benchmark index,
listing date, trust fee and distribution yield. Use the exchange ticker
(e.g. a TSE code like `1306`) as the `{code}` path param.
# ETF market heatmap
Source: https://developer.hayinsights.com/api-reference/etf/etf-market-heatmap
/openapi.yaml get /openapi/v1/etf/heatmap
Snapshot of every tracked ETF for rendering a treemap heatmap — closing
price, volume, market cap, price fluctuation and each fund's contribution to
the aggregate index movement. `contributionArea` is the relative tile size.
# ETF NAV growth
Source: https://developer.hayinsights.com/api-reference/etf/etf-nav-growth
/openapi.yaml get /openapi/v1/etf/nav-growth/{code}
NAV-growth series for a single Vietnamese fund, benchmarked against the
VN-Index, across the available period windows. Use the VN fund certificate
code (e.g. `VESAF`) as the `{code}` path param. The response shares the
comparison shape; the unused `etf2` slot has an empty `etfCode`.
# ETF price history
Source: https://developer.hayinsights.com/api-reference/etf/etf-price-history
/openapi.yaml get /openapi/v1/etf/{code}/prices-history
Daily OHLCV price history for a single ETF, ordered oldest to newest. Use the
exchange ticker (e.g. a TSE code like `1306`) as the `{code}` path param.
# List ETFs
Source: https://developer.hayinsights.com/api-reference/etf/list-etfs
/openapi.yaml get /openapi/v1/etf
The full catalogue of tracked exchange-traded funds, with descriptive
metadata (manager, benchmark index, trust fee), the latest price and assets
under management. Use an entry's `etfCode` as the `{code}` path param for the
info, holdings, prices-history and detail endpoints.
# Top ETFs by net flow
Source: https://developer.hayinsights.com/api-reference/etf/top-etfs-by-net-flow
/openapi.yaml get /openapi/v1/etf/top-netflow
ETFs ranked by net capital flow. Set `type` to `positive` for the largest
inflows or `negative` for the largest outflows.
# Top-performing ETFs
Source: https://developer.hayinsights.com/api-reference/etf/top-performing-etfs
/openapi.yaml get /openapi/v1/etf/top-performance
ETFs ranked by NAV change over the requested period, best to worst. Use the
`period` query parameter to choose the look-back window.
# Emerging-market FX stress
Source: https://developer.hayinsights.com/api-reference/fx/emerging-market-fx-stress
/openapi.yaml get /openapi/v1/fx/em-stress
Emerging-market FX stress monitor — for each tracked pair, compares recent
realised volatility against its 90-day distribution and classifies the pair
as STABLE, WARNING or PANIC.
# FX correlation matrix
Source: https://developer.hayinsights.com/api-reference/fx/fx-correlation-matrix
/openapi.yaml get /openapi/v1/fx/correlation
Rolling 90-day correlation matrix across major FX, crypto and gold
benchmarks. `matrix[i][j]` is the Pearson correlation between `symbols[i]`
and `symbols[j]`.
# FX summary
Source: https://developer.hayinsights.com/api-reference/fx/fx-summary
/openapi.yaml get /openapi/v1/fx/summary
FX dashboard summary — the US Dollar Index (DXY), the USD/JPY rate (each with
a 1-day change) and a headline emerging-market FX stress reading.
# FX table
Source: https://developer.hayinsights.com/api-reference/fx/fx-table
/openapi.yaml get /openapi/v1/fx/table
Live table of tracked currency pairs — latest price, 1-day change, a 10-day
sparkline and the 52-week high / low for each.
# Central government debt (% of GDP)
Source: https://developer.hayinsights.com/api-reference/macro/central-government-debt-%-of-gdp
/openapi.yaml get /openapi/v1/macro/monetary-policy/central-government-debt
Quarterly central-government debt expressed as a percentage of GDP for a
country, with the year-over-year change in the ratio.
# Economic data series
Source: https://developer.hayinsights.com/api-reference/macro/economic-data-series
/openapi.yaml get /openapi/v1/macro/economic-data
Time series for a selected macroeconomic indicator — GDP, CPI, PCE or
import-export — for a country, over a chosen look-back window.
# Exchange rate series
Source: https://developer.hayinsights.com/api-reference/macro/exchange-rate-series
/openapi.yaml get /openapi/v1/macro/exchange-rate
Daily closing exchange-rate history for a currency pair. Optionally limit the
look-back window or return only data before a given date.
# GDP growth rate
Source: https://developer.hayinsights.com/api-reference/macro/gdp-growth-rate
/openapi.yaml get /openapi/v1/macro/gdp-growth-rate
Quarterly nominal GDP and its period-over-period growth rate for a country.
Each point also carries the value's unit and the start/end of the quarter.
# Latest macroeconomic market recap
Source: https://developer.hayinsights.com/api-reference/macro/latest-macroeconomic-market-recap
/openapi.yaml get /openapi/v1/macro/market-recap
A point-in-time market recap bundling the latest Japanese equity / commodity
indices, REITs, TOPIX, 3-month interbank reference rates and key currency
rates into a single payload.
# Policy rates & bond yields
Source: https://developer.hayinsights.com/api-reference/macro/policy-rates-&-bond-yields
/openapi.yaml get /openapi/v1/macro/monetary-policy/rates-yields
Monthly policy / overnight call rate alongside the 10-year government bond
yield for a country, over a chosen look-back window.
# Population & unemployment
Source: https://developer.hayinsights.com/api-reference/macro/population-&-unemployment
/openapi.yaml get /openapi/v1/macro/population
Monthly total-population figures alongside the unemployment rate for a
country, over a chosen look-back window.
# Country land-price statistics
Source: https://developer.hayinsights.com/api-reference/real-estate/country-land-price-statistics
/openapi.yaml get /openapi/v1/real-estate/{country}/stats
Aggregate land-price statistics for a country — overall ward / segment totals, the
observed price range, per-area breakdowns and the highest-priced roads. Data is
available for `vn`; `jp` is empty.
# Country real-estate summary
Source: https://developer.hayinsights.com/api-reference/real-estate/country-real-estate-summary
/openapi.yaml get /openapi/v1/real-estate/{country}
Top-level real-estate summary for a country. Currently returns an empty array on
staging — use the `stats`, `wards`, `land-prices`, `provinces` and `geojson`
sub-routes for detailed data. Data is available for `vn`; `jp` is empty.
# List priced road segments
Source: https://developer.hayinsights.com/api-reference/real-estate/list-priced-road-segments
/openapi.yaml get /openapi/v1/real-estate/{country}/land-prices
Priced road segments for a country, with residential, commercial and production
prices across value-position tiers. Filter by land-use `type`, `area`, `ward_id` or
a free-text search, and cap the result count with `limit`. Data is available for `vn`.
# List provinces
Source: https://developer.hayinsights.com/api-reference/real-estate/list-provinces
/openapi.yaml get /openapi/v1/real-estate/{country}/provinces
Provinces / cities available for real-estate queries in a country. Data is
available for `vn`; `jp` is empty.
# List ward land-price summaries
Source: https://developer.hayinsights.com/api-reference/real-estate/list-ward-land-price-summaries
/openapi.yaml get /openapi/v1/real-estate/{country}/wards
Ward-level land-price summaries for a country — average residential prices across
value-position tiers, min/max prices and road counts. Data is available for `vn`;
`jp` is empty.
# Ward choropleth GeoJSON
Source: https://developer.hayinsights.com/api-reference/real-estate/ward-choropleth-geojson
/openapi.yaml get /openapi/v1/real-estate/{country}/geojson
Ward boundary geometry paired with average-price attributes, for rendering a
choropleth map. The response can be large (boundary coordinates for every ward);
the geometry is modelled permissively. Data is available for `vn`; `jp` is empty.
# Ward land-price detail
Source: https://developer.hayinsights.com/api-reference/real-estate/ward-land-price-detail
/openapi.yaml get /openapi/v1/real-estate/{country}/wards/{wardId}
Full land-price detail for a single ward — an aggregate summary plus every priced
road segment with residential, commercial and production prices across value-position
tiers. Use the `wardId` returned by the wards list. Data is available for `vn`.
# Authentication
Source: https://developer.hayinsights.com/authentication
A single API key in the X-API-Key header — no request signing.
The HayInsights Open API uses a **single authentication tier**: send your API key
in the `X-API-Key` header on every request to `/openapi/v1/*`. There is no HMAC
signing, no timestamp, and no nonce.
```bash theme={null}
curl -H "X-API-Key: $HAYINSIGHTS_API_KEY" \
"https://api-v2.hayinsights.com/openapi/v1/fx/summary"
```
| Header | When | Value |
| ----------- | ------ | ------------------------------ |
| `X-API-Key` | Always | Your API key (prefixed `apk_`) |
The API key is only accepted on the `/openapi/v1/*` surface. The dashboard
surface (`/api/v1/*`) uses a separate session-based login, so an API key can
never be used to manage itself.
## Managing keys
Create, rotate and revoke keys from the [HayInsights
dashboard](https://app.hayinsights.com) under **Account → API keys**.
Generate a key — the full secret (`apk_…`) is shown **once**. Copy it into a
secret store or environment variable immediately.
Rotating issues a new key and revokes the old one in a single step. Update
your environment with the new secret.
Revoking disables the key immediately on the next request.
Treat your API key like a password. Never commit it to source control or embed
it in client-side code. Keep it in an environment variable or secret manager.
## Access & quota
Your key inherits the **subscription plan** on your account. The plan determines
both which data domains you can access and your request quota:
* A request for a domain your plan doesn't include returns **403
`FEATURE_NOT_IN_PLAN`** — see [Plans & features](/plans-and-features).
* Exceeding your per-minute weight budget returns **429
`RATE_LIMIT_EXCEEDED`** — see [Rate limits](/rate-limits).
## Authentication errors
| Code | Meaning |
| ------------------ | -------------------------------- |
| `API_KEY_REQUIRED` | No `X-API-Key` header was sent. |
| `API_KEY_INVALID` | The key is unknown or malformed. |
| `API_KEY_DISABLED` | The key has been revoked. |
| `API_KEY_EXPIRED` | The key has expired. |
All four return HTTP `401`. See [Error codes](/errors) for the full reference.
# Changelog
Source: https://developer.hayinsights.com/changelog
Notable changes to the HayInsights Open API.
**Initial preview release.**
* 40 read endpoints across six domains: Commodities, Crypto, ETF, FX, Macro and
Real Estate.
* Single-tier authentication via the `X-API-Key` header.
* Weighted, per-minute rate limiting with `X-RateLimit-*` headers.
* Plan-based feature gating (`_data` feature codes).
* Standard response envelope `{ success, statusCode, data, meta }`.
# Error codes
Source: https://developer.hayinsights.com/errors
HTTP status mapping, the error envelope, and how to handle errors.
Errors carry two signals:
* The **HTTP status** (4xx / 5xx).
* An **error envelope** in the body.
```json theme={null}
{
"success": false,
"statusCode": 401,
"error": { "code": "API_KEY_INVALID", "message": "Invalid API key" },
"meta": { "timestamp": "2026-06-19T08:34:08.023Z" }
}
```
`error.message` is usually a string, but for validation errors (400) it can be an
**array** of messages. `error.code` is specific for authentication and quota
errors; for validation and not-found it is `INTERNAL_ERROR` and the HTTP status
carries the meaning.
## HTTP status reference
| Status | Meaning | When |
| ------ | --------------------- | ------------------------------------------------------ |
| `200` | OK | Success — payload in `data`. |
| `400` | Bad Request | Missing or invalid parameter. |
| `401` | Unauthorized | Missing, invalid, disabled or expired API key. |
| `403` | Forbidden | Your plan doesn't include this feature. |
| `404` | Not Found | The requested resource does not exist. |
| `429` | Too Many Requests | Rate limit exceeded — see [Rate limits](/rate-limits). |
| `500` | Internal Server Error | Unexpected server error — retry with backoff. |
## Authentication errors (401)
No `X-API-Key` header was sent. Every `/openapi/v1/*` request requires one.
The key is unknown or malformed. Check for stray whitespace or a truncated
value.
The key has been revoked. Create a new one in the dashboard.
The key has expired. Create a new one in the dashboard.
## Authorization & quota errors
Your subscription plan doesn't include the requested data domain. Upgrade
from the dashboard — see [Plans & features](/plans-and-features).
You've consumed your plan's per-minute weight budget. Wait until
`X-RateLimit-Reset` (or `Retry-After` seconds) then retry — see
[Rate limits](/rate-limits).
## Validation & not-found (400 / 404)
A required query parameter is missing or a value is out of range. `error.message`
lists the specific problems, e.g. `"Type parameter is required"`.
The path references something that doesn't exist (e.g. an unknown commodity
slug or fund code).
## Handling strategy
`2xx` → read `data`. `4xx` / `5xx` → read `error.code` to classify.
Retry with backoff on `429` (until `Retry-After` / `X-RateLimit-Reset`) and
`5xx` (exponential backoff, a few attempts). Do **not** retry `400`, `401` or
`403` — fix the root cause first.
Capture `error.code`, `error.message`, `meta.timestamp`, the HTTP status and
the request path when reporting an issue.
# Introduction
Source: https://developer.hayinsights.com/introduction
Programmatic access to the HayInsights financial-data hub.
The **HayInsights Open API** gives you programmatic access to the HayInsights
financial-data hub — a single API surface under `/openapi/v1/*` covering six data
domains:
Spot prices, top movers, gold–DXY correlation and historical series.
Market overview, dominance, bubble map, on-chain and derivatives metrics.
Listings, performance & net-flow rankings, holdings, NAV growth, composition.
Summary, live table, 90-day correlation matrix and EM stress monitor.
GDP, CPI/PCE, exchange rates, population, government debt, rates & yields.
Statistics, land prices, provinces / wards and choropleth GeoJSON.
## Base URL
```
https://api-v2.hayinsights.com
```
A staging environment is available at `https://stg-api.hayinsights.com`.
## How it works
* **One credential.** Send your API key in the `X-API-Key` header on every
request. There is no request signing — see [Authentication](/authentication).
* **Plan-based access.** Which data domains you can call and how much you can
call them are governed by the subscription plan attached to your key — see
[Plans & features](/plans-and-features).
* **Weighted quota.** Each endpoint consumes a weighted amount of your
per-minute budget; every response returns `X-RateLimit-*` headers — see
[Rate limits](/rate-limits).
* **Consistent envelope.** Every response is wrapped in
`{ success, statusCode, data, meta }`.
## Response envelope
```json Success theme={null}
{
"success": true,
"statusCode": 200,
"data": { "...": "endpoint-specific payload" },
"meta": { "timestamp": "2026-06-19T08:31:59.478Z" }
}
```
```json Error theme={null}
{
"success": false,
"statusCode": 401,
"error": { "code": "API_KEY_INVALID", "message": "Invalid API key" },
"meta": { "timestamp": "2026-06-19T08:34:08.023Z" }
}
```
Get an API key and fetch live data in under 5 minutes.
# Plans & features
Source: https://developer.hayinsights.com/plans-and-features
How your subscription plan unlocks data domains.
Access to each data domain is controlled by a **feature** on your subscription
plan. Your API key inherits your account's plan, and entitlement is resolved live
on every request — so plan changes take effect immediately, with no need to
rotate your key.
## Feature codes
Each domain maps to one feature code:
| Domain | Feature code | Weight per call |
| ----------- | ------------------ | --------------- |
| Commodities | `commodities_data` | 3 |
| Crypto | `crypto_data` | 3 |
| ETF | `etf_data` | 8 |
| FX | `fx_data` | 3 – 6 |
| Macro | `macro_data` | 2 |
| Real Estate | `realestate_data` | 2 |
## When a feature isn't in your plan
Calling a domain your plan doesn't include returns **HTTP 403**:
```json theme={null}
{
"success": false,
"statusCode": 403,
"error": { "code": "FEATURE_NOT_IN_PLAN", "message": "Your plan does not include this feature" },
"meta": { "timestamp": "2026-06-19T08:34:08.100Z" }
}
```
To unlock the domain, upgrade your plan from the
[dashboard](https://app.hayinsights.com).
The exact mapping of plans (and their per-minute quota) to features is managed
in the dashboard and may change as new tiers are introduced. This page lists
the feature codes; your account page shows the features and quota active on
your current plan.
## How entitlement is resolved
1. Your `X-API-Key` identifies your account.
2. The account's **effective plan** is looked up.
3. The plan's **active features** determine which domains you may call, and its
**weight budget** determines your [rate limit](/rate-limits).
Because this happens per request, upgrading or downgrading is reflected
instantly.
# Quickstart
Source: https://developer.hayinsights.com/quickstart
Make your first request in under 5 minutes — just one header.
Every HayInsights endpoint needs a single header, `X-API-Key`. No request
signing, no token exchange.
Sign in to the [HayInsights dashboard](https://app.hayinsights.com) and go to
**Account → API keys** to create a key. It looks like `apk_…`.
Store it as an environment variable:
```bash theme={null}
export HAYINSIGHTS_API_KEY="apk_your_key_here"
```
Fetch crypto market dominance:
```bash cURL theme={null}
curl -H "X-API-Key: $HAYINSIGHTS_API_KEY" \
"https://api-v2.hayinsights.com/openapi/v1/crypto/dominance"
```
```typescript TypeScript theme={null}
const res = await fetch(
"https://api-v2.hayinsights.com/openapi/v1/crypto/dominance",
{ headers: { "X-API-Key": process.env.HAYINSIGHTS_API_KEY! } }
);
const json = await res.json();
console.log(json.data);
```
```python Python theme={null}
import os, requests
res = requests.get(
"https://api-v2.hayinsights.com/openapi/v1/crypto/dominance",
headers={"X-API-Key": os.environ["HAYINSIGHTS_API_KEY"]},
)
print(res.json()["data"])
```
Every response uses the standard envelope. The payload is in `data`:
```json theme={null}
{
"success": true,
"statusCode": 200,
"data": {
"totalMarketCap": 2157717188047.44,
"coins": [
{ "symbol": "BTC", "name": "Bitcoin", "dominancePercentage": 58.16, "marketCap": 1254870895730.76 },
{ "symbol": "ETH", "name": "Ethereum", "dominancePercentage": 9.48, "marketCap": 204564386727.13 }
]
},
"meta": { "timestamp": "2026-06-19T08:31:59.478Z" }
}
```
`success: true` means the call worked. On an error, `success` is `false` and
the details are in `error` — see [Error codes](/errors).
Every response carries rate-limit headers so you can self-throttle:
```
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 997
X-RateLimit-Reset: 1781857979
X-RateLimit-Weight-Used: 3
```
See [Rate limits](/rate-limits) for the weighting model.
## Next steps
How API keys work and how to rotate them.
All 40 endpoints across the six data domains.
Which plan unlocks which datasets.
Weighted quota and the `X-RateLimit-*` headers.
# Rate limits
Source: https://developer.hayinsights.com/rate-limits
A weighted, per-minute quota tied to your plan.
HayInsights uses a **weighted, sliding-window** rate limit. Instead of counting
requests, each call consumes a **weight** from your plan's per-minute budget.
Heavier endpoints (large aggregates) cost more than light ones.
## Headers
Every response — success or error — carries the current quota state:
| Header | Meaning |
| ------------------------- | ---------------------------------------------------- |
| `X-RateLimit-Limit` | Your plan's total weight budget per 1-minute window. |
| `X-RateLimit-Remaining` | Weight remaining in the current window. |
| `X-RateLimit-Reset` | Unix timestamp (seconds) when the window resets. |
| `X-RateLimit-Weight-Used` | Weight consumed by this request. |
```
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 997
X-RateLimit-Reset: 1781857979
X-RateLimit-Weight-Used: 3
```
## Endpoint weights
| Domain | Feature | Weight per call |
| ----------- | ------------------ | ------------------------------------------------------- |
| Macro | `macro_data` | 2 |
| Real Estate | `realestate_data` | 2 |
| Commodities | `commodities_data` | 3 |
| Crypto | `crypto_data` | 3 |
| FX | `fx_data` | 3 (`summary`, `table`) · 6 (`correlation`, `em-stress`) |
| ETF | `etf_data` | 8 |
Example: on a plan with a 1,000 weight/minute budget you can make roughly 333
macro calls (weight 2) **or** 125 ETF calls (weight 8) per minute. Mixing
endpoints draws from the same shared budget.
## Exceeding the limit
When you exhaust your budget the API returns **HTTP 429** with the
`RATE_LIMIT_EXCEEDED` code and a `Retry-After` header (seconds to wait):
```json theme={null}
{
"success": false,
"statusCode": 429,
"error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Rate limit exceeded" },
"meta": { "timestamp": "2026-06-19T08:34:09.000Z" }
}
```
## Handling 429 gracefully
Read the headers and back off until the window resets.
```typescript TypeScript theme={null}
async function get(url: string, key: string): Promise {
const res = await fetch(url, { headers: { "X-API-Key": key } });
if (res.status === 429) {
const wait = Number(res.headers.get("Retry-After") ?? 1);
await new Promise((r) => setTimeout(r, wait * 1000));
return get(url, key);
}
return res;
}
```
```python Python theme={null}
import time, requests
def get(url, key):
res = requests.get(url, headers={"X-API-Key": key})
if res.status_code == 429:
time.sleep(int(res.headers.get("Retry-After", 1)))
return get(url, key)
return res
```
Watch `X-RateLimit-Remaining` and slow down **before** you hit zero, rather than
reacting to 429s after the fact.