Reference
Token Endpoints
Technical reference for the OAuth 2.0 token, refresh, and revocation endpoints.
Token lifecycle
Token endpoint
POST /api/oauth/tokenExchanges an authorization code for an access token, or refreshes an existing token.
Authorization Code grant
| Parameter | Type | Required | Description |
|---|---|---|---|
grant_type | string | Yes | Must be authorization_code |
code | string | Yes | The authorization code from the callback |
redirect_uri | string | Yes | Must match the URI used in the authorization request |
client_id | string | Yes | Your application's client ID |
code_verifier | string | Yes | The PKCE code verifier (plain-text, 43-128 chars) |
client_secret | string | Conditional | Required for confidential clients |
Response
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 7200,
"refresh_token": "def456...",
"scope": "read courses:read students:read",
"created_at": 1710000000,
"school_id": 42,
"school_subdomain": "demo"
}| Field | Description |
|---|---|
access_token | Bearer token for API requests |
token_type | Always Bearer |
expires_in | Token lifetime in seconds (default: 7200 / 2 hours) |
refresh_token | Token to obtain a new access token |
scope | Granted scopes (may be a subset of what was requested) |
school_id | The ID of the authorized school |
school_subdomain | The subdomain of the authorized school |
Refresh Token grant
| Parameter | Type | Required | Description |
|---|---|---|---|
grant_type | string | Yes | Must be refresh_token |
refresh_token | string | Yes | A valid refresh token |
client_id | string | Yes | Your application's client ID |
client_secret | string | Conditional | Required for confidential clients |
Response
Same format as the authorization code grant response. A new refresh token may be issued — always store the latest one.
Revocation endpoint
POST /api/oauth/revokeRevokes an access token or refresh token per RFC 7009.
| Parameter | Type | Required | Description |
|---|---|---|---|
token | string | Yes | The token to revoke |
token_type_hint | string | No | access_token or refresh_token |
client_id | string | Yes | Your application's client ID |
The endpoint always returns 200 OK, even if the token was already revoked or invalid. This prevents token-guessing attacks.
Introspection endpoint
POST /api/oauth/introspectReturns metadata about a token per RFC 7662.
| Parameter | Type | Required | Description |
|---|---|---|---|
token | string | Yes | The token to introspect |
client_id | string | Yes | Your application's client ID |
Response (active token)
{
"active": true,
"scope": "read courses:read",
"client_id": "abc123",
"token_type": "Bearer",
"exp": 1710007200
}Response (inactive/invalid token)
{
"active": false
}Error responses
All token endpoints return errors in the standard OAuth 2.0 format:
{
"error": "invalid_grant",
"error_description": "The authorization code has expired or has already been used."
}| Error | HTTP Status | Description |
|---|---|---|
invalid_request | 400 | Missing or malformed parameter |
invalid_client | 401 | Client authentication failed |
invalid_grant | 400 | Code expired, already used, or verifier mismatch |
unauthorized_client | 400 | Client not authorized for this grant type |
unsupported_grant_type | 400 | Only authorization_code and refresh_token are supported |