Provider credentials
Workspace owners and admins store the Credentials Sensei runs each provider on. A workspace can hold several auth methods per provider, and one of them is active at a time. To store a key or change the active method, send PUT /api/organizations/{workspaceId}/ai-provider with an operation. Any member can read the Credentials, with every secret masked.
| Method | Path | Description |
|---|---|---|
| GET | /api/organizations/{workspaceId}/ai-provider | Read the workspace credentials and active auth method per provider, with every login of claude_code, codex and muse_code oldest first. Secrets are masked. |
| PUT | /api/organizations/{workspaceId}/ai-provider | Store or switch workspace credentials. The body is one of the operation variants. Admins only. |
| DELETE | /api/organizations/{workspaceId}/ai-provider?provider=&authMethod=&loginId= | Remove the credentials of one auth method, or with loginId one login of claude_code, codex or muse_code. Which methods a provider takes is not in the schema. Admins only. |
| GET | /api/organizations/{workspaceId}/ai-provider/claude-usage?fresh=&loginId= | Read the session and weekly utilization of the workspace's Claude login: the one in use, or the one loginId names. 400 when the workspace holds no such Claude login or it needs reconnecting. |
| GET | /api/organizations/{workspaceId}/ai-provider/codex-usage?fresh=&loginId= | Read the session and weekly utilization of the workspace's Codex login: the one in use, or the one loginId names. 400 when the workspace holds no such Codex login or it needs reconnecting. |
| GET | /api/organizations/{workspaceId}/ai-provider/coding-plan-usage?fresh= | Read the session and weekly utilization of the workspace's GLM Coding Plan. 400 when the workspace holds no Coding Plan. |
| GET | /api/organizations/{workspaceId}/ai-provider/deepseek-usage?fresh= | Read the balance of the workspace's DeepSeek API key, one amount per currency, in place of usage windows. 400 when the workspace holds no DeepSeek API key. |
| GET | /api/organizations/{workspaceId}/ai-provider/google | Read saved workspace Gemini methods and selection. Secrets are masked. |
| PUT | /api/organizations/{workspaceId}/ai-provider/google | Validate and save a workspace Gemini API key without selecting it. Admins only. |
| DELETE | /api/organizations/{workspaceId}/ai-provider/google | Remove both workspace Gemini methods and clear selection. Admins only. |
| PUT | /api/organizations/{workspaceId}/ai-provider/google/method | Select a saved workspace Gemini method with its selection revision. Admins only. |
| DELETE | /api/organizations/{workspaceId}/ai-provider/google/method | Remove one workspace Gemini method. Removing the selected method leaves none selected. Admins only. |
| GET | /api/organizations/{workspaceId}/ai-provider/google/usage?fresh=&loginId= | Read the session and weekly utilization of the workspace's Antigravity sign-in, whichever Gemini method is selected: its stored reading, from its latest turn or a live read, while that is under 5 minutes old, and otherwise a live read from Google with the sign-in's own token, stored on the sign-in. When the live read fails it is the stored reading, and null before there is one. A read never changes the selected method or a limit. 400 when the workspace holds no such sign-in or it needs reconnecting. |
| GET | /api/organizations/{workspaceId}/ai-provider/grok-usage?fresh=&loginId= | Read a workspace SuperGrok login's weekly usage: its stored reading while under five minutes old, otherwise a live read with its saved access token. A failed live read returns the stored reading, or null before one exists. A free reading begun at least fifteen minutes after a limit may lift that unchanged mark. An xAI API key has no reading. 400 when the named login is absent or needs reconnecting. |
| POST | /api/organizations/{workspaceId}/ai-provider/help-request | Ask the workspace owners and admins to fix a provider. Repeated requests within one hour notify them once. |
| GET | /api/organizations/{workspaceId}/ai-provider/kimi-code-usage?fresh= | Read the session and monthly utilization of the workspace's Kimi Code. 400 when the workspace holds no Kimi Code key. |
| POST | /api/organizations/{workspaceId}/ai-provider/login/antigravity | Start workspace Antigravity sign-in. Admins only. |
| POST | /api/organizations/{workspaceId}/ai-provider/login/antigravity/cancel | Cancel workspace Antigravity sign-in. Admins only. |
| POST | /api/organizations/{workspaceId}/ai-provider/login/antigravity/complete | Complete workspace Antigravity sign-in. Admins only. |
| POST | /api/organizations/{workspaceId}/ai-provider/logins/recheck | Re-check usage for the workspace's logins of one provider (including SuperGrok on xai) at their limit, without waiting for their reset: every login of the provider, or the one loginId names. Admins only. Returns cleared, stillAtLimit and unreadable counts and retryAt, the earliest remaining reset, or null. |
| GET | /api/organizations/{workspaceId}/ai-provider/muse-usage?fresh=&loginId= | Read the session and weekly utilization of the workspace's Muse Code login: the one in use, or the one loginId names. It is the stored reading, from the login's latest turn, its sign-in, its last usage limit or a live read, while that is under 5 minutes old, and otherwise a live read from Meta; when the live read fails it is the stored reading, and null before there is one. A usage-limit reading holds only the window that hit the limit, at 100%. 400 when the workspace holds no such Muse Code login or it needs reconnecting. |
| GET | /api/organizations/{workspaceId}/ai-provider/token-usage | Read the tokens Sensei spent on the workspace's Credentials, per Provider and per login or key method, over the last 7 days, the last 30 days and everything recorded: input (uncached), cache read, cache write and output, kept apart. Each total gives its recorded items, how many reported no counts (missing, never added as 0), how many made no model call and how many are still in progress. Covers only work run through Sensei since recording began, from firstStartedAt; members' own Subscriptions and Sensei are never included. Owners and admins only. |
| POST | /api/organizations/{workspaceId}/provider-login/claude | Start a Claude login for the workspace: open the returned url in a browser, then pass the code it shows and loginToken to complete within 15 minutes. Admins only. |
| POST | /api/organizations/{workspaceId}/provider-login/claude/complete | Finish a Claude login with the loginToken from start and the code from the browser (code, code#state, or the whole callback URL). A refused code answers 200 with authenticated false. Admins only. |
| POST | /api/organizations/{workspaceId}/provider-login/codex | Start a Codex login for the workspace: enter userCode at verificationUrl in a browser, then call complete with loginToken until it answers authenticated. Admins only. |
| POST | /api/organizations/{workspaceId}/provider-login/codex/complete | Poll a Codex login with the loginToken from start: authenticated false until the code is approved in the browser, so repeat every intervalSeconds; restart true means start again. Admins only. |
| POST | /api/organizations/{workspaceId}/provider-login/muse | Start a Muse Code login for the workspace: open verificationUrl in a browser and approve userCode, then call complete with loginToken until it answers authenticated. Admins only. |
| POST | /api/organizations/{workspaceId}/provider-login/muse/complete | Poll a Muse Code login with the loginToken from start: authenticated false until the code is approved in the browser, so repeat every intervalSeconds; restart true means start again. The first login makes muse_code the active method. Admins only. |
In the web app this is Settings > your workspace > AI Providers. To connect your own Claude, Codex, GLM Coding Plan, Kimi Code or DeepSeek API access instead, see Account. Which of the two runs a given session is explained on AI providers.
Read the workspace's Credentials
Read each provider's stored auth methods and which one is active.
curl -s https://app.kosuke.ai/api/organizations/$WORKSPACE_ID/ai-provider \
-H "Authorization: Bearer $KOSUKE_API_KEY"
{
"data": {
"defaultModel": null,
"providers": {
"anthropic": {
"activeAuthMethod": "claude_code",
"selectable": true,
"authMethods": {
"api_key": { "configured": true, "maskedApiKey": "sk-ant-...9f2c", "authenticatedAt": "2026-08-11T14:02:31.000Z" },
"aws_bedrock": { "configured": false },
"claude_code": {
"configured": true,
"authenticatedAt": "2026-09-20T07:45:12.000Z",
"logins": [
{ "id": "3d7a1f52-9c4e-4b08-a6e1-5f2b8c9d0e47", "label": "[email protected]", "status": "available", "needsReauth": false, "exhaustedUntil": null, "authenticatedAt": "2026-09-20T07:45:12.000Z" }
]
}
}
},
"openai": {
"activeAuthMethod": "api_key",
"selectable": true,
"authMethods": {
"api_key": { "configured": true, "maskedApiKey": "sk-proj...41ab", "authenticatedAt": "2026-08-11T14:05:03.000Z" },
"codex": { "configured": false, "logins": [] }
}
},
"zai": {
"activeAuthMethod": null,
"selectable": false,
"authMethods": { "coding_plan": { "configured": false } }
},
"moonshot": {
"activeAuthMethod": null,
"selectable": false,
"authMethods": { "kimi_code": { "configured": false } }
},
"deepseek": {
"activeAuthMethod": null,
"selectable": false,
"authMethods": { "deepseek_api": { "configured": false } }
}
}
}
}
| Field | Meaning |
|---|---|
activeAuthMethod | The method this provider runs on, or null when none is active. |
selectable | true when the active method works. A login that needs reconnecting makes it false. |
authMethods.<method>.configured | Sensei holds this method's key or login. |
maskedApiKey | The first 7 and last 4 characters of a stored key. |
email | The account behind a Claude Code or Codex login. |
needsReauth | Present and true when a Claude Code or Codex login needs reconnecting. |
region | The AWS region of a Bedrock key. |
logins | Every Claude Code or Codex login of the method, oldest first. The oldest login wins a tie when usage is close. Each has id, label, status, needsReauth, exhaustedUntil and authenticatedAt. label is the account email. |
logins[].status | available, limit_reached or reconnect_required. exhaustedUntil is set only on limit_reached. |
defaultModel is the Workspace Default Model when its provider can run, otherwise the model Sensei would choose from the first usable provider, and null only when no provider can run. savedDefaultModel is the Workspace Default Model as saved, and hasSavedDefaultModel says whether one is saved. defaultAuto is true when the Workspace Default Model is Auto; savedDefaultModel then keeps the model that Crons on Default and a start Auto cannot take use. autoAvailable says whether the workspace Credentials can run Auto now. A member's own Default Model is on Account.
In the CLI, run kosuke providers get <workspaceId>.
Store a key or switch the active method
Set operation to one of these values. Owners and admins only. Two more values set the Workspace Default Model: default_model with a model field sets a model, turns Auto off, and answers 400 BAD_REQUEST when that model's provider cannot run; default_auto, with no other field, makes it Auto and answers 400 BAD_REQUEST when the workspace Credentials cannot run Auto.
operation | Auth method | Other fields |
|---|---|---|
anthropic_api_key | Anthropic API key | anthropicApiKey. Leave it out to switch back to the key already stored. |
anthropic_aws_bedrock | Anthropic on AWS Bedrock | region, required. bedrockApiKey, which you leave out to reuse the stored key. validationModel, an optional model value to test the key against. |
anthropic_claude_code | Claude Code login | None. Makes a stored login active. Connect the login first, as below. |
openai_api_key | OpenAI API key | openaiApiKey. Leave it out to switch back to the key already stored. |
openai_codex | Codex login | None. Makes a stored login active. Connect the login first, as below. |
zai_coding_plan | GLM Coding Plan | codingPlanKey. Leave it out to switch back to the key already stored. |
moonshot_kimi_code | Kimi Code | kimiCodeKey. Leave it out to switch back to the key already stored. |
deepseek_deepseek_api | DeepSeek API | deepseekApiKey, a key from the DeepSeek Platform. Leave it out to switch back to the key already stored. |
Sensei tests a new key with one call to the provider before it keeps it. A refused key answers 400 BAD_REQUEST with the provider's reason. A DeepSeek API key with an empty balance passes the test and is stored. A key that passes is stored and becomes the active method at once. validationModel only picks the model for that test and defaults to anthropic:opus__xhigh.
curl -s -X PUT https://app.kosuke.ai/api/organizations/$WORKSPACE_ID/ai-provider \
-H "Authorization: Bearer $KOSUKE_API_KEY" \
--json '{ "operation": "openai_api_key", "openaiApiKey": "'"$OPENAI_API_KEY"'" }'
The response has the same body as the read above. Existing sandboxes that run that provider on the workspace's Credentials receive the change. A sandbox running on a member's Subscription keeps that Subscription.
In the CLI, run kosuke providers set <workspaceId> --body '{"operation":"anthropic_claude_code"}'.
Connect a Claude Code login
A Claude Code login takes two calls and one visit to Claude in a browser. Owners and admins only.
-
Start the login.
curl -s -X POST https://app.kosuke.ai/api/organizations/$WORKSPACE_ID/provider-login/claude \-H "Authorization: Bearer $KOSUKE_API_KEY"{ "data": { "url": "https://claude.com/cai/oauth/authorize?code=true&client_id=...", "loginToken": "a3f9c2...e81d" } } -
Open
urlin a browser, sign in to Claude and authorize. The page shows a code. -
Within 15 minutes, send the code with the
loginToken.codetakes the code, the code with its#statesuffix, or the whole callback URL.curl -s https://app.kosuke.ai/api/organizations/$WORKSPACE_ID/provider-login/claude/complete \-H "Authorization: Bearer $KOSUKE_API_KEY" \--json '{ "loginToken": "'"$LOGIN_TOKEN"'", "code": "'"$CODE"'" }' -
Read the answer. A refused code still answers
200. Withauthenticated: false,messagesays why. Whenrestartis alsotrue, go back to step 1. Otherwise paste the code again. -
Make the login the active method with
PUT /api/organizations/{workspaceId}/ai-providerand{ "operation": "anthropic_claude_code" }. A finished login is stored, and it stays inactive until you do.
In the CLI, run kosuke providers logins start <workspaceId> --provider claude_code, then kosuke providers logins complete <workspaceId> --login-token <token> --code <code> --provider claude_code.
Connect a Codex login
A Codex login uses a device code that you enter on OpenAI's site. Owners and admins only.
-
Start the login.
curl -s -X POST https://app.kosuke.ai/api/organizations/$WORKSPACE_ID/provider-login/codex \-H "Authorization: Bearer $KOSUKE_API_KEY"{"data": {"userCode": "WXYZ-1234","verificationUrl": "https://auth.openai.com/codex/device","intervalSeconds": 5,"loginToken": "a3f9c2...e81d"}} -
Open
verificationUrlin a browser, sign in with the ChatGPT account and enteruserCode. -
Poll every
intervalSecondswith theloginToken.curl -s https://app.kosuke.ai/api/organizations/$WORKSPACE_ID/provider-login/codex/complete \-H "Authorization: Bearer $KOSUKE_API_KEY" \--json '{ "loginToken": "'"$LOGIN_TOKEN"'" }' -
Read the answer.
{ "authenticated": false }means the code is not approved yet, so poll again.authenticated: truecomes with the accountemail.restart: truemeans the code expired or OpenAI refused it, so go back to step 1. -
Make the login the active method with
PUT /api/organizations/{workspaceId}/ai-providerand{ "operation": "openai_codex" }.
In the CLI, run kosuke providers logins start <workspaceId> --provider codex, then kosuke providers logins complete <workspaceId> --login-token <token> --provider codex.
Remove Credentials
Delete the stored key or login of one auth method. Owners and admins only. The route answers 204.
provider | authMethod values |
|---|---|
anthropic | api_key, aws_bedrock, claude_code |
openai | api_key, codex |
zai | coding_plan |
moonshot | kimi_code |
deepseek | deepseek_api |
curl -s -X DELETE "https://app.kosuke.ai/api/organizations/$WORKSPACE_ID/ai-provider?provider=openai&authMethod=api_key" \
-H "Authorization: Bearer $KOSUKE_API_KEY"
Removing the active method leaves the provider with no active method. Its activeAuthMethod reads null until you switch to another one.
In the CLI, run kosuke providers delete <workspaceId> --provider openai --auth-method api_key.
Check usage
Read how much of its limits a Claude Code login, a Codex login, a GLM Coding Plan or a Kimi Code key has used, or the balance of a DeepSeek API key. Any member can read it, whether or not the method is active.
curl -s https://app.kosuke.ai/api/organizations/$WORKSPACE_ID/ai-provider/claude-usage \
-H "Authorization: Bearer $KOSUKE_API_KEY"
{
"data": {
"session": { "utilization": 42, "resetsAt": "2026-09-30T14:00:00.000Z" },
"week": { "utilization": 18, "resetsAt": "2026-10-04T09:00:00.000Z" },
"fetchedAt": "2026-09-30T11:37:05.000Z"
}
}
session is the 5-hour window and week the 7-day window. utilization is a percentage from 0 to 100. Either window is null when the provider reports none. Kimi Code has no weekly window, so its week is always null and its monthly window is in month. Sensei keeps an answer for up to 5 minutes, so fetchedAt says how fresh it is.
| Route | Reads |
|---|---|
GET /api/organizations/{workspaceId}/ai-provider/claude-usage | The Claude Code login. |
GET /api/organizations/{workspaceId}/ai-provider/codex-usage | The Codex login. |
GET /api/organizations/{workspaceId}/ai-provider/coding-plan-usage | The GLM Coding Plan. |
GET /api/organizations/{workspaceId}/ai-provider/kimi-code-usage | The Kimi Code key. |
GET /api/organizations/{workspaceId}/ai-provider/deepseek-usage | The DeepSeek API key's balance. |
A DeepSeek API key is paid as you go and has no windows. Its session and week are null, and balance carries the key's balance instead.
{
"data": {
"session": null,
"week": null,
"balance": { "available": true, "amounts": [{ "currency": "USD", "total": "12.40" }] },
"fetchedAt": "2026-09-30T11:37:05.000Z"
}
}
balance.available is false when the balance is too low to run a turn. balance.amounts holds one entry per currency the account holds, USD or CNY, with total as a decimal string. Sensei does not add the currencies together.
In the CLI, run kosuke providers usage get <workspaceId> --provider claude_code, and codex, coding-plan, kimi-code or deepseek in place of claude.
Errors
| Status | Code | When |
|---|---|---|
| 400 | BAD_REQUEST | The provider refused the key. You left out a key and none is stored. You picked a login method before connecting the login. The validationModel has no Bedrock equivalent, or the default_model provider cannot run. The provider and authMethod pair is invalid. A usage route found no login, GLM Coding Plan, Kimi Code or DeepSeek API key, or a login that needs reconnecting. |
| 400 | VALIDATION_ERROR | The body fails the schema, such as an unknown operation or an empty code. |
| 403 | FORBIDDEN | You are not a member of the workspace, or you are a member calling a route for owners and admins. |
| 503 | SERVICE_UNAVAILABLE | OpenAI could not start a Codex login, or the provider did not return usage. Try again. |
The full list is in Responses and errors.
Next steps
- Connect your own Subscription with Account.
- Check what members can run with Workspaces.
- Read whose credentials run what on AI providers.