---
title: "Poll and exchange an approved CLI login"
method: POST
path: "/auth/cli/device/token"
tags: ["Identity"]
---

# Poll and exchange an approved CLI login

`POST /auth/cli/device/token`

## Request

- Base URL: `https://api.pyai.com`
- URL: `https://api.pyai.com/auth/cli/device/token`
- Auth: none required

Poll no faster than the returned interval. authorization_pending means continue; slow_down permanently increases the interval by five seconds (also reflected in Retry-After). Stop for access_denied, expired_token, or invalid_grant. On approval, current membership, project status and organization key limits are checked again. The grant mints a normal signed API key once, expiring after thirty days. There is no refresh token or replay: if a successful response is lost, restart login. The key can be revoked from the console.

## Request body

- object
  - `device_code` string, required
  - `code_verifier` string, required

## Response `200`

Credential returned once. Store securely; never log it.

- object
  - `api_key` string, required
  - `key_id` string, required
  - `org_id` string, required
  - `project_id` string, required
  - `environment` 'test' | 'live', required
  - `scopes` string[], required
  - `expires_at` integer, required: Unix milliseconds.

## Other responses

- `400`: CLI login error. Branch on the final component of the problem type URI.
- `403`: CLI login error. Branch on the final component of the problem type URI.
- `429`: CLI login error. Branch on the final component of the problem type URI.
- `503`: CLI login error. Branch on the final component of the problem type URI.

---

[API](https://skmtc.dev/pyai/apis/pyai-api.md) · [All operations](https://skmtc.dev/pyai/apis/pyai-api/llms.txt) · [OpenAPI document](https://skmtc.dev/pyai/apis/pyai-api/revisions/819d8e7c4d09?raw)
