Get SMM Copper Cathode (SMM-XCU) - Per Troy Ounce prices using this API: Python example
You need the live SMM Copper Cathode price to drive a real use case—repricing SKUs, refreshing a trader’s dashboard, or triggering an alert when copper breaches a threshold. In this guide you’ll fetch SMM Copper Cathode (SMM-XCU) in “per troy ounce” units from Metals-API, parse the response in Python, convert it to USD per troy ounce, and use it directly in your app.
What SMM Copper Cathode (SMM-XCU) is and who needs it
SMM Copper Cathode refers to the Shanghai Metals Market assessment for copper cathode, a key benchmark for physical copper markets. Product managers, quant/dev teams in commodities trading, and manufacturers rely on this price to feed quoting engines, hedging dashboards, and ERP cost models. With Metals-API, you can programmatically source SMM-XCU as a structured feed for analytics or real-time pricing.
Fetch the live “per troy ounce” rate with the Latest endpoint
Metals-API’s Latest Rates endpoint returns current rates with timestamps. Rates are delivered relative to your base currency (USD by default). For metals, the JSON field values are expressed “per troy ounce,” and—critically—are quoted as OUNCES PER 1 UNIT OF BASE CURRENCY. That means you’ll often invert the rate to get USD per troy ounce for UI display or pricing logic.
cURL example: latest SMM-XCU in USD
Replace YOUR_API_KEY with your actual key. If you don’t have one yet, get a free key at the Metals-API Website.
curl -G https://metals-api.com/api/latest \
--data-urlencode "access_key=YOUR_API_KEY" \
--data-urlencode "base=USD" \
--data-urlencode "symbols=SMM-XCU"
Python example: request + invert to USD/oz
import requests
from datetime import datetime, timezone
API_URL = "https://metals-api.com/api/latest"
API_KEY = "YOUR_API_KEY"
SYMBOL = "SMM-XCU"
BASE = "USD"
params = {
"access_key": API_KEY,
"base": BASE,
"symbols": SYMBOL
}
resp = requests.get(API_URL, params=params, timeout=10)
resp.raise_for_status()
data = resp.json()
if not data.get("success", False):
# Surface the API error detail if present
raise RuntimeError(f"Metals-API error: {data}")
# Extract fields you will use
timestamp = data["timestamp"] # UNIX seconds (UTC)
as_of = datetime.fromtimestamp(timestamp, tz=timezone.utc)
unit = data.get("unit") # Expected: "per troy ounce"
base = data["base"] # e.g., "USD"
rates = data["rates"] # dict of symbol -> rate
oz_per_usd = rates[SYMBOL] # ounces per 1 USD (since base=USD)
# Invert to USD per troy ounce for UI/pricing
if oz_per_usd > 0:
usd_per_oz = 1.0 / oz_per_usd
else:
raise ValueError("Zero or negative rate returned.")
print({
"as_of_utc": as_of.isoformat(),
"symbol": SYMBOL,
"unit": unit,
"oz_per_usd": oz_per_usd,
"usd_per_oz": usd_per_oz
})
A realistic JSON response and how to read it
Below is a representative example of the Latest endpoint response for SMM-XCU. Values are illustrative.
{
"success": true,
"timestamp": 1790381333,
"base": "USD",
"date": "2026-09-26",
"rates": {
"SMM-XCU": 0.294118
},
"unit": "per troy ounce"
}
How to interpret this:
- success: Boolean status for the request.
- timestamp: UNIX epoch seconds in UTC. Use it for caching and “as-of” displays.
- base: The quote base. Here it’s USD, so every rate is expressed relative to 1 USD.
- rates: A mapping of symbol to numeric rate. For metals, with base=USD, the value is troy ounces per 1 USD.
- unit: The measurement unit of the returned rate. Metals-API returns “per troy ounce” for metals pricing.
Converting to a “screen price” (USD per troy ounce): invert the rate. If rates["SMM-XCU"] = ounces_per_usd, then usd_per_oz = 1 / ounces_per_usd. For many UI and business rules, you’ll use usd_per_oz.
Two practical uses you can ship today
1) Reprice a catalog in USD per troy ounce
Scenario: Your ERP stores a copper component bill of material in ounces. You want to reprice items at each sync cycle using SMM-XCU.
- Fields used: rates["SMM-XCU"], base, unit, timestamp.
- Steps:
- Call /latest with base=USD and symbols=SMM-XCU.
- Compute usd_per_oz = 1 / rates["SMM-XCU"].
- Multiply component ounces by usd_per_oz to get raw metal cost in USD.
- Apply scrap/yield factors, add processing and margin, persist with the timestamp for audit.
2) Alert when copper crosses a threshold
Scenario: You want to trigger a Slack/Email alert when SMM-XCU exceeds a set price in USD per troy ounce.
- Fields used: rates["SMM-XCU"], base, unit, timestamp.
- Steps:
- Poll /latest on your refresh cadence (see Caching below).
- Convert to USD per troy ounce: usd_per_oz = 1 / rates["SMM-XCU"].
- Compare usd_per_oz to your threshold; if breached, enqueue an alert payload with the timestamp.
- Debounce alerts by caching the last sent band/level to avoid noise.
Units, base currency, and conversions you’ll actually use
- Units: Metals are quoted “per troy ounce.” A troy ounce is 31.1034768 grams. If you need grams or kilograms, convert after you compute USD per troy ounce:
- USD per gram = (USD per troy ounce) / 31.1034768
- USD per kilogram = (USD per troy ounce) * 32.1507466
- Base currency: Default base is USD. When base=USD, rates are ounces per 1 USD. To get USD per ounce, invert.
- Timestamps and time zone: timestamp is UNIX seconds in UTC. Use it to show “As of” times consistently across regions.
Optional: Bid/Ask for tighter execution logic
If your plan supports it, the Bid/Ask endpoint returns a two-sided market you can use for execution-sensitive calculations (e.g., using ask for cost inputs and bid for valuation). See the Metals-API Documentation for parameters and availability. When using bid/ask, you’ll still invert to get USD per troy ounce if the values are expressed as ounces per USD.
Caching and refresh frequency
- Refresh cadence: The Latest endpoint updates on a plan-dependent interval. Use a polling interval aligned to your plan’s update frequency, then cache responses until the timestamp changes.
- Client caching:
- Key your cache by (endpoint, base, symbols) and the returned timestamp.
- Invalidate when the timestamp advances; otherwise reuse the last payload.
- Weekend/holiday handling: Metals prices may not update during market closures. If the API returns the same timestamp, keep serving the cached price with the “as of” label, or switch UI to “last available.”
- Retry/backoff: On transient failures, retry with exponential backoff and fall back to the latest cached good value.
End-to-end Python snippet: price, convert, and guardrails
import requests
from datetime import datetime, timezone
from math import isfinite
API_URL = "https://metals-api.com/api/latest"
API_KEY = "YOUR_API_KEY"
SYMBOL = "SMM-XCU"
BASE = "USD"
def fetch_smm_xcu_usd_per_oz():
resp = requests.get(API_URL, params={
"access_key": API_KEY,
"base": BASE,
"symbols": SYMBOL
}, timeout=10)
resp.raise_for_status()
data = resp.json()
if not data.get("success"):
raise RuntimeError(f"API error: {data}")
ts = datetime.fromtimestamp(data["timestamp"], tz=timezone.utc)
unit = data.get("unit")
oz_per_usd = data["rates"][SYMBOL]
if not (isfinite(oz_per_usd) and oz_per_usd > 0):
raise ValueError("Invalid rate returned.")
usd_per_oz = 1.0 / oz_per_usd
return {
"as_of_utc": ts,
"unit": unit,
"usd_per_oz": usd_per_oz
}
price = fetch_smm_xcu_usd_per_oz()
print(f"As of {price['as_of_utc'].isoformat()} | SMM-XCU: ${price['usd_per_oz']:.2f} per troy oz")
Where to confirm the symbol and find other endpoints
Before shipping to production, confirm the exact symbol string for SMM Copper Cathode on the Metals-API Supported Symbols page. If you also need backfills or analytics windows, see Historical and Time-Series endpoints in the Metals-API Documentation.
Why developers use SMM-XCU programmatically
Digital transformation in metals markets depends on reliable, automatable price discovery. With an API-first feed for SMM copper cathode, you can:
- Continuously synchronize ERP and CPQ with market-based inputs.
- Drive analytics pipelines that connect procurement volumes to market exposure.
- Build smart alerts that tie copper moves to purchasing or hedging actions.
Pairing transparent, structured pricing with your telemetry and order data enables robust cost attribution and scenario testing—core building blocks for smart, automated metals operations.
Additional resources
- Get started and retrieve your key: Metals-API Website
- Endpoint parameters, authentication, and examples: Metals-API Documentation
- Confirm SMM-XCU and other tradable symbols: Metals-API Supported Symbols
- Copper market context: LME Copper overview
- Macroeconomic backdrop: FRED economic data for correlating copper with rates/industry output
FAQ
Q: What unit does Metals-API return for SMM-XCU?
A: “per troy ounce.” With base=USD, the numeric rate is ounces per 1 USD. Invert it to get USD per troy ounce.
Q: How often should I poll the Latest endpoint?
A: Match your polling to your plan’s update frequency. Cache by timestamp and only act when it advances. During closures, the timestamp may remain unchanged; keep serving the cached price with its “as of” time.
Q: How do I convert to grams or kilograms?
A: First compute USD per troy ounce (invert). Then USD per gram = USD_per_oz / 31.1034768; USD per kilogram = USD_per_oz * 32.1507466.
Q: Can I get a historical series for SMM-XCU?
A: Yes—use Historical or Time-Series endpoints for backfills and charting. See the Metals-API Documentation for date parameters.
Q: What if I need bid/ask instead of a mid/last?
A: Use the Bid/Ask endpoint (availability depends on plan). Treat the returned values as ounces per USD and invert if you need USD per troy ounce for your calculation.
Ready to integrate SMM-XCU into your stack? Grab your key from the Metals-API Website, confirm the symbol on the Supported Symbols page, and ship your first call using the examples above.