GameQuery Docs
Endpoint Reference (v1)

POST /v1/post/fetch

The full request and response contract for live server payloads.

View as Markdown

Returns the most recent payload for every requested address, registers valid unknown addresses, and reports per-row validation problems without failing the batch.

https://api.gamequery.dev/v1/post/fetch

Request headers

Content-Type: application/json
X-API-Token: YOUR_API_KEY
X-API-Token-Type: FREE
X-API-Token-Email: [email protected]

Request body

{
  "servers": [
    {
      "game_id": "counterstrike16",
      "servers": ["192.168.0.1:27015", "192.168.0.2:27015"]
    }
  ]
}
FieldTypeRules
serversarrayRequired. Must be an array or the request returns POST_2.
servers[].game_idstringMust match an id from GET /v1/get/games.
servers[].serversstring arrayIPv4 ip:port entries. Max 1000 across all groups.

Duplicate game_id + address pairs within one request are collapsed before the lookup, so repeating an address costs nothing but does not fetch it twice.

Success response

Status 200, Content-Encoding: gzip. The body is an object keyed by ip:port, plus exactly one non-address key, _meta.

{
  "192.168.0.1:27015": {
    "name": "Example Server",
    "map": "de_dust2",
    "password": false,
    "numplayers": 16,
    "maxplayers": 32,
    "players": [
      { "name": "player-one", "raw": { "score": 61, "time": 10225.85 } }
    ],
    "bots": [],
    "connect": "192.168.0.1:27015",
    "queryPort": 27015,
    "ping": 46,
    "version": "1.1.2.7/Stdio",
    "raw": {
      "protocol": 48,
      "folder": "cstrike",
      "game": "example.mod",
      "appId": 10,
      "numbots": 0,
      "secure": 1
    },
    "updated": "2026-08-30 13:22:36",
    "_updater": {
      "status": "online",
      "firewall_interval_minutes": 1,
      "firewall_label": "none",
      "next_probe_at": "2026-08-30T13:23:00.000Z",
      "last_probe_at": "2026-08-30T13:22:36.000Z",
      "last_online_at": "2026-08-30T13:22:36.000Z"
    }
  },
  "_meta": {
    "auto_inserted": 1,
    "inserted_servers": [
      { "game_id": "counterstrike16", "server": "192.168.0.1:27015" }
    ],
    "invalid_servers": []
  }
}

Payload fields

FieldTypeNotes
namestringServer hostname as the server reports it.
mapstringCurrent map.
passwordbooleanWhether the server is password protected.
numplayersnumberCurrent player count. This is the player count, not players.
maxplayersnumberSlot count.
playersarrayRoster. Entry shape varies by game; name is the stable field.
botsarrayBot roster, often empty.
connectstringAddress a client should connect to.
queryPortnumberPort that answered the query.
pingnumberMilliseconds measured by the probing worker, not by you.
versionstringGame or protocol version string.
rawobjectProtocol-specific fields, passed through unnormalised. Shape differs per game.
updatedstringYYYY-MM-DD HH:MM:SS in UTC, not ISO 8601.
_updaterobjectProbe metadata. See Data Freshness.

Only name, connect, updated and _updater are dependable across every game. Everything else, raw above all, follows whatever the game's own protocol exposes. Treat missing fields as unknown rather than as zero.

_meta

FieldTypeMeaning
auto_insertednumberHow many game_id + address pairs were newly registered.
inserted_serversarrayThose pairs, as { game_id, server }.
invalid_serversarrayRejected rows, as { game_id, servers }.

A row lands in invalid_servers when game_id is empty, is not in the catalogue, has an empty servers array, or when an address does not match IPv4 ip:port. The rest of the batch still succeeds with 200, so this array is the only place validation failures are reported. Log it.

Address with no data yet

{
  "192.168.0.5:27015": {
    "message": "Server not updated yet, or not existing in database",
    "_updater": { "status": "unknown", "firewall_interval_minutes": 1 }
  }
}

Stale payload

{
  "192.168.0.1:27015": {
    "name": "Example Server",
    "numplayers": 16,
    "updated": "2026-08-30 12:04:11",
    "message": "Server data is stale and awaiting a fresh updater refresh",
    "_stale": true,
    "_stale_age_seconds": 4705,
    "_stale_expected_max_age_seconds": 180
  }
}

The original fields are kept. Render it as last-known state rather than discarding it.

Failure responses

StatusBody
400{"error":"POST_2","message":"Invalid request format"}
400{"error":"POST_3","message":"Exceeded maximum server request limit (1000)"}
400{"error":"POST_4","message":"Invalid JSON format"}
401{"message":"API token is required"} and the other credential messages
403{"message":"Request origin is blocked by API key whitelist settings"}
405{"error":"POST_1","message":"Method Not Allowed. Only POST requests are accepted."}
429{"message":"Daily quota exceeded for this API key","quota":1440,"used":1440}
500{"message":"Internal server error"}

See Errors and Limits for when each one fires.

On this page