Gold (XAU) latest JSON from Metals-API — quality sample 28 Sep 2026
You need a reliable JSON tick for Gold (XAU) to power a finance use case like a live price widget in a web app or an internal pricing service that quotes USD per troy ounce. By the end of this guide, you will call Metals-API’s /latest endpoint, parse the Gold price, cache it, and update on an interval while handling weekends and market pauses correctly.
What we’re building: a live Gold price for Finance use cases
We will implement a small component that fetches the latest Gold (XAU) price from Metals-API, exposes USD per troy ounce for display and quoting, and falls back to the most recent cached value when new ticks aren’t available. This is the core of:
- A lightweight finance widget that shows live XAU/USD.
- An internal pricing service that computes quotes for orders in troy ounces and grams.
- A data layer feeding alerts or dashboards in trading and treasury tools.
All calls will use Metals-API endpoints described in the Documentation. You can get a free API key here: Register.
Step 1 — Get your access key and confirm symbols
Sign up to obtain your access_key. You’ll pass it as a query parameter to authenticate.
Gold uses the symbol XAU (1 troy ounce of gold). Metals-API supports fiat currency codes and a set of metal symbols. Confirm the symbols you need, including USDXAU (USD per 1 XAU), in the official list: Symbols.
We will query these three symbols in one call:
- XAU — units of XAU per 1 USD (inverse of USD per ounce).
- USD — a passthrough of the base currency (1).
- USDXAU — USD per 1 XAU (direct spot-style price).
Step 2 — Call the /latest endpoint for Gold
The /latest endpoint returns most recent rates for requested symbols with a specified base currency. We will request base=USD and the symbols XAU, USD, and USDXAU.
Complete curl you can paste
curl -s "https://metals-api.com/api/latest?access_key=YOUR_API_KEY&base=USD&symbols=XAU,USD,USDXAU"
Notes:
- Replace YOUR_API_KEY with your real key from the Register page.
- base=USD makes all rates relative to 1 USD. In this configuration, XAU is “how many troy ounces per USD,” while USDXAU is “how many USD per troy ounce.”
- Request only the symbols you use to minimize payload size and processing.
Step 3 — Understand the JSON fields that matter
Here is a realistic JSON sample for this request (the values below are the provided example for illustrative integration purposes only):
{
"success": true,
"timestamp": 1790605080,
"date": "2026-09-28",
"base": "USD",
"rates": {
"XAU": 0.000241592578276,
"USD": 1,
"USDXAU": 4139.199999999921
}
}
Key fields to use:
- success — boolean indicating the request worked.
- timestamp — UNIX seconds (UTC) for the last update applied to these rates. Use it to detect staleness and to log when a tick changed.
- date — calendar day associated with the timestamp (UTC).
- base — the base currency you requested (USD here).
- rates — a map of symbol to numeric quote:
- rates.XAU — XAU per 1 USD. Invert to get USD per XAU: 1 / rates.XAU.
- rates.USDXAU — USD per 1 XAU (a direct spot-style figure).
- rates.USD — echo of the base: 1.
Units and conversions you will actually use
- Metals-API quotes metals in troy ounces. 1 troy ounce = 31.1034768 grams. To convert USD per XAU to USD per gram, divide by 31.1034768.
- If you requested base=USD and you need “USD per XAU,” read rates.USDXAU directly. If you only requested XAU, compute USD per XAU as 1 / rates.XAU.
- For quotes in other currencies, set base to that currency, or use the conversion endpoint (see the Documentation for details).
Symbol roles compared
| Symbol | Meaning (with base=USD) | Typical Use |
|---|---|---|
| XAU | XAU per 1 USD (ounces per dollar) | For inverse math or cross-quoting; invert to get USD per XAU |
| USDXAU | USD per 1 XAU (dollars per ounce) | Direct price for display and trading logic |
| USD | 1 (base passthrough) | Baseline for sanity checks |
Step 4 — JavaScript sample that polls and caches the last value
The following Node.js-style example fetches the latest Gold price at an interval, caches the last known good value in memory, and handles stale ticks by reusing the cache. You can adapt this to a browser (using appropriate CORS and API key handling) or a backend service.
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
const ACCESS_KEY = process.env.METALS_API_KEY || 'YOUR_API_KEY';
const ENDPOINT = 'https://metals-api.com/api/latest';
const SYMBOLS = 'XAU,USD,USDXAU';
const BASE = 'USD';
// In-memory cache
let cache = {
timestamp: 0, // UNIX seconds
date: null, // ISO date string
usdPerXau: null, // number
raw: null // original payload for debugging
};
// Helper: convert USD per XAU to USD per gram
function usdPerGram(usdPerXau) {
const TROY_OUNCE_TO_GRAMS = 31.1034768;
return usdPerXau / TROY_OUNCE_TO_GRAMS;
}
// Fetch latest and update cache if newer
async function fetchLatestGold() {
const url = `${ENDPOINT}?access_key=${ACCESS_KEY}&base=${BASE}&symbols=${SYMBOLS}`;
const res = await fetch(url, { timeout: 8000 });
if (!res.ok) {
throw new Error(`HTTP ${res.status}`);
}
const data = await res.json();
if (!data.success || !data.rates) {
throw new Error('API returned an error or missing rates');
}
// Prefer direct USDXAU; fallback to invert if not present
const usdPerXau = typeof data.rates.USDXAU === 'number'
? data.rates.USDXAU
: (data.rates.XAU > 0 ? 1 / data.rates.XAU : null);
if (typeof usdPerXau !== 'number' || !isFinite(usdPerXau)) {
throw new Error('Invalid USD/XAU value');
}
// Only update if the payload is newer than our cache
const ts = Number(data.timestamp) || 0;
if (ts > cache.timestamp) {
cache = {
timestamp: ts,
date: data.date || null,
usdPerXau,
raw: data
};
}
return {
usdPerXau: cache.usdPerXau,
usdPerGram: usdPerGram(cache.usdPerXau),
timestamp: cache.timestamp,
date: cache.date
};
}
// Poller with basic jitter and graceful fallback to cache
async function poll(intervalMs = 15000) {
const jitter = () => Math.floor(Math.random() * 400); // spread calls slightly
setInterval(async () => {
try {
const quote = await fetchLatestGold();
// Replace with your own publish/broadcast/log
console.log(`[XAU] ${quote.usdPerXau.toFixed(2)} USD/oz | ${quote.usdPerGram.toFixed(2)} USD/g | ${quote.date} (ts=${quote.timestamp})`);
} catch (err) {
// On failure, serve the cached value if present
if (cache.usdPerXau) {
console.warn(`Using cached XAU due to error: ${err.message}`);
console.log(`[XAU][cached] ${cache.usdPerXau.toFixed(2)} USD/oz | ${usdPerGram(cache.usdPerXau).toFixed(2)} USD/g | ${cache.date} (ts=${cache.timestamp})`);
} else {
console.error(`No cached XAU available yet: ${err.message}`);
}
}
}, intervalMs + jitter());
}
// Kick off the poller
poll(15000); // ~15s cadence; adjust per your rate budget and UI needs
What this code does for a finance-grade workflow:
- Prefers rates.USDXAU to avoid inversion error; falls back to 1 / rates.XAU if necessary.
- Keeps an in-memory cache to survive transient failures or market pauses.
- Honors timestamps to avoid replacing a newer cache with an older response.
- Calculates per-gram pricing for downstream product or fee calculations.
Step 5 — Refresh frequency, budgeting, and closed-market behavior
Unlike equities, Gold trades nearly 24x5 with weekend downtime and occasional holidays. Planning for real-time finance usage means thinking in terms of update cadence, market hours, and caching.
How often should you poll?
- UI widgets: 10–30 seconds is typically sufficient. Faster refreshes rarely improve user perception but consume more budget.
- Pricing services: align to your internal SLAs. If you reprice inventory every minute, a 10–15s poll with caching covers transient gaps.
- Backtests and analytics: avoid polling; use historical endpoints and time series.
Respect your rate budget
- Batch symbols you need into one /latest call using the symbols parameter.
- Cache server-side and fan out to clients via websockets or SSE to prevent duplicate API calls per user.
- Add a small random jitter to spread calls and avoid thundering herds at exact intervals.
When markets are closed or quiet
- Weekends and holidays: the timestamp may stop advancing. Keep serving the last good tick with a “last updated” label.
- Staleness checks: compare the response timestamp to your cache. If unchanged, don’t invalidate; continue outputting the cached figure.
- Error handling: timeouts or upstream errors should not break your UI; log the error and use cache.
Timezone, timestamp, and auditability
- timestamp is UNIX seconds in UTC. Convert it carefully for display and logging.
- Store both timestamp and date from the response for audit trails.
- If you persist quotes, also persist the raw payload for reconciliation.
Putting it together: compute the values you need
With base=USD, you have two straightforward ways to show and use a Gold spot:
- Direct approach: use rates.USDXAU as USD per ounce.
- Inverse approach: compute 1 / rates.XAU to derive USD per ounce.
From there, derive downstream units often needed in finance and commerce:
- USD per gram = USD per ounce / 31.1034768.
- USD per kilogram = USD per ounce × (1000 / 31.1034768).
- Quote adjustments: apply fees, spreads, or taxes on top of USD per gram or USD per ounce as needed.
Validation tips before you ship
- Cross-check that 1 / rates.XAU is close to rates.USDXAU within rounding tolerance.
- Confirm base is set to the currency you price in; otherwise your math will be inverted.
- Ensure your decimals and locales don’t truncate or reformat numbers incorrectly. Keep numbers as floats for calculations and format only for display.
- Log both timestamp and date so you can detect unchanged ticks during quiet periods.
Optional next steps for Finance workflows
Once your live price is running, consider expanding data coverage using endpoints also documented by Metals-API:
- Historical rates — backfill charts and verify day-over-day moves accurately.
- Time series — pull windows of data for analytics without many individual calls.
- Fluctuation — compute range and percentage movement over a period.
- Conversion — rebase to different currencies for localized pricing and P&L.
- OHLC — obtain open/high/low/close aggregates for charting and risk models.
If you are building against a compliance or governance framework, review Metals-API’s Market Coverage Profile here: MCP.
Troubleshooting and edge cases
- Empty or missing rates: validate success === true before reading fields. Handle error payloads gracefully and retry with backoff.
- Rounding drift: always retain full precision internally; round only for display. For inverse math, keep at least 8–10 decimal places before formatting.
- Weekend staleness: it’s expected that timestamp stays constant; don’t treat it as an error. Indicate last updated time to users.
- Symbols typo: verify symbols via the official Symbols list before deploying.
Security and deployment considerations
- Never expose raw access keys in client-side code for production. Proxy calls through your backend or a serverless function.
- Centralize caching on the server. Serve your clients from that cache to reduce egress and improve latency.
- Health checks: monitor for response freshness (timestamp delta) and response time; alert on sustained staleness or abnormal error rates.
Copy-ready snippets
curl
curl -s "https://metals-api.com/api/latest?access_key=YOUR_API_KEY&base=USD&symbols=XAU,USD,USDXAU"
JSON fields you’ll read
- rates.USDXAU — main display price (USD per XAU)
- timestamp — use to reject stale updates
- date — show “as of” in your UI
FAQ
Can I price in EUR instead of USD?
Yes. Set base=EUR and request the same symbols, or use the conversion endpoint as described in the Documentation. With base=EUR, USDXAU changes meaning to EURXAU (if available), so select symbols accordingly.
What’s the difference between XAU and USDXAU?
With base=USD, XAU is ounces per dollar (invert to get USD per ounce). USDXAU is already USD per ounce. Prefer USDXAU when available to avoid inversion rounding differences.
How do I handle weekends and holidays?
Expect timestamp to hold steady when markets are closed. Keep serving the last cached tick and display “as of” time. Resume normal updates when the timestamp advances.
How precise are the numbers?
Use the full precision returned by the API for calculations. Only round for display. For inverse math (1 / XAU), keep high precision internally to minimize drift.
Can I request multiple metals in one call?
Yes. Include more symbols in the symbols parameter (for example, XAU,XAG,USDXAU) to reduce the number of requests and stay within your rate budget.
Ready to integrate real-time Gold pricing into your finance product? Get your free key and start calling /latest in minutes: Register. Explore endpoints, parameters, and response formats here: Documentation.