CLI Device Authentication

GET/v1/cli/compatibility

This unauthenticated endpoint returns minimum/recommended CLI versions, API/catalog versions, blocked ranges, notices, canonical documentation URLs, verified-free access details, guest trial credential details, the local MCP guest trial contract, and the current hosted MCP operation boundary. Cache it for at most five minutes and revalidate its strong ETag.

Registered Chab clients start with an exact form request to POST /oauth/device/code, then open /device and poll POST /oauth/token. For a local development server, use the returned verification URL on that server. Plain HTTP is accepted only on the exact configured loopback origin (localhost, 127.0.0.1, or [::1]); hosted deployments require HTTPS.

Device grants last ten minutes and begin with a five-second interval. OAuth responses use OAuth JSON, not Chab envelopes; early polling returns slow_down. Approval requires a recently authenticated team owner/admin and a bounded token policy. The bearer token is returned once, without a refresh token.

The start form accepts required client_id and SemVer client_version, plus optional space-delimited scope and a 1–80 character device_name. It is a closed form: duplicate or unknown parameters, repeated scopes, control characters, and malformed versions return invalid_request. Omitted scope uses the client's minimal documented proposal, currently api:credits:read, rather than its full ceiling.

curl -X POST https://www.chab.ai/oauth/device/code \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data 'client_id=chab-cli&client_version=1.0.0&scope=api%3Asearch%3Aread%20api%3Acredits%3Aread&device_name=Workstation'

The chab-cli client can request 28 current scopes: all scopes in the authentication reference except api:billing:write, api:tokens:write, and api:webhooks:write. Those three management permissions require a separately configured API key and the applicable browser approval. Omitting scope requests only api:credits:read; it never requests the full set.

The browser groups permissions by purpose and explains their risk and credit use. Only requested basic defaults (api:examples:write, api:projects:read, api:credits:read) start selected. You may approve a smaller, nonempty subset. A :read permission can still run paid operations, such as search. Spending starts at none; select a capped allowance to enable bounded spending. Project access also starts at none. Project choices belong only to the selected team. Denying a connection issues no key and requires no approval settings.

Client version and API-major compatibility are checked when starting the grant, opening consent, approving it, and exchanging it. If compatibility or the client's allowed permissions change while you approve, start a new flow with a supported CLI version. Your team role, plan access, current required policies, and final key settings must still be valid when the key is issued.

Poll using the returned device_code, respecting interval and any slow_down response:

curl -X POST https://www.chab.ai/oauth/token \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code&client_id=chab-cli&device_code=DEVICE_CODE'

While approval is pending, polling returns authorization_pending. Polling too early returns slow_down and raises that grant's interval by five seconds, up to 30 seconds. Denial returns access_denied, expiry returns expired_token, a wrong or already consumed grant returns invalid_grant, and a retired client returns invalid_client. All OAuth responses carry Cache-Control: no-store, Pragma: no-cache, and X-Request-ID.

Open the returned verification_uri_complete in a system browser. Never print, persist, or place device_code or access_token in a URL. Approval requires an owner/admin authenticated within the last five minutes and selects the final team, scopes, project grants, allowance, IP rules, and 1–90 day expiry (30 days when omitted). The token name must be unique among non-revoked team tokens, and the team must remain below its configured active-token limit. Chab validates both rules during browser approval and rechecks the complete policy under the team lock when the CLI exchanges the grant.

For verified free accounts, browser approval allows api:credits:read and the scopes needed by the tools, including file read/write for conversion and model discovery. Free CLI tokens cannot carry project grants, paid credit budgets, or connected-account Mail/Drive scopes. Accepted starts spend the same one-off signup-bonus free-credit balance as dashboard-created API keys; it does not refresh monthly. A requested scope outside the current free allowlist is rejected during approval for a free team. Guest CLI credentials are also available without an account.

A successful token response contains access_token, token_type: "Bearer", lexically sorted scope, and expires_in; it never contains a refresh token. Plaintext is available only in that response. If the response is lost after commit, the consumed grant cannot reveal or recreate it. Start a new device flow.

The free_access compatibility object reports whether free operation starts are currently enabled, the supported operation keys, an operations array with operation key, family, scope, summary, and docs link for display, the selectable free scopes, credit_scope: "api:credits:read", credit_source: "signup_bonus", free_credit_policy.monthly_refresh: false, and remediation endpoint/copy hints. Use remediation.balance_endpoint and remediation.transactions_endpoint to show free-credit balance and lifecycle history, and show the upgrade/purchase copy from remediation.exhausted or remediation.operation_not_available when a free start fails. free_access.enabled is false when Chab has switched free starts off.

The guest_trial_credentials compatibility object reports whether guest trial API credential issuance is enabled, whether guest credential spend is enabled, token_type: "Bearer", the credential TTL, the active-credential cap, browser issue and revoke URLs, supported guest operation keys, supported guest /v1 route operation keys, an operations array with operation key, family, scope, summary, and docs link, selectable guest scopes, credit_scope: "api:credits:read", credit_source: "guest_trial", compatible_transports: ["api", "cli", "local_mcp"], free_credit_policy.monthly_refresh: false, and remediation URLs for auth, verification challenge, signup, exhaustion, balance, and issuance. Use this object only for active browser-trial users; it does not replace the OAuth device flow for signed-in teams. Guest trial credits are one-off promotional value and do not refresh monthly. The credential enabled and spend_enabled fields are false when Chab has switched guest API credentials or guest spending off.

The local_mcp object describes the local stdio adapter contract for guest trials. The advertised chab mcp serve command uses the same guest bearer credential against the REST /v1 routes; it does not use hosted MCP execution. local_mcp.guest_trial_credentials.tools[] maps MCP tool names to the allowed operation key, method, path, scope, docs link, funding mode, and idempotency requirement. Local MCP guest trial calls share the browser trial's promotional credit pool, risk pauses, verification challenge state, active-operation limit, credential expiry, revocation, account-claim boundary, and free_credit_policy.monthly_refresh: false. When local MCP guest access is switched off, local_mcp.operation_transport and local_mcp.guest_trial_credentials.enabled are false and no operation tools are advertised. Unsupported categories are reported in local_mcp.guest_trial_credentials.unsupported_categories and return operation_not_available_on_free when called with a guest credential. If credential issuance remains enabled while new guest spending is paused, supported_route_operation_keys still lists non-spending identity, balance, operation status/result/artifact, and cancel routes. A client can use these to reconcile work accepted before the pause; operation_keys and tools are empty, so it cannot start new work.

The hosted_mcp object reports whether hosted MCP can start operations. When enabled, guest_oauth_enabled and operation_transport are true and advertised_operation_keys lists the tools hosted MCP can start. It always reports anonymous_access: false and guest_credentials_accepted: false: guest access uses browser OAuth consent, not a REST guest bearer token. See Hosted MCP.

The OAuth/browser contract is generated at openapi/chab-oauth-device.yaml.

curl https://www.chab.ai/v1/cli/compatibility