sifting/io
Commodities
5 min readSiftingIO Team

Commodities data API: coverage, fields, and symbol names for gold, silver, oil, and metals

SiftingIO's commodities data API: real symbols (XAUUSD, XAGUSD, WTIUSD, COPPERUSD, NATGASUSD), OHLCV history, live REST quotes, and WebSocket streaming.

Commodities data API: coverage, fields, and symbol names for gold, silver, oil, and metals

A commodities market data API has to answer three questions before you write any code: which commodities it covers, what the symbols are called, and how you pull both historical bars and live prices. Vague answers cost real time. Guess a symbol name and you get a 404. Assume gold trades around the clock like BTC and your staleness alerts fire every weekend.

This post covers SiftingIO's commodities data: the metals, energy benchmarks, and agricultural products it serves, the exact symbol spellings the API expects, the REST endpoints for history and snapshots, and the WebSocket stream for live ticks.

What the commodities data API covers#

SiftingIO serves commodities as one of six asset classes behind a single API key, alongside US equities, forex, crypto, DEX activity, and on-chain metrics. The commodities coverage spans four groups: precious metals (gold, silver, platinum), industrial metals (copper), energy benchmarks (WTI and Brent crude oil, natural gas), and agricultural products (corn). For each instrument you get spot pricing and OHLCV bars, live over REST and WebSocket, historical through the bars endpoints.

Prices aren't passed through from a single source. Each published tick is an aggregate across multiple independent venues: a volume-and-reputation-weighted median rather than a simple average. A median holds until a majority of venues err in the same direction, which matters for commodities because spot markets are fragmented and quotes can go stale without any obvious signal. Every tick carries three timestamps (source, ingest, publish) and an explicit quality flag, so degraded data announces itself. The output is a synthetic reference price. It works for research, dashboards, alerting, and validating what another feed is showing you. It is not executable depth, and order routing belongs on an execution venue's own feed.

Commodities symbols: how gold, silver, and oil are spelled#

Developers search for symbols by name, and the API is strict about spelling. Commodity symbols are uppercase alphanumeric with no separators, in commodity-code-plus-USD form:

  • XAUUSD: gold
  • XAGUSD: silver
  • XPTUSD: platinum
  • COPPERUSD: copper
  • WTIUSD: WTI crude oil
  • UKOUSD: Brent crude oil
  • NATGASUSD: natural gas
  • CORNUSD: corn

Treat the browsable symbol catalog on the site as the authoritative spelling reference rather than guessing by pattern.

These are spot reference symbols. There are no futures-style contract codes with expiry months, which means there's no contract roll to manage in a backtest: XAUUSD is the continuously aggregated spot gold reference in US dollars, yesterday and today.

Historical bars and live prices over REST#

Everything authenticates with the X-API-Key header. Live snapshots live under /v1/last, historical bars under /v1/hist:

# Best bid and ask for gold
curl -H "X-API-Key: $SIFTING_KEY" \
  "https://api.sifting.io/v1/last/quote/commodities/XAUUSD"

# Last trade for WTI crude: price, size, timestamp
curl -H "X-API-Key: $SIFTING_KEY" \
  "https://api.sifting.io/v1/last/trade/commodities/WTIUSD"

# Daily silver bars (historical endpoints require gzip)
curl --compressed -H "X-API-Key: $SIFTING_KEY" \
  "https://api.sifting.io/v1/hist/commodities/XAGUSD/bars?interval=1d"

The quote endpoint returns the current best bid and ask. The trade endpoint returns the latest price with size and an epoch-millisecond timestamp. Bars come back as standard OHLCV rows with UTC timestamps, at intervals from one minute upward; the full interval list per asset class is in the docs.

Long historical pulls page with a cursor: pass a limit, then follow meta.next_cursor from each response until it comes back null. How far back you can go depends on plan tier. The free tier includes one month of history, paid tiers extend to a year and then to full history; check the pricing page for current limits before you size a backfill job.

Every response also carries rate-limit headers. X-RateLimit-Remaining tells you how many tokens remain in the current window, and a 429 arrives with Retry-After in seconds. A backfill script that honors those two headers won't get itself blocked.

Streaming live commodities prices over WebSocket#

For dashboards and alerting, polling /v1/last in a loop burns quota on requests that mostly return the same number. The WebSocket stream pushes ticks as they happen. Connect with your key in the query string:

wss://stream.sifting.io/ws/v1?key=$SIFTING_KEY

You can also connect bare and send an explicit auth frame, { "op": "auth", "key": "sft_..." }, and the server replies with an ack that includes your tier. Then subscribe to the symbols you want:

{ "op": "subscribe", "product": "com", "symbols": ["XAUUSD", "WTIUSD"] }

Subscriptions are grouped by product. Commodities use the product code com, which is not the same as the REST venue slug commodities; the product codes for the other asset classes are in the docs.

On subscribe, the server first emits the last cached value for each symbol, so a UI renders immediately instead of waiting for the next trade. After that, ticks arrive as frames discriminated by an f field: f of "tick" with s (symbol), p (price), b and a (bid and ask), and t (epoch milliseconds). Two operational details matter. The server closes any connection that has been silent for 90 seconds, so send { "op": "ping" } at least once a minute. And failures are explicit: an f of "error" with a code such as max_subscriptions when you exceed your tier's symbol allowance, which is far easier to handle than a silent drop.

Common pitfalls#

Forgetting gzip on historical bars. The bars endpoints require compression. A request without Accept-Encoding: gzip fails with HTTP 406 and the body { "error": "gzip_required" }. With curl, add, compressed. Most full-featured HTTP clients negotiate gzip by default, but minimal clients and some serverless fetch wrappers don't, and the resulting 406 looks like a permissions problem until you read the error code.

Guessing symbol spellings. XAU/USD with a slash, GOLD, and futures-style contract codes all return a 404, and so does a spelling carried over from another provider's naming scheme. Copy symbols exactly as the catalog spells them.

Treating a closed market as an outage. Metals and energy have trading sessions and weekend gaps, unlike crypto. When the latest tick is older than the freshness threshold, the snapshot endpoints return 503 with error code stale_snapshot, and the body includes last_t and server_now so you can see exactly how old the data is. Before an alerting rule flags that as an outage, check the market status endpoint, GET /v1/fnd/markets/:market/status: if the market is closed, a stale snapshot is expected behavior.

Commodities is one market in the catalog, priced per market like every other asset class, and the free tier needs no credit card. Every request in this post runs unchanged on a free key. Start building free

Keep reading

Related posts