Node¶
List All Nodes¶
GET /api/admin/locations/{location_id}/regions/{region_id}/nodes
Schema
nodes: Arrayid: Stringlabel: Stringhostname: Stringprimary_ip: Stringdisconnected: Booleanfailed_health_checks: Integeractive: Booleanonline_at: DateTimedisconnected_at: DateTimepublic_ip: Stringregion_id: Integermaintenance: Boolean - effective maintenance: the controller's hold OR the node's ownmaintenance_updated: DateTime - when the controller hold last changedmaintenance_status: Object - read from stored state; never calls the agenteffective: Boolean - same asmaintenancerequested: Boolean - the controller holdreason: String - reason given with the controller hold (internal; never shown to customers)requested_at: DateTime | nullgen: Integer - generation of the controller holdholds: Object - as the agent last reported them (sincein unix seconds)controller: Object | null -since,reason,genlocal: Object | null -since,reason,by(placed withcs-agent maintenance on)
paused_since: DateTime | nullskipped_backups: Integer - backups skipped during the maintenance windowsample: Object | null -quiesce(quiesced,busyorunknown),running_count,pending,sampled_at(unix seconds)agent: Object -supported(Boolean, cs-agent 3.4 or later),observed_at,instance_idrunning: Array - work running on the node at the last status check (id,kind,volume,started_at)pending: Integerwarnings: Array - see Maintenance Warnings
job_status: Stringssh_port: Integervolume_device: Stringblock_write_bps: Integerblock_read_bps: Integercustomer_notice: String | null - message shown to customers while the node is not onlinecustomer_status: Object - what customers see for this node; the same object asnode_statuson the User API (state,since,planned,message,operations)created_at: DateTimeupdated_at: DateTime
View Node¶
GET /api/admin/locations/{location_id}/regions/{region_id}/nodes/{id}
Schema
node: Objectid: Stringlabel: Stringhostname: Stringprimary_ip: Stringdisconnected: Booleanfailed_health_checks: Integeractive: Booleanonline_at: DateTimedisconnected_at: DateTimepublic_ip: Stringregion_id: Integermaintenance: Boolean - effective maintenance: the controller's hold OR the node's ownmaintenance_updated: DateTime - when the controller hold last changedmaintenance_status: Object - read from stored state; never calls the agenteffective: Boolean - same asmaintenancerequested: Boolean - the controller holdreason: String - reason given with the controller hold (internal; never shown to customers)requested_at: DateTime | nullgen: Integer - generation of the controller holdholds: Object - as the agent last reported them (sincein unix seconds)controller: Object | null -since,reason,genlocal: Object | null -since,reason,by(placed withcs-agent maintenance on)
paused_since: DateTime | nullskipped_backups: Integer - backups skipped during the maintenance windowsample: Object | null -quiesce(quiesced,busyorunknown),running_count,pending,sampled_at(unix seconds)agent: Object -supported(Boolean, cs-agent 3.4 or later),observed_at,instance_idrunning: Array - work running on the node at the last status check (id,kind,volume,started_at)pending: Integerwarnings: Array - see Maintenance Warnings
job_status: Stringssh_port: Integervolume_device: Stringblock_write_bps: Integerblock_read_bps: Integercustomer_notice: String | null - message shown to customers while the node is not onlinecustomer_status: Object - what customers see for this node; the same object asnode_statuson the User API (state,since,planned,message,operations)created_at: DateTimeupdated_at: DateTime
Update Node¶
PATCH /api/admin/locations/{location_id}/regions/{region_id}/nodes/{id}
Note: We currently do not allow changing the hostname of an existing node.
Schema
node: Objectlabel: Stringprimary_ip: Stringactive: Booleanpublic_ip: Stringregion_id: Integerssh_port: Integervolume_device: Stringblock_write_bps: Integerblock_read_bps: Integercustomer_notice: String (optional) - message to customers with something on this node, shown in the portal and asnode_status.messageon the User API. Plain text. Can only be set while the node is in maintenance or offline (422otherwise). Blank clears it, and it clears itself when the node is back online. Applied before the other fields, and audited.
Create Node¶
POST /api/admin/locations/{location_id}/regions/{region_id}/nodes
Schema
node: Objectlabel: Stringhostname: Stringprimary_ip: Stringactive: Booleanpublic_ip: Stringregion_id: Integerssh_port: Integervolume_device: Stringblock_write_bps: Integerblock_read_bps: Integer
Delete Node¶
DELETE /api/admin/locations/{location_id}/regions/{region_id}/nodes/{id}
Maintenance Mode¶
A node is in maintenance (maintenance is true) while either of two holds is present:
- the controller hold, placed and released with the endpoints below (or from the admin UI);
- the node (local) hold, placed on the node itself with
cs-agent maintenance onand released withcs-agent maintenance off.
A node in maintenance takes no new containers, the controller stops recovering its containers, and its agent (cs-agent 3.4 or later) pauses backups and other background work. Containers are not moved. Nodes running an older agent behave as before: the controller hold is not enforced on the node.
Every change to the controller hold is audited.
Request Maintenance¶
POST /api/admin/locations/{location_id}/regions/{region_id}/nodes/{node_id}/maintenance
Places the controller hold. Returns HTTP 202 Accepted; the hold is delivered to the node asynchronously. Repeating the request is safe: it does not bump the generation, and it re-sends the hold to the node.
If customer_message is given, it is set as the node's customer_notice once the hold is placed (see Update Node). Omit it to leave any existing notice as it is. If the notice can't be set, the request returns HTTP 422 with errors, though the hold has already been placed.
Schema
Request
reason: String (optional) - internal; never shown to customerscustomer_message: String (optional) - message to customers with something on this node
Response
maintenance: Boolean - effective maintenance (controller OR node hold)maintenance_requested: Boolean - the controller holdmaintenance_gen: Integermaintenance_status: Object - as on the node (see View Node)
Example
{
"maintenance": true,
"maintenance_requested": true,
"maintenance_gen": 4,
"maintenance_status": {
"effective": true,
"requested": true,
"reason": "kernel 6.12",
"requested_at": "2026-10-08T12:00:00.000Z",
"gen": 4,
"holds": {
"controller": { "since": 1791460805, "reason": "kernel 6.12", "gen": 4 },
"local": null
},
"paused_since": "2026-10-08T12:00:05.000Z",
"skipped_backups": 0,
"sample": { "quiesce": "quiesced", "running_count": 0, "pending": 0, "sampled_at": 1791460810 },
"agent": { "supported": true, "observed_at": "2026-10-08T12:02:00Z", "instance_id": "4f1c9e2a" },
"running": [],
"pending": 0,
"warnings": []
}
}
Release Maintenance¶
DELETE /api/admin/locations/{location_id}/regions/{region_id}/nodes/{node_id}/maintenance
Releases the controller hold only. A node that holds itself in maintenance stays in maintenance (maintenance remains true); see Release All Holds.
Returns HTTP 202 Accepted, with the same body as Request Maintenance.
Note
Older clients sent DELETE .../nodes/{node_id}/maintenance/{id}. That form is still accepted, and the trailing id is ignored.
Release All Holds¶
POST /api/admin/locations/{location_id}/regions/{region_id}/nodes/{node_id}/maintenance/release_all
Releases the controller hold and the node's own hold. Use it for a node that was left in maintenance by someone who is no longer around; whoever placed the local hold is not asked. The override is audited and raises a warning-level system event.
Returns HTTP 202 Accepted, with the same body as Request Maintenance. The node leaves maintenance once its agent applies the override; until then maintenance_status.warnings includes override_pending. A local hold placed after the override (for example, by an upgrade playbook that started while the override was still waiting to reach the agent) is left alone.
Returns HTTP 422 without confirm=true.
Schema
confirm: Boolean - must betrue
Maintenance Warnings¶
maintenance_status.warnings contains any of:
| Warning | Meaning |
|---|---|
mismatch |
The agent's copy of the controller hold still disagrees with the controller after a correction attempt. |
stale_hold |
A hold has been in place for more than 12 hours. |
unsupported_agent |
The controller hold is requested, but the agent is older than 3.4 (or has no token), so the node doesn't enforce it. |
status_stale |
No status has been read from the agent in the last 10 minutes. |
override_pending |
A Release All Holds override hasn't reached the agent yet. |