Console REST API
The public v1 REST API: xdp_ personal access tokens, the four read endpoints, the {data}/{error} envelope, and rate limits, with curl examples.
Last updated
On this page
The v1 API is the public, scriptable read surface of the console: your account, your fleet servers with health scores, and finished benchmark results. It authenticates with a personal access token: the browser session cookie is not honored, so every route is safe to call from scripts and other origins.
Create a personal access token
Create tokens in the console under Settings → API (/dashboard/settings/api). Give
each token a name, copy it immediately. The raw token is shown exactly once and only
its hash is stored. Tokens look like xdp_…, and you can revoke each one individually
from the same page at any time.
Send the token as a Bearer header on every request. Replace $CONSOLE with the base URL
where you open the dashboard:
curl -H "Authorization: Bearer xdp_..." "$CONSOLE/api/v1/me"
A token acts as your account: you see exactly the servers you can see in the dashboard, and tokens of disabled accounts stop working. Treat tokens as secrets: never commit them or paste them into tools you don't control.
Conventions
- Success bodies are wrapped in
{"data": …}; failures are{"error": "…"}. - All timestamps are Unix epoch milliseconds.
- Every response carries
Cache-Control: no-store. Always read it fresh. - The limit is 120 requests per minute per token. Over it you get
429with aRetry-Afterheader. Wait that many seconds before retrying. - Resources belonging to other accounts answer
404, not403. The API does not confirm they exist.
| Status | Meaning |
|---|---|
| 401 | Missing, revoked, or disabled-account token |
| 404 | Unknown id, or the resource belongs to someone else |
| 429 | Rate limit exceeded. Wait Retry-After seconds |
GET /api/v1/me
The account the token belongs to.
curl -H "Authorization: Bearer xdp_..." "$CONSOLE/api/v1/me"
{ "data": { "id": 7, "name": "Ada Lovelace", "email": "ada@example.com", "role": "user" } }
GET /api/v1/servers
Your fleet servers (Health Monitor), with the current health score of each.
curl -H "Authorization: Bearer xdp_..." "$CONSOLE/api/v1/servers"
{
"data": {
"servers": [
{
"id": 12,
"label": "edge-1",
"hostname": "edge-1.example.com",
"online": true,
"score": 941,
"last_seen": 1755000000000,
"public_ip": "203.0.113.10"
}
]
}
}
score is 0 to 1000 (higher is healthier); online means the daemon checked in within the
last two minutes; public_ip is null until the daemon reports one.
GET /api/v1/servers/
One server in detail: the daemon-reported facts, the score broken into its six
weighted components with human-readable score_notes, and the latest telemetry sample
(null when no sample has arrived yet).
curl -H "Authorization: Bearer xdp_..." "$CONSOLE/api/v1/servers/12"
{
"data": {
"id": 12,
"label": "edge-1",
"hostname": "edge-1.example.com",
"online": true,
"public_ip": "203.0.113.10",
"last_seen": 1755000000000,
"created_at": 1750000000000,
"facts": { "os": "Debian 12", "kernel": "6.1.0", "cores": 8 },
"score": 941,
"score_components": { "cpu": 1000, "memory": 850, "disk": 1000, "network": 1000, "stability": 1000, "freshness": 1000 },
"score_notes": ["memory p80 at 82%"],
"latest_sample": { "ts": 1755000000000, "cpu_pct": 12.4, "mem_used_mb": 3200 }
}
}
GET /api/v1/servers//benchmarks
Finished benchmark runs on the server, newest first. Runs that are still pending or running are not listed; the run log and the agent token are never exposed.
curl -H "Authorization: Bearer xdp_..." "$CONSOLE/api/v1/servers/12/benchmarks"
{
"data": {
"benchmarks": [
{
"id": 3,
"label": "edge-1",
"status": "done",
"scores": { "cpu": 72, "disk": 88, "network": 64, "stability": 91, "total": 78 },
"verified": true,
"finished_at": 1755000000000
}
]
}
}
Section scores are 0 to 100; a section is null when it could not be measured, and
verified reflects the console's consistency checks on the reported hardware.
GET /api/v1/game-services
Game Protection services visible to the token's account: services you own plus any
shared with you via a service grant. Read-only: creating or changing a service is a
console flow (/dashboard/products/game-protection), never an API action.
curl -H "Authorization: Bearer xdp_..." "$CONSOLE/api/v1/game-services"
{
"data": {
"services": [
{
"id": 7,
"name": "mc-lobby",
"status": "active",
"java_hostname": "play.example.com",
"origin_host": "203.0.113.50",
"origin_port": 25565,
"config_version": 3,
"error": null,
"created_at": 1755000000000,
"updated_at": 1755100000000
}
]
}
}
status is one of pending_config | configuring | active | failed | disabled | deleting.
GET /api/v1/game-services/
One service in detail. Staff roles only see a service when its support_access flag is
on, a service grant names them, or the owner has an open ticket linked to it. The same
rule as every shared resource in the console. Unknown or inaccessible ids return 404.
GET /api/v1/game-services//metrics
Per-interval traffic counters reported by the scrubbing edge, ascending by ts.
range is 1h (default), 24h, or 7d. bytes/packets/dropped/connections
are counters for that interval (not cumulative); latency_ms is null when the edge
did not measure one.
curl -H "Authorization: Bearer xdp_..." "$CONSOLE/api/v1/game-services/7/metrics?range=24h"
{
"data": {
"range": "24h",
"series": [
{ "ts": 1755100000000, "node_id": 2, "packets": 182044, "bytes": 118331208, "dropped": 12, "connections": 96, "latency_ms": 4 }
]
}
}
Next steps
- Troubleshooting: decode 401/403/429 responses
- What is Spaceflare