RackAtlas API

A read-only JSON API for the data RackAtlas collects about your servers: current state, metrics history, systemd services, backups and alerts. It is made for dashboards. Grafana can read it directly, see the Grafana guide.

The base URL of every endpoint is:

Base URL
https://rackatlas.dev/api/v1

Create a key in Settings → Teams → your team → API keys. Then try it:

Quick start
export RACKATLAS_KEY=rak_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

curl https://rackatlas.dev/api/v1/me \
  -H "Authorization: Bearer $RACKATLAS_KEY"

Authentication

Send the key of your team as a bearer token in the Authorization header of every request. A key belongs to one team and sees only the data of that team.

Authorization: Bearer rak_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  • A key is shown once, when you create it. RackAtlas keeps only a hash, so a lost key cannot be recovered. Create a new one and revoke the old one.
  • A key can expire (30, 90 or 365 days) or live until you revoke it. A revoked or expired key answers 401.
  • Use one key per integration, so you can revoke one without breaking the others. The page of the keys shows when each was last used.
  • Keep keys out of dashboards that are shared publicly and out of source control.

Scopes

A key gets only the scopes you tick when you create it. A request to an endpoint whose scope the key lacks answers 403. All scopes are read-only.

ScopeAllows
servers:readList and read servers with their latest sample
metrics:readMetrics and disk history of a server
applications:readSystemd services of the servers
backups:readBackups and the result of their last run
alerts:readOpen and resolved alerts

Conventions

  • JSON only. Every response, errors included, is application/json. A client that accepts nothing else than another format gets 406, and a request body that is not JSON gets 415.
  • Read-only. Only GET is supported. Other methods answer 405.
  • Envelope. Data is in the data key. Time series add a meta object with the range and bucket size that was applied.
  • Times are ISO 8601 with an offset, for example 2026-11-05T13:41:02+00:00. Sizes are in bytes, rates in bytes per second, percentages are 0 to 100.
  • Time series. Allowed intervals are 60, 300, 900, 3600, 21600, 86400 seconds. A request may span at most 31 days and 5000 points. The history is kept for 30 days.

Errors

Errors carry a message. Validation errors (422) also list the invalid fields under errors.

StatusMeaning
401The key is missing, wrong, revoked or expired.
403The key lacks the scope of the endpoint.
404No such endpoint, or the server does not belong to your team.
405Only GET is supported.
406The client does not accept application/json.
415The request body is not application/json.
422A parameter is invalid.
429Too many requests, see Retry-After.
Response 422
{
  "message": "The selected interval is invalid.",
  "errors": { "interval": ["The selected interval is invalid."] }
}

Rate limits

A key may send 120 requests per minute. Wrong keys are limited per IP address: after 20 failed attempts in a minute the address is blocked for the rest of that minute. When a limit is hit you get 429 and a Retry-After header with the seconds to wait.

Servers report once a minute, so polling more often than that returns the same data. A dashboard refresh of 30 to 60 seconds is plenty.

Who am I

GET/api/v1/meany key

Returns the team the key belongs to and the scopes it has. Needs no scope, so it is the best first call and a good health check for a data source.

Request
curl https://rackatlas.dev/api/v1/me \
  -H "Authorization: Bearer $RACKATLAS_KEY"
Response 200
{
  "data": {
    "team": { "id": 3, "name": "Acme" },
    "key": {
      "name": "Grafana",
      "scopes": ["servers:read", "metrics:read"],
      "expires_at": null
    }
  }
}

List servers

GET/api/v1/serversservers:read

All servers of the team with their latest sample. Servers that never reported have "current": null.

Request
curl https://rackatlas.dev/api/v1/servers \
  -H "Authorization: Bearer $RACKATLAS_KEY"
Response 200
{
  "data": [
    {
      "id": 12,
      "name": "web-1",
      "category": "Production",
      "provider": "Hetzner",
      "country": "DE",
      "host": "203.0.113.10",
      "status": "online",
      "agent_version": "1.6",
      "system_info": { "os": "Debian GNU/Linux 12", "kernel": "6.1.0" },
      "last_seen_at": "2026-11-05T13:41:02+00:00",
      "last_checked_at": "2026-11-05T13:41:02+00:00",
      "current": {
        "collected_at": "2026-11-05T13:41:02+00:00",
        "cpu_percent": 12.4,
        "cpu_cores": 4,
        "load_1": 0.42,
        "load_5": 0.38,
        "load_15": 0.31,
        "memory_total_bytes": 8321486848,
        "memory_used_bytes": 3120562176,
        "memory_percent": 37.5,
        "swap_total_bytes": 0,
        "swap_used_bytes": 0,
        "uptime_seconds": 864000,
        "net_rx_bps": 18200,
        "net_tx_bps": 40100,
        "disks": [
          {
            "mount": "/",
            "device": "/dev/vda1",
            "filesystem": "ext4",
            "total_bytes": 85899345920,
            "used_bytes": 31457280000,
            "used_percent": 36.6
          }
        ]
      }
    }
  ]
}

Get a server

GET/api/v1/servers/{id}servers:read

One server, in the same shape as an item of the list. A server of another team answers 404.

ParameterTypeDescription
idinteger, pathThe id of the server.
Request
curl https://rackatlas.dev/api/v1/servers/12 \
  -H "Authorization: Bearer $RACKATLAS_KEY"
Response 200
{ "data": { "id": 12, "name": "web-1", "status": "online", "current": { "...": "..." } } }

Metrics history

GET/api/v1/servers/{id}/metricsmetrics:read

CPU, memory, load and network of one server as one flat row per time bucket. Rows are averaged (and maximums kept) inside each bucket. Buckets without samples are left out.

ParameterTypeDescription
fromdatetime, optionalStart of the range, ISO 8601. Default: a day before "to".
todatetime, optionalEnd of the range, ISO 8601. Default: now.
intervalinteger, optionalBucket size in seconds. Default: the smallest allowed value that keeps the range readable.
Request
curl https://rackatlas.dev/api/v1/servers/12/metrics?from=2026-11-04T00:00:00Z&interval=300 \
  -H "Authorization: Bearer $RACKATLAS_KEY"
Response 200
{
  "data": [
    {
      "time": "2026-11-04T00:00:00+00:00",
      "samples": 5,
      "cpu_percent_avg": 11.8,
      "cpu_percent_max": 24.1,
      "memory_percent_avg": 37.2,
      "memory_percent_max": 37.6,
      "memory_used_bytes_avg": 3095000000,
      "swap_percent_avg": null,
      "load_1": 0.4,
      "load_5": 0.38,
      "load_15": 0.31,
      "net_rx_bps_avg": 17800,
      "net_rx_bps_max": 61000,
      "net_tx_bps_avg": 39500,
      "net_tx_bps_max": 120000
    }
  ],
  "meta": {
    "from": "2026-11-04T00:00:00+00:00",
    "to": "2026-11-05T13:45:00+00:00",
    "interval_seconds": 300
  }
}

Disk history

GET/api/v1/servers/{id}/metrics/disksmetrics:read

Disk usage of one server in long format: one row per mount point and time bucket. Partition or filter by "mount" in Grafana. Takes the same parameters as the metrics history.

Request
curl https://rackatlas.dev/api/v1/servers/12/metrics/disks?interval=3600 \
  -H "Authorization: Bearer $RACKATLAS_KEY"
Response 200
{
  "data": [
    {
      "time": "2026-11-05T12:00:00+00:00",
      "mount": "/",
      "used_bytes": 31457280000,
      "total_bytes": 85899345920,
      "used_percent": 36.6
    }
  ],
  "meta": { "from": "...", "to": "...", "interval_seconds": 3600 }
}

Applications

GET/api/v1/applicationsapplications:read

The systemd services of the servers that run the agent, with their state as the agent last reported it.

ParameterTypeDescription
server_idinteger, optionalOnly the services of this server.
statusstring, optionalOne of failed, running, stopped or disabled.
Request
curl https://rackatlas.dev/api/v1/applications?status=failed \
  -H "Authorization: Bearer $RACKATLAS_KEY"
Response 200
{
  "data": [
    {
      "id": 481,
      "server_id": 12,
      "server_name": "web-1",
      "unit": "php8.5-fpm.service",
      "description": "The PHP 8.5 FastCGI Process Manager",
      "status": "failed",
      "active_state": "failed",
      "sub_state": "failed",
      "unit_file_state": "enabled"
    }
  ]
}

Backups

GET/api/v1/backupsbackups:read

The backups of the team and how their last run went. "overdue" is true when no run was reported within the expected interval. The secret webhook address of a backup is never part of the answer.

Request
curl https://rackatlas.dev/api/v1/backups \
  -H "Authorization: Bearer $RACKATLAS_KEY"
Response 200
{
  "data": [
    {
      "id": 5,
      "name": "Database dump",
      "server_id": 12,
      "server_name": "web-1",
      "is_active": true,
      "expected_interval_hours": 24,
      "last_run_at": "2026-11-05T03:00:11+00:00",
      "last_status": "success",
      "last_message": null,
      "last_size_bytes": 482934112,
      "overdue": false
    }
  ]
}

Alerts

GET/api/v1/alertsalerts:read

Problems RackAtlas detected on the servers of the team, newest first (at most 500).

ParameterTypeDescription
statusstring, optionalopen (default), resolved or all.
server_idinteger, optionalOnly the alerts of this server.
Request
curl https://rackatlas.dev/api/v1/alerts?status=open \
  -H "Authorization: Bearer $RACKATLAS_KEY"
Response 200
{
  "data": [
    {
      "id": 77,
      "server_id": 12,
      "server_name": "web-1",
      "type": "resource",
      "key": "disk:/",
      "context": { "percent": 93.1 },
      "opened_at": "2026-11-05T11:20:00+00:00",
      "resolved_at": null,
      "open": true
    }
  ]
}

Grafana

Use the Infinity data source, which reads JSON from any HTTP API. You need no Prometheus or database in between.

  1. Create a key with the scopes servers:read and metrics:read (add the others for the panels you want).
  2. In Grafana, install the Infinity plugin and add a data source. Under Authentication choose Bearer token and paste the key.
  3. Under Allowed hosts add https://rackatlas.dev.
  4. Press Save & test. You can set the health check URL to https://rackatlas.dev/api/v1/me.

A panel with the CPU of one server:

Type JSON, Parser Backend, Format Time series

URL https://rackatlas.dev/api/v1/servers/12/metrics?from=${__from:date:iso}&to=${__to:date:iso}

Rows / root data

Columns time (Timestamp), cpu_percent_avg (Number), memory_percent_avg (Number)

The from and to variables follow the time picker of the dashboard. Leave interval out and RackAtlas picks a bucket that suits the range. For tables of servers, services, backups or alerts use the endpoints above with the format Table. To draw one line per disk, use the disk history and add the mount column to Group by.

Questions or something missing? Back to RackAtlas