# Sites

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 /sites

**List sites**

Scope: `sites:read`

## POST /sites

**Create a site**

Scope: `sites:write`

Creates the site on a provisioned server. The repository is optional: give repository (a Git URL), or github_account + github_repository (a repository of a connected GitHub account; deploys on push), or neither: the site, folders, Nginx and database are created but it can't deploy until a repository is connected with PUT /sites/{site}/github.

| Body field | Type | Description |
| --- | --- | --- |
| `server` | string |  |
| `domain` | string |  |
| `aliases` | string |  |
| `type` | string | laravel, php, static, nextjs, node, python, custom, docker or wordpress |
| `repository` | string | SSH or HTTPS Git URL. Optional. |
| `branch` | string | Branch to deploy; for a GitHub repository the default branch when omitted |
| `php_version` | string |  |
| `app_port` | integer |  |
| `start_command` | string |  |
| `container_port` | integer |  |
| `create_database` | boolean |  |
| `wordpress_title` | string |  |
| `wordpress_admin` | string |  |
| `wordpress_email` | string |  |
| `github_account` | string | Login of a connected GitHub account (GET /github/accounts) |
| `github_repository` | string | owner/name of a repository that account lets pfcloud read (GET /github/accounts/{account}/repositories) |

## GET /sites/{site}

**Get a site**

Scope: `sites:read`

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

## PATCH /sites/{site}

**Change site settings**

Scope: `sites:write`

Fields are applied one by one in the order listed; if one is refused (422), the ones before it are already saved. Send one field per call when that matters.

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

| Body field | Type | Description |
| --- | --- | --- |
| `auto_deploy` | boolean |  |
| `backup_before_deploy` | boolean |  |
| `uptime_enabled` | boolean |  |
| `uptime_path` | string |  |
| `health_check_path` | string |  |
| `build_script` | string |  |
| `after_deploy_script` | string |  |
| `start_command` | string |  |
| `app_port` | integer |  |
| `canonical_host` | string | www, apex or empty |
| `custom_nginx` | string |  |
| `php_version` | string |  |

## GET /sites/{site}/certificate

**Get a site's certificate and its history**

Scope: `sites:read`

Expiry, issuer and the last 20 history entries (first seen, renewed, renewal requested, renewal failed).

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

## POST /sites/{site}/certificate/renew

**Renew a Let's Encrypt certificate now**

Scope: `certificates:renew`

Asks Let's Encrypt for a new certificate and reloads Nginx; the site stays online. Only Let's Encrypt and wildcard certificates of sites pfcloud created; at most once every 10 minutes. Anyone who can see the site may do it.

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

## GET /github/accounts

**List connected GitHub accounts**

Scope: `sites:read`

The GitHub accounts or organisations your team connected to pfcloud (Team settings → GitHub). Use a login as github_account when creating a site.

## GET /github/accounts/{account}/repositories

**List the repositories of a connected GitHub account**

Scope: `sites:read`

Repositories pfcloud may read, with their default branch. Use full_name as github_repository when creating a site.

| Parameter | In | Description |
| --- | --- | --- |
| `account` | path | Login of a connected GitHub account (required) |

## GET /sites/{site}/compatibility

**Does the server fit what the site's code needs?**

Scope: `sites:read`

status is ok, warning, problem or unknown. items lists each language the code pins (PHP, Node.js, Python, Go…), what the server has, a message, and a fix (switch_php or install_php with a version, install_language, or manual). frameworks lists the framework versions found (Laravel, Next.js…). Read after each deploy.

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

## GET /site-imports

**Sites an adopted server runs that can be imported**

Scope: `sites:read`

| Parameter | In | Description |
| --- | --- | --- |
| `server` | query | Server id (required) |

## POST /site-imports

**Import a site from an adopted server**

Scope: `sites:write`

| Body field | Type | Description |
| --- | --- | --- |
| `server` | string |  |
| `domain` | string |  |
| `type` | string |  |
| `mode` | string | in-place or watch |
| `run_as` | string |  |
| `branch` | string |  |

## POST /site-imports/all

**Import every site of an adopted server**

Scope: `sites:write`

| Body field | Type | Description |
| --- | --- | --- |
| `server` | string |  |
| `mode` | string | watch or suggested |

## POST /sites/{site}/retry

**Retry a failed create or import**

Scope: `sites:write`

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

## PUT /sites/{site}/deploy-mode

**Switch an imported site between watch-only and in-place**

Scope: `sites:write`

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

| Body field | Type | Description |
| --- | --- | --- |
| `mode` | string | watch or in-place |

## POST /sites/{site}/deploy-webhook

**Replace the deploy webhook (secret shown once)**

Scope: `sites:write`

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

| Body field | Type | Description |
| --- | --- | --- |
| `confirm` | string | The site’s domain, typed out to confirm |

## POST /sites/{site}/maintenance

**Put the site in maintenance mode**

Scope: `sites:write`

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

## DELETE /sites/{site}/maintenance

**Take the site out of maintenance mode**

Scope: `sites:write`

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

## PUT /sites/{site}/github

**Deploy from a GitHub repository**

Scope: `sites:write`

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

| Body field | Type | Description |
| --- | --- | --- |
| `account` | string | Login of a connected GitHub account |
| `repository` | string |  |
| `branch` | string |  |

## DELETE /sites/{site}/github

**Stop deploying from GitHub**

Scope: `sites:write`

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

## PUT /sites/{site}/repository

**Give a site without code a Git address**

Scope: `sites:write`

For sites created without a repository (POST /sites with no repository). Sets the SSH or HTTPS Git address and branch; the first deploy then fetches it. SSH addresses use the server's deploy key. To follow a GitHub repository instead use PUT /sites/{site}/github.

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

| Body field | Type | Description |
| --- | --- | --- |
| `repository` | string | SSH or HTTPS Git URL |
| `branch` | string | Defaults to main |

