Quickstart
From API key to a parsed payload, with the exact request the API accepts.
1) Collect your credentials
The dashboard issues a key immediately. You need three values, and every authenticated request sends all three:
X-API-Token- the key itselfX-API-Token-Type-FREEorPRO, and it must match the key's packageX-API-Token-Email- the account email the key belongs to
export GQ_API_BASE_URL="https://api.gamequery.dev"
export GQ_API_VERSION="v1"
export GQ_API_TOKEN="your-token"
export GQ_API_TOKEN_TYPE="FREE"
export GQ_API_TOKEN_EMAIL="[email protected]"2) Look up valid game IDs
curl "$GQ_API_BASE_URL/$GQ_API_VERSION/get/games"[
{ "id": "counterstrike16", "name": "Counter-Strike 1.6" },
{ "id": "minecraft", "name": "Minecraft" }
]No auth is needed here. Use the id value verbatim as game_id; the catalogue
is cached for 24 hours, so cache it on your side too.
3) Send a fetch request
Addresses are grouped by game. This is the only body shape the endpoint accepts:
{
"servers": [
{
"game_id": "counterstrike16",
"servers": ["192.168.0.1:27015", "192.168.0.2:27015"]
},
{
"game_id": "minecraft",
"servers": ["192.168.0.3:25565"]
}
]
}curl -X POST "$GQ_API_BASE_URL/$GQ_API_VERSION/post/fetch" \
-H "Content-Type: application/json" \
-H "X-API-Token: $GQ_API_TOKEN" \
-H "X-API-Token-Type: $GQ_API_TOKEN_TYPE" \
-H "X-API-Token-Email: $GQ_API_TOKEN_EMAIL" \
-d '{
"servers": [
{
"game_id": "counterstrike16",
"servers": ["192.168.0.1:27015"]
}
]
}'4) Read the response
The response is an object keyed by ip:port, plus a single _meta key.
{
"192.168.0.1:27015": {
"name": "Example Server",
"map": "de_dust2",
"numplayers": 16,
"maxplayers": 32,
"updated": "2026-08-30 13:22:36",
"_updater": { "status": "online" }
},
"_meta": {
"auto_inserted": 1,
"inserted_servers": [
{ "game_id": "counterstrike16", "server": "192.168.0.1:27015" }
],
"invalid_servers": []
}
}Iterate the keys and skip _meta. The player count is numplayers and
maxplayers; players is the roster array, not a number.
5) Expect the first request to be empty
An address the platform has never seen is registered on the spot and reported in
_meta.inserted_servers, but no worker has probed it yet, so its value is:
{ "message": "Server not updated yet, or not existing in database" }That is normal. Ask again about a minute later and the payload will be there. See Data Freshness for the full lifecycle.
Limits worth knowing before you build
- Maximum 1000 addresses per request, counted across every group.
- Addresses must be IPv4
ip:port. Hostnames and IPv6 are rejected into_meta.invalid_servers. Content-Type: application/jsonis required onPOST /v1/post/fetch.- Duplicate
game_id + addresspairs inside one request are de-duplicated.