LME Nickel (LME-NI) - Per Troy Ounce Price API in Python: Getting Started Guide for Developers
You need to quote, hedge, or reprice nickel exposures in real time, but your downstream systems expect a USD-per-troy-ounce price, not the usual LME-per-ton convention. By the end of this guide you will request live LME Nickel (LME-NI) rates from Metals-API, read the USD/oz field you actually need, convert to other units used in trading (kg and metric ton), and wire this into a Python workflow you can ship.
What you will build: a clean USD-per-oz feed for LME Nickel
We will focus on a single, dependable building block: the Latest Rates endpoint for LME Nickel (symbol: LME-NI). You will:
- Call the latest endpoint for LME-NI and USDLME-NI in one request.
- Parse the response to get USD per troy ounce (USDLME-NI) directly.
- Convert oz-based prices to kg and metric ton, which many nickel workflows require.
- Handle timestamps, units, caching, and market-closure nuances you’ll run into in production.
If you’re new to Metals-API, you can skim supported symbols and exact codes for LME instruments on the Metals-API Supported Symbols page. When you’re ready to code, get an API key here: Register.
Understand the two nickel fields you actually need
With base=USD, Metals-API returns rates in two complementary forms for each metal symbol:
- rates.LME-NI: troy ounces of nickel per 1 USD (oz/USD)
- rates.USDLME-NI: USD per troy ounce of nickel (USD/oz)
You will typically consume USDLME-NI for pricing and P&L, because it’s directly the price per troy ounce. LME contracts are often discussed per metric ton; we’ll convert from USD/oz to USD/metric ton in your code.
| Symbol | Meaning when base=USD | Primary use |
|---|---|---|
| LME-NI | oz per 1 USD (invert to get USD per oz) | Arbitrage/ratios; sanity checks |
| USDLME-NI | USD per 1 oz | Direct pricing, P&L, invoicing |
Call the Latest endpoint for LME-NI
The Latest Rates endpoint gives current values at a cadence that depends on your plan. Always request both LME-NI and USDLME-NI so you have the direct price and its reciprocal for validation.
cURL request
curl "https://metals-api.com/api/latest?access_key=YOUR_API_KEY&symbols=LME-NI,USDLME-NI"
This endpoint responds with JSON. Below is an official sample response for this exact request. Use it to wire your parser before connecting your live key.
{"success":true,"timestamp":1791245400,"date":"2026-10-06","base":"USD","rates":{"LME-NI":2.0782611506141,"USD":1,"USDLME-NI":0.48117148304702345}}
What these fields mean and how you’ll use them
- success: Boolean guard; handle false with retries or fallbacks.
- timestamp: Unix epoch seconds for when the rates were last updated. Treat it as authoritative for staleness checks and caches.
- date: ISO date associated with the snapshot.
- base: The base currency for all rates. Here it’s USD.
- rates.LME-NI: oz per USD. You can invert this if needed: USD/oz = 1 / LME-NI.
- rates.USDLME-NI: USD per oz. This is the direct nickel price per troy ounce that most apps consume.
Python: fetch USD/oz, then convert to kg and metric ton
The snippet below reads USDLME-NI for pricing, validates it against 1 / LME-NI, and outputs common unit conversions. It also shows basic error handling, timestamp conversion, and a place to inject caching.
import os
import time
import json
import math
import urllib.request
from datetime import datetime, timezone
API_KEY = os.environ.get("METALS_API_KEY", "YOUR_API_KEY")
URL = f"https://metals-api.com/api/latest?access_key={API_KEY}&symbols=LME-NI,USDLME-NI"
# Unit constants
TROY_OUNCES_PER_TROY_POUND = 12.0 # FYI (not used directly)
GRAMS_PER_TROY_OUNCE = 31.1034768
TROY_OUNCES_PER_KG = 1000.0 / GRAMS_PER_TROY_OUNCE
TROY_OUNCES_PER_METRIC_TON = 1_000_000.0 / GRAMS_PER_TROY_OUNCE # 1,000 kg ton
def fetch_latest():
with urllib.request.urlopen(URL, timeout=10) as resp:
data = json.loads(resp.read().decode("utf-8"))
if not data.get("success"):
raise RuntimeError("Metals-API returned success=false")
return data
def main():
data = fetch_latest()
ts = int(data["timestamp"])
as_of = datetime.fromtimestamp(ts, tz=timezone.utc)
base = data.get("base", "USD")
rates = data["rates"]
usd_per_oz = rates.get("USDLME-NI")
oz_per_usd = rates.get("LME-NI")
if usd_per_oz is None or oz_per_usd is None:
raise KeyError("Expected both USDLME-NI and LME-NI in rates")
# Cross-check reciprocal
reciprocal = 1.0 / oz_per_usd if oz_per_usd else float("nan")
if not math.isfinite(reciprocal) or abs(reciprocal - usd_per_oz) / usd_per_oz > 1e-6:
raise ValueError("Data validation failed: reciprocal mismatch")
# Unit conversions
usd_per_kg = usd_per_oz * TROY_OUNCES_PER_KG
usd_per_metric_ton = usd_per_oz * TROY_OUNCES_PER_METRIC_TON
print(f"As of {as_of.isoformat()} (base={base})")
print(f"Nickel (LME-NI):")
print(f" USD per troy ounce: {usd_per_oz:.6f}")
print(f" USD per kilogram: {usd_per_kg:.2f}")
print(f" USD per metric ton: {usd_per_metric_ton:.2f}")
if __name__ == "__main__":
main()
Implementation notes:
- Store your key in METALS_API_KEY and avoid hardcoding in source control.
- If you run this in a loop, cache responses keyed by the rounded timestamp and avoid re-downloading until a new timestamp appears.
- If your plan updates every N minutes, a cache TTL that aligns with that cadence prevents wasted calls without staleness.
Units you must get right: troy ounces vs. grams vs. metric ton
Metals-API rates are explicitly “per troy ounce.” Nickel workflows may need kg or metric tons:
- 1 troy ounce = 31.1034768 grams
- 1 kilogram = 32.1507466 troy ounces
- 1 metric ton = 1,000 kilograms = 32,150.7466 troy ounces
From USD/oz (USDLME-NI), multiply by 32.1507466 for USD/kg and by 32,150.7466 for USD/metric ton. Keep the source-of-truth constant values in one module to avoid drift across services.
Production details that save time
- Base currency: The response shows base: USD. If you only need nickel in USD, keep base=USD and read rates.USDLME-NI directly. If you must quote in another currency, convert on your side with your currency rates or use Metals-API currency features described in the Documentation.
- Timestamps and timezone: timestamp is Unix epoch seconds (UTC). Convert to aware datetimes in Python and carry the timezone through your pipeline.
- Weekends and closures: LME Nickel does not trade continuously through weekends or holidays. If the market is closed, you may see the last tradable date reflected in date and timestamp; build logic to detect staleness and decide whether to freeze, surface a warning, or fall back.
- Caching: Cache the entire JSON by timestamp. In distributed systems, cache at the edge (CDN) and in your pricing engine to minimize duplicate requests.
- Validation: As shown above, cross-check USDLME-NI ≈ 1 / LME-NI. Reject data outside a tight tolerance to catch integration mistakes early.
- Decimals and rounding: Keep internal math in float or Decimal until the final display. Round only at UI or invoice boundaries.
- Rate limits and scheduling: Polling more frequently than the data refresh cadence yields duplicates. Schedule fetches just after the expected update boundary to lower drift while minimizing calls.
- Resilience: Treat success=false or network errors as signals to serve the latest cached price along with the cached timestamp. Log anomalies (e.g., sudden spreads in reciprocal check).
Beyond “latest”: intraday snapshots and history for LME Nickel
Most teams want more than a single snapshot: trend analysis, backtests, and alerts need a history. Metals-API supports:
- Historical and LME-specific historical endpoints for day-level snapshots. These are suitable for backfilling charts and validating EOD marks. See the LME historical notes in the Documentation.
- Time-series queries to fetch a range between two dates, ideal for trend lines and rolling statistics. Use the LME-NI and USDLME-NI symbols in those requests as you did with the latest endpoint.
- Intraday where available, for higher-frequency snapshots of a single symbol; again, request LME-NI or USDLME-NI as needed.
When you wire these endpoints, keep the same unit handling you built above. Ensure you request USDLME-NI if your downstream expects USD-per-oz. For symbol discovery and verification, rely on the Symbols list.
Why nickel data is central to “smart” metals software
LME Nickel is at the intersection of energy transition, stainless steel, and battery supply chains. Developers building modern pricing and analytics need reliable USD/oz values to drive:
- Real-time product pricing for alloy surcharges and procurement portals.
- ERP and MRP updates that reconcile PO lines and hedges with latest market prices.
- Quant research on volatility, mean reversion, and seasonality of nickel used in hedging policy and inventory strategies.
- Trade surveillance and alerting when nickel diverges from correlated inputs or energy costs.
With a single, consistent USDLME-NI field, you can push nickel into dashboards, notebooks, or microservices without unit confusion. If you are coordinating multiple systems, consider Metals-API’s MCP for managed connectivity and governance: MCP.
Security, governance, and deployment tips
- API keys: Store in env vars or secrets managers; rotate per your policy.
- Network: Use HTTPS endpoints only; validate TLS defaults in your platform.
- Service boundaries: Put a tiny “pricing adapter” service in front of Metals-API that normalizes fields (e.g., always serves USD/oz and USD/ton), applies caching, and exposes a minimal internal contract to all your apps.
- Observability: Log the Metals-API timestamp, symbol set, and the reciprocal check error. Alert on staleness beyond acceptable windows.
- Cost control: Align polling to your plan’s update frequency and deduplicate requests via shared caches in workers and lambdas.
Common transformations with nickel prices
Use these formulas around rates.USDLME-NI inside your pricing engine:
- USD/kg = USD/oz × 32.1507466
- USD/metric ton = USD/oz × 32,150.7466
- Local currency per oz = (USD/oz) × (FX rate to local currency)
- Invoice line total = (USD/kg) × (net weight in kg) ± (fees, discounts)
If your analytics still use “oz per USD," you can also derive it from LME-NI = 1 / USDLME-NI. Persist both the direct and derived forms to support consistency checks later.
Putting it together in an app
Here’s a minimal flow you can copy into a service:
- On a schedule, GET latest for symbols=LME-NI,USDLME-NI with your key.
- Validate success and reciprocal check.
- Store the raw JSON, the parsed USD/oz, and the Metals-API timestamp in your database or cache.
- Expose a simple internal endpoint like /price/nickel that returns:
- value_usd_per_oz
- value_usd_per_kg
- value_usd_per_metric_ton
- as_of_utc
- source="metals-api"
- Downstream systems read your normalized endpoint and never touch upstream keys.
Where to learn more and verify symbol details
- API capabilities, endpoints, and parameters: Metals-API Documentation
- All supported symbols and conventions: Metals-API Supported Symbols
- LME background on nickel: London Metal Exchange Nickel
FAQ
Q: Which field is “nickel price per troy ounce in USD”?
A: Use rates.USDLME-NI. It is the direct USD-per-oz price. rates.LME-NI is the reciprocal (oz per USD).
Q: How do I convert USD/oz to USD/metric ton?
A: Multiply by 32,150.7466 (the number of troy ounces in a metric ton). Example: usd_per_ton = usd_per_oz × 32150.7466.
Q: What timezone is the timestamp?
A: The timestamp is Unix epoch seconds in UTC. Convert it to an aware datetime in Python and propagate UTC throughout your system.
Q: What happens on weekends or market holidays?
A: You will receive the latest available snapshot with its timestamp/date. Detect staleness via timestamp; you may choose to freeze prices or show a “market closed” banner.
Q: Can I get a historical series for backtesting?
A: Yes. Use the historical and time-series capabilities described in the Documentation, requesting the same symbols (LME-NI and USDLME-NI).
Ready to integrate LME Nickel into your Python stack? Get your API key and start with the Latest endpoint today: Register. For team-level governance and connectivity, explore MCP. For more about the platform, visit metals-api.com and keep the Metals-API Documentation open as you build.