> ## Documentation Index
> Fetch the complete documentation index at: https://docs.masterskills.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Device flow

> How a machine becomes an authorized device with a lifetime token.

Device authorization is a three-party dance: the CLI requests a code, the user confirms it in a browser, the CLI polls until the token arrives.

## `POST /device/code`

Called by the CLI to start a login. No authentication.

```json theme={"dark"}
// request
{ "client": "cli", "hostname": "devbox-01" }

// 200
{
  "deviceCode": "…",
  "userCode": "XXXX-XXXX",
  "verificationUri": "https://masterskills.dev/device?code=XXXX-XXXX",
  "interval": 5,
  "expiresIn": 900
}
```

The CLI shows `userCode`, opens `verificationUri`, and polls `/device/token` every `interval` seconds until the code expires.

## `POST /device/token`

Polled by the CLI with the `deviceCode`.

```json theme={"dark"}
// request
{ "deviceCode": "…" }

// 200 — approved
{
  "token": "…",
  "device": { "id": "…", "name": "devbox-01" },
  "user": { "email": "dev@acme.com" },
  "org": { "slug": "acme" }
}
```

| Status | Code                    | Meaning                                        |
| ------ | ----------------------- | ---------------------------------------------- |
| `428`  | `authorization_pending` | Not approved yet — keep polling at `interval`  |
| `410`  | `expired_token`         | Code expired or was denied — restart the login |

The returned `token` is the lifetime device token. Store it securely; it never appears again.

## `POST /device/approve`

<Note>Panel-session endpoint — called by the browser page at `/device`, not with a device token.</Note>

```json theme={"dark"}
// request
{ "userCode": "XXXX-XXXX", "orgName": "Acme" }
```

`orgName` is only sent when the user has no organization yet — approval then creates a team org on the spot. The organization chosen here becomes the device's **home org**.

| Status | Code           | Meaning                                                           |
| ------ | -------------- | ----------------------------------------------------------------- |
| `200`  | —              | `{ org, device }` — approval done, the polling CLI gets its token |
| `403`  | `device_limit` | Free plan: 1 device per user — revoke the old device first        |
| `404`  | `invalid_code` | Unknown or mistyped user code                                     |
| `409`  | `org_required` | User has no organization and none was provided                    |
