Authentication
Device auth flow, tokens, and API keys
Device Auth Flow
The OpenSkill CLI uses the device authorization flow for authentication. This is the same pattern used by GitHub CLI and other developer tools — it opens a browser to complete authentication without requiring you to paste tokens into the terminal.
Request Device Code
Start the auth flow by requesting a device code:
POST /api/auth/device/code
{
"client_info": {
"name": "osk-cli",
"version": "1.0.0"
}
}| Parameter | Type | Description |
|---|---|---|
| client_info | object | Optional client information (name, version) |
Response:
200 OK
{
"device_code": "ABCD-1234",
"user_code": "ABCD-1234",
"verification_uri": "https://openskill.dev/auth/device",
"expires_in": 900,
"interval": 5
}| Parameter | Type | Description |
|---|---|---|
| device_code* | string | Code used to poll for the token |
| user_code* | string | Code displayed to the user |
| verification_uri* | string | URL to open in the browser |
| expires_in* | number | Seconds until code expires |
| interval* | number | Polling interval in seconds |
Poll for Token
After the user completes browser authentication, poll for the access token:
POST /api/auth/device/token
{
"device_code": "ABCD-1234"
}Response (success):
200 OK
{
"access_token": "osk_...",
"token_type": "Bearer",
"expires_in": 86400,
"refresh_token": "osk_rt_..."
}If the user hasn't completed authentication yet, the endpoint returns a
authorization_pending error. Continue polling at the specified interval.Using Tokens
Include the access token in the Authorization header:
Authorization: Bearer osk_...Token Refresh
When the access token expires, use the refresh token to get a new one:
POST /api/auth/refresh
{
"refresh_token": "osk_rt_..."
}Response:
200 OK
{
"access_token": "osk_...",
"token_type": "Bearer",
"expires_in": 86400,
"refresh_token": "osk_rt_..."
}Token Revocation
Revoke a refresh token to log out. This invalidates both the refresh token and any associated access tokens.
POST /api/auth/revoke
{
"refresh_token": "osk_rt_..."
}Response:
200 OK
{
"success": true
}