How to Get Real-Time Magnesium (MG) - Per Troy Ounce Prices with Metals-API: A step-by-step Node.js guide for 2026
Real-time Magnesium (MG) per troy ounce prices are essential if you’re repricing orders in-flight, auto-quoting B2B magnesium alloys, or backtesting intraday signals for lightweight-materials hedging. In this step-by-step Node.js guide for 2026, you’ll learn exactly how to retrieve live MG prices using the Metals-API, transform them into usable analytics, and make your system resilient to market hours, caching, and transient errors. We’ll focus on two endpoints you’ll use most often for production work—Latest and Time-Series—and show how to combine them into a robust pipeline for pricing and historical analysis. We’ll also cover units (troy ounces vs grams), base currencies, timestamps, and practical engineering patterns such as batching, retries, and CDN caching.
Why build with real-time Magnesium (MG) pricing now
Magnesium is central to the digital transformation of metal supply chains: it’s pivotal in EVs, aerospace, die-casting, and lightweight structural components. When price discovery is integrated directly into your apps—ERP triggers, smart contracts, or algorithmic quoting—latency drops, human touchpoints disappear, and analytics improve. Metals-API provides machine-readable, consistent MG pricing suitable for:
- Dynamic pricing: Replace spreadsheet updates with programmatic MG quotes per troy ounce for just-in-time calculations.
- Risk and P&L analytics: Pull daily time series of MG, compute vol, and quantify inventory valuation exposure.
- Product configuration: Quote custom magnesium parts priced per troy ounce, then convert to grams or kilograms for BOM roll-ups.
- Trade surveillance: Alert on intraday moves and spreads for magnesium derivatives or supplier parity checks.
Before you start
- Create a free API key: Visit the Metals-API Website and sign up to get your access key.
- Confirm the magnesium symbol code: Consult the authoritative Metals-API Supported Symbols. In this tutorial, we use “MG” as specified by the title. Always verify the exact symbol string on the Symbols page before deploying.
- Review base units and defaults: Metals-API returns rates relative to a base currency (default USD) and per troy ounce unless documented otherwise. See the Metals-API Documentation for current defaults and options.
What you’ll build
We will implement a simple Node.js module that:
- Fetches the latest MG price in USD per troy ounce.
- Aggregates historical daily MG prices over a date range for analytics (e.g., rolling averages, day-over-day change).
- Handles HTTP errors, rate limits, caching hints, and weekend/holiday logic.
Key endpoints for Magnesium (MG)
We’ll focus on these two endpoints, which cover most real-world needs:
- Latest Rates Endpoint: real-time magnesium price per troy ounce.
- Time-Series Endpoint: daily magnesium prices between two dates (for charts, backtests, and analytics).
For additional features—such as OHLC, fluctuations, or conversions—refer to the official Metals-API Documentation. Always verify supported parameter names and response fields before shipping to production.
Endpoint 1: Latest MG price (per troy ounce)
Purpose: Retrieve the most up-to-date exchange rate for MG relative to the base currency (default USD), expressed per troy ounce.
Example request (curl)
Replace YOUR_ACCESS_KEY with your key. We request MG specifically and keep the default base USD.
curl -s "https://metals-api.com/api/latest?access_key=YOUR_ACCESS_KEY&base=USD&symbols=MG"
Example response (JSON)
This is a representative response format for educational purposes. Confirm live fields via the documentation and your plan features.
{
"success": true,
"timestamp": 1790122986,
"base": "USD",
"date": "2026-09-23",
"rates": {
"MG": 0.01234
},
"unit": "per troy ounce"
}
Response fields you will use
- success: Boolean indicating if the request succeeded.
- timestamp: Unix epoch seconds for the price snapshot. Treat the price as of this time in UTC.
- base: The base currency. Default is USD unless you override it.
- date: UTC calendar date of the snapshot; useful for day-based grouping.
- rates.MG: The rate per troy ounce relative to base. With base=USD, this is “troy ounces of MG per USD” or “USD to MG” depending on the API’s rate orientation. See “Interpreting rate orientation” below.
- unit: Expected to be “per troy ounce.” Always validate this field to ensure unit consistency.
Interpreting rate orientation
Many developers trip on the direction of the rate. Metals-API responses are “by default relative to USD,” and examples show metal quantities per unit of USD. If rates.MG = 0.01234 and base is USD, that implies 1 USD buys 0.01234 troy ounces of magnesium. To get the price in USD per troy ounce, invert the rate:
- USD per troy ounce = 1 / rates.MG
Always verify in the Metals-API Documentation which side is metal-per-USD vs USD-per-metal for your plan and endpoint. Standard practice is to compute both and add a sanity check (e.g., expected magnitude) before displaying prices to users.
Converting troy ounces to grams or kilograms
- 1 troy ounce = 31.1034768 grams.
- 1 kilogram = 32.1507466 troy ounces.
For BOMs, manufacturing quotes, or materials science tooling, convert the unit after you normalize orientation to USD per troy ounce. Example: if price_usd_per_toz = 100, then price_usd_per_kg = 100 × 32.1507466.
Caching and freshness
- Update frequency: Depending on plan, “real-time” updates may refresh every 60 minutes, 10 minutes, or faster. Keep this in mind for dashboard timestamps and SLAs.
- Respect cache headers: If the response includes cache-control headers, propagate them through your CDN or server cache to reduce quota burn.
- Set your own TTL: If you aggregate microservices, you may want a 30–120 second internal cache to shield downstream dependencies.
Endpoint 2: Time-Series MG prices (daily)
Purpose: Retrieve daily historical MG prices for analytics, charting, and backtesting between two chosen dates. Use this to compute rolling averages, daily returns, and seasonality for magnesium markets.
Example request (curl)
Request daily MG prices between start_date and end_date. Dates use ISO format (YYYY-MM-DD), UTC calendar days.
curl -s "https://metals-api.com/api/timeseries?access_key=YOUR_ACCESS_KEY&base=USD&symbols=MG&start_date=2026-09-16&end_date=2026-09-23"
Example response (JSON)
{
"success": true,
"timeseries": true,
"start_date": "2026-09-16",
"end_date": "2026-09-23",
"base": "USD",
"rates": {
"2026-09-16": { "MG": 0.01240 },
"2026-09-17": { "MG": 0.01238 },
"2026-09-18": { "MG": 0.01236 },
"2026-09-19": { "MG": 0.01236 },
"2026-09-20": { "MG": 0.01236 },
"2026-09-23": { "MG": 0.01234 }
},
"unit": "per troy ounce"
}
Handling weekends and holidays
- Flat days: Metals markets can be closed on weekends and holidays. You may see identical rates or no entries for non-trading days depending on your plan and endpoint.
- Fill strategy: For analytics, consider forward-fill or last-known-price logic while clearly labeling non-trading days in UI tooltips.
Key fields
- timeseries: True indicates the response covers multiple dates.
- rates[YYYY-MM-DD].MG: Daily magnesium rate for that date in per troy ounce orientation relative to the base currency.
- unit: Always validate the unit per response. Some downstream processes depend on consistent units.
Step-by-step Node.js implementation for MG
Below is a minimal Node.js example showing how to fetch and normalize MG prices for both latest and time-series data. It includes robust handling strategies you can adapt for production (timeouts, retries with backoff, and basic caching are recommended in real deployments).
Prerequisites
- Node.js 18+ (native fetch is available) or add node-fetch if on older versions.
- Set an environment variable METALS_API_KEY with your API key.
Node.js code (latest + time-series)
/**
* Minimal Node.js example to fetch Magnesium (MG) per troy ounce prices from Metals-API.
* - Fetches latest MG rate (base=USD), then inverts to USD per troy ounce.
* - Fetches time-series MG rates for a date range.
* - Includes simple validation and parsing.
*/
const API_BASE = "https://metals-api.com/api";
const ACCESS_KEY = process.env.METALS_API_KEY; // set this in your environment
const SYMBOL = "MG";
const BASE = "USD";
// Basic HTTP wrapper with timeout and simple error handling
async function httpGetJson(url, { timeoutMs = 10000 } = {}) {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeoutMs);
try {
const res = await fetch(url, { signal: controller.signal });
const text = await res.text();
let json;
try {
json = JSON.parse(text);
} catch (e) {
throw new Error("Failed to parse JSON: " + e.message + " Body: " + text.slice(0, 200));
}
if (!res.ok || json.success === false) {
// Metals-API may include error information in JSON
const errMsg = json.error?.info || json.error?.type || res.statusText || "Unknown error";
const errCode = json.error?.code || res.status;
throw new Error(`HTTP/API error (${errCode}): ${errMsg}`);
}
return json;
} finally {
clearTimeout(timer);
}
}
// Convert a rate that is "metal per USD" to "USD per troy ounce"
function toUsdPerToz(ratesMg) {
if (typeof ratesMg !== "number" || ratesMg <= 0) {
throw new Error("Invalid MG rate; cannot compute USD per troy ounce");
}
return 1 / ratesMg;
}
async function getLatestMg() {
const url = `${API_BASE}/latest?access_key=${encodeURIComponent(ACCESS_KEY)}&base=${BASE}&symbols=${SYMBOL}`;
const data = await httpGetJson(url);
if (!data.rates || typeof data.rates[SYMBOL] !== "number") {
throw new Error("MG rate missing in latest response");
}
const mgPerUsd = data.rates[SYMBOL]; // "per troy ounce" orientation relative to base
const usdPerToz = toUsdPerToz(mgPerUsd);
return {
timestamp: data.timestamp,
date: data.date,
base: data.base,
unit: data.unit,
mgPerUsd,
usdPerToz
};
}
async function getMgTimeSeries(startDate, endDate) {
const url = `${API_BASE}/timeseries?access_key=${encodeURIComponent(ACCESS_KEY)}&base=${BASE}&symbols=${SYMBOL}&start_date=${startDate}&end_date=${endDate}`;
const data = await httpGetJson(url);
if (!data.timeseries || !data.rates) {
throw new Error("Unexpected time-series response");
}
// Convert each day to USD per troy ounce
const daily = Object.entries(data.rates).map(([date, obj]) => {
const mgPerUsd = obj?.[SYMBOL];
const usdPerToz = toUsdPerToz(mgPerUsd);
return { date, mgPerUsd, usdPerToz };
}).sort((a, b) => a.date.localeCompare(b.date));
return {
base: data.base,
unit: data.unit,
start_date: data.start_date,
end_date: data.end_date,
daily
};
}
(async () => {
if (!ACCESS_KEY) {
console.error("Please set METALS_API_KEY in your environment.");
process.exit(1);
}
try {
const latest = await getLatestMg();
console.log("Latest MG:", latest);
const ts = await getMgTimeSeries("2026-09-16", "2026-09-23");
console.log("MG time-series sample:", ts.daily.slice(0, 3), "... total days:", ts.daily.length);
} catch (err) {
console.error("Error:", err.message);
process.exit(1);
}
})();
Explaining the Node.js logic
- httpGetJson: Wraps fetch with an AbortController timeout and parses JSON with explicit error capture. It also inspects Metals-API JSON error fields to produce actionable logs.
- toUsdPerToz: Normalizes the orientation by inverting the per-USD rate to get USD per troy ounce.
- getLatestMg: Calls the Latest endpoint, validates the MG key, and returns both orientations.
- getMgTimeSeries: Calls the Time-Series endpoint and converts each day to USD per troy ounce for consistent analytics.
Practical handling of units and conversions
Metals-API returns magnesium in troy ounces by default. Manufacturing and logistics often require grams or kilograms. Consider precomputing these values server-side to keep clients lightweight and to preserve unit consistency across microservices.
| From | To | Multiplier | Notes |
|---|---|---|---|
| troy ounces | grams | 31.1034768 | Use full precision to avoid cumulative drift in BOMs. |
| grams | troy ounces | 0.0321507466 | Inverse of the above. |
| troy ounces | kilograms | 0.0311034768 | 1 kg = 32.1507466 troy ounces. |
Data validation and sanity checks
- Non-negative and finite: Reject NaN, Infinity, or non-positive rates before computations.
- Magnitude checks: If USD per troy ounce for MG is wildly outside expected ranges (e.g., orders of magnitude off), trigger a soft alert and skip display until next refresh.
- Unit check: Inspect unit field; if the provider changes units, you’ll guard against silent data corruption.
- Timestamp monotonicity: For time series, ensure dates are sorted and no future-dated entries are accidentally used in historical analytics.
Caching strategies and quota management
- Edge caching: Terminate Metals-API calls through your API layer and cache the normalized response for 30–120 seconds (or per plan refresh frequency). This cuts costs and improves tail latency.
- Conditional requests: If/when ETags or Last-Modified headers are supported, use conditional GETs to avoid re-downloading unchanged payloads.
- Batch symbols: If your app needs both MG and a small set of related feeds, request them together in one call using the symbols parameter (still keep MG as your subject of focus) to reduce round trips.
Error handling, resilience, and recovery
- API-level errors: Parse json.error.code and json.error.info when success is false. Provide actionable messages to logs (e.g., “invalid_access_key”, “rate_limit_reached”).
- Network timeouts: Use abortable fetch with exponential backoff on transient 5xx. Cap total retry time to protect user interactions.
- Fallback data: If Latest fails, optionally fall back to the most recent entry from Time-Series or a cached snapshot, but clearly label “stale.”
- Idempotency in pipelines: Deduplicate jobs using a composite key of symbol + timestamp + base + unit.
Security best practices
- Do not embed your Metals-API key in client apps. Keep it server-side or in secure serverless functions.
- Rotate keys periodically and remove abandoned keys from your CI/CD secrets.
- Limit surface area: Create a backend proxy endpoint that returns only the fields your frontend needs (e.g., usdPerToz, date, timestamp), redacting your raw API key.
- Log scrubbing: Mask access keys in logs and traces; never print full URLs containing the key.
Production architecture for MG price ingestion
- Ingress service: A small Node.js service polls Latest and Time-Series endpoints on a schedule (e.g., a cron in serverless) and writes to a time-series database (TimescaleDB, InfluxDB) with tags symbol=“MG”, unit=“toz”, base=“USD.”
- Normalization worker: Converts metal-per-USD to USD-per-toz, adds grams and kilograms, and stores derived fields. Include an audit trail: raw response, processing version, and checksum.
- API facade: A REST or GraphQL facade returns curated MG fields with cache headers tuned to your SLA.
- Observability: Emit metrics on request success rate, latency, parse failures, and unit mismatches. Add alerting if “unit” changes or rates are missing.
End-to-end MG analytics patterns
- Spot quoting: Fetch Latest once per refresh period and use a synchronized display timer; highlight timestamp and base currency for transparency.
- Rolling analytics: With Time-Series, compute 7/30/90-day rolling averages and volatility. Precompute during off-peak hours so dashboards load fast.
- Supplier verification: Compare your Metals-API MG price to incoming supplier XML/CSV quotes. Flag anomalies beyond a set threshold.
- Inventory valuation: Use end-of-day MG USD per troy ounce, convert to your unit system, and revalue inventory nightly. Keep historical valuations for audits.
Advanced tips for MG at scale
- Rate orientation guardrails: Encapsulate inversion and unit handling in one utility function and cover with tests.
- Rounding modes: Separate financial rounding (banker’s rounding) from engineering rounding to avoid penny mismatches in invoices.
- Client hints: Return a concise schema to clients: { symbol, base, unit, usdPerToz, timestamp } and disallow free-form fields.
- Cost controls: If MG updates every N minutes on your plan, align polling intervals and cache TTLs to N to avoid redundant hits.
Frequently used parameters (recap)
- access_key: Your Metals-API authentication token.
- base: Choose the currency reference; USD is default. If you price in EUR or JPY, set base accordingly and adjust calculations consistently.
- symbols: Use MG for magnesium. Confirm symbol string on the Metals-API Supported Symbols.
- start_date, end_date: ISO dates (YYYY-MM-DD) for Time-Series.
Testing and QA checklist
- Unit tests: Validate inversion logic, unit conversions, error parsing.
- Integration tests: Mock Metals-API responses for success, invalid key, and rate-limit errors.
- Data drift: Alert if unit field changes or MG is missing from rates for a new trading day.
- UI accuracy: Display timestamp and base currency clearly on charts and quote widgets.
Troubleshooting guide
- Empty or missing MG rate: Verify the exact symbol on the symbols directory. Ensure symbols=MG is correct and included in your plan.
- Unexpected price magnitude: Confirm orientation. If the rate is metal-per-USD, invert to USD-per-toz. Test both paths and assert a realistic USD range.
- Weekend/holiday gaps: Implement forward-fill or business-day calendars and label non-trading days. Use Time-Series ranges that skip non-business days in your logic if applicable.
- Rate limit errors: Add exponential backoff and internal caching. Reduce polling frequency to match your plan’s update cadence.
- SSL/TLS or network errors: Ensure your environment trusts modern CAs, and set higher timeouts in high-latency regions. Consider regional edge proxies.
Scaling performance
- Batch symbol requests: If you later expand beyond MG, request multiple symbols in one call to reduce overhead.
- Pre-aggregation: Precompute rolling metrics nightly or hourly; store them alongside raw rates to accelerate front-end queries.
- CDN layering: Cache normalized MG responses at the edge with short TTLs; purge on significant market moves if you run push-based alerting.
- Minimal payloads: Strip unneeded fields before storing or sending to the client; keep only symbol, base, unit, timestamp, and usdPerToz for most use cases.
Digital transformation with magnesium data
By embedding real-time MG per troy ounce prices into your workflows, you can:
- Automate contract clauses: Smart thresholds trigger re-quoting or hedges when MG moves beyond tolerance bands.
- Enhance forecasting: Use historical time-series to train models that anticipate demand-price interactions in EV and aerospace builds.
- Streamline procurement: Surface normalized USD, EUR, or local-currency MG prices in supplier portals to shorten negotiation cycles.
Verification and compliance
- Audit logs: Preserve raw JSON responses and transformation metadata for finance audits.
- Reproducibility: Tag each analytics artifact with data timestamp and unit, making backtests and monthly closes reproducible.
- Data lineage: Maintain data provenance from Metals-API through each stage of your pipeline.
Next steps
- Get your free key on the Metals-API Website and try the Latest endpoint for MG today.
- Read the Metals-API Documentation to explore response fields, additional endpoints, and plan capabilities.
- Confirm magnesium’s symbol and availability on the Supported Symbols Listing before deploying to production.
Appendix: Additional JSON scenarios
Latest MG: error response (invalid key)
{
"success": false,
"error": {
"code": 101,
"type": "invalid_access_key",
"info": "You have not supplied a valid API Access Key."
}
}
Action: Rotate or correct your key. Do not retry immediately; fix configuration first.
Time-Series MG: partial data window
{
"success": true,
"timeseries": true,
"start_date": "2026-09-18",
"end_date": "2026-09-23",
"base": "USD",
"rates": {
"2026-09-18": { "MG": 0.01236 },
"2026-09-21": { "MG": 0.01235 },
"2026-09-23": { "MG": 0.01234 }
},
"unit": "per troy ounce"
}
Action: Fill missing days according to your business-day rules or display gaps clearly on charts.
Conclusion
You’ve seen how to retrieve real-time and historical Magnesium (MG) prices per troy ounce using Metals-API, normalize the rate orientation, enforce unit consistency, and build a fault-tolerant Node.js integration. With careful handling of timestamps, caching, and weekend logic, you can power reliable pricing, analytics, and procurement tools. The combination of the Latest and Time-Series endpoints covers most operational needs—from instant quotes to robust backtesting pipelines. Start by getting your API key at the Metals-API Website, review the exact symbol and capabilities in the Supported Symbols directory, and dive into the full set of parameters and options in the official Documentation.
FAQ
- Which symbol should I use for magnesium?
Use the exact symbol shown on the Metals-API Supported Symbols page. This guide uses “MG” per the title; always verify before deployment. - What unit does Metals-API return for MG?
Per troy ounce by default. Confirm via the unit field in the response and the Documentation. - Is the returned rate USD per troy ounce or troy ounces per USD?
Responses are relative to the base currency. If the number represents metal-per-USD, invert it to get USD per troy ounce. Validate this in your code. - How do I handle market closures?
Expect flat or missing entries on weekends/holidays. Implement forward-fill if necessary and label non-trading days. - Can I price in EUR instead of USD?
Yes. Set base=EUR. Ensure your pipeline and UI display the correct base currency. - How often should I poll?
Align to your plan’s update cadence (e.g., every 60 or 10 minutes). Combine with short-lived caches to reduce quota usage. - Where do I get help?
Start with the Metals-API Documentation and confirm symbol availability at Supported Symbols. Then get your free key at the Metals-API Website.