Token endpoint (authorization code + device grant)
Issues an il_oauth_ access token. application/x-www-form-urlencoded per RFC 6749 §4.1.3; JSON is also accepted, because several MCP clients send it. Client authentication (Basic or body, required only for a confidential client) runs FIRST for both grants, before anything is consumed.
grant_type=authorization_code
Then an ATOMIC single-use consumption of the code, then expiry, client_id, redirect_uri and the PKCE code_verifier. The code is consumed BEFORE the later checks on purpose — a code that fails one of them must not remain usable for a better-formed retry.
grant_type=urn:ietf:params:oauth:grant-type:device_code
RFC 8628 §3.4. No PKCE: the flow has none, because the device_code is itself the high-entropy secret and it never travels through a browser. Checks run in this order, and the order is the specification: unknown/wrong-client device_code → invalid_grant; polled faster than interval → slow_down; past 600s → expired_token; refused by the human → access_denied; nobody has answered yet → authorization_pending; approved → an atomic single-use consume, then mint.
slow_down deliberately precedes expiry and status: §3.5 treats it as a rate-limit signal rather than a state report, and a client hammering a dead code should be told to slow down first — otherwise the cheapest way to poll fast is to poll an expired code. A refused poll still updates the clock, so hammering never advances it.
There are no refresh tokens in v1: Kairos has nowhere to store one, so a single longer-lived access token is issued instead (90 days by default). Refresh is a follow-up that lands with Kairos's refresh storage.
Namespace limitation: OAuth tokens cannot be restricted below the workspace in v1: Kairos's oauth_tokens table has no scoped_namespaces column (only the gateway's key_metadata sidecar does, and that is keyed by api-key key_id). A consented workspace grants every namespace in it.
Request
- Base URL: https://api.infolang.ai
- URL: https://api.infolang.ai/oauth/token
- Auth: none declared
Response
The access token (Cache-Control: no-store)
Changes
No recorded changes to this operation across all 1 revision of this API.