OAuth 2.0

Connected apps

Let a third-party app act on behalf of a Telos user without handling their password or an API key. Standard authorization-code flow with PKCE; access tokens start telos_oat_and authenticate the REST API and MCP exactly like a personal key — the difference is the token's permissions are its granted scopes, nothing more.

Step 1

Authorization code + PKCE

Send the user to the authorize screen. An org admin reviews the requested scopes and approves; Telos redirects back to your redirect_uri with a one-time code and your state. PKCE (S256) is required for public clients and recommended for all.

GET /oauth/authorize
https://www.telos-app.com/oauth/authorize
  ?client_id=app_…
  &redirect_uri=https://your-app.example.com/callback
  &response_type=code
  &scope=opportunity:read%20task:read%20insight:create
  &state=<opaque-csrf-token>
  &code_challenge=<base64url-sha256(verifier)>
  &code_challenge_method=S256
Step 2

Exchange the code for a token

Exchange the code at the token endpoint. Public clients prove possession with the PKCE code_verifier; confidential clients send their client_secret. The endpoint speaks RFC 6749 form-encoding and returns RFC 6749 shapes — not the /api/v1 envelope.

POST /api/oauth/token
curl -X POST 'https://www.telos-app.com/api/oauth/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d grant_type=authorization_code \
  -d client_id=app_… \
  -d code=<authorization-code> \
  -d redirect_uri=https://your-app.example.com/callback \
  -d code_verifier=<pkce-verifier>          # public clients
  # -d client_secret=<secret>               # confidential clients
response
{
  "access_token": "telos_oat_…",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "…"
}
Step 3

Refresh

Access tokens are short-lived (expires_in seconds). Trade the refresh token for a new pair; refresh tokens rotate on use, so store the latest one each time.

POST /api/oauth/token
curl -X POST 'https://www.telos-app.com/api/oauth/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d grant_type=refresh_token \
  -d client_id=app_… \
  -d refresh_token=<refresh-token>
Setup

Registering an app

Apps are registered in-product under Configurations → Connected accounts by an org admin (the oauth_app:manage capability). You set the app name, one or more redirect_uris, the allowed scopes, and the client type: confidential (server-side, issued a secret you can rotate) or public(SPA/native, PKCE only, no secret). A granted token can never exceed the app's allowed scopes, and is re-intersected with the granting user's live permissions on every call — if that user is demoted or deactivated, the token shrinks or dies with them.

Reference

Scopes

Scopes are capability strings of the form resource:action. A token's scopes are its entire permission set. The full vocabulary (96 capabilities) is below; the ones marked admin can never be granted to an app or API key, only held by a signed-in user.

api_key
  • api_key:read
  • api_key:manageadmin
comment
  • comment:read
  • comment:create
  • comment:update
  • comment:delete
compensation
  • compensation:read
  • compensation:update
cost
  • cost:read
  • cost:update
customer
  • customer:read
  • customer:create
  • customer:update
  • customer:delete
file
  • file:read
  • file:manage
insight
  • insight:read
  • insight:create
  • insight:update
  • insight:delete
intake
  • intake:read
  • intake:create
  • intake:update
  • intake:delete
integration
  • integration:read
  • integration:manageadmin
llm_config
  • llm_config:read
  • llm_config:update
message
  • message:read
  • message:create
  • message:update
  • message:delete
metric
  • metric:read
  • metric:create
  • metric:update
  • metric:delete
oauth_app
  • oauth_app:read
  • oauth_app:manageadmin
objective
  • objective:read
  • objective:create
  • objective:update
  • objective:delete
opportunity
  • opportunity:read
  • opportunity:create
  • opportunity:update
  • opportunity:delete
org
  • org:manageadmin
prd_template
  • prd_template:read
  • prd_template:create
  • prd_template:update
  • prd_template:delete
role
  • role:read
  • role:manageadmin
room
  • room:read
  • room:create
  • room:update
  • room:delete
strategy
  • strategy:read
  • strategy:create
  • strategy:update
  • strategy:delete
tag
  • tag:read
  • tag:create
  • tag:update
  • tag:delete
task
  • task:read
  • task:create
  • task:update
  • task:delete
team
  • team:read
  • team:create
  • team:update
  • team:delete
time_entry
  • time_entry:read
  • time_entry:create
  • time_entry:update
  • time_entry:delete
  • time_entry:read_others
user
  • user:read
  • user:update
vision
  • vision:read
  • vision:create
  • vision:update
  • vision:delete
webhook
  • webhook:read
  • webhook:create
  • webhook:update
  • webhook:delete
workflow
  • workflow:read
  • workflow:create
  • workflow:update
  • workflow:delete
workflow_category
  • workflow_category:read
  • workflow_category:create
  • workflow_category:update
  • workflow_category:delete