Metals API
Hourly gold, silver, platinum and palladium prices in euros, with history since November 2023.
/v1/metalsNot counted in your quota2 endpointsMade for systems that keep their own copy of the prices: load the whole history once, then ask every hour for what is new. We collect XAU (gold), XAG (silver), XPT (platinum) and XPD (palladium) around minute 40 of every hour, in euros per gram and per kilo.
Times are UTC, ISO 8601 with a Z. quoted_at is the market time of the quote, added_at the time we stored it.
metal and quoted_at (a handful exist), and skip any quote more than 50% away from the last one you kept: the provider sent a wrong price for two hours on 15 April 2024.Latest prices
The newest quote of each of the four metals.
| statusstring | ok |
| countinteger | Rows returned, one per metal |
| rows[].idinteger | Quote ID, growing over time: the cursor for the history |
| rows[].metalstring | XAU, XAG, XPT or XPD |
| rows[].currencystring | Always EUR |
| rows[].per_gram, rows[].per_kilonumber | Price of a gram and of a kilo, in euros |
| rows[].quoted_atstring | Market time of the quote, UTC |
| rows[].added_atstring | When we stored it, UTC |
curl "https://api.calenzy.app/v1/metals/latest" \ -H "Authorization: Bearer YOUR_API_KEY"
{ "status": "ok", "count": 4, "rows": [ { "id": 96959, "metal": "XAU", "currency": "EUR", "per_gram": 127.51910322242, "per_kilo": 127519.10322242, "quoted_at": "2026-08-24T00:10:05Z", "added_at": "2026-08-24T00:40:03Z" }, { "id": 96958, "metal": "XAG", "currency": "EUR", "per_gram": 1.9148696089158, "per_kilo": 1914.8696089158, "quoted_at": "2026-08-24T00:10:05Z", "added_at": "2026-08-24T00:40:03Z" }, { "id": 96961, "metal": "XPT", "currency": "EUR", "per_gram": 51.9, "per_kilo": 51900.0, "quoted_at": "2026-08-24T00:10:05Z", "added_at": "2026-08-24T00:40:03Z" }, { "id": 96960, "metal": "XPD", "currency": "EUR", "per_gram": 37.1, "per_kilo": 37100.0, "quoted_at": "2026-08-24T00:10:05Z", "added_at": "2026-08-24T00:40:03Z" } ] }
History
Quotes page by page, oldest first, from a cursor.
Start with after_id=0 to load everything, then pass the next_after_id of the last page you received. An empty page means you are up to date.
| after_idinteger | Quotes after this ID. 0 by default, the start of the history |
| limitinteger | Rows per page, 1 to 5000. 1000 by default; a value out of range counts as 5000 |
| metalstring | Only XAU, XAG, XPT or XPD |
| sincestring | Only quotes from this day on, YYYY-MM-DD, UTC. Works together with after_id |
| statusstring | ok |
| countinteger | Rows in this page, 0 when you are up to date |
| next_after_idinteger | The ID of the last row, to send as after_id next time. Equal to your after_id when the page is empty |
| rows[]array | Quotes, oldest first, as in Latest prices |
curl "https://api.calenzy.app/v1/metals/history?after_id=0&limit=5000" \ -H "Authorization: Bearer YOUR_API_KEY"
curl "https://api.calenzy.app/v1/metals/history?after_id=96961&limit=5000" \ -H "Authorization: Bearer YOUR_API_KEY"
curl "https://api.calenzy.app/v1/metals/history?metal=XAU&since=2026-08-01" \ -H "Authorization: Bearer YOUR_API_KEY"
{ "status": "ok", "count": 2, "next_after_id": 96959, "rows": [ { "id": 96958, "metal": "XAG", "currency": "EUR", "per_gram": 1.9148696089158, "per_kilo": 1914.8696089158, "quoted_at": "2026-08-24T00:10:05Z", "added_at": "2026-08-24T00:40:03Z" }, { "id": 96959, "metal": "XAU", "currency": "EUR", "per_gram": 127.51910322242, "per_kilo": 127519.10322242, "quoted_at": "2026-08-24T00:10:05Z", "added_at": "2026-08-24T00:40:03Z" } ] }
Errors
Besides these, any call can answer one of the common errors.
| Code | HTTP | When |
|---|---|---|
bad_request | 400 | An unknown metal, or a since that is not YYYY-MM-DD |