Account
These routes act on you, not on a workspace. Your Subscriptions, Default Model, Personal Skills and Personal Plugins follow you into every workspace you belong to. The chat sessions you are the Assignee of run on your Subscription when you hold one, whoever starts them.
| Method | Path | Description |
|---|---|---|
| POST | /api/push/devices | Register an iPhone or Apple Watch for push notifications with its hex APNs device token, the app bundle id it was issued to and its APNs environment. A token already registered moves to you. The Watch also sends its installationId and a generation it raises on every registration; one older than the registration already held for that installation answers 409. Called by the Kosuke iOS and Watch apps; answers 204. |
| DELETE | /api/push/devices | Stop push notifications to one of your devices, by its APNs device token. A token that is not yours, or not registered, is left alone; answers 204 either way. |
| DELETE | /api/user/api-keys/current | Revoke the API key this request is made with, and no other. The Apple Watch and the Meta glasses call it when they sign out. Answers 204. |
| GET | /api/user/plugins?provider= | List the plugins the Official Marketplaces offer, or one Provider's with provider=anthropic or provider=openai, with whether you have each on as a personal plugin, the last failed install in the chat sessions you are the assignee of, and the workspaces of yours that already have it on. Plugins that carry MCP servers or ChatGPT apps are not offered. Personal plugins follow you into every workspace you belong to, alongside its workspace plugins. From an agent token, those of the member it acts as, with only this workspace and, for a sandbox or a Cron Run, this project's sessions. From a Cron Run with no member behind it, none. |
| PATCH | /api/user/plugins/{pluginId} | Turn one of your personal plugins on or off by its plugin@marketplace id, as the list returns it, in every workspace at once. Chat sessions you are the assignee of install or remove it at their next turn. Answers 204. |
| GET | /api/user/profile | Read your account: id, email, name, onboarding state, default model, auto-commit setting and Reply Style. |
| GET | /api/user/skills | List your personal skills: what each SKILL.md declares, how many files the skill holds, whether it is enabled, and the workspaces where it replaces an enabled workspace skill of the same name. Personal skills follow you into every workspace you belong to and reach the chat sessions you are the assignee of. From an agent token, those of the member it acts as, naming only this workspace. From a Cron Run with no member behind it, none. |
| POST | /api/user/skills | Add a personal skill from its files. A SKILL.md is required; its frontmatter carries the kebab-case name, the description and an optional argument-hint. Text files only, 100 KiB each, 50 files and 1 MiB in all. Names are unique among your own personal skills. Answers 201 with the id of the new skill. |
| GET | /api/user/skills/{skillId} | Get one of your personal skills with every file it holds, SKILL.md included. From an agent token, one of the member it acts as. From a Cron Run with no member behind it, never one: it acts as Kosuke, which holds no personal skills. |
| PATCH | /api/user/skills/{skillId} | Enable or disable one of your personal skills, or replace every file it holds; at least one of enabled and files. The switch applies in every workspace at once. Answers 204. |
| DELETE | /api/user/skills/{skillId} | Delete one of your personal skills. Running chat sessions drop it at their next turn. |
| GET | /api/user/subscriptions | Read your Claude, Codex, GLM Coding Plan and Kimi Code subscriptions and your default model. Per provider: the login in use (connected, needsReauth, accountEmail, and maskedApiKey for a pasted plan key) and every login in the order it is used (logins). |
| PATCH | /api/user/subscriptions | Save the model new chat sessions start on, as an encoded id such as anthropic:sonnet__medium, or null to let Kosuke choose. Answers 204. |
| PUT | /api/user/subscriptions/{provider} | Add a GLM Coding Plan (zai) or Kimi Code (moonshot) key to your subscriptions: Claude and Codex connect by signing in. With loginId it replaces that key instead. The key is tested with one call before it is kept; 409 when it is already connected or you hold five. |
| DELETE | /api/user/subscriptions/{provider} | Disconnect every login of your subscription for one provider, anthropic, openai, zai or moonshot, and release the sandboxes running on it. Answers 204. |
| DELETE | /api/user/subscriptions/{provider}/logins/{loginId} | Disconnect one login of your subscription for a provider, by its id under logins. Sessions move to your next login of that provider on their next message, or off the subscription when it was the last. Answers 204. |
| PUT | /api/user/subscriptions/{provider}/logins/order | Set the order your logins of one provider are used in: the first that is neither at its limit nor needs reconnecting runs your sessions. ids must be every login of that provider, once each; 409 when they are not. Answers 204. |
| POST | /api/user/subscriptions/login/claude | Start connecting your Claude subscription: open the returned url in a browser, then pass the code it shows and loginToken to complete within 15 minutes. |
| POST | /api/user/subscriptions/login/claude/complete | Finish connecting your Claude subscription 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. |
| POST | /api/user/subscriptions/login/codex | Start connecting your Codex subscription: enter userCode at verificationUrl in a browser, then call complete with loginToken until it answers authenticated. |
| POST | /api/user/subscriptions/login/codex/complete | Poll your 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. |
| GET | /api/user/subscriptions/usage?provider=&loginId= | Read the session and weekly utilization of your Claude (claude_code, the default), Codex, GLM Coding Plan (coding_plan) or Kimi Code (kimi_code) subscription: of the login in use, or of the one loginId names. Kimi Code reports a monthly window instead of a weekly one. 400 when it is not connected or needs reconnecting. |
In the web app these settings live under Settings > Your Account.
Read your profile
Read your account and the preferences that shape your sessions.
curl -s https://app.kosuke.ai/api/user/profile \
-H "Authorization: Bearer $KOSUKE_API_KEY"
{
"data": {
"id": "u8Rk2mQ4xT7vB1nP9sL3cW6yD0fH5jZa",
"email": "sam@acme.dev",
"name": "Sam Rivera",
"imageUrl": null,
"onboardingCompleted": true,
"createdAt": "2026-05-12T09:30:00.000Z",
"marketingEmails": false,
"autoCommit": true,
"replyStyle": "standard",
"plainLanguage": false,
"defaultModel": "anthropic:opus__xhigh",
"isSuperAdmin": false
}
}
autoCommit holds the Commits preference, true for Automatic and false for Manual. replyStyle holds the Agent replies preference: not_tech, simplified or standard. plainLanguage is true when it is not_tech, and stays for callers written before replyStyle. To change your profile or preferences, use Settings > Your Account in the web app. See Your account and preferences.
In the CLI, run kosuke user profile.
Connect a Subscription
A Subscription is your own Claude Code login, Codex login, GLM Coding Plan or Kimi Code. While you hold one, the sessions you are the Assignee of run that provider on it instead of the workspace's Credentials. A session filed from a Slack Thread runs on the workspace's Credentials whoever its Assignee is, and a session the Cron Agent files does too until a member reassigns it.
Claude or Codex
The login works like the workspace one, with its own routes. Any signed-in member can call them.
- Start the login with
POST /api/user/subscriptions/login/claudeorPOST /api/user/subscriptions/login/codex. - Sign in in the browser as the Claude Code and Codex login steps on Provider credentials describe. The start responses and the browser steps are the same.
- Finish with
POST /api/user/subscriptions/login/claude/completeor pollPOST /api/user/subscriptions/login/codex/complete, passing theloginTokenfrom step 1. - Check that the answer says
authenticated: true. The login is your Subscription at once. From their next turn, the sessions you are the Assignee of run that provider on it.
A loginToken from these routes only finishes a personal login, and a workspace login's token only finishes a workspace login.
curl -s -X POST https://app.kosuke.ai/api/user/subscriptions/login/codex \
-H "Authorization: Bearer $KOSUKE_API_KEY"
In the CLI, run kosuke user subscriptions login claude start, then kosuke user subscriptions login claude complete --login-token <token> --code <code>. For Codex, use login codex start and login codex complete --login-token <token>.
GLM Coding Plan
A GLM Coding Plan connects with its API key. Send it to PUT /api/user/subscriptions/{provider} with zai as {provider}. Kosuke tests the key with one call to Z.ai, stores it, and answers 204.
| Body field | Meaning |
|---|---|
apiKey | The API key of your GLM Coding Plan. A Team Plan key works too. |
PROVIDER=zai
curl -s -X PUT https://app.kosuke.ai/api/user/subscriptions/$PROVIDER \
-H "Authorization: Bearer $KOSUKE_API_KEY" \
--json '{ "apiKey": "'"$ZAI_API_KEY"'" }'
In the CLI, run kosuke user subscriptions set-key zai --field-api-key <key>.
Kimi Code
Kimi Code connects with an API key from the Kimi Code Console. Send it to PUT /api/user/subscriptions/{provider} with moonshot as {provider}. Kosuke tests the key with one call to Moonshot AI on Kimi K3, stores it, and answers 204. A key whose membership does not include Kimi K3 is refused.
| Body field | Meaning |
|---|---|
apiKey | An API key from your Kimi Code Console. |
PROVIDER=moonshot
curl -s -X PUT https://app.kosuke.ai/api/user/subscriptions/$PROVIDER \
-H "Authorization: Bearer $KOSUKE_API_KEY" \
--json '{ "apiKey": "'"$KIMI_API_KEY"'" }'
In the CLI, run kosuke user subscriptions set-key moonshot --field-api-key <key>.
Disconnect a Subscription
DELETE /api/user/subscriptions/{provider} removes your Subscription for anthropic, openai, zai or moonshot and answers 204. From their next turn, the sessions you are the Assignee of run that provider on the workspace's Credentials.
In the CLI, run kosuke user subscriptions delete <provider>.
Check Subscription usage
Read which Subscriptions you hold and your Default Model.
curl -s https://app.kosuke.ai/api/user/subscriptions \
-H "Authorization: Bearer $KOSUKE_API_KEY"
{
"data": {
"anthropic": {
"connected": true,
"needsReauth": false,
"accountEmail": "sam@acme.dev",
"authenticatedAt": "2026-09-01T08:12:40.000Z",
"logins": [
{ "id": "5b7e2c91-3d4a-4f6b-8e1c-9a0d2f7b4c63", "label": "sam@acme.dev", "status": "in_use", "needsReauth": false, "exhaustedUntil": null, "authenticatedAt": "2026-09-01T08:12:40.000Z" }
],
"maskedApiKey": null
},
"openai": null,
"zai": null,
"moonshot": {
"connected": true,
"needsReauth": false,
"accountEmail": null,
"authenticatedAt": "2026-10-05T09:30:00.000Z",
"logins": [
{ "id": "e2a9c4f7-6b1d-4a3e-9c8f-0d5b7e2a1f94", "label": "…a91F", "status": "in_use", "needsReauth": false, "exhaustedUntil": null, "authenticatedAt": "2026-10-05T09:30:00.000Z" }
],
"maskedApiKey": "sk-kimi...a91F"
},
"defaultModel": "anthropic:opus__xhigh"
}
}
A provider is null when you hold no Subscription for it. A GLM Coding Plan or Kimi Code is named by maskedApiKey, the start and end of the key you pasted; it is null for the other two. needsReauth: true means you have to connect it again. Until you do, turns that need it stop and say which Subscription needs reconnecting.
logins lists every login of that provider in the order Kosuke uses them. Each has an id, a label (the account email, or the key's last four characters), needsReauth, exhaustedUntil and authenticatedAt. status is in_use, fallback, limit_reached or reconnect_required.
GET /api/user/subscriptions/usage reads how much of its limits one Subscription has used. Pass provider as claude_code (the default), codex, coding_plan or kimi_code.
curl -s "https://app.kosuke.ai/api/user/subscriptions/usage?provider=codex" \
-H "Authorization: Bearer $KOSUKE_API_KEY"
{
"data": {
"session": { "utilization": 12, "resetsAt": "2026-09-30T15:00:00.000Z" },
"week": { "utilization": 64, "resetsAt": "2026-10-02T00:00:00.000Z" },
"fetchedAt": "2026-09-30T11:40:22.000Z"
}
}
session is the 5-hour window and week the 7-day window, each as a percentage from 0 to 100. Kimi Code has no 7-day window: its week is null and month carries its monthly window. The other Subscriptions send no month.
In the CLI, run kosuke user subscriptions get and kosuke user subscriptions usage --provider codex.
Set your Default Model
Save the model a new chat session starts on when nobody picks one. It applies to the sessions you are the Assignee of, in every workspace.
| Body field | Meaning |
|---|---|
defaultModel | A model value from Models, such as anthropic:sonnet-5-5__medium. null uses the Workspace Default Model when you can run its Provider, and otherwise lets Kosuke choose. The web app shows null as Automatic. |
curl -s -X PATCH https://app.kosuke.ai/api/user/subscriptions \
-H "Authorization: Bearer $KOSUKE_API_KEY" \
--json '{ "defaultModel": "anthropic:sonnet-5-5__medium" }'
The route answers 204. A value outside the catalog answers 400 VALIDATION_ERROR. Kosuke saves any catalog model, including one whose provider you cannot run in some workspace. Check providers in provider access before you rely on it there.
In the CLI, run kosuke user subscriptions set-default-model --default-model anthropic:sonnet-5-5__medium.
Personal Skills
A Personal Skill is a skill only you edit. It reaches the sessions you are the Assignee of in every workspace, and it replaces a Custom Skill of the same name there. It never replaces a Factory Skill, whose name starts with kosuke:. It takes the same files and limits as a Custom Skill, described on Workspaces.
curl -s https://app.kosuke.ai/api/user/skills \
-H "Authorization: Bearer $KOSUKE_API_KEY"
{
"data": [
{
"id": "d4a8b1c6-2e7f-4f3a-8c5d-1b9e0f6a2c73",
"name": "release-notes",
"description": "Draft release notes in our team's format.",
"enabled": true,
"fileCount": 1,
"replaces": [{ "workspaceId": "YzH4k2P9sQ1mVx7bN3cR8tL5wD0fG6jA", "workspaceName": "Acme" }]
}
]
}
replaces lists the workspaces where this skill takes the place of an enabled Custom Skill of the same name. It is empty while the skill is disabled.
| Route | Body | Answers |
|---|---|---|
POST /api/user/skills | files, an array of { "path", "content" } with a SKILL.md, and optional enabled (default true) | 201 with the new id |
GET /api/user/skills/{skillId} | None | The skill with every file |
PATCH /api/user/skills/{skillId} | enabled, files or both. files replaces every file. | 204 |
DELETE /api/user/skills/{skillId} | None | 204 |
curl -s https://app.kosuke.ai/api/user/skills \
-H "Authorization: Bearer $KOSUKE_API_KEY" \
--json '{
"files": [
{
"path": "SKILL.md",
"content": "---\nname: standup\ndescription: Summarize what changed on this branch since yesterday.\n---\n\nRead the commits since yesterday and list them as three short bullets."
}
]
}'
Names are unique among your own Personal Skills. A change reaches a running session at its next turn, and switching enabled applies in every workspace at once.
In the CLI, the commands are kosuke user skills list, get, create, update and delete. Skills in general are explained on Skills.
Personal Plugins
A Personal Plugin installs in the sessions you are the Assignee of, alongside the Workspace Plugins. GET /api/user/plugins returns the same list as the workspace route on Workspaces, with the same provider filter. Each item adds workspaces, the workspaces of yours that already have that plugin on.
{
"data": [
{
"id": "code-review@claude-plugins-official",
"provider": "anthropic",
"name": "code-review",
"marketplace": "claude-plugins-official",
"description": "Automated code review for pull requests using multiple specialized agents with confidence-based scoring to filter false positives",
"category": "productivity",
"author": "Anthropic",
"version": "1.0.0",
"components": { "skills": [], "commands": ["code-review"], "agents": [], "hooks": [], "lspServers": [] },
"enabled": true,
"lastInstallFailure": null,
"workspaces": [{ "workspaceId": "YzH4k2P9sQ1mVx7bN3cR8tL5wD0fG6jA", "workspaceName": "Acme" }]
}
]
}
To turn one on or off, send { "enabled": true } or { "enabled": false } to PATCH /api/user/plugins/{pluginId}. It applies in every workspace at once and answers 204. Sessions you are the Assignee of install or remove the plugin at their next turn.
curl -s -X PATCH https://app.kosuke.ai/api/user/plugins/$PLUGIN_ID \
-H "Authorization: Bearer $KOSUKE_API_KEY" \
--json '{ "enabled": true }'
In the CLI, run kosuke user plugins list --provider anthropic and kosuke user plugins update <pluginId> --enabled (or --no-enabled). See Plugins.
Errors
| Status | Code | When |
|---|---|---|
| 400 | BAD_REQUEST | PUT .../subscriptions/{provider} named a provider other than zai or moonshot, Z.ai or Moonshot AI refused the key, the provider is unknown, or the usage route found no Subscription or one that needs reconnecting. |
| 400 | VALIDATION_ERROR | The model is not in the catalog, a skill breaks the file or frontmatter rules, or a plugin id is not plugin@marketplace. |
| 404 | NOT_FOUND | No such Personal Skill, or the Official Marketplace does not offer that plugin, because it is missing or carries an MCP server or a ChatGPT app. |
| 409 | SKILL_NAME_TAKEN | You already have a Personal Skill with that name. |
| 409 | PROVIDER_LOGIN_DUPLICATE, PROVIDER_LOGIN_LIMIT | The key is already connected, or you already hold five for that provider. |
| 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
- Find model values for your Default Model on Models.
- Store the workspace's own Credentials with Provider credentials.
- Read whose credentials run what on AI providers.