# Goblin Exchange > Goblin Exchange (https://heyfatguy.com) is a fan site for the World of Warcraft Forever auction house: live prices, flips, crafting profits, an advisor brief, an item index with sources, talent trees, and (for Kewk's friends) their own characters and upgrade picks. This API serves only the site's own data. It never calls Blizzard and cannot act in the game or on Battle.net. Base URL: https://heyfatguy.com/api/v1 Human docs: https://heyfatguy.com/api OpenAPI: https://heyfatguy.com/api/openapi.json Money is in copper (10000 copper = 1 gold). Times are unix seconds. Data refreshes about hourly; cache it. ## Auth - Public routes need no key. - Key routes need `Authorization: Bearer gex_...`. A key belongs to one Battle.net account and reads only that account's data. - Keys are made by a logged-in friend at https://heyfatguy.com/api ("Create key"), shown once, revocable there. Scopes: `read` (always), `import` (opt-in, allows POST /import). - Never put the key in a URL. ## Limits - Per key: 30 requests/minute, 1,000/day (UTC). All keys together: 2,000/day. - Over a limit: HTTP 429 with `Retry-After` (seconds). Wait that long, don't retry in a loop. - Responses carry `X-RateLimit-Remaining-Minute` and `X-RateLimit-Remaining-Day`. - Public routes are static files: no counter, but fetch each at most once per run. ## Errors Key routes return `{"error": {"status": , "code": "", "message": ""}}`. Codes: 400 bad_request, 401 unauthorized (no, unknown or revoked key), 403 forbidden (missing scope, account no longer allowed), 404 not_found, 405 method_not_allowed, 413 too_large, 415 unsupported_media_type, 429 rate_limited, 502 upstream. CORS: `Access-Control-Allow-Origin: *` on all /api/v1 routes and public data. ## Public routes (no key) - GET /api/v1/market: every item on the auction house now. Top level: `items` (list), `last` (newest snapshot time), `scans`, `cut` (0.05 AH cut), `sales_hours`, `house`, `houses`. Item fields: id, name, quality, class, sub, ilvl, vendor (vendor sell price), ask (lowest buyout), fair, mv (market value), qty, n (auctions), chg24 (% 24h), vs_mv (% ask vs market value), sold24, sold_day, sell_through, supply, vol, flip {units, cost, relist, profit, roi}, signal (BUY, SELL or empty), vendor_profit. About 1.5 MB. Example: `curl -s https://heyfatguy.com/api/v1/market | jq '[.items[] | select(.signal=="BUY")] | sort_by(-.flip.profit) | .[:10]'` - GET /api/v1/item/{id}: one item. `item` {id, name, quality, class, sub, ilvl, vendor}, `history` (per snapshot: t, ask, med, fair, qty, n, sold), `book` (order book levels). 404 means no price history here; use /items/search?q={id} for the item's stats. Example: `curl -s https://heyfatguy.com/api/v1/item/2589` - GET /api/v1/advisor: the advisor brief. `brief` {headline, market_read, picks [{action (flip, buy, craft, sell...), item_id, name, why, risk, size_gold, confidence}], avoid, data_caveats}; `picks` {flip, craft, vendor, sell, momentum} scored lists; `snapshot`, `generated`, `sales_hours`. Example: `curl -s https://heyfatguy.com/api/v1/advisor | jq '.brief.picks'` - GET /api/v1/crafts: `recipes` [{spell, name, prof, skill, item, product, sell, cost, profit, margin, sold_day, profit_day, reagents [{id, n, unit, src (ah or vendor), name}]}]. - GET /api/v1/houses: `default` and `houses` {house key: slug}. Other houses: /data/{slug}/market.json, crafts.json, advisor.json, item/{id}.json. - GET /api/v1/items: the whole item index (about 11k items, 2.7 MB): id, name, q (quality), ilvl, req, lvl (required level), inv, type, subName, slots, stats, dmg, classMask, raceMask, bond, base (1 = Classic stats). Prefer /items/search. - GET /api/v1/items/sources: `items` {id: [{t (quest, dungeon, raid, drop, vendor, crafted, other), ..., p (provenance list)}]}, `quests` {id: {n, lvl, req, f (H, A, B), z, chain, step}}. - GET /api/v1/items/meta: statNames, weights (ret, prot, holy Paladin weights), slots. - GET /api/v1/talents: class list, points per level (`points`), build info. - GET /api/v1/talents/{class}: class = warrior, paladin, hunter, rogue, priest, shaman, mage, warlock, druid. Trait tree: `tabs`, nodes with ranks, spells, prerequisites. Share links: https://heyfatguy.com/#talents:{class}:{code}. ## Key routes - GET /api/v1/me: account, battletag, key {id, name, scopes, created}, limits, usage {total, today, remainingMinute, remainingDay}. - GET /api/v1/characters: `characters` [{guid, name, fullName, level, class, classFile, race, faction, realm, guild, gold, spec, time}], newest first. - GET /api/v1/characters/{guid}: `character`: the full addon snapshot (worn gear and bag items with ids, links and stats, character sheet stats, talents {spec, tabs, picks}, completedQuests). Example: `curl -s -H "Authorization: Bearer $GEX_KEY" https://heyfatguy.com/api/v1/characters/Player-5826-0ABCDEF1` - GET /api/v1/upgrades[?guid=]: `characters` {guid: {by_role {ret, prot, holy}: AH upgrades with score gain and gold per point, note {text, buy_first, spend_gold}, gold, snapshot}}, `updated`. - GET /api/v1/talent-templates[?class=]: `templates` [{id, name, cls, code, ranks, level, role, created, updated, share}]. - GET /api/v1/items/search: server-side Planner search over the item index with live AH prices. Params: - q: name contains (case-insensitive), or exact item id - slot: 1 Head, 2 Neck, 3 Shoulder, 5 Chest, 6 Waist, 7 Legs, 8 Feet, 9 Wrist, 10 Hands, 11/12 Finger, 13/14 Trinket, 15 Back, 16 Main Hand, 17 Off Hand, 18 Relic - min, max: required level range - quality: minimum (0 poor .. 5 legendary) - class: drops items restricted to other classes and quests for other classes; for paladin also armor/weapon proficiency (plate from level 40) - level: character level for the paladin plate check (default max, else 60) - role: ret, prot or holy; adds `score` (Paladin weights) and sorts by it - onAh=1: only items listed now - obtain: any (default; item needs an allowed source), ah (on the AH, or a quest reward when quests=1), all (every item) - quests, dungeons, raids: 0 or 1 (default 1). Given any of these, an item needs an allowed source; it still shows when it also comes from the AH, a vendor, a world drop or a quest - faction (H or A), race (race id): skip quests for the other side - sort: score, ilvl (default), lvl, price (cheapest first) - limit (default 50, max 200), offset Returns {total, offset, limit, sort, house, items [{id, name, quality, ilvl, reqLevel, type, subName, slots, stats, dmg, bind, classicStats, score, ask, marketValue, listed, sources}]}. Example: `curl -s -H "Authorization: Bearer $GEX_KEY" "https://heyfatguy.com/api/v1/items/search?slot=1&min=20&max=30&class=paladin&role=ret&raids=0&limit=10"` - POST /api/v1/import (scope import): body `{"chars": {"": {...}}}` = the GoblinExchangeDB.chars table from WTF/Account//SavedVariables/GoblinExchange.lua as JSON. 1 MB max, Content-Type application/json. Keeps the newest snapshot per GUID. Returns {saved, total, updated}. ## Tips for agents - Start with GET /api/v1/advisor and /api/v1/market (no key). Use /items/search instead of downloading /items. - For "what should I upgrade": GET /characters, then /upgrades?guid=..., then /items/search with that character's level, class and role. - Gold on a character is in copper.