// reference

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

Quick start

Get live prices in 30 seconds. If you don’t have an API key yet, get one here.

GET/v1/latest
curl -H "X-API-Key: bullion_your_key" \
  "https://api.bullionapi.dev/v1/latest?currency=USD"
// endpoint
GET/v1/latest

Latest prices

Returns the most recent gold spot price and the FX rates needed to convert it into the requested base currency.

// parameters

Query parameters

NameTypeDescription
currencystringISO 4217 currency code. Defaults to USD. See supported currencies below.
unitstringOptional output mass unit: gram/g, kilogram/kg, or troy_oz/toz. Omit or leave empty for legacy toz; invalid values return 400.
api_keystringFallback credential for clients that cannot set the X-API-Key header. Prefer the header transport whenever possible.
// no-code

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.

text
GET https://api.bullionapi.dev/v1/latest?currency=USD&api_key=bullion_your_key
// response

Response

json
{
  "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.

// endpoint
GET/v1/carat

Gold karat prices per gram

Returns cached gold prices per gram for common karats. Gold is the only supported metal and grams are the only response unit.

// parameters

Query parameters

NameTypeDescription
currencystringThree-letter ISO 4217 code, case-insensitive. Defaults to USD; the currency must have cached gold data.
dateYYYY-MM-DDOptional exact UTC day. The final cached gold observation in that day is used.
api_keystringFallback credential for clients that cannot set the X-API-Key header. Prefer the header transport whenever possible.
// example

Example

GET/v1/carat
curl -H "X-API-Key: bullion_your_key" \
  "https://api.bullionapi.dev/v1/carat?currency=USD"
// response

Response

json
{
  "status": "success",
  "currency": "USD",
  "unit": "gram",
  "as_of": "2026-08-10T14:30:00.000Z",
  "karats": {
    "24k": 145.57407936,
    "23k": 139.50849272,
    "22k": 133.44290608,
    "21.6k": 131.01667142,
    "21k": 127.37731944,
    "18k": 109.18055952,
    "16k": 97.04938624,
    "14k": 84.91821296,
    "12k": 72.78703968,
    "10k": 60.6558664,
    "9k": 54.59027976,
    "8k": 48.52469312,
    "6k": 36.39351984
  }
}

Without date, the current cached gold row is used. With date, the final observation in that UTC day is used. Values are calculated from the exact karat ratio and rounded to eight decimal places. Malformed currency or date values return invalid_currency or invalid_date; a valid but unseeded currency or day returns no_data. Cache read failures return data_unavailable. Requests never bridge currencies or call upstream providers.

// endpoint
GET/v1/timeseries

Historical prices

Returns daily gold closes across a date range. Up to 365 days per request.

// parameters

Query parameters

NameTypeDescription
start_dateYYYY-MM-DDFirst day to include (inclusive).
end_dateYYYY-MM-DDLast day to include (inclusive). Max 365-day range.
currencystringISO 4217 base currency. Defaults to USD.
unitstringOptional output mass unit: gram/g, kilogram/kg, or troy_oz/toz. Omit or leave empty for legacy toz; invalid values return 400.
api_keystringFallback credential for clients that cannot set the X-API-Key header. Prefer the header transport whenever possible.
// example

Example

GET/v1/timeseries
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

Response

json
{
  "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.

// endpoint
GET/v1/change

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.

// parameters

Query parameters

NameTypeDescription
currencystringISO 4217 base currency. Defaults to USD.
start_dateYYYY-MM-DDFirst UTC day to compare. Use together with end_date.
end_dateYYYY-MM-DDLast UTC day to compare. Use together with start_date.
date_typestringRolling UTC window: yesterday (1 day), week (7 days), month (30 days), or year (365 days). Use instead of the explicit date pair.
api_keystringFallback credential for clients that cannot set the X-API-Key header. Prefer the header transport whenever possible.
// example

Example

GET/v1/change
curl -H "X-API-Key: bullion_your_key" \
  "https://api.bullionapi.dev/v1/change?currency=USD&date_type=week"
// response

Response

json
{
  "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.

// endpoint
GET/v1/rates/{region}

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.

// parameters

Path and query parameters

NameTypeDescription
regionpathUse us, uk, or eu for the requested macro region.
api_keystringFallback credential for clients that cannot set the X-API-Key header. Prefer the header transport whenever possible.
// example

Example

GET/v1/rates/us
curl -H "X-API-Key: bullion_your_key" \
  "https://api.bullionapi.dev/v1/rates/us"
GET/v1/rates/eu
curl -H "X-API-Key: bullion_your_key" \
  "https://api.bullionapi.dev/v1/rates/eu"
// response

Response

json
{
  "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.

// endpoint
GET/v1/central-bank-reserves

Annual central-bank reserves

Annual central-bank reserve values and gold share for Pro and Enterprise accounts. This endpoint is served from Bullion API’s automated cache.

// parameters

Query parameters

NameTypeDescription
countryISO2Optional case-insensitive country code, such as GB.
startYYYYOptional first observation year to include (inclusive).
endYYYYOptional last observation year to include (inclusive).
// example

Example

GET/v1/central-bank-reserves
curl -H "X-API-Key: bullion_your_key" \
  "https://api.bullionapi.dev/v1/central-bank-reserves?country=GB&start=2020&end=2025"
// response

Response

json
{
  "status": "success",
  "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.

// endpoint
GET/v1/central-bank-gold

Central-bank gold holdings

Monthly central-bank gold holdings for Pro and Enterprise accounts, served from Bullion API’s scheduled cache of official national central-bank feeds.

// parameters

Query parameters

NameTypeDescription
layerreported | estimated | bothUse reported. estimated and both remain accepted for response compatibility.
start / endYYYY-MMPaired inclusive month bounds, up to 120 months. Omit both for the latest twelve months.
countryISO2Optional case-insensitive reported-layer country filter, such as GB.
// example

Example

GET/v1/central-bank-gold
curl -H "X-API-Key: bullion_your_key" \
  "https://api.bullionapi.dev/v1/central-bank-gold?layer=reported&start=2021-01&end=2026-06"
// response

Response

json
{
  "status": "success",
  "query": { "layer": "reported", "start": "2021-01", "end": "2026-06", "country": null },
  "reported": {
    "status": "ready",
    "observations": [{
      "country": "GB", "month": "2026-06", "holdings_tonnes": 852.24,
      "net_change_tonnes": 6.22
    }],
    "latest_country_changes": [{ "country": "GB", "direction": "buying" }]
  },
  "estimated": {
    "status": "not_requested",
    "observations": []
  }
}

Reported holdings are sourced from Official national central-bank feeds, including the ECB Data Portal and the Bank of England Database.

// portfolio
GETPUT/v1/portfolio

Gold portfolio settings

Configure one private gold portfolio and its reporting currency. Both methods accept X-API-Key only; the api_key query parameter is not accepted for portfolio routes.

Existing and new keys start with portfolio access set to None. Grant Read for GET, or Read and write for GET and PUT, from the API keys dashboard. Write always includes read. Portfolio requests keep the rolling per-key and source-IP abuse limits but do not increment the monthly market-data quota.

// settings

Create or change the reporting currency

Send { "reporting_currency": "GBP" } with PUT. The value must be one of the supported currencies below and can change while the portfolio has no transactions.

// example

Read the portfolio

GET/v1/portfolio
curl -H "X-API-Key: bullion_your_key" \
  "https://api.bullionapi.dev/v1/portfolio"
// response

Empty portfolio response

json
{
  "status": "success",
  "portfolio": {
    "id": "d799789a-e1af-4c41-a79a-611e18f0df31",
    "metal": "gold",
    "reporting_currency": "GBP",
    "created_at": "2026-08-14T11:00:00.000Z",
    "updated_at": "2026-08-14T11:00:00.000Z"
  },
  "summary": {
    "gold_quantity_grams": "0.000000000000000",
    "cost_basis": "0.00000000",
    "realised_pnl": "0.00000000",
    "valuation": {
      "status": "unavailable",
      "spot_price": null,
      "current_value": null,
      "unrealised_pnl": null,
      "price_timestamp": null
    }
  }
}

Decimal summary values remain strings, including zero. Valuation comes from the latest stored gold spot price in the reporting currency and is current when that price is at most six hours old, stale when older, and unavailable when no matching-currency price exists — there is no cross-currency fallback and portfolio reads never call an upstream provider. When unavailable, spot_price, current_value, unrealised_pnl, and price_timestamp are null rather than zero; holdings and cost basis always remain available. Missing portfolios return portfolio_not_found, and keys without the required action return insufficient_scope.

// purchase

Record an exact purchase

POST /v1/portfolio/transactions with portfolio write access and an opaque Idempotency-Key header. Quantity accepts up to eight fractional digits in grams, kilograms, or troy ounces and is returned in grams at 15 decimal places. Money is returned as eight-place decimal strings using round-half-up.

bash
curl -X POST "https://api.bullionapi.dev/v1/portfolio/transactions" \
  -H "X-API-Key: bullion_your_key" \
  -H "Idempotency-Key: purchase-2026-08-19-001" \
  -H "content-type: application/json" \
   --data '{"transaction_date":"2026-08-19","quantity":"1.005","weight_unit":"troy_oz","unit_price":"2500.125","delivery_cost":"12.345678945","fees":"1.005","form":"coin","cgt_status":"exempt"}'

A repeated canonical request with the same key replays its original result. A changed request with that key returns 409 idempotency_conflict. Dates must be real calendar dates no later than today; descriptions are optional and limited to 500 characters. Invalid fields return 400 invalid_purchase with field details.

// allocation

List open lots and allocate a sale explicitly

GET /v1/portfolio/lots lists only your open purchase lots with a positive remaining quantity, ordered by purchase date, creation time, then ID. Each lot carries its stable lot_id, originating purchase_transaction_id, date, form, CGT status, remaining quantity, and remaining cost basis.

GET/v1/portfolio/lots
curl -H "X-API-Key: bullion_your_key" \
  "https://api.bullionapi.dev/v1/portfolio/lots"
json
{
  "status": "success",
  "lots": [{
    "lot_id": "22222222-2222-4222-8222-222222222222",
    "purchase_transaction_id": "11111111-1111-4111-8111-111111111111",
    "transaction_date": "2026-08-19",
    "form": "coin",
    "cgt_status": "exempt",
    "remaining_quantity_grams": "31.258994184000000",
    "remaining_cost_basis": "2525.97630395"
  }]
}

A sale defaults to FIFO lot selection. To choose the disposed lots yourself, send allocations on the sale body: an array of { "lot_id", "quantity_grams" } objects whose quantities sum exactly to the sale quantity. Every selected lot must belong to your account, match the sale's form and CGT treatment, predate or equal the sale date, and have enough remaining quantity. Any missing, foreign, duplicated, incompatible, over-allocated, or under-allocated lot fails the whole sale without mutation: eligibility and exact-sum violations return 400 invalid_allocation, lots dated after the sale return 400 sale_date_invalid, and exhausted selections return 409 insufficient_holdings. Committed sales report their allocation_method as fifo or explicit and return the committed allocations.

// history

Browse transaction history

GET /v1/portfolio/transactions returns only the authenticated owner's transactions. Results use the stable order transaction_date DESC, created_at DESC, id DESC. The limit defaults to 50 and is capped at 100. Follow the opaque cursor in next_cursorwith cursor for the next page; do not depend on its internal format.

GET/v1/portfolio/transactions?limit=50
curl -H "X-API-Key: bullion_your_key" \
  "https://api.bullionapi.dev/v1/portfolio/transactions?limit=50"
json
{
  "status": "success",
  "transactions": [{
    "type": "purchase",
    "version": 1,
    "id": "11111111-1111-4111-8111-111111111111",
    "transaction_date": "2026-08-19",
    "created_at": "2026-08-19T12:00:00.000Z",
    "entered_quantity": "1.00500000",
    "weight_unit": "troy_oz",
    "quantity_grams": "31.258994184000000",
    "unit_price": "2500.12500000",
    "gross_cost": "2512.62562500",
    "delivery_cost": "12.34567895",
    "fees": "1.00500000",
    "total_cost": "2525.97630395",
    "cost_per_gram": "80.80798407",
    "form": "coin",
    "cgt_status": "exempt",
    "description": "One-ounce gold coin",
    "lots": [{
      "id": "22222222-2222-4222-8222-222222222222",
      "open_quantity_grams": "31.258994184000000",
      "open_cost_basis": "2525.97630395"
    }],
    "allocations": [],
    "gross_proceeds": "0.00000000",
    "net_proceeds": "0.00000000",
    "disposed_cost": "0.00000000",
    "realised_pnl": "0.00000000"
  }],
  "next_cursor": null
}

GET /v1/portfolio/transactions/{id} returns the same transaction representation, including its open lot and allocation collections. Decimal quantities and monetary values are always strings. Invalid page parameters return invalid_limit or invalid_cursor; missing and cross-account identifiers return transaction_not_found.

// deletion

Delete a transaction

DELETE /v1/portfolio/transactions/{id} removes an owned purchase or sale with portfolio write access and rebalances your holdings. Send the transaction's version as an ETag-style If-Match header ("1"); a missing or mismatched version returns 412 stale_transaction without mutating anything. Deleting a sale restores every allocated quantity and cost basis to its originating purchase lot.

bash
curl -X DELETE "https://api.bullionapi.dev/v1/portfolio/transactions/11111111-1111-4111-8111-111111111111" \
  -H "X-API-Key: bullion_your_key" \
  -H 'If-Match: "1"'
json
{ "status": "success", "deleted_transaction_id": "11111111-1111-4111-8111-111111111111" }

A purchase that has already funded a sale cannot be deleted and returns 409 transaction_in_use; delete the dependent sale first. Missing and cross-account identifiers return transaction_not_found.

// rate limits

Rate limits

Authenticated successful market-data /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. Portfolio responses omit these monthly quota headers because portfolio operations do not use the monthly market-data quota. 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.

HeaderTypeDescription
x-ratelimit-limitintegerYour plan’s monthly cap.
x-ratelimit-usedintegerRequests used this month.
x-ratelimit-remainingintegerRequests remaining.
x-ratelimit-resetISO 8601When the quota resets (1st 00:00 UTC).
X-API-CURRENTintegerCompatibility alias for x-ratelimit-used.
X-API-QUOTAintegerCompatibility alias for x-ratelimit-limit.
// errors

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
HTTP/1.1 401 Unauthorized
content-type: application/json

{
  "status": "error",
  "error": {
    "code": "missing_api_key",
    "message": "Missing API key"
  }
}

401 — Conflicting credentials

http
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
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
HTTP/1.1 429 Too Many Requests
retry-after: 42

{
  "status": "error",
  "error": {
    "code": "rate_limited",
    "message": "Rate limit exceeded"
  }
}

400 — Bad request

http
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
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

CodeStatusDescription
config_error500The API is not configured correctly.
billing_state_conflict503The billing state needs support attention.
annual_billing_unavailable503Annual billing is not currently available.
billing_interval_change_conflict409The billing interval change conflicts with current billing state.
billing_interval_change_expired409The billing interval change preview has expired.
billing_interval_change_failed402The billing interval change payment failed.
billing_interval_change_invalid400The billing interval change is invalid.
billing_interval_change_processing409The billing interval change is already processing.
billing_cancellation_conflict409The subscription cancellation conflicts with current billing state.
billing_cancellation_failed503The subscription cancellation could not be applied.
billing_cancellation_invalid400The subscription cancellation is invalid.
conflicting_credentials401The supplied API-key credentials do not match.
data_unavailable503The requested data is not available.
email_not_verified403The API-key owner must verify their email address.
invalid_api_key401The API key is invalid or revoked.
invalid_country400The country code is invalid.
invalid_currency400The reporting currency is invalid.
invalid_date400The date format is invalid.
invalid_layer400The central-bank gold layer is invalid.
invalid_range400The requested range is invalid.
invalid_region400The macro region is invalid.
invalid_unit400The requested output unit is invalid.
invalid_year400The year format is invalid.
method_not_allowed405The API does not support this method.
missing_api_key401An API key is required.
missing_params400Required request parameters are missing.
no_data404Cached data is not available.
plan_required403The request requires an eligible subscription plan.
quota_exceeded429The monthly request quota has been exceeded.
rate_limited429The API key has exceeded its rolling request window.
unauthenticated401A signed-in session is required.
api_key_not_found404The API key was not found.
insufficient_scope403The API key lacks the required portfolio scope.
invalid_portfolio_permission400The portfolio permission is invalid.
portfolio_not_found404The account does not have a portfolio.
portfolio_currency_locked409The reporting currency is locked after the first purchase.
missing_idempotency_key400An Idempotency-Key header is required for portfolio mutations.
invalid_purchase400The purchase request is invalid.
invalid_sale400The sale request is invalid.
invalid_allocation400The selected sale lots are invalid. Lots must belong to the account, match the sale form and CGT treatment, and the allocated quantities must sum exactly to the sale quantity.
idempotency_conflict409The Idempotency-Key was already used with another request.
invalid_cursor400The transaction history cursor is invalid.
invalid_limit400The transaction history page size is invalid.
transaction_not_found404The transaction was not found.
stale_transaction412The transaction was modified by another request. Refresh and retry.
transaction_in_use409Gold from this purchase has been sold and cannot be deleted.
sale_date_invalid400The sale date is invalid.
insufficient_holdings409The portfolio does not have enough gold for this sale.
// currencies

Supported currencies

Pass any of these ISO 4217 codes as the currency query parameter. Defaults to USD.

USDEURGBPJPYCHFCADAUDNZDCNYHKDSGDSEKNOKDKKPLNCZKHUFTRYZARINRKRWBRLMXNAEDSARILSTHBIDRMYRPHP
// mcp server

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.

// one-click install

Install in Cursor · Install in VS Code

// manual install

Claude Desktop, ChatGPT (Settings → Connectors) and other clients: add the server with your API key as a Bearer token.

json
{
  "mcpServers": {
    "bullion": {
      "type": "http",
      "url": "https://mcp.bullionapi.dev",
      "headers": { "Authorization": "Bearer bullion_your_key" }
    }
  }
}
// terminal CLI

Use the CLI

For people working in a terminal, @paulund/bullion-cli provides a focused command-line view of the cached gold price data.

bash
npm install --global @paulund/bullion-cli
export BULLION_API_KEY=your_key_here
bullion --asset gold
npx @paulund/bullion-cli --asset gold --currency EUR

This is the terminal-user path. For AI agents, see the MCP server documentation.

// machine-readable

OpenAPI spec

The full API contract as OpenAPI 3.1, for code-gen, Postman and AI function-calling clients: api.bullionapi.dev/openapi.json.