WARPANEL API
Your WARDOGS server's live status, leaderboards, matches, kill feed, weapons, maps, totals and history as JSON — enough to run a whole community website for one server or a network of them. Premium servers make keys in WARPANEL → Settings → API.
The basics
- Read-only JSON over HTTPS. Base URL: https://warpanel.gg/api/v1
- Auth: send the key as Authorization: Bearer wpk_… (or X-API-Key: wpk_…). Keys are made by the server's owner in WARPANEL → Settings → API. A server key reads one server; a network key (owner only) reads every server the owner has in WARPANEL.
- Network keys pick the server with ?server=<id> (ids from GET /servers; a slug or join code works too) or ?server=all to combine the servers (players are merged by Steam ID). Without ?server, endpoints that can combine do (all), and /server asks for one. A server key may leave ?server out.
- Premium servers only. A key stops answering (403 premium_required) while the server it was made on is on Free.
- 60 requests a minute per key. Headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset (seconds). Over the limit: 429 with Retry-After.
- Live data is cached 10 seconds, the event feed 5 seconds, stats 1–2 minutes and history 10 minutes on our side, so polling faster gains nothing. Cache on your side too (30–60 s is plenty for a website).
- Times are ISO 8601 in UTC. /totals and /history take ?tz= (an IANA zone like Europe/Berlin) for "today" and the busiest hours. Steam IDs are 17-digit SteamID64 strings. Teams are Valkyra (red), Lonestar (blue) and Manticore (green); a server holds up to 100 players.
- Players who hid themselves from leaderboards are left out of player lists; elsewhere (live list, matches, events) they appear as "Hidden player" with steamId null.
- CORS is open for GET, but keep the key on a server (a backend route, serverless function or Cloudflare Worker) — anything in browser JavaScript can be read by every visitor.
curl -H "Authorization: Bearer $WARPANEL_API_KEY" https://warpanel.gg/api/v1/serverGET /servers — Your servers right now (server browser)
Every server the key reads with online, players and free slots, map, lighting, mode, match time and scores, team sizes and the join code players paste into the in-game browser — plus totals. A server key lists just its server.
https://warpanel.gg/api/v1/servers
{
"servers": [
{
"id": "x7k2p9",
"slug": "dog-house-1",
"name": "[DOGS] Dog House EU #1",
"joinCode": "ABCD1234",
"region": "eu-central",
"online": true,
"source": "rcon",
"players": {
"current": 96,
"max": 100,
"free": 4
},
"mode": "KOTK",
"map": "Ozeti",
"lighting": "Day",
"match": {
"startedAt": "2026-10-21T18:02:10.000Z",
"elapsedSeconds": 1204,
"scoreCap": 100,
"scores": [
{
"team": "Lonestar",
"score": 61
},
{
"team": "Valkyra",
"score": 55
},
{
"team": "Manticore",
"score": 40
}
]
},
"teams": [
{
"name": "Valkyra",
"players": 32
},
{
"name": "Lonestar",
"players": 33
},
{
"name": "Manticore",
"players": 31
}
]
}
],
"totals": {
"servers": 25,
"online": 25,
"players": 1832,
"slots": 2500,
"free": 668
},
"fetchedAt": "2026-10-21T18:22:14.000Z"
}GET /server — The server right now
Online or not, player count, map, match time and team scores, kills this match and the best player, team sizes and everyone on the server. Live parts need RCON connected (match kills need the kill feed too); without RCON server.source is "server_list" and you get what the game's server list says (no player list).
| Parameter | Values | Default | Notes |
|---|---|---|---|
| server | string | Network keys: which server (an id from GET /servers, or its slug / join code). Server keys can leave it out. |
https://warpanel.gg/api/v1/server
{
"server": {
"id": "x7k2p9",
"name": "[DOGS] Dog House EU | KOTK",
"joinCode": "ABCD1234",
"region": "eu-central",
"source": "rcon"
},
"online": true,
"players": {
"current": 58,
"max": 100
},
"match": {
"map": "Bakurani",
"lighting": "Day",
"mode": "KOTK",
"startedAt": "2026-10-20T13:21:40.000Z",
"elapsedSeconds": 1104,
"scoreCap": 1000,
"scores": [
{
"team": "Valkyra",
"score": 412
},
{
"team": "Lonestar",
"score": 377
},
{
"team": "Manticore",
"score": 290
}
],
"kills": 795,
"topPlayer": {
"steamId": "76561198000000001",
"name": "Kettu",
"team": "Valkyra",
"kills": 36
}
},
"teams": [
{
"name": "Valkyra",
"players": 20
},
{
"name": "Lonestar",
"players": 19
},
{
"name": "Manticore",
"players": 19
}
],
"onlinePlayers": [
{
"steamId": "76561198000000001",
"name": "Kettu",
"team": "Valkyra",
"kills": 14,
"deaths": 6,
"pingMs": 38,
"onlineSince": "2026-10-20T12:58:00.000Z"
}
],
"fetchedAt": "2026-10-20T13:40:04.000Z"
}GET /players — Players and their stats (leaderboards)
Everyone seen on the server (or, with ?server=all, on all your servers — merged by Steam ID), ranked by the stat you pick, in pages. Use it for leaderboards (most kills, K/D, playtime, headshots…) and player lists.
| Parameter | Values | Default | Notes |
|---|---|---|---|
| server | string | Network keys: a server id from GET /servers (or its slug / join code), or `all` for every server combined. Server keys can leave it out. | |
| period | all · 24h · 7d · 30d · season | all | Time window. season = the current WARDOGS Tracker season. |
| sort | kills · deaths · kd · hs · longest · streak · kph · playtime · matches · wins · winrate | kills | What to rank by. hs = headshot %, kph = kills per hour, longest = longest kill. |
| min | integer 0–500 | 0 | Kills (or matches for winrate) a player needs to be ranked — set 10 or more for ratio sorts (kd, hs, kph, winrate) so a 3–0 doesn't top the board. |
| q | string | Search by name, or a SteamID64. | |
| limit | integer 1–100 | 50 | Players per page. |
| page | integer 1–… | 1 | Page number (1-based). |
https://warpanel.gg/api/v1/players
{
"server": {
"id": "x7k2p9",
"name": "[DOGS] Dog House EU #1"
},
"period": {
"name": "30d",
"from": "2026-09-20T13:40:00.000Z",
"to": "2026-10-20T13:40:00.000Z"
},
"sort": "kills",
"page": 1,
"limit": 10,
"total": 842,
"pages": 85,
"players": [
{
"rank": 1,
"steamId": "76561198000000001",
"name": "Kettu",
"kills": 1284,
"deaths": 611,
"kd": 2.1,
"headshots": 302,
"headshotPct": 23.5,
"longestKillM": 412,
"bestStreak": 27,
"killsPerHour": 31.2,
"playtimeMinutes": 2469,
"seedingMinutes": 140,
"matches": 58,
"wins": 31,
"winRate": 53,
"favoriteWeapon": "AK-74M",
"favoriteMap": "Bakurani",
"mostPlayedTeam": "Valkyra",
"regular": true,
"firstSeen": "2026-08-02T18:11:04.000Z",
"lastSeen": "2026-10-20T13:40:12.000Z"
}
]
}GET /players/{steamId} — One player
One player's all-time stats on the server, first and last seen, and their records here (with their place in the server's all-time top 3, or null). With ?server=all: stats added up over your servers, the best record of each kind (with the server it was set on) and perServer lines. 404 when the player was never seen or hid themselves.
| Parameter | Values | Default | Notes |
|---|---|---|---|
| steamId | string | The player's 17-digit SteamID64. | |
| server | string | Network keys: a server id from GET /servers (or its slug / join code), or `all` for every server combined. Server keys can leave it out. |
https://warpanel.gg/api/v1/players/{steamId}
{
"server": {
"id": "x7k2p9",
"name": "[DOGS] Dog House EU #1"
},
"player": {
"rank": 0,
"steamId": "76561198000000001",
"name": "Kettu",
"kills": 1284,
"deaths": 611,
"kd": 2.1,
"headshots": 302,
"headshotPct": 23.5,
"longestKillM": 412,
"bestStreak": 27,
"killsPerHour": 31.2,
"playtimeMinutes": 2469,
"seedingMinutes": 140,
"matches": 58,
"wins": 31,
"winRate": 53,
"favoriteWeapon": "AK-74M",
"favoriteMap": "Bakurani",
"mostPlayedTeam": "Valkyra",
"regular": true,
"firstSeen": "2026-08-02T18:11:04.000Z",
"lastSeen": "2026-10-20T13:40:12.000Z"
},
"firstSeen": "2026-08-02T18:11:04.000Z",
"lastSeen": "2026-10-20T13:40:12.000Z",
"records": {
"longestKill": {
"meters": 412,
"weapon": "SVD",
"at": "2026-09-14T20:02:11.000Z",
"serverPlace": 2
},
"mostKillsInAMatch": {
"kills": 41,
"map": "Bakurani",
"at": "2026-10-01T19:44:00.000Z",
"serverPlace": 1
},
"bestStreak": {
"kills": 27,
"at": "2026-10-19T18:41:20.000Z",
"serverPlace": 1
},
"mostHeadshotsInAMatch": {
"headshots": 12,
"map": "Madrid",
"at": "2026-09-30T21:10:00.000Z",
"serverPlace": null
}
}
}GET /matches — Recent matches
Rounds newest first: map, lighting, start and end, length, team scores, winner, peak players and the best player (most kills). live: true = still running; abandoned = the server went quiet without a result. Page back with ?before=<next>. Needs RCON (match history is built from it).
| Parameter | Values | Default | Notes |
|---|---|---|---|
| server | string | Network keys: a server id from GET /servers (or its slug / join code), or `all` for every server combined. Server keys can leave it out. | |
| limit | integer 1–50 | 20 | Matches per page. |
| before | string | Only matches that started before this ISO time — pass the answer's `next` for the next page. | |
| players | 0 · 1 | 0 | 1 = add `lineup`: every player in the match with team, kills and deaths. |
https://warpanel.gg/api/v1/matches
{
"server": {
"id": "x7k2p9",
"name": "[DOGS] Dog House EU #1"
},
"matches": [
{
"id": "cm3x…",
"server": {
"id": "x7k2p9",
"name": "[DOGS] Dog House EU #1"
},
"map": "Ozeti",
"lighting": "Day",
"startedAt": "2026-10-21T17:21:40.000Z",
"endedAt": "2026-10-21T17:58:02.000Z",
"live": false,
"durationSeconds": 2182,
"scores": [
{
"team": "Lonestar",
"score": 100
},
{
"team": "Valkyra",
"score": 94
},
{
"team": "Manticore",
"score": 71
}
],
"winner": "Lonestar",
"abandoned": false,
"peakPlayers": 100,
"players": 131,
"bestPlayer": {
"steamId": "76561198000000001",
"name": "Kettu",
"team": "Lonestar",
"kills": 36,
"deaths": 9
}
}
],
"next": "2026-10-21T17:21:40.000Z"
}GET /events — Event feed (kills and match results)
What just happened, newest first: every kill (killer, victim, weapon, distance, headshot, suicide) and every finished match (winner, scores, length). Poll with ?since=<the newest at you have> to get only new events. Kills need the kill feed; match results need RCON. Without ?since: the last 7 days.
| Parameter | Values | Default | Notes |
|---|---|---|---|
| server | string | Network keys: a server id from GET /servers (or its slug / join code), or `all` for every server combined. Server keys can leave it out. | |
| limit | integer 1–100 | 50 | Events to return. |
| since | string | Only events after this ISO time. | |
| types | string | kill,match_end | Comma list: kill, match_end. |
https://warpanel.gg/api/v1/events
{
"server": {
"id": "x7k2p9",
"name": "[DOGS] Dog House EU #1"
},
"events": [
{
"type": "kill",
"id": "ck1…",
"at": "2026-10-21T18:21:58.000Z",
"server": {
"id": "x7k2p9",
"name": "[DOGS] Dog House EU #1"
},
"map": "Ozeti",
"killer": {
"steamId": "76561198000000001",
"name": "Kettu"
},
"victim": {
"steamId": "76561198000000002",
"name": "Rekku"
},
"weapon": "AK-74M",
"distanceM": 212,
"headshot": true,
"suicide": false
},
{
"type": "match_end",
"id": "cm3x…",
"at": "2026-10-21T17:58:02.000Z",
"server": {
"id": "x7k2p9",
"name": "[DOGS] Dog House EU #1"
},
"map": "Ozeti",
"winner": "Lonestar",
"scores": [
{
"team": "Lonestar",
"score": 100
},
{
"team": "Valkyra",
"score": 94
},
{
"team": "Manticore",
"score": 71
}
],
"durationSeconds": 2182
}
],
"fetchedAt": "2026-10-21T18:22:00.000Z"
}GET /weapons — Weapons
Kills per weapon in the period, most used first: share of all kills, headshots and headshot %, longest and average kill distance, how many players got kills with it, the top 3 shooters, and an icon URL when the item is known. Needs the kill feed.
| Parameter | Values | Default | Notes |
|---|---|---|---|
| server | string | Network keys: a server id from GET /servers (or its slug / join code), or `all` for every server combined. Server keys can leave it out. | |
| period | all · 24h · 7d · 30d · season | 30d | Time window. season = the current WARDOGS Tracker season. |
| limit | integer 1–200 | 50 | Weapons to return. |
https://warpanel.gg/api/v1/weapons
{
"server": {
"id": "x7k2p9",
"name": "[DOGS] Dog House EU #1"
},
"period": {
"name": "30d",
"from": "2026-09-21T18:00:00.000Z",
"to": "2026-10-21T18:00:00.000Z"
},
"totalKills": 182400,
"weapons": [
{
"weapon": "AK-74M",
"icon": "https://wardogstracker.gg/images/weapons/ak-74m.png",
"kills": 24110,
"share": 13.2,
"headshots": 5120,
"headshotPct": 21.2,
"longestKillM": 611,
"avgDistanceM": 64,
"players": 3911,
"topPlayers": [
{
"steamId": "76561198000000001",
"name": "Kettu",
"kills": 812
}
]
}
]
}GET /maps — Maps
Per map in the period: rounds played, average length and peak players, wins and win rate per team (and rounds without a winner), kills, kills per round, headshots and the longest kill. Rounds need RCON; kills need the kill feed.
| Parameter | Values | Default | Notes |
|---|---|---|---|
| server | string | Network keys: a server id from GET /servers (or its slug / join code), or `all` for every server combined. Server keys can leave it out. | |
| period | all · 24h · 7d · 30d · season | 30d | Time window. season = the current WARDOGS Tracker season. |
https://warpanel.gg/api/v1/maps
{
"server": {
"id": "x7k2p9",
"name": "[DOGS] Dog House EU #1"
},
"period": {
"name": "30d",
"from": "2026-09-21T18:00:00.000Z",
"to": "2026-10-21T18:00:00.000Z"
},
"maps": [
{
"map": "Ozeti",
"rounds": 412,
"avgDurationSeconds": 2090,
"avgPeakPlayers": 92,
"wins": [
{
"team": "Lonestar",
"wins": 150,
"winRate": 36.4
},
{
"team": "Valkyra",
"wins": 139,
"winRate": 33.7
},
{
"team": "Manticore",
"wins": 118,
"winRate": 28.6
}
],
"noWinner": 5,
"kills": 98112,
"killsPerRound": 238,
"headshots": 20110,
"longestKillM": 744
}
]
}GET /totals — Totals (today, season, all time)
Kills, deaths (every death, suicides included), headshots, hours played, unique players and finished matches — today so far (with % change against yesterday at the same time of day), yesterday, the last 7 days, the current season and all time. Days follow ?tz.
| Parameter | Values | Default | Notes |
|---|---|---|---|
| server | string | Network keys: a server id from GET /servers (or its slug / join code), or `all` for every server combined. Server keys can leave it out. | |
| tz | string | UTC | IANA time zone for days and hours, e.g. Europe/Berlin. |
https://warpanel.gg/api/v1/totals
{
"servers": [
{
"id": "x7k2p9",
"name": "[DOGS] Dog House EU #1"
}
],
"timeZone": "Europe/Berlin",
"today": {
"from": "2026-10-20T22:00:00.000Z",
"kills": 163696,
"deaths": 178661,
"headshots": 33010,
"playtimeHours": 29451,
"players": 18093,
"matches": 410,
"changePct": {
"kills": -5,
"deaths": -6,
"playtimeHours": -4,
"players": -6
}
},
"yesterday": {
"from": "2026-10-19T22:00:00.000Z",
"to": "2026-10-20T22:00:00.000Z",
"kills": 201330,
"deaths": 219004,
"headshots": 40122,
"playtimeHours": 36120,
"players": 21400,
"matches": 506
},
"last7Days": {
"kills": 1240110,
"deaths": 1350332,
"headshots": 250100,
"playtimeHours": 221040,
"players": 69047,
"matches": 3420
},
"season": {
"number": 2,
"name": "Season 2",
"startsAt": "2026-10-16T00:00:00.000Z",
"endsAt": null,
"kills": 901233,
"deaths": 980011,
"headshots": 180400,
"playtimeHours": 160200,
"players": 52110,
"matches": 2510
},
"allTime": {
"kills": 3015443,
"deaths": 3313807,
"headshots": 610220,
"playtimeHours": 508256,
"players": 106431,
"matches": 11820
},
"fetchedAt": "2026-10-21T18:22:00.000Z"
}GET /history — History and busiest hours
Per day (UTC days): peak and average players (from the game's server list; with ?server=all the servers' own peaks added up), unique players, hours played and kills. Per hour for the last 48 hours: average players online and unique players. And the week (last 28 days, in ?tz): average players for every weekday and hour, and the busiest one. Players and hours need RCON.
| Parameter | Values | Default | Notes |
|---|---|---|---|
| server | string | Network keys: a server id from GET /servers (or its slug / join code), or `all` for every server combined. Server keys can leave it out. | |
| days | integer 1–90 | 30 | Days of daily history. |
| tz | string | UTC | IANA time zone for days and hours, e.g. Europe/Berlin. |
https://warpanel.gg/api/v1/history
{
"servers": [
{
"id": "x7k2p9",
"name": "[DOGS] Dog House EU #1"
}
],
"timeZone": "Europe/Berlin",
"daily": [
{
"day": "2026-10-20",
"peakPlayers": 2500,
"avgPlayers": 1220,
"uniquePlayers": 21400,
"playtimeHours": 36120,
"kills": 201330
}
],
"hourly": [
{
"hour": "2026-10-21T17:00:00.000Z",
"avgPlayers": 1810.4,
"uniquePlayers": 2410
}
],
"week": {
"busiest": {
"weekday": "Sunday",
"weekdayIndex": 6,
"hour": 17,
"avgPlayers": 2469
},
"hours": [
{
"weekday": "Monday",
"weekdayIndex": 0,
"hour": 0,
"avgPlayers": 412.5
}
]
},
"fetchedAt": "2026-10-21T18:22:00.000Z"
}Errors
Every error looks like { "error": { "code": "…", "message": "…" } }.
- 400 bad_request — A parameter is wrong — the message says which.
- 401 missing_key — No key sent.
- 401 invalid_key — Not a WARPANEL key, or it was deleted.
- 403 premium_required — The server the key was made on doesn't have Premium right now.
- 403 forbidden — A server key asked for another server (make a network key).
- 404 not_found — No such player or server for this key.
- 429 rate_limited — Over 60 requests a minute — wait Retry-After seconds.
- 503 unavailable — Try again shortly.
Keep the key secret
Call the API from your own backend and cache the answer for a minute; your page reads your backend. A static website can use a free Cloudflare Worker for that.
// A tiny backend route that keeps the key secret and caches for 60 s.
// Next.js (app/api/leaderboard/route.ts) — the same idea works in Express, PHP or a Cloudflare Worker.
export const revalidate = 60;
export async function GET() {
const res = await fetch("https://warpanel.gg/api/v1/players?period=30d&sort=kills&limit=10", {
headers: { Authorization: `Bearer ${process.env.WARPANEL_API_KEY}` },
next: { revalidate: 60 },
});
if (!res.ok) return Response.json({ players: [] }, { status: 502 });
const { players } = await res.json();
return Response.json({ players });
}// Cloudflare Worker (free) for a static website: set WARPANEL_API_KEY as a secret, then
// fetch("https://<your-worker>.workers.dev/leaderboard") from your page.
export default {
async fetch(req, env, ctx) {
const cache = caches.default;
const hit = await cache.match(req);
if (hit) return hit;
const api = await fetch("https://warpanel.gg/api/v1/players?period=30d&sort=kills&limit=10", {
headers: { Authorization: `Bearer ${env.WARPANEL_API_KEY}` },
});
const res = new Response(api.body, { status: api.status, headers: { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*", "Cache-Control": "public, max-age=60" } });
ctx.waitUntil(cache.put(req, res.clone()));
return res;
},
};