Korey supports OAuth 2.0 so third-party tools — editor extensions, scripts, CI jobs — can ask for your permission before accessing the Korey API on your behalf. No passwords are shared, and you can revoke access at any time.
How it works
The standard authorization code flow is used:
- The tool redirects you to Korey’s authorization page (
/oauth/authorize). - You review the requested scopes and click Approve.
- Korey redirects back to the tool with an authorization code.
- The tool exchanges the code for an access token (and optionally a refresh token).
- The tool calls the Korey API using the access token as a
Bearertoken.
Access tokens are short-lived. The tool uses the refresh token to obtain new access tokens automatically without asking you to approve again.
Scopes
Scopes control what a connected app can do. Korey follows a least-privilege model — tools should request only what they need.
| Scope | What it allows |
|---|---|
| threads:read | List and read all threads visible to the user, stream AI responses |
| threads:read:own | Read only threads owned by the token’s user — no access to other users’ threads |
| threads:write | Create threads, send messages, and submit feedback |
Scopes are explicit and composable — threads:write does not imply threads:read. A client that needs both must request both. For example, a client that only posts messages but never lists threads can request threads:write alone.
The /me endpoint (your profile and workspace membership) requires no scope — any valid token can call it.
Admin: OAuth client management
Org admins can view and manage all OAuth clients registered in the workspace from Settings → Organization → OAuth Clients.
The table shows each client’s name, owner, redirect URIs, and when it was last used. Admins can:
- View client details — click a row to open the detail panel showing client ID, redirect URIs, logo, and metadata.
- Rotate the client secret — invalidates the existing secret and generates a new one (confidential clients only). The new secret is shown once.
- Delete a client — permanently removes the client and revokes all associated tokens. Any integrations using that client will stop working immediately.
- Generate a registration token — issue a one-time token so an OAuth client can self-register programmatically.
Connected apps (for users)
To see which apps have been authorized and revoke any of them:
- Open Settings → Connected Apps.
- Each row shows the app name, the scopes it holds, and when it last used its token.
- Click Revoke and confirm the dialog. The app’s tokens are invalidated immediately and it will need to ask for your permission again the next time it needs access.
OAuth clients (for developers)
If you’re building an app that integrates with Korey, you need to register an OAuth client:
- Open Settings → OAuth Clients.
- Click Create client.
- Fill in the form:
- Name — shown to users on the consent screen.
- Redirect URIs — the callback URL(s) Korey will redirect to after the user approves. Must use
httpsin production;http://localhost,http://127.0.0.1, andhttp://[::1]are allowed for local development. Port is ignored when matching loopback URIs — per RFC 8252 §7.3, you can registerhttp://localhost/callbackand Korey will accept a redirect to any port on that host (e.g.http://localhost:52413/callback). This is intentional: native apps often listen on an ephemeral port that isn’t known at registration time.
- After creation, copy the Client ID and Client secret. The secret is shown once — store it securely (e.g. in a vault or environment variable).
Public clients
If your app runs in an environment where a client secret cannot be kept confidential (e.g. a native app or a browser extension), you can use a public client. Public clients have no secret and use PKCE (Proof Key for Code Exchange) instead to prove they initiated the authorization request.
Public clients are registered automatically via Dynamic Client Registration — they cannot currently be created through the Settings UI.
With PKCE, before redirecting the user your app generates a random code_verifier, computes code_challenge = BASE64URL(SHA256(code_verifier)), and includes it in the authorization request. The code_verifier is then sent at the token exchange step so Korey can verify the two requests came from the same client.
Authorization endpoint
Redirect the user to this URL to start the authorization flow. Korey will show the consent screen, and on approval redirect back to your redirect_uri with a short-lived code that you exchange for tokens. The state parameter is strongly recommended — generate a random value, store it in the user’s session, and verify it matches when Korey redirects back to prevent CSRF attacks.
GET https://api.korey.ai/oauth/authorize GET https://api.korey.ai/oauth/authorize
?response_type=code
&client_id=YOUR_CLIENT_ID
&redirect_uri=YOUR_REDIRECT_URI
&scope=threads:read%20threads:write
&state=RANDOM_NONCE
| Parameter | Required | Description |
|---|---|---|
| response_type | Yes | Must be code |
| client_id | Yes | Your registered client ID |
| redirect_uri | Yes | Must exactly match a registered redirect URI |
| scope | Yes | Space-separated list of requested scopes |
| state | Recommended | Opaque value you generate; returned unchanged to prevent CSRF |
| code_challenge | Public clients | BASE64URL(SHA256(code_verifier)) |
| code_challenge_method | Public clients | Must be S256 |
Token endpoint
Both obtaining and refreshing tokens use the same endpoint with different grant_type values.
POST https://api.korey.ai/oauth/token POST https://api.korey.ai/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=CODE_FROM_REDIRECT
&redirect_uri=YOUR_REDIRECT_URI
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET POST https://api.korey.ai/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=CODE_FROM_REDIRECT
&redirect_uri=YOUR_REDIRECT_URI
&client_id=YOUR_CLIENT_ID
&code_verifier=YOUR_CODE_VERIFIER POST https://api.korey.ai/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token
&refresh_token=YOUR_REFRESH_TOKEN
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET Both grant types return the same token payload:
{
"access_token": "kt_oauth_...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "kt_refresh_...",
"scope": "threads:read"
}
Revoking tokens
Revoke a token when a user disconnects your app, when a token is no longer needed, or if you suspect a token has been compromised. Revoking a token immediately invalidates it — any subsequent API calls using it will return 401 Unauthorized. Both access tokens and refresh tokens can be revoked; revoking a refresh token also invalidates the associated access token.
POST https://api.korey.ai/oauth/token/revoke POST https://api.korey.ai/oauth/token/revoke
Content-Type: application/x-www-form-urlencoded
token=TOKEN_TO_REVOKE
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
The endpoint always returns 200 OK regardless of whether the token existed or was already revoked — this prevents token enumeration.
Client registration
Korey supports two ways to register an OAuth client programmatically, both using the same endpoint:
POST https://api.korey.ai/oauth/register The request body is JSON and follows RFC 7591:
POST https://api.korey.ai/oauth/register
Content-Type: application/json
{
"client_name": "My App",
"redirect_uris": ["https://myapp.example.com/callback"],
"scope": "threads:read threads:write",
"token_endpoint_auth_method": "client_secret_basic",
"client_uri": "https://myapp.example.com",
"logo_uri": "https://myapp.example.com/logo.png"
}
| Field | Required | Description |
|---|---|---|
| client_name | Yes | Display name shown on the consent screen |
| redirect_uris | Yes | Array of allowed redirect URIs |
| scope | No | Space-separated scopes to request; defaults to all scopes |
| token_endpoint_auth_method | No | client_secret_basic (default) or none for public clients |
| client_uri | No | URL of the application’s homepage |
| logo_uri | No | URL of the application’s logo |
| tos_uri | No | URL of the terms of service |
| policy_uri | No | URL of the privacy policy |
On success Korey returns a 201 with the registered client including client_id and (for confidential clients) client_secret.
Open registration
If no Authorization header is provided, the client is registered without being tied to any organization. It becomes associated with the first organization whose user approves the consent screen.
Registration tokens
For tighter control, any Korey workspace member can generate a one-time registration token from Settings → OAuth Clients → Registration token → Generate token. The token is valid for 60 minutes and single-use — it can only be consumed once.
Include it as a Bearer token on the registration request:
POST https://api.korey.ai/oauth/register
Authorization: Bearer REGISTRATION_TOKEN
Content-Type: application/json
{ ... }
Using a registration token ties the new client to the generating user’s organization immediately, rather than waiting for first consent.
Dynamic Client Registration
Tools that support RFC 7591 can use the same endpoint with open registration — they discover it automatically via the OAuth metadata document at /.well-known/oauth-authorization-server and register themselves at first connection without any manual setup. MCP clients such as Cursor and Claude Code use this mechanism. See the MCP page for details.