# Servers

Base URL `https://pfcloud.pfctek.com/api/v1`. Every call needs `Authorization: Bearer mf_…`. Changes accept an `Idempotency-Key` header. Ids are public ids (UUIDs).

## GET /servers

**List servers**

Scope: `servers:read`

## POST /servers

**Add a server**

Scope: `servers:write`

Same checks as the Add server form (plan limit, IP not already in the team or waiting to be purged). Saved as pending; the answer includes pfcloud’s public key and the command to authorize it. Then POST /servers/{server}/connect. Tokens limited to some servers can’t add servers.

| Body field | Type | Description |
| --- | --- | --- |
| `name` | string |  |
| `ip_address` | string |  |
| `ssh_port` | integer |  |
| `provider` | string |  |
| `origin` | string |  |

## GET /servers/{server}

**Get a server**

Scope: `servers:read`

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

## GET /servers/{server}/sites

**List a server's sites**

Scope: `servers:read sites:read`

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

## GET /servers/{server}/certificates

**List the HTTPS certificates of a server's sites**

Scope: `servers:read sites:read`

Each live site with HTTPS: domain, type, issuer, expires_at, days_left, whether pfcloud can renew it. Soonest expiry first.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

## GET /servers/{server}/runtimes

**Language versions installed on a server**

Scope: `servers:read`

PHP versions installed, PHP versions that could be installed, and the versions of Node.js, npm, Python, Composer, Go, Ruby, Rust, Java, .NET and Elixir found on the server, with the time they were read (daily and after installs).

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

## POST /servers/{server}/runtimes/check

**Read the language versions on a server again**

Scope: `servers:write`

Starts a read-only check over SSH. Read the result with GET /servers/{server}/runtimes a minute later.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

## GET /servers/{server}/authorized-key

**Get pfcloud’s key for a server**

Scope: `servers:read`

The public key to authorize on the server and the commands that install it for root (or through sudo). Needs the manage-servers permission.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

## GET /servers/{server}/health

**Get a server’s health**

Scope: `servers:read`

The health collector’s last summary, issues found, the live agent and the last restart.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

## GET /servers/{server}/security

**Get the latest security report**

Scope: `servers:read`

Score and findings (id, severity, title, detail, fix) of the last daily security check; data is null before the first one.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

## GET /servers/{server}/runs

**List scripts run on a server**

Scope: `servers:read`

The server’s activity log, newest first, 25 per page. No output here.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

## GET /servers/{server}/runs/{run}

**Get one script run with its output**

Scope: `servers:read`

The log the server page shows. Environment values are never stored, so never shown.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |
| `run` | path | Public id of the run (required) |

## GET /servers/{server}/services

**List services pfcloud can restart**

Scope: `servers:read`

Empty for servers pfcloud didn’t set up.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

## GET /servers/{server}/languages

**List language build tools**

Scope: `servers:read`

Languages pfcloud can install, the ones installed and when Docker was installed.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

## POST /servers/{server}/languages

**Install a language’s build tools**

Scope: `servers:write`

Servers pfcloud set up only.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

| Body field | Type | Description |
| --- | --- | --- |
| `language` | string |  |

## GET /servers/{server}/databases

**List databases**

Scope: `servers:read`

Each database with its user and status. Passwords are never stored.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

## POST /servers/{server}/databases

**Create a database and its user**

Scope: `servers:write`

Servers pfcloud set up with a database engine. The answer has the password once; pfcloud never stores it. To drop a database, ask with POST /servers/{server}/databases/{database}/deletion-requests.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

| Body field | Type | Description |
| --- | --- | --- |
| `name` | string |  |
| `user` | string | Defaults to the name |

## GET /servers/{server}/firewall-rules

**List firewall rules**

Scope: `servers:read`

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

## POST /servers/{server}/firewall-rules

**Open a port**

Scope: `servers:write`

Servers pfcloud set up only.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

| Body field | Type | Description |
| --- | --- | --- |
| `name` | string |  |
| `port` | string | 6379 or a range like 6000:6010 |
| `protocol` | string |  |
| `source` | string | any, an IP address or a range like 10.0.0.0/8 |

## GET /servers/{server}/ssh-keys

**List people’s SSH keys on the server**

Scope: `servers:read`

Key name and fingerprint, login and status; never the key itself.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

## POST /servers/{server}/ssh-keys

**Add your SSH key for a login**

Scope: `servers:write`

One of the token maker’s own keys (Settings → SSH keys), for a login pfcloud lists on this server (never root).

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

| Body field | Type | Description |
| --- | --- | --- |
| `key` | string | Public id of your saved key |
| `login` | string | Defaults to the first login |

## GET /servers/{server}/php

**Get PHP versions and settings**

Scope: `servers:read`

Installed and available versions, settings per version as last read, extensions pfcloud can install.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

## POST /servers/{server}/connect

**Connect (or try again)**

Scope: `servers:write`

Inspects the server, then provisions a fresh one or adopts an existing one. The provisioning choices apply to fresh servers only.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

| Body field | Type | Description |
| --- | --- | --- |
| `stacks` | array |  |
| `php_version` | string |  |
| `node_version` | string |  |
| `database` | string |  |
| `redis` | boolean |  |

## POST /servers/{server}/reboot

**Restart the server**

Scope: `servers:write`

Servers pfcloud set up only. Send the server’s name in confirm.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

| Body field | Type | Description |
| --- | --- | --- |
| `confirm` | string | The server’s name, exactly |

## POST /servers/{server}/rescan

**Re-scan the server**

Scope: `servers:write`

Runs the read-only inspection again. Nothing on the server changes.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

## POST /servers/{server}/services/{service}/restart

**Restart a service**

Scope: `servers:write`

One of GET /servers/{server}/services. Runs now; the answer includes the run and its output.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |
| `service` | path | e.g. nginx or php8.4-fpm (required) |

## POST /servers/{server}/security-checks

**Run the security check now**

Scope: `servers:write`

Read-only. At most once every 10 minutes per server.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

## POST /servers/{server}/security-fixes

**Apply a one-click security fix**

Scope: `servers:write`

For a finding in the latest report that has a fix. Servers pfcloud set up only; the check runs again afterwards.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

| Body field | Type | Description |
| --- | --- | --- |
| `finding` | string | The finding’s id |

## PUT /servers/{server}/monitoring

**Turn health monitoring on or off**

Scope: `servers:write`

Turning it on needs a plan with monitoring.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

| Body field | Type | Description |
| --- | --- | --- |
| `enabled` | boolean |  |

## PUT /servers/{server}/agent

**Install or remove the live metrics agent**

Scope: `servers:write`

Installing needs a plan with monitoring.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

| Body field | Type | Description |
| --- | --- | --- |
| `installed` | boolean |  |

## POST /servers/{server}/docker

**Install Docker**

Scope: `servers:write`

Servers pfcloud set up only, once.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

## DELETE /servers/{server}/firewall-rules/{rule}

**Close a port**

Scope: `servers:write`

SSH, HTTP and HTTPS can never be closed.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |
| `rule` | path | Public id of the rule (required) |

## DELETE /servers/{server}/ssh-keys/{key}

**Remove an SSH key from the server**

Scope: `servers:write`

Your own, or anyone’s if you manage servers.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |
| `key` | path | Public id from GET /servers/{server}/ssh-keys (required) |

## POST /servers/{server}/php/versions

**Install a PHP version**

Scope: `servers:write`

Servers pfcloud set up only.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

| Body field | Type | Description |
| --- | --- | --- |
| `version` | string |  |

## POST /servers/{server}/php/refresh

**Read the PHP settings again**

Scope: `servers:write`

They appear in GET /servers/{server}/php afterwards.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |

## PUT /servers/{server}/php/{version}

**Change a PHP version’s settings**

Scope: `servers:write`

Checked with php-fpm -t and nginx -t before reloading; the old files come back on failure.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |
| `version` | path | e.g. 8.4 (required) |

| Body field | Type | Description |
| --- | --- | --- |
| `upload_max` | string | e.g. 64M or 1G |
| `memory_limit` | string | e.g. 512M, 2G or -1 |
| `max_execution_time` | integer |  |
| `max_input_vars` | integer |  |
| `opcache` | boolean |  |
| `opcache_validate` | boolean |  |

## POST /servers/{server}/php/{version}/extensions

**Install a PHP extension**

Scope: `servers:write`

From the list in GET /servers/{server}/php.

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |
| `version` | path | e.g. 8.4 (required) |

| Body field | Type | Description |
| --- | --- | --- |
| `extension` | string |  |

## DELETE /servers/{server}/php/{version}/extensions/{extension}

**Remove a PHP extension**

Scope: `servers:write`

| Parameter | In | Description |
| --- | --- | --- |
| `server` | path | Public id from the dashboard address (required) |
| `version` | path | e.g. 8.4 (required) |
| `extension` | path | e.g. redis (required) |

