Inference Logoinference.sh

Device Authorization

OAuth 2.0 device authorization flow (RFC 8628) for signing in from CLIs, IDEs, and other devices without a browser on the same machine.

The belt and infsh CLIs use this flow by default when you run belt login or infsh login in a terminal. You can also call the endpoints directly to build your own login experience.

No API key is required to start or poll a device authorization. Approving a request requires a logged-in workspace session in the browser.

Authentication · Magic link sign-in · CLI setup


Flow overview

mermaid
1sequenceDiagram2    participant CLI as CLI or client3    participant API as api.inference.sh4    participant Browser as Browser (logged in)56    CLI->>API: POST /device/auth7    API-->>CLI: user_code, device_code, approve_url, interval8    CLI->>Browser: Open approve_url (optional)9    Browser->>API: POST /device/auth/approve (session cookie)10    loop Every interval seconds11        CLI->>API: GET /device/auth/poll/{device_code}12        API-->>CLI: status pending | approved | denied | expired13    end14    API-->>CLI: api_key when approved
  1. Your client calls POST /device/auth and receives a short user code and a secret device code.
  2. The user opens approve_url in a browser (or enters the user code at the workspace device-auth page) and approves while signed in.
  3. Your client polls GET /device/auth/poll/{device_code} every interval seconds until the status is approved, denied, or expired.
  4. On approved, the poll response includes an api_key (30-day CLI key named CLI, source: device-auth). Store it securely and send it as Authorization: Bearer … on subsequent API calls.

Codes expire after 300 seconds (5 minutes). The recommended poll interval is 3 seconds.


Start device authorization

POST /device/auth

Authentication: None.

Response

FieldTypeDescription
user_codestringShort code shown to the user (format XXXX-XXXX)
device_codestringSecret code used only for polling (do not display to the user)
approve_urlstringWorkspace URL to open for one-click approval
poll_urlstringConvenience URL (workspace host); clients should poll the API path below
expires_innumberSeconds until the code expires (300)
intervalnumberRecommended seconds between poll requests (3)

Example:

bash
1curl -X POST https://api.inference.sh/device/auth \2  -H "X-API-Version: 2"
json
1{2  "user_code": "ABCD-2345",3  "device_code": "01HXYZ…",4  "approve_url": "https://app.inference.sh/auth/device?code=ABCD-2345&utm_source=cli&utm_medium=app",5  "poll_url": "https://app.inference.sh/device/auth/poll/01HXYZ…",6  "expires_in": 300,7  "interval": 38}

Poll for approval

GET /device/auth/poll/{device_code}

Authentication: None.

Poll until status is terminal (approved, denied, or expired). Wait at least interval seconds between requests.

Response

FieldTypeDescription
statusstringpending, approved, denied, or expired
api_keystringPresent when status is approved (starts with inf_)
team_idstringTeam the key was issued for (when approved)

Example:

bash
1curl "https://api.inference.sh/device/auth/poll/DEVICE_CODE_HERE" \2  -H "X-API-Version: 2"
json
1{2  "status": "approved",3  "api_key": "inf_…",4  "team_id": "team_abc123"5}

While status is pending, the response omits api_key.


Check user code (approval page)

GET /device/auth/code/{code}

Authentication: None.

Used by the workspace device-auth UI to validate a user code before approval. Accepts codes with or without the dash (ABCD2345 or ABCD-2345).

Response

FieldTypeDescription
user_codestringNormalized code
validbooleanWhether the code can still be approved
statusstringpending, approved, or expired
expires_atstringISO timestamp (when known)

Approve device authorization

POST /device/auth/approve

Authentication: Workspace session (browser cookie after SSO or magic link). Guests cannot approve.

Creates a CLI API key for the signed-in user (30-day expiry, full scopes unless scopes is set).

Request

FieldTypeRequiredDescription
codestringYesUser code from POST /device/auth
team_idstringNoTeam to issue the key for (defaults to active team)
scopesstring[]NoAPI key scopes; omit for full access
json
1{2  "code": "ABCD-2345"3}

Response

json
1{2  "success": true,3  "message": "Device authorized successfully"4}

Errors include invalid_code, expired, and already_processed when the code is no longer pending.


CLI usage

bash
1belt login              # device flow, then fallback to manual key entry2belt login --key inf_  # skip device flow (required in CI / non-interactive shells)3belt auth token         # print stored key to stdout (no newline) for scripts

In non-interactive environments (no TTY, CI set, or BELT_NON_INTERACTIVE=1), device authorization is skipped; pass --key or set INFSH_API_KEY. After login, use belt auth token in subshells: curl -H "Authorization: Bearer $(belt auth token)" ...

Session-start hook: When the belt plugin is installed for Claude Code or Codex, the SessionStart hook calls belt plugin hook session-start. If no API key is configured (including anonymous guest sessions), the hook opens a browser for device authorization, prints the approval URL and user code into session context, and polls for up to 45 seconds. A 6-hour cooldown prevents reopening the browser on every session (~/.inferencesh/hook-auth-cooldown). When already logged in, the hook prints your account email instead.

CLI setup — Login · Coding agents — SessionStart hook


we use cookies

we use cookies to ensure you get the best experience on our website. for more information on how we use cookies, please see our cookie policy.

by clicking "accept", you agree to our use of cookies.
learn more.