OAuth

Integrate your app

Add 'Sign in with Teamcast' using the authorization_code grant with mandatory PKCE.

Your OAuth client must be registered by Teamcast platform staff first (POST /admin/oauth-clients), which issues a client_id (and a client_secret for confidential clients — public/browser clients get none and authenticate with PKCE alone).

1. Generate a PKCE pair and redirect

Generate a random code_verifier, derive code_challenge = BASE64URL(SHA256(code_verifier)), and send the recruiter's browser to GET /oauth/authorize. Only S256 is accepted — plain is rejected.

text
GET https://devapi.teamcast.ai/api/v2/oauth/authorize
  ?response_type=code
  &client_id=oauth_client_9f3a1c...
  &redirect_uri=https://yourapp.example.com/callback
  &scope=interview:read+interview:create
  &state=8f14e45fceea167a5a36dedd4bea2543
  &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
  &code_challenge_method=S256

2. Recruiter consents on tc-web

Teamcast validates the request, mints a short-lived signed pending-request token (PRT), and 302s the browser to tc-web's consent screen. If the recruiter isn't logged in, they authenticate first (return URL preserved); if they've already consented to these exact scopes for this client, the screen is skipped. Otherwise they see your client's name and the requested scopes, and choose Allow or Deny.

3. Receive the authorization code

On Allow, Teamcast redirects to your redirect_uri (exact-match against the registered value — no wildcards) with a single-use code.

text
https://yourapp.example.com/callback
  ?code=a1f9c2b7e6d4...
  &state=8f14e45fceea167a5a36dedd4bea2543

Verify state matches what you sent before continuing — this is your CSRF protection on the redirect.

4. Exchange the code for tokens

bash
curl -X POST https://devapi.teamcast.ai/api/v2/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d grant_type=authorization_code \
  -d client_id=oauth_client_9f3a1c... \
  -d client_secret=oauth_secret_... \
  -d code=a1f9c2b7e6d4... \
  -d redirect_uri=https://yourapp.example.com/callback \
  -d code_verifier=<the_original_code_verifier>

# → {
#     "access_token": "eyJhbGciOiJSUzI1NiIs...",
#     "token_type": "Bearer",
#     "expires_in": 900,
#     "scope": "interview:read interview:create",
#     "refresh_token": "8f3a...c2"
#   }

Public clients (mobile/SPA, no client_secret) omit client_secret and rely entirely on code_verifier — the code is bound to the original challenge, so a stolen code is useless without it.

5. Call the API, then refresh

Use the access token as a normal bearer token against any endpoint your granted scopes cover (mapped 1:1 onto Teamcast permission keys, e.g. interview:create). When it expires, rotate it:

bash
curl -X POST https://devapi.teamcast.ai/api/v2/oauth/token \
  -d grant_type=refresh_token \
  -d client_id=oauth_client_9f3a1c... \
  -d client_secret=oauth_secret_... \
  -d refresh_token=8f3a...c2
Refresh tokens rotate on every use and belong to a single-use family: reusing an already- rotated refresh token is treated as theft and revokes the entire token family. Store only the newest one, and treat a invalid_grant on refresh as a signal to restart the authorization flow.
Was this page helpful?