WORLD MARKETS
PUBLIC API · NO KEY

Docs.

Everything the site draws is served by four read-only endpoints. They are open, need no key, send access-control-allow-origin: *, and are the same endpoints the pages themselves call.

01GET /api/summary

Every index with its latest price, 24h change, source quality and a 15-minute sparkline.

# all 220
curl https://werid.77.42.65.214.sslip.io/api/summary

# one category, no sparkline (much smaller)
curl 'https://werid.77.42.65.214.sslip.io/api/summary?category=Metals&spark=0'
[
  {
    "id": 0,
    "t": "GLD", // symbol
    "name": "Gold",
    "category": "Metals",
    "unit": "oz",
    "last": 4398.0,
    "ts": 1789747200, // unix seconds, from the source
    "age": 644, // seconds since that observation
    "quality": "live", // live | daily | static | reference
    "stale": false,
    "chg24": -0.41, // percent
    "spark": [4391.2, 4393.8, ...]
  }
]
PARAMDEFAULTMEANING
categoryallExact category name, as listed by /api/commodities.
spark1Set to 0 to drop the sparkline arrays.

02GET /api/history

OHLC candles for one index. The market can be given as a numeric id or as a symbol.

curl 'https://werid.77.42.65.214.sslip.io/api/history?market=GLD&tf=900&limit=96'

{ "market": 0, "symbol": "GLD", "unit": "oz", "tf": 900,
  "candles": [ { "t": 1789747200, "o": 4391.2, "h": 4398.0, "l": 4390.1, "c": 4398.0, "n": 3 } ] }
PARAMDEFAULTMEANING
marketRequired. Numeric id or symbol, case insensitive.
tf900Bucket size in seconds: 60, 300, 900, 3600 or 86400.
limit961 to 1000 candles, oldest first.
since0Unix seconds; only candles at or after this bucket.
Candles exist only where observations exist. A gap in the array is a gap in the feed, not a missing field, and retention is 3 days at 1m, 14 days at 5m, 60 days at 15m and 400 days at 1h. Daily candles are kept.

03GET /api/commodities

The catalogue: what exists, in what unit, from which source. Static enough to cache.

{ "count": 220,
  "categories": [ { "name": "Metals", "count": 6 }, ... ],
  "markets": [ { "id": 0, "symbol": "GLD", "name": "Gold", "category": "Metals",
    "unit": "oz", "quality": "live",
    "source": "Front-month futures quote (Yahoo Finance), converted to USD per catalogue unit" } ] }

04GET /api/health

Whether the feed is doing its job. status is ok only while every adapter has succeeded within three of its own poll intervals, so a dead source shows up here before anyone notices a stale price.

{ "status": "ok", "markets": 220, "priced": 220, "stale": 0,
  "sources": [ { "kind": "yahoo", "label": "Yahoo Finance futures", "everyMs": 300000,
    "lastSuccess": 1789747200000, "lastCount": 29, "expected": 29,
    "consecutiveFailures": 0, "healthy": true, "error": null } ],
  "store": { "candles": 1869, "priced": 220 } }
Point a monitor at status != "ok". The previous version of this site published a dead feed for nineteen days because nothing was watching this number.

05Running it yourself

One Node process, no external database, no runtime dependencies.

git clone <repo> && cd weridarc
npm start  # http://localhost:4800

# environment
PORT 4800
HOST 0.0.0.0

State lives in data/werid.db (SQLite via node:sqlite) and resolved TCGplayer ids are cached in data/cache/. Deleting either is safe: the catalogue re-seeds from data/universe.txt and the ids resolve again on the next poll.

06Links