Create a site
Create a site of any type, with a Git URL, a GitHub repository, or no code yet, then add DNS and HTTPS.
When to use this
You have an active server and want a new site on it. Scope: sites:write (and sites:read to check). For servers that already run sites, see "Import" at the end.
Site types
type is one of:
| Type | For | Extra fields |
|---|---|---|
laravel |
Laravel apps | php_version, create_database |
php |
Other PHP apps | php_version, create_database |
static |
HTML files, or a front end built with a tool: React (Vite, Create React App), Vue, Svelte, Angular. pfcloud runs npm install and npm run build, then serves dist (or build / out if the build writes that) |
none |
nextjs, node |
Next.js (runs as a server with npm run start) and other Node apps |
app_port, start_command (see the API reference for the exact rules) |
python |
Python apps | app_port, start_command |
custom |
Any language, started by your own command | app_port, start_command (required) |
docker |
A Dockerfile at the repository root | container_port; the server needs Docker installed |
wordpress |
WordPress installed for you (MySQL or MariaDB servers only) | wordpress_title, wordpress_admin, wordpress_email |
Common fields: server (public id), domain, aliases, branch, create_database (boolean). The complete list is in Sites.
Three ways to give the site its code
A. A Git URL
curl -s -X POST $MYFORGE/sites \
-H "Authorization: Bearer $TOKEN" -H "Idempotency-Key: create-shop-1" \
-H "Content-Type: application/json" \
-d '{"server":"SERVER_ID","domain":"shop.example.com","type":"laravel",
"repository":"git@github.com:your-org/shop.git","branch":"main",
"php_version":"8.4","create_database":true}'
For a private repository over SSH, pfcloud's deploy key must be allowed on the repository (the server page and site page show it).
B. A repository from a connected GitHub account
Connect your GitHub account to the team first (team settings, GitHub). Then list accounts and repositories:
curl -s -H "Authorization: Bearer $TOKEN" $MYFORGE/github/accounts
curl -s -H "Authorization: Bearer $TOKEN" $MYFORGE/github/accounts/ACCOUNT/repositories
Accounts show their login. Repositories show full_name and default_branch. Both need sites:read. Then create the site:
curl -s -X POST $MYFORGE/sites \
-H "Authorization: Bearer $TOKEN" -H "Idempotency-Key: create-shop-2" \
-H "Content-Type: application/json" \
-d '{"server":"SERVER_ID","domain":"shop.example.com","type":"laravel",
"github_account":"your-org","github_repository":"your-org/shop"}'
branch is optional here and defaults to the repository's default branch. The site follows the repository through pfcloud's GitHub App, and a push to the branch deploys it. No deploy key or webhook is needed.
C. No code yet
Leave out repository and the GitHub fields. pfcloud creates the site's folder on the server, the Nginx configuration and the database, but the site has no code. It shows as waiting for a repository and cannot be deployed. A deploy request answers 409. Connect a repository later:
curl -s -X PUT $MYFORGE/sites/SITE_ID/github \
-H "Authorization: Bearer $TOKEN" -H "Idempotency-Key: connect-shop-1" \
-H "Content-Type: application/json" \
-d '{"account":"your-org","repository":"your-org/shop","branch":"main"}'
For a plain Git address instead of GitHub:
curl -s -X PUT $MYFORGE/sites/SITE_ID/repository \
-H "Authorization: Bearer $TOKEN" -H "Idempotency-Key: repo-shop-1" \
-H "Content-Type: application/json" \
-d '{"repository":"git@github.com:your-org/shop.git","branch":"main"}'
This works only while the site has no repository. You can also use the Repository card on the site page. To stop following GitHub use DELETE /sites/SITE_ID/github.
WordPress sites are the exception: they are installed by pfcloud and need no repository.
Wait for it
The answer is 201. Poll GET /sites/{site} until status is active or failed (see Requests and errors). If it failed, read the reason in the dashboard run log, then POST /sites/{site}/retry.
A WordPress answer contains wordpress_admin once (the generated admin password). It is never stored and never replayed, so save it at once.
DNS and HTTPS
- Point the domain to the server. If your team connected a DNS provider,
POST /sites/{site}/dnsadds the missing A records. See DNS and domains. - HTTPS is automatic for sites pfcloud created: once the domain points at the server, pfcloud requests a Let's Encrypt certificate (
auto_httpsis on by default). To ask now,POST /sites/{site}/https. See HTTPS certificates.
Settings after creation
PATCH /sites/{site} accepts auto_deploy, backup_before_deploy, uptime_enabled, uptime_path, health_check_path, build_script, after_deploy_script, start_command, app_port, canonical_host, custom_nginx, php_version. Fields are applied in that order. If one is refused (422), the ones before it are already saved, so send one field per call when that matters.
Import a site that already runs on a server
For servers pfcloud adopted: GET /site-imports?server=SERVER_ID lists importable sites; POST /site-imports imports one (server, domain, type, mode = in-place or watch, run_as, branch); POST /site-imports/all imports all. pfcloud backs up the database first and refuses to import if it cannot.
What can go wrong
| Problem | Cause and fix |
|---|---|
422 plan limit |
Your plan's site limit is reached. Remove a site or upgrade. |
422 domain used |
The domain is already in the team, or was deleted and is waiting to be purged. |
404 on the server |
The server is outside the token's limits, or not in the team. |
Site failed |
Read the run log, fix the cause (for example a PHP version missing on the server), then POST /sites/{site}/retry. |
Deploy 409 |
No repository connected yet, or the site is not active. |