API overview
Base URL, keys, limits, errors, caching and the OpenAPI document.
The API is plain JSON over HTTPS. You can read it without an account and without a key. It is meant for building datasets and tools; to answer questions in an assistant, the MCP server is the better fit.
Base URL#
Every endpoint is under one host.
https://everloot.app
Your first request:
curl "https://everloot.app/api/rollups/drops?limit=5"
const res = await fetch("https://everloot.app/api/rollups/drops?limit=5"); const body = await res.json(); console.log(body.dataAsOf, body.rates.length);
import requests body = requests.get("https://everloot.app/api/rollups/drops", params={"limit": 5}).json() print(body["dataAsOf"], len(body["rates"]))
Keys and limits#
You do not need a key to read. Without one, the corpus feed and the drop list answer 30 requests per hour for each IP address, 500 records a page. A free key raises that to 2,000 requests per hour and 5,000 records a page. The MCP server and the market prices have their own per-IP limits. All of it is on Limits and keys.
Response conventions#
Every answer says what kind of data it holds and how old it is.
- Player data carries its licence. Answers built from player uploads have an
attributionfield with the licence, the credit line and the page the data comes from. The same goes in theX-Everloot-Licence,X-Everloot-CreditandLinkheaders, for clients that never read the body. Show the credit wherever the data appears; see Licence and credit. - Game-file data is labelled. Facts read from the game files are Blizzard's. They carry a
gameDatanotice with the label "Found in game files, unconfirmed", the game build and a credit to Blizzard, instead of Everloot's licence. Endpoints that mix both say so, and label each layer. dataAsOfsays how fresh it is. It is when the uploads behind the answer were current. Check it before you trust a number. It is null or absent when that is unrecorded, never "now".- Unrecorded is not zero. When storage cannot be read, an answer says so with
unreachable: trueor a503, and the lists in it are empty. An empty list then means unknown, not measured as none. - Single reports are not facts. The corpus feed holds single reports. The site states a fact only once 3 installs agree; do the same if you publish numbers. How Everloot works explains the rule.
Errors#
A refusal is JSON with ok: false and a sentence that says what is wrong.
{
"ok": false,
"error": "Unknown record kind."
}| Status | Meaning |
|---|---|
400 | A parameter is wrong. error says which. |
401 | The key you sent is not valid or was revoked. Only when keys are switched on. |
404 | Nothing there: an unknown tool, or no page players have reported. |
429 | Rate limited. The Retry-After header is the number of seconds to wait. |
503 | A dependency is unavailable. The answer is unrecorded, not zero. |
getAKey appears in an error only while free keys exist; it is the address where you make one.
Paging#
Endpoints that return lists take offset (0 or more) and limit (1 or more), whole numbers. The answer repeats offset and limit, gives the total, and gives next: the full URL of the following page, or null on the last one. Follow next until it is null.
CORS#
The tooltip endpoint, the OpenAPI document and the JSON Schemas send Access-Control-Allow-Origin: *, so a web page on any site can read them. The other endpoints set no CORS headers: call them from a server, a script or a desktop tool. The MCP endpoint lets browsers call it only from a short list of AI sites.
Caching#
Read each answer's Cache-Control header. The corpus feed and the health check are no-store. The snapshot behind the feed is rebuilt about every ten minutes, so asking more often gains nothing. Tooltip answers are cached by the CDN for an hour, and the OpenAPI document and schema files for about an hour in browsers.
OpenAPI document#
The whole API in one file, OpenAPI 3.1, for client generators, request tools and assistants that read OpenAPI. It is assembled from the same definitions the server uses, so it cannot describe an endpoint that does not exist.
curl -s https://everloot.app/api/openapi.json | jq '.paths | keys'JSON Schemas#
Every response shape, every record kind and every MCP tool input is also a JSON Schema file. The list is at /schema/index.json. The shapes are described on Schemas and the protocol.
Protocol version#
The contract behind the API is one package, @everloot/protocol, currently version 1.2.0. A new kind, field or tool is a minor release. A removal, a rename or a tighter limit is a major release.
Endpoints#
Each endpoint has its own page with parameters, answers and examples.
Player data#
| Method | Path | What it does |
|---|---|---|
GET | /corpus/public | The public corpus: every public record players reported, without install ids |
GET | /rollups/drops | Corroborated drop rates with loot-window counts |
GET | /market/prices | Forever market values from full auction scans players started |
Game data#
| Method | Path | What it does |
|---|---|---|
GET | /items | Every item of the current build with its class, subclass, slot and quality |
GET | /items/categories | The item class and subclass tree of the current build, with the slot and quality slugs |
GET | /edges | Typed relations between items, NPCs, spells, quests, zones and sets |
GET | /edges/client-layer | The whole game-file relation layer of the current build |
Tools and cards#
| Method | Path | What it does |
|---|---|---|
GET | /tools/{tool} | One MCP tool's answer over plain HTTP |
GET | /tooltip/{type}/{id} | The hover card for one item, NPC, quest or object page, for the embeddable tooltip script |