Skip to main content

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.

MethodPathDescription
POST/api/push/devicesRegister 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. Both apps send their appVersion, which decides the notification categories they are sent. Called by the Sensei iOS and Watch apps; answers 204.
DELETE/api/push/devicesStop 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/currentRevoke 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/files?folder=List a folder of your personal Files by id or path, with its breadcrumb and items, folders first. Omit folder for the root. Personal Files belong to you and no workspace, and only you see them; an agent reads those of the member it acts as.
POST/api/user/filesPut a file in your personal Files by path, creating parent folders and replacing an existing file. Send text or exactly one attachment, at most 25 MiB. ifVersion refuses a stale replace. Alternatively provide name and parentId (null for the root). onConflict=rename never replaces: a name the folder already holds is stored as the first free "name (2).ext", "name (3).ext", and the response names the file it became; it takes no ifVersion.
GET/api/user/files/{fileId}Get an item of your personal Files. Text up to 1 MiB includes body; other files include downloadUrl and expiresAt. url always opens the item in your Files.
PATCH/api/user/files/{fileId}Rename an item of your personal Files with name, move it with parentId (null for the root), or both. Name clashes and moving a folder into its descendants are refused.
DELETE/api/user/files/{fileId}Delete a file of your personal Files, or a folder and every item inside it. Agents cannot delete Files.
POST/api/user/files/foldersCreate a folder in your personal Files, with its missing parents. An existing folder is returned unchanged; a file with the same name is refused.
GET/api/user/integrationsList personal integrations, including unavailable entries marked availability: restricted with no held connections, such as Gmail or Notion, with your own connections to each: label, status and whether a Reconnect is needed. They belong to you and follow you into every workspace you belong to. Never a credential or a connected-account identifier, and only a signed-in member or their own API key can read them: an agent token, a workspace admin and every other member cannot.
DELETE/api/user/integrations/{toolkit}/connections/{connectionId}Disconnect one of your own integration connections by toolkit slug and connection id, such as gmail and the id kosuke integrations connections list personal returns: agents lose it at once, then the platform deletes the stored authorization, retrying in the background if needed. Revoking the authorization at the toolkit itself is not part of this. A connection that is not yours, or is already gone, answers 404.
GET/api/user/integrations/linkedin/connectionsList your LinkedIn browser connections, oldest first: each is one LinkedIn account Sensei may act as in its browser, in one Chrome profile of one of your Macs, with what Sensei's last check saw. account is null while it waits for Sensei to read it on the page; device.removed is true once that Mac was removed.
POST/api/user/integrations/linkedin/connectionsConnect LinkedIn in one allowed Chrome profile of one of your online Macs: creates the connection waiting for Sensei and sends Sensei the request as you, in a new Sensei thread, whose ID it answers. 404 MAC_NOT_FOUND or PROFILE_NOT_FOUND, 409 MAC_OFFLINE, DEVICE_CALL_INTERRUPTED (the connection to the Mac dropped; try again), PROFILE_OFF, or ALREADY_CONNECTED with details.connectionId.
GET/api/user/integrations/x/connectionsList your X browser connections, oldest first: each is one X account Sensei may act as in its browser, in one Chrome profile of one of your Macs, with what Sensei's last check saw. account is null while it waits for Sensei to read it on the page; device.removed is true once that Mac was removed.
POST/api/user/integrations/x/connectionsConnect X in one allowed Chrome profile of one of your online Macs: creates the connection waiting for Sensei and sends Sensei the request as you, in a new Sensei thread, whose ID it answers. 404 MAC_NOT_FOUND or PROFILE_NOT_FOUND, 409 MAC_OFFLINE, DEVICE_CALL_INTERRUPTED (the connection to the Mac dropped; try again), PROFILE_OFF, or ALREADY_CONNECTED with details.connectionId.
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 acting as the workspace, 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/profileRead your account: id, email, name, onboarding state, default model, FYI digest interval and UI language.
GET/api/user/skillsList 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 acting as the workspace, none.
POST/api/user/skillsAdd 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 acting as the workspace, never one: it acts as the system user, 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/subscriptionsRead holdsSubscription (any saved login on a pickable provider, including a limit or reconnect) and autoAvailable (Jev is configured and the Model Router qualifies at least one of your Subscriptions), plus your Claude, Codex, GLM Coding Plan, Kimi Code, DeepSeek API and Muse Code subscriptions and your default model, with defaultAuto when it is Auto. Per provider: the login in use (connected, needsReauth, accountEmail, and maskedApiKey for a pasted key) and every login, oldest first (logins). Google is in googleAccess: your Antigravity sign-in, activated when saved.
PATCH/api/user/subscriptionsSave the model new chat sessions start on, as an encoded id such as anthropic:sonnet__medium, or null to let the platform choose, kosuke-free to use Auto - Sensei free, or defaultAuto: true for personal Auto. Answers 204.
PUT/api/user/subscriptions/{provider}Save a personal GLM Coding Plan (zai), Kimi Code (moonshot), or DeepSeek API (deepseek) key after one validation call. Providers keep up to 20 keys; loginId replaces one.
DELETE/api/user/subscriptions/{provider}Disconnect all your saved access to one provider. Google disconnects your Antigravity sign-in. 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.
POST/api/user/subscriptions/{provider}/logins/recheckRe-check usage for your own Subscriptions of one provider (including SuperGrok on xai) at their limit, without waiting for their reset. Returns cleared, stillAtLimit and unreadable counts and retryAt, the earliest remaining reset, or null.
POST/api/user/subscriptions/login/antigravityStart your personal Antigravity Subscription sign-in. Poll complete with attemptId and revision until authorizationUrl is ready, then open it and paste the whole loopback return URL into complete. Saving does not select the method.
POST/api/user/subscriptions/login/antigravity/cancelCancel your pending Google sign-in. The isolated login host is removed by the cleanup worker. Saved Google methods and selection stay as they are.
POST/api/user/subscriptions/login/antigravity/completePoll your Antigravity sign-in, or submit the whole http://127.0.0.1 return URL once it is waiting. Repeating completion returns its confirmed receipt. Never pass a return URL from another attempt.
POST/api/user/subscriptions/login/claudeStart 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/completeFinish 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/codexStart 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/completePoll 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.
POST/api/user/subscriptions/login/museStart connecting your Muse Code subscription: open verificationUrl in a browser and approve userCode, then call complete with loginToken until it answers authenticated.
POST/api/user/subscriptions/login/muse/completePoll your 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.
GET/api/user/subscriptions/token-usageRead the tokens Sensei spent on your own Subscriptions, 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, with the Sensei share (Personal Crons included) beside it. Covers only work run through Sensei since recording began, from firstStartedAt; Sensei Free and workspace Credentials are not included.
GET/api/user/subscriptions/usage?fresh=&provider=&loginId=Read the session and weekly utilization of your Claude (claude_code, the default), Codex, GLM Coding Plan (coding_plan), Kimi Code (kimi_code), Muse Code (muse_code) or Antigravity (antigravity) subscription, or the balance of your DeepSeek API (deepseek_api) key: of the login in use, or of the one loginId names. Kimi Code reports a monthly window instead of a weekly one; DeepSeek reports no windows, only a balance per currency. Muse Code answers with its stored reading, from its latest turn, its sign-in, its last usage limit or a live read, while that is under 5 minutes old, and otherwise reads it live from Meta; when the live read fails it answers with the stored reading, and null before it has one. A usage-limit reading holds only the window that hit the limit, at 100%. Antigravity answers for your saved Google sign-in, whichever Google 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 token, stored on the sign-in; when the live read fails it answers with the stored reading, and null before it has one. A read never changes the selected method or a limit. SuperGrok (grok) returns each login’s stored weekly reading while under five minutes old, otherwise a live read using its saved access token; failure returns the stored reading or null. A free reading begun at least fifteen minutes after a limit may lift that unchanged mark. An xAI API key has no reading. A Gemini API key has no windows. 400 when it is not connected or needs reconnecting.
GET/api/user/subscriptions/xai/accessRead your saved Grok connection labels.
POST/api/user/subscriptions/xai/accessConnect, poll, cancel or remove your SuperGrok login. An xAI API key is a workspace connection.
GET/api/user/usage/breakdown?range=&tz=Read what used your AI work over range (7d by default, 30d or all) in calendar days of tz (an IANA time zone, UTC by default): totals and per-day counts, then rows grouped by work, repository and model, each with its Providers and busiest Chat Sessions or Sensei Threads (the top five by every count, so sort by the one you show). Counts your personal Subscription attempts and Sensei free Turns since recording began on 22 October 2026; days before it have recorded false and are never 0. turns counts every attempt; the four token counts are sums of reported counts only, never added together, with missing and inProgress counted apart. A repository or session in a workspace you no longer belong to keeps its counts but no name, title or link. Workspace Credentials and platform work are excluded. Your own sign-in or API key only; agent tokens are refused. 400 on another range or an unknown time zone.

Sensei Free models, Sources and Providers stay hidden in usage breakdowns.

In the web app these settings live under Settings > You.

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": "[email protected]",
"name": "Sam Rivera",
"imageUrl": null,
"onboardingCompleted": true,
"createdAt": "2026-05-12T09:30:00.000Z",
"marketingEmails": false,
"defaultModel": "anthropic:opus__xhigh",
"isSuperAdmin": false,
"canRedeemPromoCode": false
}
}

canRedeemPromoCode is true until you claim your one free grant, which your first workspace does. To change your profile or preferences, use Settings > You in the web app. See Your account and preferences.

In the CLI, run kosuke user profile get.

Connect a Subscription​

A Subscription is your own Claude Code login, Codex login, GLM Coding Plan, Kimi Code or DeepSeek API key. While you hold one, the sessions you are the Assignee of run that provider on it instead of the workspace's Credentials. A session the Cron Agent files runs on the workspace's Credentials until a member starts or reassigns it.

Claude or Codex​

The login works like the workspace one, with its own routes. Any signed-in member can call them.

  1. Start the login with POST /api/user/subscriptions/login/claude or POST /api/user/subscriptions/login/codex.
  2. 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.
  3. Finish with POST /api/user/subscriptions/login/claude/complete or poll POST /api/user/subscriptions/login/codex/complete, passing the loginToken from step 1.
  4. 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 providers logins start personal --provider claude_code, then kosuke providers logins complete personal --login-token <token> --code <code> --provider claude_code. For Codex, pass --provider codex to both, and complete takes no --code.

GLM Coding Plan​

A GLM Coding Plan connects with its API key. Send it to PUT /api/user/subscriptions/{provider} with zai as {provider}. Sensei tests the key with one call to Z.ai, stores it, and answers 204.

Body fieldMeaning
apiKeyThe 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 providers keys set personal 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}. Sensei 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 fieldMeaning
apiKeyAn 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 providers keys set personal moonshot --field-api-key <key>.

DeepSeek API​

A DeepSeek API key comes from the DeepSeek Platform. Send it to PUT /api/user/subscriptions/{provider} with deepseek as {provider}. Sensei tests the key with one call to DeepSeek on DeepSeek V4.1 Flash, stores it, and answers 204. A key with an empty balance is valid and is stored.

Body fieldMeaning
apiKeyAn API key from the DeepSeek Platform.
PROVIDER=deepseek
curl -s -X PUT https://app.kosuke.ai/api/user/subscriptions/$PROVIDER \
-H "Authorization: Bearer $KOSUKE_API_KEY" \
--json '{ "apiKey": "'"$DEEPSEEK_API_KEY"'" }'

In the CLI, run kosuke providers keys set personal deepseek --field-api-key <key>.

Disconnect a Subscription​

DELETE /api/user/subscriptions/{provider} removes your Subscription for anthropic, openai, zai, moonshot or deepseek 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 providers delete personal --provider <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": "[email protected]",
"authenticatedAt": "2026-09-01T08:12:40.000Z",
"logins": [
{
"id": "5b7e2c91-3d4a-4f6b-8e1c-9a0d2f7b4c63",
"label": "[email protected]",
"status": "available",
"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": "available",
"needsReauth": false,
"exhaustedUntil": null,
"authenticatedAt": "2026-10-05T09:30:00.000Z"
}
],
"maskedApiKey": "sk-kimi...a91F"
},
"deepseek": null,
"defaultModel": "anthropic:opus__xhigh"
}
}

A provider is null when you hold no Subscription for it. A GLM Coding Plan, Kimi Code or DeepSeek API key is named by maskedApiKey, the start and end of the key you pasted. It is null for a Claude Code or Codex login. 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 oldest first. Each Chat Session, Cron Run or Deploy keeps its Login Pin across Turns until a limit, reconnect requirement, removal or owner change moves it. Each has an id, a label (the account email, or the key's last four characters), needsReauth, exhaustedUntil and authenticatedAt. status is available, 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, kimi_code or deepseek_api.

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.

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. The other Subscriptions send no balance.

{
"data": {
"session": null,
"week": null,
"balance": { "available": true, "amounts": [{ "currency": "USD", "total": "12.40" }] },
"fetchedAt": "2026-09-30T11:40:22.000Z"
}
}
FieldMeaning
balance.availablefalse when the balance is too low to run a turn.
balance.amountsOne entry per currency the account holds, USD or CNY. total is a decimal string. Sensei does not add the currencies together.

A read that finds the balance available again makes a key that ran out usable at once, without its one-hour wait.

In the CLI, run kosuke providers get personal and kosuke providers usage get personal --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 fieldMeaning
defaultModelA 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 Sensei choose. The web app shows null as Default.
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. Sensei 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 providers default-model set personal --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.

RouteBodyAnswers
POST /api/user/skillsfiles, an array of { "path", "content" } with a SKILL.md, and optional enabled (default true)201 with the new id
GET /api/user/skills/{skillId}NoneThe skill with every file
PATCH /api/user/skills/{skillId}enabled, files or both. files replaces every file.204
DELETE /api/user/skills/{skillId}None204
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 skills list personal, 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 plugins list personal --provider anthropic and kosuke plugins update personal <pluginId> --enabled (or --no-enabled). See Plugins.

Errors​

StatusCodeWhen
400BAD_REQUESTPUT .../subscriptions/{provider} named a provider other than zai, moonshot or deepseek, Z.ai, Moonshot AI or DeepSeek refused the key, the provider is unknown, or the usage route found no Subscription or one that needs reconnecting.
400VALIDATION_ERRORThe model is not in the catalog, a skill breaks the file or frontmatter rules, or a plugin id is not plugin@marketplace.
404NOT_FOUNDNo 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.
409SKILL_NAME_TAKENYou already have a Personal Skill with that name.
409PROVIDER_LOGIN_DUPLICATE, PROVIDER_LOGIN_LIMITThe key is already connected, or you already hold 20 for that provider.
503SERVICE_UNAVAILABLEOpenAI 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​