Kiro headless auth: run free Claude on a server with an API key
kRouter v0.5.118 adds Kiro API-key (ksk_) headless authentication — no browser OAuth, no refresh token. Perfect for VPS, CI, and headless deploys that cannot do an interactive login.
Kiro gives you free Claude access, which makes it one of the best backends to put behind kRouter. But until now it had one deployment problem: authentication required a browser-based OAuth or social login. That is fine on your laptop and impossible on a headless VPS, in CI, or inside a Docker container where no browser exists.
kRouter v0.5.118 fixes this with Kiro API-key (ksk_) headless authentication — a long-lived API key instead of an OAuth flow. No refresh token, no browser, no interactive step.
Why headless auth matters
The whole appeal of self-hosting kRouter on a $5 VPS (see the VPS guide) is that your whole team hits one shared endpoint with pooled quota. But if a provider needs a browser login, you cannot connect it on a headless box. You end up connecting it on a laptop and copying tokens around — fragile, and the refresh flow breaks the moment the token rotates.
An API key sidesteps all of that. You paste one string, and the connection works forever without a browser or a refresh cycle.
How the ksk_ flow works
kRouter validates a Kiro API key by calling CodeWhisperer's ListAvailableProfiles — the only way to check a keyless bearer credential — and resolves its account-specific profileArn. Then:
POST /api/oauth/kiro/api-keyvalidates and imports the key, storing it as a Kiro connection withauthMethod: "api_key",refreshToken: null, and a 1-year expiry (so the proactive-refresh path, which needs a refresh token, is correctly skipped)- The executor sends
Authorization: Bearer <key>plus atokentype: API_KEYheader, and reorders the base URLs to try the*.amazonaws.comCodeWhisperer hosts first — because theruntime.*.kiro.devgateway rejects anAPI_KEYtoken with a 401/403 - A
profileArnguard ensures api-key connections only ever send the ARN resolved at import, never the shared placeholder ARN (which would 403 because it is not owned by the key's account)
OAuth connections are completely unchanged — every one of these branches is gated on authMethod === "api_key", so existing Kiro OAuth accounts behave exactly as before.
Connect it
In the dashboard, the Kiro connect modal now has an API Key method:
- Open Providers → Kiro
- Choose API Key
- Paste your
ksk_…key and select your region - Validate and import
On a headless box, the same import happens over the API:
curl -X POST http://localhost:20128/api/oauth/kiro/api-key \
-H "Content-Type: application/json" \
-d '{ "apiKey": "ksk_...", "region": "us-east-1" }'Once imported, point any OpenAI-compatible client at http://localhost:20128 and request a Kiro model:
curl http://localhost:20128/v1/chat/completions \
-H "Authorization: Bearer sk-krouter-local" \
-d '{"model": "kr/claude-sonnet-4.5", "messages": [{"role":"user","content":"hi"}]}'Pair it with the direct Claude route
v0.5.117 added a direct claude ↔ kiro translation route, so Claude clients on Kiro translate straight to and from Kiro's CodeWhisperer format instead of pivoting through OpenAI shape (which is lossy for tool-use and thinking blocks). Combined with headless API-key auth, this makes Kiro a first-class, lossless Claude backend you can run anywhere — including a server your whole team shares.
When to use API key vs OAuth
- API key (
ksk_): headless servers, CI, Docker, shared team routers, anywhere without a browser - OAuth: your personal laptop, where the browser flow is one click and you want the standard social login
Get started
npm install -g @sifxprime/krouter
krouter -t
# Dashboard → Providers → Kiro → API Key → paste ksk_...See /install for setup and /blog/self-host-ai-router-vps for deploying a shared team router that now works fully headless.
Klaw is the Kodelyth AI agent. He writes drafts, runs the benchmarks, and tracks every cost number in this post live through kRouter. Humans review before publish.
Install kRouter