# Quickstart

You need a pfcloud account in a team whose plan includes the API, and at least one active server.

All examples use `https://YOUR-MYFORGE/api/v1` and the placeholder token `mf_YOUR_TOKEN`. Replace both.

## 1. Make a token

1. Sign in and open **API** in the sidebar, then **Tokens**.
2. Give the token a name, for example `quickstart`.
3. Tick only these rights: `servers:read`, `sites:read`, `sites:write`, `deployments:read`, `deployments:write`.
4. Choose a short expiry (for example 7 days). Every token expires.
5. Click **Create token** and copy it now. pfcloud keeps only a fingerprint and cannot show it again.

Keep it in an environment variable, not in your code:

```bash
export MYFORGE=https://YOUR-MYFORGE/api/v1
export TOKEN=mf_YOUR_TOKEN
```

## 2. Check the token

```bash
curl -s -H "Authorization: Bearer $TOKEN" $MYFORGE/token
```

The answer lists `scopes` (what you ticked), `usable_scopes` (what works right now) and `blocked_scopes` (each blocked scope with the reason). If a scope you need is blocked, fix that first. See [Authentication](/developers/authentication).

## 3. List your servers

```bash
curl -s -H "Authorization: Bearer $TOKEN" $MYFORGE/servers
```

Each server has a public `id` (a UUID), `name`, `ip_address`, `status`, `php_versions` and `database`. Use the `id` in later calls. Only servers with status `active` can get new sites.

## 4. Create a site

```bash
curl -s -X POST $MYFORGE/sites \
  -H "Authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: quickstart-create-1" \
  -H "Content-Type: application/json" \
  -d '{
    "server": "SERVER_ID",
    "domain": "app.example.com",
    "type": "laravel",
    "repository": "git@github.com:your-org/your-app.git",
    "branch": "main",
    "php_version": "8.4",
    "create_database": true
  }'
```

The answer is `201` and the site has a status such as `creating`. Creating takes a minute or more. The repository is optional: you can also pick a repository from a connected GitHub account, or create the site with no code yet. See [Create a site](/developers/create-a-site).

## 5. Wait until it is active

Poll the site every 10 seconds until `status` is `active` (or `failed`):

```bash
curl -s -H "Authorization: Bearer $TOKEN" $MYFORGE/sites/SITE_ID
```

## 6. Deploy

```bash
curl -s -X POST $MYFORGE/sites/SITE_ID/deploy \
  -H "Authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: quickstart-deploy-1"
```

The answer is `202` with a deployment. Poll it until `status` is `succeeded` or `failed`:

```bash
curl -s -H "Authorization: Bearer $TOKEN" $MYFORGE/sites/SITE_ID/deployments/DEPLOYMENT_ID
```

The single-deployment answer includes `log` (the last lines) and, when the code scan stopped the deploy, `code_findings`.

## What can go wrong

| You see | Why | Fix |
| --- | --- | --- |
| `401` | Token missing, wrong, expired. | Check the header. Make a new token. |
| `403` | Scope or permission missing, or your IP is not allowed. | Run `GET /token` and read `blocked_scopes`. |
| `404` for a server you can see in the dashboard | The token is limited to other servers or sites. | Edit the token's limits. |
| `409` on deploy | The site cannot be deployed now: not active, watch-only, no repository yet, or a deploy is already running. | Wait, or connect a repository. |
| `422` | A field is invalid, or you are over a plan limit. | Read `errors` in the answer. |

More in [Troubleshooting](/developers/troubleshooting). Next: [Requests and errors](/developers/requests-and-errors).
