OAuth
Endpoint reference
Every endpoint exposed by the OAuth 2.1 authorization server.
| Endpoint | Auth | Purpose |
|---|---|---|
GET /.well-known/oauth-authorization-server | Public | RFC 8414 metadata document |
GET /.well-known/jwks.json | Public | RFC 7517 public signing keys (RS256) |
GET /api/v2/oauth/authorize | Public (browser) | Authorization endpoint — validates request, issues PRT, 302s to consent |
GET /api/v2/oauth/authorize/context?prt= | User Bearer | Consent-screen data for a pending PRT |
POST /api/v2/oauth/authorize/decision | User Bearer | Record Allow/Deny, issue authorization code |
POST /api/v2/oauth/token | Client credentials | Token endpoint — all three grants |
POST /api/v2/oauth/introspect | Client credentials | RFC 7662 token introspection |
POST /api/v2/oauth/revoke | Client credentials | RFC 7009 token revocation |
GET /api/v2/oauth/consents | User Bearer | List apps the user has authorized |
DELETE /api/v2/oauth/consents/:clientId | User Bearer | Revoke consent (and the client's tokens) for one app |
POST /api/v2/admin/oauth-clients | Platform admin | Register a partner OAuth client |
Client audiences
Every OAuth client is created with an immutable audience that controls who can complete its consent flow:
TENANT — the client belongs to one customer tenant. Only users of that exact tenant can authorize it: a user from any other tenant gets user tenant does not match client tenant. This is the right choice for a partner app integrating on behalf of a single customer workspace.
PLATFORM — the client is registered at platform level and any customer tenant's users may authorize it. Platform-workspace accounts (platform admins themselves) can never complete an OAuth consent flow with either audience — platform-workspace accounts cannot complete OAuth flows — because tokens always represent a customer-tenant user. The audience is set at creation in the admin console and cannot be changed afterwards; re-register the client to switch.
POST /oauth/token
Client authentication is HTTP Basic (client_secret_basic), POST body (client_secret_post), or none for public clients using PKCE alone.
| grant_type | Required fields |
|---|---|
authorization_code | code, redirect_uri (must match /authorize exactly), code_verifier |
refresh_token | refresh_token, optional scope (may only narrow) |
client_credentials | optional scope (subset of the client's allowed scopes) |
{
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6Ii4uLiJ9...",
"token_type": "Bearer",
"expires_in": 900,
"scope": "interview:read interview:create",
"refresh_token": "8f3a1c9b7e6d4f2a..."
}Access token claims
Access tokens are RS256-signed at+jwt. Verify against /.well-known/jwks.json, matching on the kid header (two kids may be published during key rotation).
{
"iss": "https://devapi.teamcast.ai",
"sub": "usr_4471",
"aud": "teamcast-api",
"client_id": "oauth_client_9f3a1c...",
"scope": "interview:read interview:create",
"tenant_id": "tnt_8a21b6",
"jti": "6e2f...",
"iat": 1735689600,
"exp": 1735690500
}Scope catalog
| Scope | Grants |
|---|---|
interview:create | Create interviews in the account |
interview:read | View interviews in the account |
interview:approve | Approve interview plans and assessments |
interview:update | Edit interviews in the account |
candidate:read | View candidate information |
recording:read | Access interview recordings |
webhook:read | View webhook configuration |
webhook:update | Create, update, and delete webhook configuration |
OAuthClient.scopes) are the authoritative ceiling — re-checked at /authorize, /authorize/decision, and every grant. Requesting a scope outside that set fails the request rather than silently downgrading it.