Skip to content

Device Login (OAuth Device Code)

RFC 8628 device-authorization flow. Issues OAuth access/refresh tokens for browserless CLI login (no API key).

A login flow for CLI and terminal environments that cannot open a browser directly. It has three steps — request a code (the CLI receives a device_code and a user_code) → approve in the browser (the user opens verification_url and enters the user_code while logged in) → poll for tokens (the CLI calls the token endpoint every interval seconds and receives access/refresh JWTs once approved).

1. Request a device code#

POST/v1/auth/device/code

No auth and no body. The CLI keeps the device_code and shows the user the user_code and verification_url. The code expires if not approved within expires_in seconds.

200 OK
{
  "device_code": "f1d2c3b4a5...e9f0",
  "user_code": "WXYZ-1234",
  "verification_url": "https://router.pleum.ai/device",
  "interval": 5,
  "expires_in": 600
}

2. Approve in the browser#

POST/v1/auth/device/authorize

Requires a logged-in browser session (JWT). Send the user_code the user entered at verification_url to attach the device code to that account.

ParameterTypeRequiredDescription
user_codestringRequiredThe user_code from the code response (e.g. WXYZ-1234).
request body
{
  "user_code": "WXYZ-1234"
}
200 OK
{
  "ok": true
}

3. Poll for tokens#

POST/v1/auth/device/token

No auth. The CLI polls with device_code every interval seconds. On approval, returns access_token/refresh_token once.

ParameterTypeRequiredDescription
device_codestringRequiredThe device_code from the code response.
request body
{
  "device_code": "f1d2c3b4a5...e9f0"
}
200 OK
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer",
  "expires_in": 3600
}

Poll statuses — 202 authorization_pending (keep polling) · 400 expired_token · 400 already_consumed · 404 invalid_device_code.

202 authorization_pending
{
  "detail": "authorization_pending"
}

Full flow example#

Request a code, then poll the token endpoint until the user approves in the browser.

curl
# 1. Request a device code (no auth)
curl -X POST https://router.pleum.ai/v1/auth/device/code

# -> { "device_code": "f1d2...e9f0", "user_code": "WXYZ-1234",
#      "verification_url": "https://router.pleum.ai/device",
#      "interval": 5, "expires_in": 600 }

# 2. Open verification_url in a browser and enter the user_code.

# 3. Poll for OAuth tokens every 5s until success (no auth).
curl -X POST https://router.pleum.ai/v1/auth/device/token \
  -H "Content-Type: application/json" \
  -d '{"device_code": "f1d2...e9f0"}'

# 202 -> still pending, wait 5s and poll again
# 200 -> { "access_token", "refresh_token", ... }  store them and stop polling

Session vs API keys#

This flow does not mint a plm_ API key. The CLI uses an OAuth session; the server maps it to one hidden per-user session key for billing. Create a dashboard API key if you need a long-lived plm_ credential.