Best Practices
Cache wisely, batch symbols, stream instead of polling, and keep your keys and webhooks secure.
Match your polling to your plan
Each plan delivers prices at a fixed update interval: daily on Free, 30 minutes on Lite, 10 minutes on Standard, 60 seconds on Advanced and Pro, 15 seconds on Ultra and Business, and 5 seconds on Enterprise. Requesting /latest more often than that returns the same prices and spends quota for nothing.
As a rule of thumb, cache /latest for your plan’s update interval and cache data for past days forever.
Request many symbols at once
One request can return any number of symbols and costs the same as a request for a single symbol. Ask for everything you need in one call:
GET /api/v1/latest?api_key=YOUR_API_KEY¤cies=XAU,XAG,XPT,XPD,EUR,GBPPolling once every 10 minutes takes about 4,500 requests a month, and polling once a minute takes about 45,000. Choose your plan accordingly.
Cache on your side
A small cache in front of the API keeps your app fast and your usage predictable. It also lets you keep serving the last good prices if a request fails:
const TTL = 10 * 60 * 1000; // Standard plan: 10-minute updates
let cache = { at: 0, data: null };
export async function getPrices() {
if (cache.data && Date.now() - cache.at < TTL) return cache.data;
const res = await fetch("https://metalapi.com/api/v1/latest?currencies=XAU,XAG,XPT,XPD", {
headers: { "X-API-Key": process.env.METALAPI_KEY },
});
const data = await res.json();
if (!data.success) {
if (cache.data) return cache.data; // serve the last good prices
throw new Error(`${data.error.code}: ${data.error.info}`);
}
cache = { at: Date.now(), data };
return data;
}Stream instead of polling
For dashboards and trading tools that need every update, use /stream on the Pro plan and above. A single long-lived Server-Sent Events connection delivers new prices as soon as they arrive, with no polling loop to tune.
For threshold logic like “tell me when gold crosses $4,000”, use price alerts and webhooks and skip polling entirely.
Handle errors gracefully
- Check
successon every response and branch onerror.code. - Retry
104,500and503with backoff. Don't retry validation errors. - If the API is unreachable, keep showing the last good price together with its timestamp.
- Watch the
X-RateLimit-Remainingheader and the system status page.
Details and code are in Error handling.
Keep your integration secure
- Store keys in environment variables or a secrets manager, never in Git or client-side bundles.
- Use domain-restricted keys for any calls from the browser.
- Use one key per application and environment, and rotate keys when someone leaves or a key may have leaked.
- Verify the
X-MetalAPI-Signatureheader of every webhook and reject old timestamps.
Performance tips
- Reuse one HTTP client so connections are kept alive between requests.
- Accept compressed responses (
gziporbr). Most HTTP clients do this by default. - Set a request timeout of around 10 seconds so a slow network never blocks your app.
- Load
/symbolsonce at startup and validate user input against it instead of letting bad symbols fail requests. - Call
/usagefrom your monitoring to warn you before you run out of quota. It's free.
Related guides
Ready to start building?
Create a free account to get your API key, or explore every endpoint in the API reference.