Contents Lesson 9 of 16

7 min read · practitioner

What is actually in a row of commodity history?

/commodities/historical/{code} takes a commodity code in the path and four documented query parameters: interval, from, to and fmt (json or csv). Simple enough. Then you call it and discover that almost everything you assumed about the response is worth checking.

Call it and read the envelope

Requested on 2026-07-28 for WTI at monthly interval, the response came back like this:

{"meta": {"name": "Crude Oil Prices: West Texas Intermediate (WTI) - Cushing, Oklahoma",
          "interval": "monthly", "unit": "Dollars per Barrel",
          "offset": 0, "limit": 1000, "total": 486},
 "data": [{"date": "2026-06-01", "value": 70.56}, ...],
 "links": {"next": null}}

Two things deserve your attention immediately.

First, a row has a value, not a close. There is no open, no high, no low, no volume — one observation per period. The published OpenAPI schema for this path describes an array of OHLCV objects instead. The specification and the live response do not agree, and the live response is the authority. This is not unusual in any API of this size; specifications drift behind implementations. The habit that protects you is to print one raw row before you write a parser, every time, on every endpoint.

Second, rows arrive newest first. If your chart looks like it is running backwards, that is why.

meta.unit is the most important field

Three series from this one endpoint, all fetched on 2026-07-28:

  • WTI — "Crude Oil Prices: West Texas Intermediate (WTI) - Cushing, Oklahoma", unit "Dollars per Barrel"
  • COPPER — "Global price of Copper", unit "U.S. Dollars per Metric Ton"
  • ALL_COMMODITIES — "Global Price Index of All Commodities", unit "Index 2016 = 100"

One endpoint, three incompatible units: a dollar price per volume, a dollar price per mass, and a dimensionless index. Plot them on one axis and the chart is meaningless. Average them into a "commodity basket" and you have performed arithmetic on unlike things — adding barrels to tonnes to index points.

Percentage changes are comparable across all three, which is exactly why returns rather than levels are the common currency of cross-asset work.

The code list is a vocabulary, and it is not the documented one

These codes are not tickers. There is no exchange behind them and no SYMBOL.EXCHANGE structure — WTI is the name of a published statistical series.

The endpoint's own documentation lists example codes including WTI, BRENT, NATURAL_GAS, GOLD, SILVER, COPPER and about seventeen others. On 2026-07-28, GOLD and SILVER both returned 404 Symbol not found, while WTI, COPPER and ALL_COMMODITIES returned data — and all five still behaved the same way when re-checked a month later, so this is a standing gap rather than an outage.

Two lessons in that. The documented example list is a hint, not a contract — discover the real vocabulary by probing and record what worked. And note what a 404 means here: "no such code", which is a completely different failure from "no data in that date range", which elsewhere in this API returns an empty array. Code that treats every non-200 the same will report a missing metal and a missing decade identically.

Gold is in the API — under a different namespace

The honest completion of that story: gold is not missing from the platform, only from this path. A separate virtual exchange, COMM, held 245 active tickers on 2026-07-28, with Type values Commodity and Futures — including GC, "Gold (COMEX)", and ES, "S&P 500 E-Mini Futures".

So the same physical commodity is reachable through two unrelated namespaces with different codes, different response shapes and different underlying sources. That is a normal condition in market data, not a defect, and the practical rule is: when a code 404s, ask which namespace the instrument lives in before concluding it is not covered.

Dates you send, pages you get

Three more behaviours, all checked on 29 September 2026, and none of them visible until you count rows.

Leave out interval and you get monthly. meta.interval says so, which is the only place the default is written down.

Not every code has every interval. WTI, BRENT and NATURAL_GAS answer daily and weekly. CORN and COPPER answer both with 422 Invalid parameters and serve only monthly, quarterly and annual. A pipeline that asks every code for daily data fails on some of them for a reason the error does not name.

The date window does nothing. Neither from/to nor filter[from]/filter[to] narrows the answer: ask daily WTI for March and April 2020 and you get the newest 1,000 days of the whole series. The window you can set is the page: page[limit] and page[offset] work, meta.total says how many rows exist, and links.next is the next page's URL, without your key on it. To reach 2020 you walk the pages and filter the dates yourself.

Try it now

  1. Here is /commodities/historical/WTI?interval=monthly as it arrives: the envelope and the first two rows with every key they carry. Confirm for yourself whether a row has value or close, which way the dates run, and note the date beside the table's title as the day it was checked.
Live API response: mda2 wti monthly raw
2. Here are `COPPER` and `ALL_COMMODITIES` from the same endpoint; `WTI` is the table in step 1. Read the three `meta.unit` strings side by side. Then try to write one sentence comparing their levels. You will not be able to, and that is the lesson.
Live API response: mda22 copper monthly unit
Live API response: mda22 all commodities monthly unit
  1. Thirteen codes probed at interval=monthly on 28 September 2026:
Code Answer meta.unit
WTI data Dollars per Barrel
BRENT data Dollars per Barrel
NATURAL_GAS data Dollars per Million BTU
COPPER data U.S. Dollars per Metric Ton
ALUMINUM data U.S. Dollars per Metric Ton
WHEAT data U.S. Dollars per Metric Ton
CORN data U.S. Dollars per Metric Ton
SUGAR data U.S. Cents per Pound
COTTON data U.S. Cents per Pound
ALL_COMMODITIES data Index 2016 = 100
GOLD 404 Symbol not found
SILVER 404 Symbol not found
COFFEE 404 Symbol not found

Turn it into the vocabulary your code will use, with the date. Then find the unit that is not a dollar amount at all, and the two that would be off by a factor of 100 if read as dollars.

  1. Here is daily WTI asked for from=2020-03-01&to=2020-04-30. Compare the first date with the window you asked for, then divide meta.total by meta.limit and round up: that is how many requests the whole daily history costs. Say how your loader finds April 2020, and where it gets the key for the links.next call.
Live API response: mda4 wti daily window ignored