Clusters
Registering a data-plane cluster, checking its health, and managing its join
token. See Cluster operations for the
deprovision vs. rm distinction (deprovision is a local tofu destroy,
not an API call — this page only covers the control-plane record).
POST /v1/clusters — register a cluster
Auth: admin.
Request body
| Field | Type | Required |
|---|---|---|
name |
string | yes |
$ curl -s https://api.stagdb.com/v1/clusters -X POST -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"name":"prod"}'
Response 201 Created
{
"id": "1c9c14da-8b0e-4c6e-9f1a-2d7c3a5b6e42",
"name": "prod",
"token": "x7Dq2m4T9vKcW1pZa8Rf3sLn0uYbEjH5gOiA6dNqVwM"
}
token is the agent's join token — shown once, never retrievable again.
It's what the agent running in your AWS cluster uses to authenticate to the
control-plane broker (ADJ_CLUSTER_TOKEN). If you lose it, rotate instead of
re-registering (see below).
| Status | When |
|---|---|
| 400 | name empty — body is {"error": "invalid input: name required"} (cluster routes surface the specific reason after an invalid input: prefix). |
| 403 | Caller is not an admin. |
GET /v1/clusters — list clusters
Auth: bearer.
$ curl -s https://api.stagdb.com/v1/clusters -H "Authorization: Bearer $TOKEN"
Response 200 OK
{
"clusters": [
{
"id": "1c9c14da-8b0e-4c6e-9f1a-2d7c3a5b6e42",
"name": "prod",
"created_at": "2026-06-01T09:14:02Z",
"last_seen_at": "2026-07-19T08:12:41Z",
"health": "connected",
"active_instance_count": 14
}
]
}
health is "connected" (agent checked in within the last 90 seconds),
"stale" (checked in before, but not recently), or "never" (no agent
check-in recorded yet). last_seen_at is null when health is "never".
| Status | When |
|---|---|
| 401 | Missing/invalid/expired bearer token. |
GET /v1/clusters/{id} — get one cluster
Auth: bearer.
$ curl -s https://api.stagdb.com/v1/clusters/1c9c14da-8b0e-4c6e-9f1a-2d7c3a5b6e42 -H "Authorization: Bearer $TOKEN"
Response 200 OK — a single cluster object, same shape as above.
| Status | When |
|---|---|
| 400 | {id} not a valid UUID. |
| 404 | No such cluster in this org. |
DELETE /v1/clusters/{id} — deregister
Auth: admin.
Deletes the cluster's control-plane record only — it does not touch AWS
infrastructure. Blocked while any instance is still registered against
it. The normal teardown order is: destroy instances → tofu destroy
(adj cluster deprovision, a local operation, not an API call) →
deregister here.
$ curl -s https://api.stagdb.com/v1/clusters/1c9c14da-8b0e-4c6e-9f1a-2d7c3a5b6e42 -X DELETE \
-H "Authorization: Bearer $TOKEN" -o /dev/null -w '%{http_code}\n'
204
Response: 204 No Content.
| Status | When |
|---|---|
| 400 | {id} not a valid UUID. |
| 403 | Caller is not an admin. |
| 404 | No such cluster in this org. |
| 409 | The cluster still has active instances registered against it ("cluster has active instances"). |
POST /v1/clusters/{id}/rotate-token — rotate the join token
Auth: admin.
$ curl -s https://api.stagdb.com/v1/clusters/1c9c14da-8b0e-4c6e-9f1a-2d7c3a5b6e42/rotate-token -X POST \
-H "Authorization: Bearer $TOKEN"
Response 200 OK
{"token": "kR2wZ8vN4xQmP1jY6bT9dLcF3sHo7uEg5aVi0nWpXkA"}
Invalidates the previous token immediately. An already-connected agent keeps
its live connection — the new token only matters the next time an agent
needs to (re)join. adj cluster bootstrap and adj cluster provision also
rotate the token as a side effect (they call this internally).
| Status | When |
|---|---|
| 400 | {id} not a valid UUID. |
| 403 | Caller is not an admin. |
| 404 | No such cluster in this org. |
POST /v1/clusters/{id}/bootstrap — get a provisioning bundle
Auth: admin.
Rotates the cluster's token and returns everything adj cluster provision
needs to hand to OpenTofu in one self-contained bundle. The token in this
response is never audited or logged — it appears only here.
$ curl -s https://api.stagdb.com/v1/clusters/1c9c14da-8b0e-4c6e-9f1a-2d7c3a5b6e42/bootstrap -X POST \
-H "Authorization: Bearer $TOKEN"
Response 200 OK
{
"broker_addr": "broker.stagdb.com:443",
"cluster_token": "kR2wZ8vN4xQmP1jY6bT9dLcF3sHo7uEg5aVi0nWpXkA",
"tfvars": "cluster_id = \"1c9c14da-8b0e-4c6e-9f1a-2d7c3a5b6e42\"\nbroker_addr = \"broker.stagdb.com:443\"\ncluster_token = \"kR2wZ8vN4xQmP1jY6bT9dLcF3sHo7uEg5aVi0nWpXkA\"\n"
}
tfvars is a ready-to-write OpenTofu variables file body; the CLI writes it
straight to disk and passes it to tofu apply.
| Status | When |
|---|---|
| 400 | {id} not a valid UUID ("invalid id"); or the server has no broker public address configured — a deployment misconfiguration, not something a caller can fix ("invalid input: broker public address not configured"). |
| 403 | Caller is not an admin. |
| 404 | No such cluster in this org. |
Next
- Sources & imports — the import pipeline that runs against a registered cluster.
- Org —
GET /v1/org/usage'sCLUSTERSsection rolls up the same health data for every cluster in the org at once.