# Nodes endpoints (Admin API)

> 23 FeatherPanel Admin API endpoints from admin/nodes.php: methods, paths, auth, permissions, rate limits, parameters and responses.

Source: https://featherpanel.com/docs/api/reference/admin/nodes/

Defined in [`backend/app/routes/admin/nodes.php`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php). Authentication used here: **Admin**. Read [Authentication](https://featherpanel.com/docs/api/authentication/) for how to send credentials and [Rate limits and errors](https://featherpanel.com/docs/api/rate-limits-and-errors/) for the response envelope.

Paths, methods, permissions and rate limits come from the route file. Summaries, parameters and response codes come from the OpenAPI annotations on the controllers; endpoints without annotations show only what the route file declares.

## Endpoints

### GET `/api/admin/nodes/status/global`

- Auth: Admin
- Permission: `admin.nodes.view`
- Route name: `admin-nodes-status-global`
- Controller: [`NodeStatusController::getGlobalStatus`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodeStatusController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L28)

**Get global node status and utilization** Retrieve aggregated utilization and status information from all nodes including CPU, memory, disk usage, and health status.

| Response `data` field | Type | Description |
| --- | --- | --- |
| `global` | object |  |
| `nodes` | object\[\] |  |

```bash
curl -X GET "$PANEL_URL/api/admin/nodes/status/global" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` Global node status retrieved successfully · `401` Unauthorized · `403` Forbidden - Insufficient permissions

### GET `/api/admin/nodes`

- Auth: Admin
- Permission: `admin.nodes.view`
- Route name: `admin-nodes`
- Controller: [`NodesController::index`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L38)

**Get all nodes** Retrieve a paginated list of all nodes with optional search functionality.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `page` | query | integer | no | Page number for pagination |
| `limit` | query | integer | no | Number of records per page |
| `search` | query | string | no | Search term to filter nodes by name or FQDN |
| `location_id` | query | integer | no | Location ID to filter nodes by |
| `exclude_node_id` | query | integer | no | Node ID to exclude from results (useful for transfer destinations) |

| Response `data` field | Type | Description |
| --- | --- | --- |
| `nodes` | Node\[\] |  |
| `pagination` | NodePagination |  |
| `search` | object |  |

```bash
curl -X GET "$PANEL_URL/api/admin/nodes" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` Nodes retrieved successfully · `401` Unauthorized · `403` Forbidden - Insufficient permissions

### GET `/api/admin/nodes/{id}`

- Auth: Admin
- Permission: `admin.nodes.view`
- Route name: `admin-nodes-show`
- Controller: [`NodesController::show`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L48)

**Get node by ID** Retrieve a specific node by its ID.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | yes | Node ID |

| Response `data` field | Type | Description |
| --- | --- | --- |
| `node` | Node |  |

```bash
curl -X GET "$PANEL_URL/api/admin/nodes/$ID" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` Node retrieved successfully · `400` Bad request - Invalid node ID · `401` Unauthorized · `403` Forbidden - Insufficient permissions · `404` Node not found

### GET `/api/admin/nodes/{id}/diagnostics`

- Auth: Admin
- Permission: `admin.nodes.view`
- Route name: `admin-nodes-diagnostics`
- Controller: [`NodesController::diagnostics`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L62)

**Generate node diagnostics bundle** Fetches diagnostics output from the Wings daemon. Returns plain-text content by default or an uploaded report URL when format=url.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | yes | Node ID |
| `include_endpoints` | query | boolean | no | Include HTTP endpoint metadata |
| `include_logs` | query | boolean | no | Include daemon logs in the report |
| `log_lines` | query | integer | no | Number of log lines to include (1-500) |
| `format` | query | string | no | Response format: raw text or uploaded URL |
| `upload_api_url` | query | string | no | Override upload endpoint when requesting format=url |

| Response `data` field | Type | Description |
| --- | --- | --- |
| `diagnostics` | object |  |

```bash
curl -X GET "$PANEL_URL/api/admin/nodes/$ID/diagnostics" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` Diagnostics generated successfully · `400` Bad request - Invalid query parameters · `401` Unauthorized · `403` Forbidden - Insufficient permissions · `404` Node not found · `500` Internal server error - Failed to generate diagnostics

### GET `/api/admin/nodes/{id}/system-logs`

- Auth: Admin
- Permission: `admin.nodes.view`
- Route name: `admin-nodes-system-logs`
- Controller: [`NodesController::listSystemLogs`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L76)

**List node system log files** Lists daemon log files via Calagopus GET /api/system/logs.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | yes | Node ID |

```bash
curl -X GET "$PANEL_URL/api/admin/nodes/$ID/system-logs" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` System logs listed successfully · `404` Node not found · `500` Failed to list system logs · `501` Daemon feature unsupported

### GET `/api/admin/nodes/{id}/system-logs/{file}`

- Auth: Admin
- Permission: `admin.nodes.view`
- Route name: `admin-nodes-system-log-file`
- Controller: [`NodesController::getSystemLogFile`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L90)

**Read a node system log file** Reads a daemon log file via Calagopus GET /api/system/logs/{file}.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | yes | Node ID |
| `file` | path | string | yes | Log file name |

```bash
curl -X GET "$PANEL_URL/api/admin/nodes/$ID/system-logs/$FILE" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` System log file retrieved successfully · `400` Invalid log file name · `404` Node not found · `500` Failed to read system log · `501` Daemon feature unsupported

### PATCH `/api/admin/nodes/{id}`

- Auth: Admin
- Permission: `admin.nodes.edit`
- Route name: `admin-nodes-update`
- Controller: [`NodesController::update`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L108)

**Update node** Update an existing node. Only provided fields will be updated. Validates location existence and UUID format.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | yes | Node ID |

Request body: [`NodeUpdate`](https://featherpanel.com/docs/api/schemas/#schema-nodeupdate) (application/json)

| Body field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | no | Node name |
| `fqdn` | string | no | Fully qualified domain name |
| `location_id` | integer | no | Location ID |
| `uuid` | string | no | Node UUID (must be valid UUID format) |
| `daemon_type` | string | no | Daemon implementation for this node |
| `public_ip_v4` | string | no | Public IPv4 address reachable by clients. Set this if you plan to use the subdomain manager. |
| `public_ip_v6` | string | no | Public IPv6 address reachable by clients. |
| `sftp_subdomain` | string | no | Optional custom hostname for SFTP connections shown to users. |

| Response `data` field | Type | Description |
| --- | --- | --- |
| `node` | Node |  |

```bash
curl -X PATCH "$PANEL_URL/api/admin/nodes/$ID" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"name":"","fqdn":"","location_id":0,"uuid":"","daemon_type":"","public_ip_v4":"","public_ip_v6":"","sftp_subdomain":""}'
```

Plugin events: [`featherpanel:admin:nodes:node:updated`](https://featherpanel.com/docs/plugins/events/nodes/#node-updated)

Responses: `200` Node updated successfully · `400` Bad request - Invalid JSON, no data provided, validation errors, location not found, or invalid UUID format · `401` Unauthorized · `403` Forbidden - Insufficient permissions · `404` Node not found · `500` Internal server error - Failed to update node

### DELETE `/api/admin/nodes/{id}`

- Auth: Admin
- Permission: `admin.nodes.delete`
- Route name: `admin-nodes-delete`
- Controller: [`NodesController::delete`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L123)

**Delete node** Permanently delete a node from the database. This action cannot be undone.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | yes | Node ID |

| Response `data` field | Type | Description |
| --- | --- | --- |
| `message` | string | Success message |

```bash
curl -X DELETE "$PANEL_URL/api/admin/nodes/$ID" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Plugin events: [`featherpanel:admin:nodes:node:deleted`](https://featherpanel.com/docs/plugins/events/nodes/#node-deleted)

Responses: `200` Node deleted successfully · `400` Bad request - Invalid node ID · `401` Unauthorized · `403` Forbidden - Insufficient permissions · `404` Node not found · `500` Internal server error - Failed to delete node

### PUT `/api/admin/nodes`

- Auth: Admin
- Permission: `admin.nodes.create`
- Route name: `admin-nodes-create`
- Controller: [`NodesController::create`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L138)

**Create new node** Create a new node with name, FQDN, and location. Automatically generates UUID and daemon tokens. Validates location existence and ensures UUID uniqueness.

Request body: [`NodeCreate`](https://featherpanel.com/docs/api/schemas/#schema-nodecreate) (application/json)

| Body field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | yes | Node name |
| `fqdn` | string | yes | Fully qualified domain name |
| `location_id` | integer | yes | Location ID |
| `daemon_type` | string | no | Daemon implementation for this node |
| `public_ip_v4` | string | no | Public IPv4 address reachable by clients. Set this if you plan to use the subdomain manager. |
| `public_ip_v6` | string | no | Public IPv6 address reachable by clients. |
| `sftp_subdomain` | string | no | Optional custom hostname for SFTP connections shown to users. |
| `id` | integer | no | Optional node ID (useful for migrations from other platforms) |

| Response `data` field | Type | Description |
| --- | --- | --- |
| `node` | Node |  |

```bash
curl -X PUT "$PANEL_URL/api/admin/nodes" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"name":"","fqdn":"","location_id":0,"daemon_type":"","public_ip_v4":"","public_ip_v6":"","sftp_subdomain":"","id":0}'
```

Plugin events: [`featherpanel:admin:nodes:node:created`](https://featherpanel.com/docs/plugins/events/nodes/#node-created)

Responses: `201` Node created successfully · `400` Bad request - Invalid JSON, validation errors, location not found, or UUID already exists · `401` Unauthorized · `403` Forbidden - Insufficient permissions · `500` Internal server error - Failed to create node

### POST `/api/admin/nodes/{id}/reset-key`

- Auth: Admin
- Permission: `admin.nodes.edit`
- Route name: `admin-nodes-reset-key`
- Controller: [`NodesController::resetKey`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L148)

**Reset node daemon tokens** Generate new daemon token ID and daemon token for a node. This invalidates the current tokens and requires the node to be reconfigured with the new tokens.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | yes | Node ID |

| Response `data` field | Type | Description |
| --- | --- | --- |
| `node` | Node |  |

```bash
curl -X POST "$PANEL_URL/api/admin/nodes/$ID/reset-key" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` Node daemon tokens reset successfully · `400` Bad request - Invalid node ID · `401` Unauthorized · `403` Forbidden - Insufficient permissions · `404` Node not found · `500` Internal server error - Failed to reset node tokens

### GET `/api/admin/nodes/{id}/setup-command`

- Auth: Admin
- Permission: `admin.nodes.edit`
- Route name: `admin-nodes-setup-command`
- Controller: [`NodesController::getSetupCommand`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L163)

**Get node setup command** Returns install command (step 1) and setup command (step 2) to configure the node. Step 1 installs FeatherWings only; step 2 runs the interactive featherwings configure wizard.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | yes | Node ID |

| Response `data` field | Type | Description |
| --- | --- | --- |
| `panel_url` | string | Panel base URL |
| `config_url` | string | Full URL to fetch config (GET with Wings Bearer token) |
| `install_command` | string | Step 1: Install FeatherWings on the node (binary + Docker, no SSL) |
| `setup_command` | string | Step 2: Run featherwings configure (handles node join, SSL, and systemd) |
| `config_path_hint` | string | Suggested config path on the node (e.g. /etc/featherpanel/config.yml) |

```bash
curl -X GET "$PANEL_URL/api/admin/nodes/$ID/setup-command" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` Setup commands (install + config) · `401` Unauthorized · `403` Forbidden · `404` Node not found

### POST `/api/admin/nodes/{id}/self-update`

- Auth: Admin
- Permission: `admin.nodes.edit`
- Route name: `admin-nodes-self-update`
- Controller: [`NodesController::triggerSelfUpdate`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L177)

**Trigger Wings self-update** Initiate a self-update on the Wings daemon either via GitHub release channel or a custom download URL.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | yes | Node ID |

| Body field | Type | Required | Description |
| --- | --- | --- | --- |
| `source` | string | no | Update source (e.g. github, url) |
| `version` | string | no | Specific Wings version to install |
| `url` | string | no | Direct download URL for installing Wings |
| `repo_owner` | string | no | GitHub repository owner (when source=github) |
| `repo_name` | string | no | GitHub repository name (when source=github) |
| `sha256` | string | no | SHA256 checksum for validating download |
| `force` | boolean | no | Force reinstall even if Wings is up-to-date |
| `disable_checksum` | boolean | no | Skip checksum validation of the downloaded artifact |

```bash
curl -X POST "$PANEL_URL/api/admin/nodes/$ID/self-update" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"source":"","version":"","url":"","repo_owner":"","repo_name":"","sha256":"","force":false,"disable_checksum":false}'
```

Responses: `200` Self-update already applied or not required · `202` Self-update accepted and queued · `400` Bad request - Invalid payload or updates disabled · `401` Unauthorized · `403` Forbidden - Insufficient permissions or API updates disabled · `404` Node not found · `500` Failed to trigger self-update

### POST `/api/admin/nodes/{id}/terminal/exec`

- Auth: Admin
- Permission: `admin.nodes.edit`
- Route name: `admin-nodes-terminal-exec`
- Controller: [`NodesController::executeTerminalCommand`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L192)

**Execute command on node host** Execute a command on the node host system via Wings terminal API. Requires system.host\_terminal.enabled=true in Wings config.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | yes | Node ID |

| Body field | Type | Required | Description |
| --- | --- | --- | --- |
| `command` | string | yes | Command to execute on the host |
| `timeout_seconds` | integer | no | Timeout in seconds (default: 60) |
| `working_directory` | string | no | Working directory for command execution |
| `environment` | object | no | Environment variables for the command |

| Response `data` field | Type | Description |
| --- | --- | --- |
| `exit_code` | integer | Command exit code |
| `stdout` | string | Standard output |
| `stderr` | string | Standard error |
| `timed_out` | boolean | Whether command timed out |
| `duration_ms` | integer | Execution duration in milliseconds |

```bash
curl -X POST "$PANEL_URL/api/admin/nodes/$ID/terminal/exec" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"command":"","timeout_seconds":0,"working_directory":"","environment":{}}'
```

Responses: `200` Command executed successfully · `400` Bad request - Invalid payload or missing command · `401` Unauthorized · `403` Forbidden - Insufficient permissions or host terminal disabled · `404` Node not found · `500` Internal server error - Failed to execute command · `504` Gateway Timeout - Command execution timed out

### GET `/api/admin/nodes/{id}/config`

- Auth: Admin
- Permission: `admin.nodes.edit`
- Route name: `admin-nodes-config-get`
- Controller: [`NodesController::getConfig`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L207)

**Get Wings configuration** Retrieve the complete Wings configuration file as raw YAML with all comments preserved.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | yes | Node ID |

| Response `data` field | Type | Description |
| --- | --- | --- |
| `config` | string | Raw YAML configuration content |

```bash
curl -X GET "$PANEL_URL/api/admin/nodes/$ID/config" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` Wings configuration retrieved successfully · `401` Unauthorized · `403` Forbidden - Insufficient permissions · `404` Node not found · `500` Internal server error - Failed to retrieve configuration

### PUT `/api/admin/nodes/{id}/config`

- Auth: Admin
- Permission: `admin.nodes.edit`
- Route name: `admin-nodes-config-put`
- Controller: [`NodesController::putConfig`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L222)

**Replace Wings configuration** Replace the entire Wings configuration file with new YAML content. All comments and formatting are preserved. Optionally restart Wings after update.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | yes | Node ID |

| Body field | Type | Required | Description |
| --- | --- | --- | --- |
| `config` | string | yes | Complete YAML configuration content |
| `restart` | boolean | no | Whether to restart Wings after update |

| Response `data` field | Type | Description |
| --- | --- | --- |
| `config` | string | Updated YAML configuration content |

```bash
curl -X PUT "$PANEL_URL/api/admin/nodes/$ID/config" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"config":"","restart":false}'
```

Responses: `200` Configuration updated successfully · `400` Bad request - Invalid JSON or missing config · `401` Unauthorized · `403` Forbidden - Insufficient permissions · `404` Node not found · `500` Internal server error - Failed to update configuration

### PATCH `/api/admin/nodes/{id}/config/patch`

- Auth: Admin
- Permission: `admin.nodes.edit`
- Route name: `admin-nodes-config-patch`
- Controller: [`NodesController::patchConfig`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L237)

**Patch Wings configuration values** Update specific configuration values using dot notation (e.g., "api.port", "system.root\_directory"). Preserves comments and other values.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | yes | Node ID |

| Body field | Type | Required | Description |
| --- | --- | --- | --- |
| `values` | object | yes | Configuration values to update using dot notation (e.g., {"api.port": 8443, "system.root\_directory": "/var/lib/featherpanel"}) |
| `restart` | boolean | no | Whether to restart Wings after update |

| Response `data` field | Type | Description |
| --- | --- | --- |
| `result` | object | Patch operation result |

```bash
curl -X PATCH "$PANEL_URL/api/admin/nodes/$ID/config/patch" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"values":{},"restart":false}'
```

Responses: `200` Configuration patched successfully · `400` Bad request - Invalid JSON or missing values · `401` Unauthorized · `403` Forbidden - Insufficient permissions · `404` Node not found · `500` Internal server error - Failed to patch configuration

### GET `/api/admin/nodes/{id}/config/schema`

- Auth: Admin
- Permission: `admin.nodes.view`
- Route name: `admin-nodes-config-schema`
- Controller: [`NodesController::getConfigSchema`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L252)

**Get Wings configuration schema** Retrieve a schema describing all configurable fields in the Wings configuration, useful for building GUIs.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | yes | Node ID |

| Response `data` field | Type | Description |
| --- | --- | --- |
| `schema` | object | Configuration schema |

```bash
curl -X GET "$PANEL_URL/api/admin/nodes/$ID/config/schema" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` Configuration schema retrieved successfully · `401` Unauthorized · `403` Forbidden - Insufficient permissions · `404` Node not found · `500` Internal server error - Failed to retrieve schema

### GET `/api/admin/nodes/{id}/version-status`

- Auth: Admin
- Permission: `admin.nodes.view`
- Route name: `admin-nodes-version-status`
- Controller: [`NodesController::getVersionStatus`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L267)

**Check FeatherWings version status** Check if the node's FeatherWings version matches the latest version available on GitHub. Compares the installed version with the latest release from mythicalltd/featherwings repository.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | yes | Node ID |

| Response `data` field | Type | Description |
| --- | --- | --- |
| `current_version` | string | Currently installed FeatherWings version |
| `latest_version` | string | Latest available version from GitHub |
| `is_up_to_date` | boolean | Whether the installed version matches the latest |
| `update_available` | boolean | Whether an update is available |
| `github_error` | string | Error message if GitHub check failed |

```bash
curl -X GET "$PANEL_URL/api/admin/nodes/$ID/version-status" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` Version status retrieved successfully · `401` Unauthorized · `403` Forbidden - Insufficient permissions · `404` Node not found · `500` Internal server error - Failed to check version status

### GET `/api/admin/nodes/{id}/wings/config`

- Auth: Admin
- Permission: `admin.nodes.edit`
- Route name: `admin-nodes-wings-config-get`
- Controller: [`NodesController::getConfig`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L283)

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | \- | yes |  |

```bash
curl -X GET "$PANEL_URL/api/admin/nodes/$ID/wings/config" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

### PUT `/api/admin/nodes/{id}/wings/config`

- Auth: Admin
- Permission: `admin.nodes.edit`
- Route name: `admin-nodes-wings-config-put`
- Controller: [`NodesController::putConfig`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L298)

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | \- | yes |  |

```bash
curl -X PUT "$PANEL_URL/api/admin/nodes/$ID/wings/config" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

### POST `/api/admin/nodes/{id}/wings/config`

- Auth: Admin
- Permission: `admin.nodes.edit`
- Route name: `admin-nodes-wings-config-put`
- Controller: [`NodesController::putConfig`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L298)

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | \- | yes |  |

```bash
curl -X POST "$PANEL_URL/api/admin/nodes/$ID/wings/config" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

### GET `/api/admin/nodes/{id}/mass-transfer/preview`

- Auth: Admin
- Permission: `admin.servers.edit`
- Route name: `admin-nodes-mass-transfer-preview`
- Controller: [`NodesController::previewMassTransfer`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L314)

**Preview mass server transfer from a node** Lists transferable servers on the source node and free allocation capacity on a destination node.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | yes | Source node ID |
| `destination_node_id` | query | integer | yes | Destination node ID |

```bash
curl -X GET "$PANEL_URL/api/admin/nodes/$ID/mass-transfer/preview?destination_node_id=$DESTINATION_NODE_ID" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` Preview retrieved successfully · `400` Bad request · `404` Node not found

### POST `/api/admin/nodes/{id}/mass-transfer`

- Auth: Admin
- Permission: `admin.servers.edit`
- Route name: `admin-nodes-mass-transfer`
- Controller: [`NodesController::massTransfer`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/Admin/NodesController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/admin/nodes.php#L330)

**Mass transfer servers from a node** Transfer selected servers (or all transferable servers) from this node to another. Free allocations on the destination node are assigned automatically.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | yes | Source node ID |

| Body field | Type | Required | Description |
| --- | --- | --- | --- |
| `destination_node_id` | integer | yes |  |
| `server_ids` | integer\[\] | no | Server IDs to move (ignored when move\_all is true) |
| `move_all` | boolean | no | Move every transferable server on this node |

```bash
curl -X POST "$PANEL_URL/api/admin/nodes/$ID/mass-transfer" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"destination_node_id":0,"server_ids":[],"move_all":false}'
```

Responses: `200` Mass transfer processed · `400` Bad request · `404` Node not found
