Conventions
Envelopes, pagination, ids, units and timestamps — what every endpoint has in common.
Everything below holds across all three areas. The per-endpoint detail is in the reference.
Two response envelopes
Reads return their payload under data. Endpoints with something to say about
the result add meta, and the paginated one adds links as well:
{ "data": [], "meta": {}, "links": {} }GET /game-servers sends data alone; the firewall read adds counts and limits
in meta; /attacks sends all three.
Power and command on game servers are the exception. They acknowledge an instruction rather than return a resource, so they answer with two fields:
{ "ok": true, "message": "" }ok reports acceptance, not completion. See
Game servers.
Pagination
Only /attacks paginates. It takes page and per_page (default 25, maximum
100) and answers with both links and meta:
{
"links": { "first": "…", "last": "…", "prev": null, "next": "…" },
"meta": { "current_page": 1, "per_page": 25, "total": 128 }
}Follow links.next until it is null rather than incrementing page against
meta.total — a page boundary can move under you while you walk it.
What addresses what
| Resource | Addressed by | Looks like |
|---|---|---|
| Game server | UUID | 3f2a1c9e-5b4d-4a8e-9c7f-1d2e3a4b5c6d |
| Firewall address | the IP itself | 203.0.113.10 |
| Firewall rule | integer id | 101 |
| Firewall filter | type:port key | synproxy:25565 |
A game server also carries a short identifier, and an attack an integer id.
Neither is accepted as a path parameter — identifier is a display value, and
attacks have no detail endpoint.
Build a filter key by reading key off the object rather than joining type and
port yourself. The format is ours to change; the field will follow it.
Units
| Field | Unit |
|---|---|
peak_bps | bits per second |
peak_pps | packets per second |
limits.memory, limits.disk | MiB |
limits.cpu | percent of one core — 200 is two cores |
Attack peaks also come pre-rendered as peak_bps_formatted and
peak_pps_formatted. Those are display strings whose formatting may change; read
the raw numbers in anything that calculates.
Timestamps
Every timestamp is ISO 8601 with an explicit UTC offset:
2026-08-19T14:02:11+00:00The from and to query parameters accept the same, and Z in place of
+00:00.
Live limits beat documented ones
Numbers written on these pages are defaults. Where an endpoint publishes
meta.limits, that is the authority for your organisation:
{ "meta": { "limits": { "rules_per_ip": 100, "filters_per_ip": 25, "max_ports_per_request": 101 } } }Read it rather than hardcoding. Exceeding a limit is a 422, never a silent
truncation.