API documentation
Use the X-API-Key header as the canonical and preferred credential transport. Clients that cannot set custom headers can use the api_key query parameter as a fallback. Base URL is https://api.bullionapi.dev. Usage increments after API-key and quota checks but before endpoint validation.
Query credentials may appear in browser history, copied URLs, referrers, intermediary infrastructure, and logs. Use the X-API-Key header whenever your client supports custom headers. Query authentication does not enable cross-origin browser fetch; CORS remains separate. If both transports are supplied, they must match; differing values return 401 conflicting_credentials.
Quick start
Get live prices in 30 seconds. If you don’t have an API key yet, get one here.
curl -H "X-API-Key: bullion_your_key" \
"https://api.bullionapi.dev/v1/latest?currency=USD"Latest prices
Returns the most recent gold spot price and the FX rates needed to convert it into the requested base currency.
Query parameters
| Name | Type | Description |
|---|---|---|
currency | string | ISO 4217 currency code. Defaults to USD. See supported currencies below. |
unit | string | Optional output mass unit: gram/g, kilogram/kg, or troy_oz/toz. Omit or leave empty for legacy toz; invalid values return 400. |
api_key | string | Fallback credential for clients that cannot set the X-API-Key header. Prefer the header transport whenever possible. |
Spreadsheet and no-code example
For a client that cannot set custom headers, request the URL below. Treat the URL as a secret and prefer the header transport whenever your client supports it.
GET https://api.bullionapi.dev/v1/latest?currency=USD&api_key=bullion_your_keyResponse
{
"status": "success",
"currency": "USD",
"unit": "toz",
"metals": { "gold": 4527.86 },
"currencies": { "EUR": 0.9134, "GBP": 0.7783, "JPY": 154.22, "CAD": 1.3715 },
"timestamps": { "metal": "2026-07-08T11:58:50.781Z", "currency": "2026-07-08T11:58:50.781Z" }
}Cached for 1 hour and refreshed by the scheduled data pipeline. Prices default to troy ounces (toz). Request unit=gram or unit=kilogram for converted values; aliases are g, kg, and troy_oz. Results are rounded to eight decimal places.
Historical prices
Returns daily gold closes across a date range. Up to 365 days per request.
Query parameters
| Name | Type | Description |
|---|---|---|
start_date | YYYY-MM-DD | First day to include (inclusive). |
end_date | YYYY-MM-DD | Last day to include (inclusive). Max 365-day range. |
currency | string | ISO 4217 base currency. Defaults to USD. |
unit | string | Optional output mass unit: gram/g, kilogram/kg, or troy_oz/toz. Omit or leave empty for legacy toz; invalid values return 400. |
api_key | string | Fallback credential for clients that cannot set the X-API-Key header. Prefer the header transport whenever possible. |
Example
curl -H "X-API-Key: bullion_your_key" \
"https://api.bullionapi.dev/v1/timeseries?currency=USD&start_date=2025-07-08&end_date=2026-07-08"Response
{
"status": "success",
"currency": "USD",
"unit": "toz",
"start_date": "2025-07-08",
"end_date": "2026-07-08",
"rates": {
"2025-07-08": {
"currencies": { "EUR": 0.9134, "GBP": 0.7783 },
"date": "2025-07-08",
"metals": { "gold": 3320.10 }
},
"2025-07-09": {
"currencies": { "EUR": 0.9141, "GBP": 0.7790 },
"date": "2025-07-09",
"metals": { "gold": 3342.55 }
}
}
}Only cached dates are included in rates. Scheduled refresh and backfill jobs populate the cache; API requests never call upstream providers. Prices default to troy ounces (toz). Request unit=gram or unit=kilogram for converted values; aliases are g, kg, and troy_oz. Results are rounded to eight decimal places; FX rates and date metadata are unchanged.
Gold price change
Returns gold's absolute and percentage change between the final cached observation in two UTC days. The endpoint reads the database cache and never calls an upstream provider.
Query parameters
| Name | Type | Description |
|---|---|---|
currency | string | ISO 4217 base currency. Defaults to USD. |
start_date | YYYY-MM-DD | First UTC day to compare. Use together with end_date. |
end_date | YYYY-MM-DD | Last UTC day to compare. Use together with start_date. |
date_type | string | Rolling UTC window: yesterday (1 day), week (7 days), month (30 days), or year (365 days). Use instead of the explicit date pair. |
api_key | string | Fallback credential for clients that cannot set the X-API-Key header. Prefer the header transport whenever possible. |
Example
curl -H "X-API-Key: bullion_your_key" \
"https://api.bullionapi.dev/v1/change?currency=USD&date_type=week"Response
{
"status": "success",
"currency": "USD",
"metal": "gold",
"start_date": "2026-08-03",
"end_date": "2026-08-10",
"start_price": 4500,
"end_price": 4600,
"change": 100,
"change_pct": 2.2222
}The final observation in each UTC day is selected deterministically. Use either both explicit dates or one date_type; mixing them returns conflicting_params. Absolute change is rounded to eight decimal places and change_pct to four. Invalid dates return invalid_date; reversed or overlong ranges return invalid_range; unsupported date types return invalid_date_type. Missing cached data returns no_change_data; a zero start price returns invalid_change_baseline.
US, UK, and euro-area macro rates
Returns the latest stored macro observations for us, uk, or eu. Each series keeps its own observation period, so the response does not expose one region-wide as_of value. The euro-area response identifies its geography as euro_area; uk provides Bank Rate and CPI.
Path and query parameters
| Name | Type | Description |
|---|---|---|
region | path | Use us, uk, or eu for the requested macro region. |
api_key | string | Fallback credential for clients that cannot set the X-API-Key header. Prefer the header transport whenever possible. |
Example
curl -H "X-API-Key: bullion_your_key" \
"https://api.bullionapi.dev/v1/rates/us"curl -H "X-API-Key: bullion_your_key" \
"https://api.bullionapi.dev/v1/rates/eu"Response
{
"status": "success",
"region": "us",
"policy": {
"policy_target_lower": {
"series_id": "policy_target_lower",
"value": 3.5,
"unit": "percent",
"observation_period": "2026-07-30",
"method": "latest",
"source_series_id": "EFFR.targetRateFrom",
"source_id": "ny_fed",
"attribution": "Federal Reserve Bank of New York",
"fetched_at": "2026-08-01T06:00:00.000Z"
},
"policy_target_upper": {
"series_id": "policy_target_upper",
"value": 3.75,
"unit": "percent",
"observation_period": "2026-07-30",
"method": "latest",
"source_series_id": "EFFR.targetRateTo",
"source_id": "ny_fed",
"attribution": "Federal Reserve Bank of New York",
"fetched_at": "2026-08-01T06:00:00.000Z"
},
"effective_federal_funds_rate": {
"series_id": "effective_federal_funds_rate",
"value": 3.63,
"unit": "percent",
"observation_period": "2026-07-30",
"method": "latest",
"source_series_id": "EFFR",
"source_id": "ny_fed",
"attribution": "Federal Reserve Bank of New York",
"fetched_at": "2026-08-01T06:00:00.000Z"
}
},
"yields": {
"treasury_nominal_yield_10y": {
"series_id": "treasury_nominal_yield_10y",
"value": 4.25,
"unit": "percent",
"observation_period": "2026-06-30",
"method": "monthly_average",
"source_series_id": "BC_10YEAR",
"source_id": "us_treasury",
"attribution": "U.S. Department of the Treasury",
"fetched_at": "2026-08-01T06:00:00.000Z"
}
},
"inflation": {
"cpi_u_yoy": {
"series_id": "cpi_u_yoy",
"value": 2.7,
"unit": "percent",
"observation_period": "2026-06-30",
"method": "latest",
"source_series_id": "CUUR0000SA0",
"source_id": "bls",
"attribution": "U.S. Bureau of Labor Statistics",
"fetched_at": "2026-08-01T06:00:00.000Z"
}
}
}Every observation includes its stable Bullion API series ID, numeric value, unit, observation period, calculation method, source series ID, source ID, attribution, and fetch time. UK gilt curves include nominal and real zero-coupon spot yields plus RPI-linked implied inflation at 2Y, 5Y, 10Y, and 30Y tenors, using official month-end archive dates with the month_end method. The API reads the database cache; protected cron collection is the only upstream caller. Free, Pro, and Enterprise keys receive the same data contract, with only existing quota limits differing.
Methodology: Treasury nominal and real yields cover nominal 2Y, 5Y, 10Y, and 30Y plus real 5Y, 10Y, and 30Y series; each is an arithmetic average of valid daily observations in complete UTC calendar months. Treasury 5Y, 10Y, and 30Y breakevens are daily nominal-minus-real differences calculated only on common dates, then averaged by month. Empty, missing, and N/A Treasury values are absent rather than treated as zero. The BLS CPI-U NSA series CUUR0000SA0 is exposed as year-over-year percent; when BLS does not publish an annual-percent field, Bullion API calculates the twelve-month change from the same month in the prior year. UK Bank Rate uses the latest valid BoE IUDBEDR observation for each date in the refresh range; UK CPI uses the latest numeric monthly ONS D7G7 annual-rate value, stored at month end. UK curve values are direct BoE spot observations and BoE-derived RPI-linked implied inflation values; source dates are preserved, including final business days. Neither UK curve values nor UK Bank Rate/CPI are averaged.
Euro-area data includes ECB deposit facility, main refinancing, and marginal lending rates; AAA nominal 2Y, 5Y, 10Y, and 30Y spot yields; metadata-verified all-items HICP year-over-year inflation as ecb_hicp_yoy; and Consumer Expectations Survey weighted-median 12-month and five-year inflation expectations. CES values use survey_expectationand are not market-implied. ECB AAA yields are arithmetic averages of valid observations from complete UTC calendar months. HICP uses HICP.M.U2.N.000000.4D0.ANR and the provider validates its geography, adjustment, all-items, unit, and annual-rate metadata before accepting rows.
Sources: Federal Reserve Bank of New York reference rates, U.S. Department of the Treasury Daily Interest Rate XML Feed, Bank of England Database and BoE yield curve archives, plus Office for National Statistics D7G7 CPI series, and U.S. Bureau of Labor Statistics Public Data API, and the European Central Bank Data Portal. BLS disclaimer: BLS.gov cannot vouch for the data or analyses derived from these data after retrieval.
Annual central-bank reserves
Annual central-bank reserve values and gold sharefor Pro and Enterprise accounts. This endpoint is served from Bullion API’s automated cache.
Query parameters
| Name | Type | Description |
|---|---|---|
country | ISO2 | Optional case-insensitive country code, such as GB. |
start | YYYY | Optional first observation year to include (inclusive). |
end | YYYY | Optional last observation year to include (inclusive). |
Example
curl -H "X-API-Key: bullion_your_key" \
"https://api.bullionapi.dev/v1/central-bank-reserves?country=GB&start=2020&end=2025"Response
{
"status": "success",
"source": {
"name": "World Bank, World Development Indicators",
"underlying_provider": "International Monetary Fund, International Financial Statistics",
"url": "https://data.worldbank.org/"
},
"methodology": {
"gold_reserve_value_usd": "total reserves including gold minus total reserves excluding gold",
"annual_gold_value_change_usd": "current derived gold reserve value minus the prior calendar year",
"transformation_notice": "Bullion API derives gold reserve values, shares, and annual value changes.",
"warning": "Annual value changes combine holdings changes, gold-price movement, and revisions and do not measure tonnes bought or sold."
},
"coverage": {
"countries": 1,
"start_year": 2020,
"end_year": 2025,
"source_updated_at": "2026-07-13",
"fetched_at": "2026-07-30T07:10:00.000Z"
},
"reserves": [{
"country": "GB",
"country_iso3": "GBR",
"country_name": "United Kingdom",
"as_of_year": 2025,
"total_reserves_usd": 200000000000,
"reserves_excluding_gold_usd": 175000000000,
"gold_reserve_value_usd": 25000000000,
"gold_share_pct": 12.5,
"annual_gold_value_change_usd": 10000000000,
"data_quality": null
}]
}Source: World Bank, World Development Indicators. The underlying provider is International Monetary Fund, International Financial Statistics. Annual value changes combine holdings changes, gold-price movement, and revisions and do not measure tonnes bought or sold.
Rate limits
Authenticated successful /v1 responses include these headers so you can track usage in real time. X-API-CURRENT and X-API-QUOTA are additive compatibility aliases; the existing x-ratelimit-* names remain supported. Each API key also permits 60 requests per rolling 60-second window across REST and hosted MCP; short-window denials return rate_limitedand do not consume monthly quota.
| Header | Type | Description |
|---|---|---|
| x-ratelimit-limit | integer | Your plan’s monthly cap. |
| x-ratelimit-used | integer | Requests used this month. |
| x-ratelimit-remaining | integer | Requests remaining. |
| x-ratelimit-reset | ISO 8601 | When the quota resets (1st 00:00 UTC). |
| X-API-CURRENT | integer | Compatibility alias for x-ratelimit-used. |
| X-API-QUOTA | integer | Compatibility alias for x-ratelimit-limit. |
Error responses
This is a breaking change: application-authored errors from every current /v1/*route now use one nested envelope. Clients must stop reading legacy top-level error, code, and quota fields. The HTTP status remains the source of truth.
401 — Missing API key
HTTP/1.1 401 Unauthorized
content-type: application/json
{
"status": "error",
"error": {
"code": "missing_api_key",
"message": "Missing API key"
}
}401 — Conflicting credentials
HTTP/1.1 401 Unauthorized
content-type: application/json
{
"status": "error",
"error": {
"code": "conflicting_credentials",
"message": "Conflicting API key credentials"
}
}429 — Monthly quota exceeded
HTTP/1.1 429 Too Many Requests
x-ratelimit-limit: 30
x-ratelimit-used: 30
x-ratelimit-remaining: 0
x-ratelimit-reset: 2026-08-01T00:00:00.000Z
X-API-CURRENT: 30
X-API-QUOTA: 30
retry-after: 86400
{
"status": "error",
"error": {
"code": "quota_exceeded",
"message": "Your monthly usage limit has been reached. Please upgrade your subscription plan.",
"plan": "free",
"used": 30,
"limit": 30,
"reset_at": "2026-08-01T00:00:00.000Z"
}
}429 — Rolling API-key limit
HTTP/1.1 429 Too Many Requests
retry-after: 42
{
"status": "error",
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded"
}
}400 — Bad request
HTTP/1.1 400 Bad Request
content-type: application/json
{
"status": "error",
"error": {
"code": "invalid_range",
"message": "start_date must be <= end_date"
}
}400 — Invalid unit
HTTP/1.1 400 Bad Request
content-type: application/json
{
"status": "error",
"error": {
"code": "invalid_unit",
"message": "unit must be one of: gram, g, kilogram, kg, troy_oz, toz"
}
}Registered error codes
| Code | Status | Description |
|---|---|---|
| config_error | 500 | The API is not configured correctly. |
| billing_state_conflict | 503 | The billing state needs support attention. |
| annual_billing_unavailable | 503 | Annual billing is not currently available. |
| billing_interval_change_conflict | 409 | The billing interval change conflicts with current billing state. |
| billing_interval_change_expired | 409 | The billing interval change preview has expired. |
| billing_interval_change_failed | 402 | The billing interval change payment failed. |
| billing_interval_change_invalid | 400 | The billing interval change is invalid. |
| billing_interval_change_processing | 409 | The billing interval change is already processing. |
| billing_cancellation_conflict | 409 | The subscription cancellation conflicts with current billing state. |
| billing_cancellation_failed | 503 | The subscription cancellation could not be applied. |
| billing_cancellation_invalid | 400 | The subscription cancellation is invalid. |
| conflicting_credentials | 401 | The supplied API-key credentials do not match. |
| data_unavailable | 503 | The requested data is not available. |
| email_not_verified | 403 | The API-key owner must verify their email address. |
| invalid_api_key | 401 | The API key is invalid or revoked. |
| invalid_country | 400 | The country code is invalid. |
| invalid_date | 400 | The date format is invalid. |
| invalid_range | 400 | The requested range is invalid. |
| invalid_region | 400 | The macro region is invalid. |
| invalid_unit | 400 | The requested output unit is invalid. |
| invalid_year | 400 | The year format is invalid. |
| method_not_allowed | 405 | The API does not support this method. |
| missing_api_key | 401 | An API key is required. |
| missing_params | 400 | Required request parameters are missing. |
| plan_required | 403 | The request requires an eligible subscription plan. |
| quota_exceeded | 429 | The monthly request quota has been exceeded. |
| rate_limited | 429 | The API key has exceeded its rolling request window. |
| unauthenticated | 401 | A signed-in session is required. |
Supported currencies
Pass any of these ISO 4217 codes as the currency query parameter. Defaults to USD.
Use from Claude, ChatGPT, Cursor
Bullion hosts an MCP server at https://mcp.bullionapi.dev. AI clients call the get_gold_latest tool directly — same API key, same quota.
Install in Cursor · Install in VS Code
Claude Desktop, ChatGPT (Settings → Connectors) and other clients: add the server with your API key as a Bearer token.
{
"mcpServers": {
"bullion": {
"type": "http",
"url": "https://mcp.bullionapi.dev",
"headers": { "Authorization": "Bearer bullion_your_key" }
}
}
}Use the CLI
For people working in a terminal, @paulund/bullion-cli provides a focused command-line view of the cached gold price data.
npm install --global @paulund/bullion-cli
export BULLION_API_KEY=your_key_here
bullion --asset gold
npx @paulund/bullion-cli --asset gold --currency EURThis is the terminal-user path. For AI agents, see the MCP server documentation.
OpenAPI spec
The full API contract as OpenAPI 3.1, for code-gen, Postman and AI function-calling clients: api.bullionapi.dev/openapi.json.