Live lookups
Player stats can be refreshed on demand. The API waits a few seconds for the new numbers before it answers.
When you call GET /v1/players/{username} and the stored stats are more than 30 seconds old, the API starts a live refresh for that player. It waits up to 15 seconds, then answers with whatever is freshest. If the refresh finished in time you get brand new numbers. If not, you get the stored numbers and the refresh keeps going, so the next call is fresh.
Every answer includes a Lookup object that tells you what happened and when the stats were refreshed.
{
"status": "skipped",
"checkedAt": 1792722587957
}The first time anyone asks for a player, there is nothing stored to fall back on. If the refresh finishes within 15 seconds you get the full profile. If it does not, you get 202 with no player yet:
{
"player": null,
"lookup": {
"status": "pending",
"checkedAt": null
}
}Wait a few seconds and ask again. This helper does that for you:
async function player(username) {
for (let attempt = 0; attempt < 5; attempt++) {
const response = await fetch(
`https://api.donutstats.io/v1/players/${encodeURIComponent(username)}`,
{ headers: { "x-api-key": process.env.DONUTSTATS_API_KEY } },
);
if (response.status === 202) {
await new Promise((resolve) => setTimeout(resolve, 3000));
continue;
}
if (response.status === 404) return null;
if (!response.ok) throw new Error(`DonutStats API returned ${response.status}`);
return (await response.json()).player;
}
return null;
}Live refreshes are expensive, so each key can start a limited number per minute, separate from its request limit. When the budget is spent you still get stored data, marked rate_limited. Only when there is no stored data at all does the API answer 429:
{
"error": "Lookup rate limit exceeded",
"lookup": {
"status": "rate_limited",
"checkedAt": null
}
}- Use the default
autowhen a person is looking at one profile. - Use
lookup=nonefor anything in bulk, such as refreshing a list of players for a leaderboard of your own. - Check
lookup.checkedAtbefore showing numbers as live. - Keep
forcefor rare cases where seconds matter, like confirming a payment.
Lookups make the whole API better
Every lookup also refreshes the player's presence and what they are selling on the auction house, so their listings show up in the listings endpoint shortly after.
