Metals API documentation
Everything you need to call the metals API. Base URL https://api.metalrates.cloud. All endpoints are GET, return JSON and live under /v1.
Metals API quick start
- Request a free key. It arrives by email.
- Send it in the
X-API-Keyheader. - Read
datafrom the JSON response.
Authentication
Send your key in the X-API-Key header on every request. Keys start with mr_live_. Call the API from your server and keep the key out of browser and mobile code. Keys can optionally be locked to your server IP addresses.
curl "https://api.metalrates.cloud/v1/metals/gold" \
-H "X-API-Key: YOUR_API_KEY"const res = await fetch("https://api.metalrates.cloud/v1/metals/gold", {
headers: { "X-API-Key": process.env.METALRATES_API_KEY }
});
const { success, data, meta } = await res.json();
console.log(data);import os, requests
res = requests.get(
"https://api.metalrates.cloud/v1/metals/gold",
headers={"X-API-Key": os.environ["METALRATES_API_KEY"]},
timeout=10,
)
body = res.json()
print(body["data"])<?php
$ch = curl_init("https://api.metalrates.cloud/v1/metals/gold");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-API-Key: ' . getenv('METALRATES_API_KEY')],
CURLOPT_TIMEOUT => 10,
]);
$body = json_decode(curl_exec($ch), true);
print_r($body['data']);Endpoints
| Method | Path | Returns |
|---|---|---|
| GET | /v1/metals/gold | Gold per gram, 24K to 10K, SAR and USD |
| GET | /v1/metals/gold/sar, /usd | Gold in one currency |
| GET | /v1/metals/silver | Silver per gram, 999 to 800, SAR and USD |
| GET | /v1/metals/silver/sar, /usd | Silver in one currency |
| GET | /v1/forex | SAR rates for 14 currencies |
| GET | /v1/forex/{currency} | One SAR pair |
| GET | /v1/snapshot | Gold, silver and up to 10 rates |
| GET | /v1/{metals/gold|metals/silver|forex}/status | Freshness status |
| GET | /v1/health | API status, no key needed |
Response format
Every endpoint returns the same envelope. data holds the result; meta tells you where it came from and how fresh it is.
{
"success": true,
"data": { ... },
"error": null,
"meta": {
"source": "DevstromToolsAPI",
"cacheStatus": "HIT",
"updatedAt": "...",
"updatedIso": "...",
"nextUpdateUtc": "..."
}
}Price data also carries isStale. When it is true, the value is the last one we had because a refresh failed, and staleReason says why.
Rate limits
| Plan | Requests per day | Price per month |
|---|---|---|
| Free | 100 | $0 |
| Starter | 500 | $5 |
| Pro | 5,000 | $19 |
| Business | About 33,000 | $49 |
| Enterprise | Unlimited | Custom |
Every response includes X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset and X-Plan. Limits reset at midnight UTC. Over the limit you get HTTP 429 with Retry-After.
Errors
Errors return success: false and an error object with a code and a readable message.
| HTTP | Code | Meaning |
|---|---|---|
| 401 | MISSING_API_KEY | No X-API-Key header |
| 401 | INVALID_API_KEY | Key unknown, revoked or expired |
| 403 | IP_NOT_ALLOWED | Request came from an IP not on the key’s allowlist |
| 429 | RATE_LIMIT_EXCEEDED | Daily limit reached |
| 400 | INVALID_INPUT | A parameter is missing or out of range |
| 404 | CURRENCY_NOT_FOUND | Currency not supported |
| 503 | SERVICE_UNAVAILABLE | Data temporarily unavailable; retry later |
Gold and silver
| Endpoint | Description |
|---|---|
/v1/metals/gold | Per-gram 24K to 10K in SAR and USD, spot, change, day range |
/v1/metals/gold/sar, /usd | One currency only |
/v1/metals/silver | Per-gram 999, 925, 900, 800 in SAR and USD, spot, change |
/v1/metals/silver/sar, /usd | One currency only |
/v1/metals/{metal}/status | Cache and freshness status |
Gold Price API and Silver Price API pages show live examples.
Exchange rates
| Endpoint | Description |
|---|---|
/v1/forex | SAR rates for PKR, INR, BDT, LKR, NPR, PHP, EGP, IDR, MMK, KES, ETB, USD, GBP, EUR |
/v1/forex/{currency} | One currency, e.g. /v1/forex/INR |
/v1/forex/status | Cache and freshness status |
Snapshot
GET /v1/snapshot?currencies=PKR,INR,BDT,PHP returns gold 24K, silver 999 and up to 10 SAR exchange rates in one request. Each section has its own available flag, so one missing source does not break the rest.
{
"success": true,
"data": {
"gold": {
"available": true,
"label": "Gold 24K",
"pricePerGramSar": 482.14,
"pricePerGramUsd": 128.4561,
"spotPriceSar": 14996.32,
"changePercent": 0,
"changeDirection": "flat",
"isStale": false,
"updatedAt": "27 Oct 2026, 03:08 PM",
"updatedIso": "2026-10-27T12:08:19.4654293Z"
},
"silver": {
"available": true,
"label": "Silver 999",
"pricePerGramSar": 6.5085,
"pricePerGramUsd": 1.7341,
"spotPriceSar": 202.64,
"changePercent": 0,
"changeDirection": "flat",
"isStale": false,
"updatedAt": "27 Oct 2026, 12:44 PM",
"updatedIso": "2026-10-27T09:44:57.4401314Z"
},
"forex": {
"available": true,
"baseCurrency": "SAR",
"rates": [
{
"currency": "PKR",
"label": "PKR / SAR",
"rate": 73.8929,
"perSar": 73.8929
},
{
"currency": "INR",
"label": "INR / SAR",
"rate": 25.4058,
"perSar": 25.4058
}
],
"updatedAt": "27 Oct 2026, 03:03 AM",
"updatedIso": "2026-10-27T00:03:11.9115024Z"
},
"anyAvailable": true,
"generatedAtIso": "2026-10-27T14:24:13.4761552Z"
},
"error": null,
"meta": {
"source": "DevstromToolsAPI",
"cacheStatus": null,
"updatedAt": null,
"updatedIso": null,
"nextUpdateUtc": null
}
}SDKs and code samples
The API is plain HTTPS and JSON, so any language with an HTTP client works without an SDK. Every product page has copy-ready samples in cURL, JavaScript, Python and PHP.
| Data | Status | Notes |
|---|---|---|
| Code samples: cURL, JavaScript, Python, PHP | Available | On every product page and above |
| Postman collection | Planned | Import and test every endpoint |
| Official SDKs (JavaScript, Python, PHP, .NET) | Planned | Tell us which language you need first |
| WordPress gold rate widget | Planned | Free plugin for jewellers’ sites |
Health
GET /v1/health needs no key and returns {"status":"ok"} when the API is up.
Start with a free key today
100 requests a day, every endpoint, no card required. Upgrade when your traffic grows.
