Kiro API key (ksk_) auth: run Kiro on a headless server
Kiro API keys let kRouter use Kiro with no browser sign-in, on a VPS, in CI or Docker. They need a paid Kiro plan. Setup, curl import and caveats.
Updated October 2026. An earlier version of this post promised "free Claude on a server with an API key". Kiro only issues API keys on its paid plans, so that was wrong. The import-over-curl example also skipped the dashboard login the API needs; both are fixed below.
Kiro is a useful backend to put behind kRouter: its plans include Claude Sonnet and other models, and kRouter translates between Kiro's format and the OpenAI or Anthropic formats your tools speak. But until v0.5.118 every way to connect it needed a person at a browser. AWS Builder ID, IAM Identity Center, Google and GitHub sign-ins all ask someone to log in or approve a code. That can be done for a server if you can reach its dashboard, but it cannot be scripted, and the connection then lives on a refresh token.
kRouter v0.5.118 added Kiro API-key (ksk_) authentication -- a long-lived key instead of an OAuth flow. No refresh token, no browser, no interactive step.
Who can use it
Kiro issues API keys only on paid plans. Its authentication docs say API key sign-in "is only available for Kiro Pro, Pro+, Pro Max, and Power subscribers", and an admin-managed subscription may need an admin to enable key generation first. You create a key at app.kiro.dev, in the API Keys section; the full value is shown once.
Two things to know before you rely on it:
- Kiro documents API keys for its own CLI in non-interactive mode, for CI and headless use. Sending the same key through a router is not a use Kiro documents. kRouter shows a risk notice before you connect Kiro at all: the session is not licensed for proxy use, and the account may be restricted.
- The free plan still needs a sign-in. On Kiro's free plan (50 credits a month) there is no key to paste, so connect it with Builder ID, Google or GitHub from the dashboard instead.
Why headless auth matters
Running kRouter on a VPS (see the VPS guide) gives you one endpoint that every machine you work from can reach. If a provider needs an interactive login, someone has to reach the dashboard and finish it by hand, and do it again whenever the session is lost.
An API key sidesteps that. It is one string you can paste or send from a provisioning script, and kRouter stores it with a one-year expiry and never tries to refresh it.
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: nulland a one-year expiry, so the proactive-refresh path, which needs a refresh token, is skipped- The executor sends
Authorization: Bearer <key>plus atokentype: API_KEYheader, and tries the*.amazonaws.comCodeWhisperer hosts first, because theruntime.*.kiro.devgateway rejects anAPI_KEYtoken with a 401 or 403 - A
profileArnguard makes API-key connections send only the ARN resolved at import, never the shared placeholder ARN, which would 403 because the key's account does not own it
OAuth connections are 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:
- Open Providers and choose Kiro AI (kRouter shows its risk notice first)
- In the Connect Kiro dialog, pick API Key
- Paste your
ksk_…key and set the region (the default isus-east-1) - Click Import API Key; kRouter validates the key before it saves anything
On a box where you never open the dashboard, the same import works over its API. That API needs a dashboard session, so log in first and keep the cookie. Run this on the server itself:
read -rs -p "kRouter dashboard password: " KROUTER_PW; echo
curl -s -c ~/.krouter-cookies -X POST http://localhost:20128/api/auth/login \
-H "Content-Type: application/json" \
-d "{\"password\":\"$KROUTER_PW\"}"
curl -s -b ~/.krouter-cookies -X POST http://localhost:20128/api/oauth/kiro/api-key \
-H "Content-Type: application/json" \
-d '{ "apiKey": "ksk_...", "region": "us-east-1" }'A successful import returns {"success":true,...}. A key Kiro rejects comes back as an HTTP 500 with the error message. On a fresh npm install with no password set, the default password works only from the server itself; set a real one before you expose the dashboard anywhere else.
Once imported, any OpenAI-compatible client can request a Kiro model:
curl http://localhost:20128/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-krouter-key>" \
-d '{"model": "kr/claude-sonnet-4.5", "messages": [{"role":"user","content":"hi"}]}'The kRouter key comes from the dashboard's Endpoint page. Callers on the same machine can leave the header out unless you set REQUIRE_API_KEY=true; remote callers always need it. Which models you get depends on your Kiro plan, because kRouter reads the live model list from your Kiro account.
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 the OpenAI shape, which is lossy for tool-use and thinking blocks. Combined with API-key auth, that makes Kiro a Claude-format backend you can run on a server with no interactive step.
What has and has not been tested
The v0.5.118 release notes are explicit about this. The API-key code is a port of upstream's feature and is covered by unit tests: the tokentype header, the host ordering and profileArn parsing. It was also checked live not to change existing OAuth connections. It was not run end to end against a real ksk_ key at the time, because none was available. If an import fails, read the error in the response before assuming the key is bad.
When to use API key vs OAuth
- API key (
ksk_): a paid Kiro plan, and a headless server, CI job, Docker container or anything you set up from a script - OAuth: the free plan, or any machine where you can open the dashboard and approve a sign-in once
Get started
npm install -g @sifxprime/krouter
krouter --skip-update # on a server; use krouter -t on a desktop
# Dashboard → Providers → Kiro AI → API Key → paste ksk_...The CLI binds to 0.0.0.0 by default. On a VPS, either start it with --host 127.0.0.1 and reach the dashboard through an SSH tunnel, or put it behind a reverse proxy with a real password; the deploy docs cover both. See /install for other install methods.
Common questions
Can I get a Kiro API key on the free plan?
No. Kiro's documentation limits API keys to Pro, Pro+, Pro Max and Power subscribers. On the free plan, connect Kiro with AWS Builder ID, IAM Identity Center, Google or GitHub instead.
Where do I create a Kiro API key?
Sign in at app.kiro.dev and open the API Keys section. The full key is shown only when you create it, so copy it then.
Does a Kiro API key expire?
Kiro describes keys as long-lived credentials and does not publish an expiry; you can revoke them in app.kiro.dev. kRouter records a one-year expiry on the connection and skips token refresh for it.
Why does kRouter call AWS hosts first for API-key connections?
Kiro's runtime gateway (runtime.*.kiro.dev) rejects an API_KEY token with a 401 or 403, so for these connections kRouter tries the *.amazonaws.com CodeWhisperer hosts first. OAuth connections keep the default order.
Will my existing Kiro OAuth connection change?
No. Every API-key branch checks authMethod === "api_key", so OAuth connections behave exactly as before.
Published by Kodelyth, the team that builds kRouter. Posts are drafted with AI assistance and reviewed by a person before they go out. kRouter is free and MIT licensed.
Install kRouterRelated posts
- How kRouter worksCodex CLI with any model: model_providers and wire_apiCodex now speaks only the Responses API. How to run it on Claude, GLM, Kimi or DeepSeek through config.toml, and what breaks along the way.
- How kRouter worksResponses API vs Chat Completions: why proxies breakCodex, some Copilot models and OpenCode Go's Grok speak only OpenAI's Responses API. Five ways it differs from Chat Completions, and where proxies break.
- How kRouter worksUse GitHub Copilot as a native Claude endpoint with kRouterkRouter sends Claude requests on GitHub Copilot to Copilot's Anthropic-style /v1/messages endpoint, so prompt caching works. How it works, and its limits.
Relevant docs
- Core conceptsProviders, combos, account routing, token savers, MITM mode, quota tracking, the response cache and remote access: the eight ideas behind kRouter.
- The Zenith Routing EngineHow kRouter picks which of your accounts serves a request: Zenith scoring, conversation stickiness, cooldowns, and the round-robin, P2C and random options.
- Token savers: RTK, Caveman, Ponytail, Headroom, PXPIPEFive ways kRouter can shrink a request before it reaches the provider. Only RTK is on by default. What each saver does, what it needs, and its limits.