Avnology ID
API ReferenceOAuth 2.1 / OIDC

Device Authorization

Initiate the OAuth 2.1 device authorization flow (RFC 8628) for CLI tools, IoT devices, and smart TVs.

Endpoint

POST /oauth2/device/auth

Base URL: https://api-id.avnology.net

Content-Type: application/x-www-form-urlencoded

Initiates the device authorization flow for devices that lack a browser or have limited input capabilities (CLI tools, smart TVs, IoT devices, AI agents). The device displays a user code and verification URL, and the user completes authentication on a separate device.

Step 1: Request Device Code

Response (200 OK)

{
  "device_code": "dc_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "user_code": "WDJB-MJHT",
  "verification_uri": "https://id.avnology.net/device",
  "verification_uri_complete": "https://id.avnology.net/device?user_code=WDJB-MJHT",
  "expires_in": 900,
  "interval": 5
}
FieldDescription
device_codeUsed by the device to poll for completion
user_codeDisplayed to the user (short, easy to type)
verification_uriURL where the user enters the code
verification_uri_completeURL with code pre-filled (for QR codes)
expires_inSeconds before the device code expires
intervalMinimum seconds between polling attempts

Step 2: Display to User

Show the user:

To sign in, visit: https://id.avnology.net/device
Enter code: WDJB-MJHT

Or display a QR code linking to verification_uri_complete.

Step 3: Poll for Token

The device polls the token endpoint until the user completes authentication:

curl -X POST https://api-id.avnology.net/oauth2/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=urn:ietf:params:oauth:grant-type:device_code" \
  -d "device_code=dc_a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
  -d "client_id=cli_device_app_123"

Pending (400)

{ "error": "authorization_pending", "error_description": "The user has not yet authorized the device" }

Slow Down (400)

{ "error": "slow_down", "error_description": "Polling too frequently. Increase interval." }

Success (200 OK)

{
  "access_token": "eyJhbGciOiJSUzI1NiI...",
  "token_type": "Bearer",
  "expires_in": 900,
  "refresh_token": "rt_device_...",
  "id_token": "eyJhbGciOiJSUzI1NiI...",
  "scope": "openid profile email"
}

Expired (400)

{ "error": "expired_token", "error_description": "The device code has expired" }

Complete Example

JavaScript (CLI Tool)

async function deviceLogin(clientId) {
  // Step 1: Request device code
  const deviceRes = await fetch('https://api-id.avnology.net/oauth2/device/auth', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({ client_id: clientId, scope: 




























Python (httpx)

import httpx
import time

def device_login(client_id: str) -> dict:
    # Request device code
    device = httpx.post("https://api-id.avnology.net/oauth2/device/auth", data={




















Go (net/http)

func deviceLogin(ctx context.Context, clientID string) (*TokenResponse, error) {
	// Request device code
	data := url