API reference
The same data behind this website, free for community projects — Discord bots, addons, tools, spreadsheets. No API key required. CORS is open (*), so browser apps can call it directly.
Base URL: https://forevermarket-api.vajgrtlabs.workers.dev
Conventions
- All responses are JSON with
ok: trueon success,{ok:false, error:"..."}on failure. - Prices are in copper (1 gold = 10,000 copper, 1 silver = 100 copper).
- Timestamps are unix seconds (UTC).
ruleset:normal|pvp|rp|hardcore(defaultnormal).faction:horde|alliance(defaulthorde).
Endpoints
GET /api/status
Market freshness for every ruleset: last scan, scans and items in the last 24h, and whether each market is stale (no scan in 6+ hours).
Returns: rulesets keyed by ruleset, each with last_scan, scans_24h, items_24h, stale, and a per-faction breakdown.
curl https://forevermarket-api.vajgrtlabs.workers.dev/api/status
GET /api/version
Latest released addon version, for update checks.
Returns: {ok, version, download} — e.g. {"ok":true,"version":"1.3.5","download":"https://forevermarket.pages.dev/import.html"}.
curl https://forevermarket-api.vajgrtlabs.workers.dev/api/version
GET /api/prices
Compact median-price map from the latest hourly rollup — what the addon tooltips and the desktop uploader use.
Params: ruleset, faction, with_samples=1 (also returns per-item scan counts).
Returns: {ok, ruleset, faction, count, prices: {"12345": 42000, ...}}. Cached 10 minutes.
curl "https://forevermarket-api.vajgrtlabs.workers.dev/api/prices?ruleset=pvp&faction=alliance&with_samples=1"
GET /api/items
Name search. Query must be at least 2 characters; up to 25 results.
Params: q (required).
Returns: {ok, items: [{item_id, name, quality, icon}]}.
curl "https://forevermarket-api.vajgrtlabs.workers.dev/api/items?q=iron"
GET /api/items/:id
Full detail for one item: hourly price history plus the latest snapshot. Items nobody has scanned yet still return ok:true with a placeholder name and empty history.
Params: ruleset, faction, days (default 14, max 90).
Returns: {ok, item: {item_id, name, quality, icon, ...}, history: [{hour, min_price, median_price, mean_price, quantity, listings, samples}], latest: {...} | null}.
curl "https://forevermarket-api.vajgrtlabs.workers.dev/api/items/10308?ruleset=pvp&faction=alliance&days=14"
GET /api/trending
Biggest 24-hour median movers (up to 50), by absolute percent change. If there isn't enough history yet, falls back to the most-listed items at their latest median (fallback: true, change_pct: null).
Params: ruleset, faction.
Returns: {ok, trending: [{item_id, name, quality, price, listings, samples, change_pct}]}.
curl "https://forevermarket-api.vajgrtlabs.workers.dev/api/trending?ruleset=pvp&faction=alliance"
GET /api/deals
Sniper feed: items whose current minimum listing is at least min_discount% below their 7-day median. Up to 100, biggest discount first.
Params: ruleset, faction, min_discount (1–90, default 20).
Returns: {ok, ruleset, faction, min_discount, deals: [{item_id, name, icon, min_price, median_price, samples, discount_pct, listings, quantity}]}.
curl "https://forevermarket-api.vajgrtlabs.workers.dev/api/deals?ruleset=pvp&faction=alliance&min_discount=30"
GET /api/arbitrage
Horde vs Alliance medians side by side for one ruleset — only items with data on both factions and a spread at or above min_spread%. Up to 100, biggest spread first.
Params: ruleset, min_spread (0–500, default 10).
Returns: {ok, ruleset, min_spread, arbitrage: [{item_id, name, icon, quality, horde_price, alliance_price, horde_qty, alliance_qty, spread_pct, buy_faction}]}.
curl "https://forevermarket-api.vajgrtlabs.workers.dev/api/arbitrage?ruleset=pvp&min_spread=15"
GET /api/contributors
Anonymous scanner leaderboard — top 50 by items uploaded. Cached 5 minutes.
Returns: {ok, contributors: [{goblin_name, scans, items, last_seen}]}.
curl https://forevermarket-api.vajgrtlabs.workers.dev/api/contributors
GET /api/health
Liveness ping.
Returns: {ok, ts}.
curl https://forevermarket-api.vajgrtlabs.workers.dev/api/health
Uploading scans — POST /api/ingest
Accepts auction-house scans as JSON. The addon produces the FM2 format: a header line followed by one line per item.
FM2;<ruleset>;<faction>;<unix_ts>;<scanner_version>
<item_id>,<min_copper>,<quantity>
<item_id>,<min_copper>,<quantity>
...
Body: {ruleset, faction, format: 2, ts, lines: ["12345,42000,200", ...], uploader_tag} — ruleset is required, faction must be horde or alliance for format 2, lines is 1–60,000 item lines, uploader_tag is an optional anonymous client id (stable per install). Older format 1 (no faction) is still accepted.
curl -X POST https://forevermarket-api.vajgrtlabs.workers.dev/api/ingest -H "Content-Type: application/json" -d '{"ruleset":"pvp","faction":"alliance","format":2,"ts":1728000000,"lines":["12345,42000,200"],"uploader_tag":"my-bot"}'
One scan per minute per client is plenty — faster uploads just get throttled by aggregation.
Feedback — POST /api/feedback
Submit a bug report or feature request programmatically.
Body: {type: "bug"|"feature"|"other", message, page?, contact?} — message must be at least 5 characters.
Fair use
This API is free for community projects — Discord bots, addons, tools, research. No key, no signup. In return, be polite:
- Cache responses. Medians update on an hourly rollup; polling
/api/pricesevery 30 seconds gains you nothing. Ten minutes is a good cache TTL. - Don't hammer. If you're building a bot for a big server, fetch once and serve your users from your own cache.
- Say what you are. Set a descriptive
User-Agentso your traffic is identifiable. - Give credit. A "prices by GoblinLedger" link back keeps the data flowing — every scan comes from a player who chose to share.
GoblinLedger