AHledger API
The same data behind every page on this site, as JSON and plain text. No key needed, 300 requests a minute, credit with a link required. Base URL https://api.ahledger.com. Writing an addon? Read prices in game without calling anything.
Endpoints
| Endpoint | Returns | Cached |
|---|---|---|
| GET /v1/markets | Every market: id, game, ruleset, faction, region, label. | 5 minutes |
| GET /v1/items/{itemId}?game=forever | One item by Blizzard item id: name, quality, class, level, requirement, vendor value, icon. | 5 minutes |
| GET /v1/prices/{market}/{itemId}?range=7d | Latest price for an item on a market plus its history: 24h is one point per full scan, 7d hourly buckets, 30d and 90d daily buckets. Also the estimated units sold per day over the last week (sales.estimatedPerDay, null until enough hours of scans back it). | 1 minute |
| GET /v1/pricetable/{market} | Every priced item on a market as plain text, the format the addon reads. Sends an ETag, so an unchanged table answers 304. | 1 minute |
| GET /v1/tooltip/{market}?items=2589,2592 | Latest price, 7 and 30 day medians and estimated units sold a day (salesPerDay) for up to 100 items at once, for embeds and tooltips. The market comes back with slashes (forever/pvp/horde/us). | 1 minute |
| GET /v1/deals/{market}?discount=25&units=5 | Listings under their own 30 day median, biggest saving first, each with its estimated units sold a day (salesPerDay). discount 15, 25, 35, 50 or 70; units 1, 5, 20 or 100; sells 0, 1, 10 or 100 (minimum salesPerDay); sort=saving, discount or sales; limit up to 200; format=csv. | 10 minutes |
| GET /v1/crafting/{market}?profession=Tailoring | Every priced recipe ranked by margin at this market: result value after the house cut, reagent cost, reagents, the estimated units of the result sold a day (resultSalesPerDay) and the margin times that (profitPerDay). all=1 adds recipes with unpriced reagents and lists everything in skill order, as the page does; format=csv. | 15 minutes |
| GET /v1/structure/{market} | Depth, spread, turnover, supply shocks and volatility for the biggest positions, plus the weekday price and listing pattern. | 15 minutes |
| GET /v1/timing/{market}/{itemId}?days=28 | One item by hour of the day: typical price, lowest buyout, listings and days scanned per hour, the best three hour windows to buy and to sell, the spread after the house cut, and a confidence note. Hours are UTC with the market zone beside them. | 15 minutes |
| GET /v1/signals/{market}?discount=20&days=7 | A buy rule per item (price under its 30 day average) with how often it has recovered within the horizon, and whether it fires now. discount 10, 20, 30 or 40; days 3, 7 or 14. | 15 minutes |
| GET /v1/disenchant/{market} | Gear listed for less than its expected disenchant value, with each material priced. all=true includes the rest, format=csv. | 10 minutes |
| GET /v1/economy | The size of every Forever market: gold listed, auctions, units and items, the change on the week, PvP against Normal and Horde against Alliance, value by item class, the items holding the most gold, and daily history. | 10 minutes |
| GET /v1/economy/{market} | The same for one market, with its daily history. | 10 minutes |
| GET /health | Service status: database, queue, workers, ingestion, newest backup. | 10 seconds |
Market ids use dots: forever.pvp.horde.us is the PvP Horde market in the US region. Item ids are Blizzard's, the same numbers in every item URL on this site. Every response carries a Cache-Control header; honor it.
Examples
Markets:
curl https://api.ahledger.com/v1/markets{
"markets": [
{ "id": "forever.normal.alliance.us", "game": "forever", "ruleset": "normal",
"faction": "alliance", "region": "us", "label": "Normal Alliance" },
...
]
}Latest price and seven days of history for Linen Cloth on PvP Horde:
curl "https://api.ahledger.com/v1/prices/forever.pvp.horde.us/2589?range=7d"{
"market": "forever.pvp.horde.us",
"item": { "id": 2589, "name": "Linen Cloth", "quality": "COMMON" },
"latest": {
"observedAt": "2026-11-05T14:02:11.000Z", "source": "Addon scan",
"minBuyout": 18, "median": 20, "quantity": 3420, "auctions": 212,
"median7d": 22, "median30d": 21, "median90d": null
},
"range": "7d",
"series": [
{ "t": "2026-11-04T14:00:00.000Z", "min": 17, "median": 21, "p25": 19, "p75": 24,
"quantity": 3100, "auctions": 190 },
...
]
}Prices are copper: 10,000 copper is one gold. latest is null until a market has been scanned. The series is hourly buckets for 24h and 7d, daily for 30d and 90d.
The addon's price table, one line per item:
curl https://api.ahledger.com/v1/pricetable/forever.pvp.horde.us
AHL1|forever/pvp/horde/us|1793000000|18422
2589:20:18:3420:22:21:18:25:3600
12784:1500000:1400000:2:1600000:1550000:1200000:1800000:4
...Header: format, market, unix time, row count. Row: item id, median, minimum buyout, quantity, 7 day median, 30 day median, 30 day low, 30 day high, and the estimated units sold a day times ten (a whole number: 3600 is 360 a day, 4 is 0.4). An empty field means unknown. This is what AHledger sync writes into the addon.
Market tools
The deal scanner, crafting margins, market structure, timing signals and disenchant values are available for one market at a time, computed by the same queries as the pages, so a program and a person looking at the same market see the same rows. Every response leads with the market it covers; marketStatus (scanned, or not open yet, or no scans yet, with a message when there is nothing to rank); pricesAsOf, the newest full scan behind these figures (a partial scan never sets the figures, so it never sets this either); generatedAt, when they were worked out; and the page that shows the same data, so a client can check what it received. Rows link to the item's page on that market (url) and straight to its price charts (chartUrl). Money is copper. A page and the API refresh on their own schedules, so for a few minutes after a new scan they can differ; compare pricesAsOf.
curl "https://api.ahledger.com/v1/crafting/forever.pvp.alliance.us?profession=Enchanting"{
"market": "forever.pvp.alliance.us",
"marketLabel": "PvP Alliance",
"marketStatus": "scanned",
"pricesAsOf": "2026-11-05T14:02:11.000Z",
"generatedAt": "2026-11-05T14:10:00.000Z",
"page": "https://ahledger.com/crafting?market=forever/pvp/alliance/us&profession=Enchanting&utm_source=ahledger_api&...",
"filters": { "profession": "Enchanting", "all": false, "limit": 500 },
"notes": "netValue is the result price times the average yield, less the 5% house cut; ...",
"attribution": { "text": "Prices from AHledger", "url": "https://ahledger.com/crafting?...",
"html": "<a href="https://ahledger.com/crafting?...">Prices from AHledger</a>" },
"recipes": [
{ "recipe": { "spellId": 7421, "name": "Runed Copper Rod", "profession": "Enchanting",
"skillRequired": 1, "acquisition": "trainer" },
"result": { "id": 6218, "name": "Runed Copper Rod", "quality": "COMMON", "qtyMin": 1,
"qtyMax": 1, "url": "https://ahledger.com/items/6218-runed-copper-rod/forever.pvp.alliance.us?utm_source=ahledger_api&...",
"chartUrl": "https://ahledger.com/items/6218-runed-copper-rod/forever.pvp.alliance.us?utm_source=ahledger_api&...#price-history" },
"resultPrice": 9500, "netValue": 9025, "cost": 6200, "margin": 2825, "marginRatio": 0.4556,
"reagents": [ { "id": 6217, "name": "Copper Rod", "qty": 1, "price": 1200 }, ... ],
"unpriced": [] },
...
]
}Deals, crafting and disenchant take format=csv for a spreadsheet. Each response explains its fields in a notes string. Filters take the same values as the page controls, and the page parameter names work too (pct for discount). Parameters an endpoint does not take are ignored. A refused filter value is answered with the values it accepts, an unknown market with the list of markets, and an unknown profession with the list of professions. The figures move when new scans are read, so polling more often than the cache time returns the same answer. Each market tool endpoint allows 60 requests a minute per key or address. When they are busy they answer 503 with a Retry-After header; try again after that many seconds.
Pages for one market
The pages take the market in the address too, so a link or an AI assistant always opens the market it asks for. Without it, a page shows the market with the newest prices, or the one this browser last picked.
https://ahledger.com/deals?market=forever/pvp/alliance/us
https://ahledger.com/crafting?market=forever/pvp/alliance/us&profession=Tailoring
https://ahledger.com/structure?market=forever/pvp/alliance/us
https://ahledger.com/signals?market=forever/pvp/alliance/us
https://ahledger.com/items/2589-linen-cloth/forever.pvp.alliance.usPages use the market with slashes, the API with dots. The Forever markets are normal, pvp, rp and rppvp, each for alliance and horde, in the us, eu and cn regions: twenty-four in all.
The economy of each market
/v1/economy measures every Forever auction house at once, as the economy page does. Each market carries its current figures (the median across contributors over its newest 24 hours), the same 24 hours a week earlier, and its share by item class; the response adds totals, the PvP against Normal and Horde against Alliance comparisons, and one point per market per day. Value is in copper: every listed unit at its median price, except an item above three times its own 7 day median, which counts at that median, and an item listed in more than ten times the most it was listed in on any of the previous seven days, which counts at ten times; an item seen on fewer than two earlier days here, with no median on two other markets, counts at no more than 1,000 gold a unit. Each current figure is the median across contributors, one vote per uploader, and contributors says how many. It is listed value only, not the gold players hold.
GET https://api.ahledger.com/v1/economy
{
"totals": { "markets": ["forever.pvp.horde.us", ...], "value": 1813600000, "auctions": 408206, "weekChange": 1.71 },
"comparisons": { "pvpAgainstNormal": { "pvp": 1102160000, "normal": 711440000, "bigger": "PvP", "lead": 0.5492 }, ... },
"markets": [
{ "market": "forever.pvp.horde.us", "marketLabel": "PvP Horde", "marketStatus": "scanned",
"current": { "observedAt": "2026-10-04T09:02:41.000Z", "value": 585350000, "auctions": 102484,
"classes": [ { "name": "Armor", "value": 202520000, "share": 0.346 }, ... ],
"topItems": [ { "item": { "id": 9999, "name": "...", "url": "..." }, "value": 10010000 }, ... ] },
"weekAgo": { "value": 202610000, ... }, "weekChange": 1.889 },
...
],
"daily": [ { "market": "forever.pvp.horde.us", "day": "2026-10-03", "value": 571150000, "scans": 37 }, ... ]
}Limits
- 300 requests per minute per address, with or without a key, while everything is free. Keys are free; past the limit you get 429 with a Retry-After header.
- Responses are cached at the edge for the times above; polling faster than that returns the same bytes.
- Read only. The upload endpoint used by AHledger sync is signed with per-key secrets and is not part of the public surface.
- A market has prices only where somebody is scanning; the rest return null latest values and empty series until someone does. The catalog endpoints are live for every market now.
Need more than this, a bulk export, or a webhook? Say so through the contact form.
Price tooltips on your own site
One script tag, and every link to an AHledger item on your page gains a hover card with the item's icon, level and live price. Useful on a guide, a guild site, a forum post, or anywhere you already link items.
<script src="https://ahledger.com/embed.js" defer></script>
<a href="https://ahledger.com/items/2589-linen-cloth">Linen Cloth</a>Anything that is not a link can carry a card too, by naming the item id on the element. Put it on the word itself rather than a whole paragraph: the element becomes the thing you hover, and it is made reachable by keyboard so the card is not pointer-only.
<span data-ahledger-item="2589">Linen Cloth</span>It prices against PvP Horde by default. Name a different market on the script tag with data-market="forever.normal.alliance.us", using the same market ids as the endpoints above.
- A page with forty item links makes one request, not forty, and the answer is cached for the life of the page.
- The card opens on focus as well as hover and closes on Escape, so it works without a mouse.
- If anything fails, the link is left exactly as it was. Nothing is stored and no cookie is set.
- Links added after the page loads, as in a forum that loads more posts or a single page app, are picked up too, and only the items not yet seen are fetched.
- A Discord bot or any other program can call the same endpoint the card uses:
/v1/tooltip/<market>?items=2589,2592returns name, quality, icon, item level, class, median, cheapest listing and units listed for up to a hundred items in one call, with permissive CORS.
A whole card rather than a tooltip? The embed page has live item and deals cards for iframes and image links, and the open data page describes each dataset.
Sharing a link rather than embedding one? Pasting an item URL into Discord or anywhere that reads Open Graph tags renders a card with the current price and the time it was observed, with no script needed.
Feeds
Two RSS feeds, for readers and for bots. Build changes only is the one to point an automation at: one entry per World of Warcraft: Forever build, with what it added, removed and renamed. Everything adds guides and releases.
Using a key
A key lifts your rate limit and is tied to your account rather than to a machine, so the same key works from anywhere. Create one on your account page; the secret is shown once. Send it as a bearer token, or as an x-ahl-api-key header if that is easier:
curl -H "Authorization: Bearer ahlk_your_key_here" \
https://api.ahledger.com/v1/prices/forever.normal.alliance.us/2589Requests without a key still work at the free rate, so a key is about how often you can ask, never about what you are allowed to see. Every endpoint here is open to everyone.
Prices in your own addon
Writing a leveling guide, a profession helper, a bag or loot addon? It can show what an item sells for on the player's own auction house without scanning anything. The AHledger addon already carries a price table for the player's market, refreshed every 30 minutes by AHledger sync, and from version 0.9.8 it hands those prices to other addons through a global, AHledgerAPI. Make AHledger an optional dependency and check that the global exists:
## OptionalDeps: AHledger
if AHledgerAPI then
-- copper, or nil when the item has no price on this market
local median = AHledgerAPI.GetMedian(itemID)
-- an item id, a numeric string or an item link all work
local p = AHledgerAPI.GetPrice(itemLink)
if p then
-- p.median, p.minBuyout, p.quantity, p.median7d, p.median30d,
-- p.low30d, p.high30d, p.soldPerDay, p.market, p.updated, p.snapshot
end
-- show the credit wherever the prices appear
tooltip:AddLine(AHledgerAPI.CREDIT) -- "Prices from AHledger (ahledger.com)"
endGetPrice(item [, market])returns a fresh table you may keep;GetMedianis the cheap call for a tooltip line. Without a market they read the player's own, whichGetMarket()andGetMarketLabel()name.p.snapshotis true while the player runs on the copy of the prices that ships with the addon rather than live ones from sync. Say so when you show a price from it, the way AHledger does.- Nothing raises an error into your code: a bad argument, a market without prices or a failure inside AHledger returns nil. The table is read-only, so one addon cannot break it for the next.
AHledgerAPI.VERSIONchanges only on an incompatible change. New functions and fields arrive without changing it.
Players without AHledger see nothing from it, so make the feature quietly optional. If you would rather ship your own prices, the same tables are on the API as /v1/pricetable/{market}, under the terms below. Tell us through the contact form when yours is out and we will list it here and on the addon page.
Attribution and terms
Free use, personal or commercial, on two conditions. The data comes from players' scans and Blizzard's own game data; nothing here is scraped from third parties, and we ask the same of you.
- Credit AHledger with a link wherever the data is shown: the words
Prices from AHledgerlinked to ahledger.com or to the page of the item shown. Where a link cannot be clicked, as inside the game or in an image, write the address out:Prices from AHledger (ahledger.com). - Do not present the data as your own scan, and do not resell it as a feed. Building a paid product that shows it, credited, is fine.
Copy the credit in whichever form fits:
HTML <a href="https://ahledger.com">Prices from AHledger</a>
Markdown [Prices from AHledger](https://ahledger.com)
Discord Prices from AHledger <https://ahledger.com>
In game AHledgerAPI.CREDIT ("Prices from AHledger (ahledger.com)")The API does most of it for you. Item, price and market tool responses carry an attribution block with the text, a link and ready HTML, linked to the matching page, and every /v1 answer, the plain-text price table included, names these terms in a Link: <…/developers#terms>; rel="license" header. Show the credit where the figures appear. Links in responses carry campaign tags so we can see which tools send players our way; please keep them.
Built something with the API, a bot, a sheet, an addon or a site? Tell us through the contact form and we will link to it from this page.
The full terms of service apply. The API can change. Breaking changes will keep the old version running for at least 30 days and will be announced on this page.
Status
api.ahledger.com/health reports the database, queue, worker state and the age of the newest database backup, and is safe to poll every 30 seconds.
Where the data comes from
The About page explains every source and how a price gets from a scan to a page.