# Start a device authorization

Creates a device code and a user code, and returns the approval page a person opens to authorize the device. Poll `POST /v1/auth/device/poll` with `deviceCode` no faster than `interval` seconds, until `expiresAt`. The response also carries a `requiresAction` envelope whose continuation token drives the same wait through `POST /v1/actions/resume`. Send `claim` to attach an unclaimed Space, which the approver then assigns to one of their teams.

## POST `/v1/auth/device`

### Request body

- **required** `application/json`

#### Parameters

- `clientId` **string**  
  Client starting the flow, shown to the person on the approval page. Only `spacefast-cli` is accepted, and it is the default.
  - min length 1 · max length 255 · default: "spacefast-cli"

- `access` **string**  
  How much access the device asks for: `read` for reading teams, Spaces, and domains, or `agent` for everything an interactive login can grant. The approver can narrow the resulting scopes but never widen them.
  - default: "agent"
  - Allowed: `read` `agent`

- `claim` **object**  
  Attaches an unclaimed Space to this login. Omit for an ordinary sign-in. When present, the approver must pick a team to receive the Space.
  - `spaceId` **string** required  
    Unclaimed Space to claim when this login is approved.
    - min length 1
  - `claimToken` **string** required  
    Space key proving control of `spaceId`. Only its hash is stored.
    - min length 1 · max length 512

### Responses

- **200** Response for status 200

- `$schema` **string** <uri>  
    Canonical JSON Schema URL for this response body. The server also sends it in the `Link: rel="describedby"` response header.
  - `data` **object** required
    - `deviceCode` **string** required  
      Secret the device polls with. Send it in the request body only, and never log or display it.
      - min length 1
    - `userCode` **string** required  
      Short code the person enters on the approval page. Uppercase alphanumerics, at most eight characters, with a dash after the fourth.
      - min length 1
    - `verificationUrl` **string** <uri> required  
      Approval page to open in a browser. It carries `userCode` already filled in when one is available, otherwise the person types the code.
    - `interval` **integer** required  
      Seconds to wait between polls. Polling faster answers 429 `slow_down`.
      - max 9007199254740991
    - `expiresAt` **string** <date-time> required  
      ISO 8601 timestamp after which both codes stop working.
      - matches ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$

- `requiresAction` **object**
  - `actionType` **string** required  
    Which step is blocking: `device_authorization` waits for a browser sign-in, `confirmation` waits for a person to approve one action, `elevation` waits for a person to grant temporary access.
    - Allowed: `device_authorization` `confirmation` `elevation`
  - `instruction` **string** required  
    One sentence an agent can show a person, naming what they have to do.
  - `url` **string** <uri> | **any**  
    Page to send the person to. Absent on a `device_authorization` poll, where the agent already holds the verification URL from the response that started the flow.
  - `pollUrl` **string** <uri>  
    Endpoint that takes `continuationToken` and drives this flow: `POST /v1/actions/resume`.
  - `continuationToken` **string** required  
    Signed capability naming this one flow and the principal that started it. It is the only credential `POST /v1/actions/resume` needs for a device sign-in; a confirmation or elevation also has to be resumed with the same agent credential that requested it. Treat it as a secret and never log it.
    - min length 1
  - `pollAfterSeconds` **integer** required  
    How long to wait before calling resume again, in seconds.
    - max 9007199254740991
  - `expiresAt` **string** <date-time> required  
    ISO 8601 deadline for the human step. Resuming after it answers `expired`. The token itself outlives the deadline by a short grace so resume can report that rather than rejecting the token.
    - matches ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$

## Try it

### cURL Example
```
curl -X POST "https://api.spacefast.com/v1/auth/device" \
  -H "Content-Type: application/json" \
  -d '{
  "clientId": "spacefast-cli",
  "access": "read",
  "claim": {
    "spaceId": "string",
    "claimToken": "string"
  }
}'
```

### JavaScript Example
```
const response = await fetch("https://api.spacefast.com/v1/auth/device", {
  method: "POST",
  headers: {
    "Content-Type": "application/json"
  },
  body: "{\n  \"clientId\": \"spacefast-cli\",\n  \"access\": \"read\",\n  \"claim\": {\n    \"spaceId\": \"string\",\n    \"claimToken\": \"string\"\n  }\n}"
});
```

### Python Example
```
import requests

response = requests.post(
    "https://api.spacefast.com/v1/auth/device",
    headers={
        "Content-Type": "application/json"
    },
    data="{\n  \"clientId\": \"spacefast-cli\",\n  \"access\": \"read\",\n  \"claim\": {\n    \"spaceId\": \"string\",\n    \"claimToken\": \"string\"\n  }\n}",
)
```

### Response Example
```
{
  "$schema": "http://example.com",
  "data": {
    "deviceCode": "string",
    "userCode": "string",
    "verificationUrl": "http://example.com",
    "interval": 9007199254740991,
    "expiresAt": "2019-08-24T14:15:22Z"
  },
  "requiresAction": {
    "actionType": "device_authorization",
    "instruction": "string",
    "url": "http://example.com",
    "pollUrl": "http://example.com",
    "continuationToken": "string",
    "pollAfterSeconds": 9007199254740991,
    "expiresAt": "2019-08-24T14:15:22Z"
  }
}
```

### Error Example
```
{
  "$schema": "http://example.com",
  "type": "string",
  "title": "string",
  "status": -9007199254740991,
  "detail": "string",
  "code": "string",
  "pointer": "string",
  "details": {
    "property1": null,
    "property2": null
  },
  "suggestions": [
    "string"
  ],
  "next": [
    "string"
  ],
  "requestId": "string"
}
```
