2.9 KiB
Auth API
Base path: /api/v1/auth
All endpoints require Authorization: Bearer <jwt> unless noted otherwise.
Related: 02 - Authentication, 09 - Teams API
Endpoints
GET /auth/google
Initiates the Google OAuth flow. Redirects the browser to the Google consent screen.
No authentication required.
GET /auth/google/callback
OAuth callback handler. Called by Google after the user grants consent. Sets JWT tokens and redirects to the frontend.
No authentication required. Handled entirely by the backend.
POST /auth/refresh
Refreshes the access token using a valid refresh token.
Request body:
{ "refreshToken": "string" }
Response:
{
"accessToken": "string",
"refreshToken": "string"
}
POST /auth/logout
Invalidates the current refresh token. Requires authentication.
Response:
{ "message": "Logged out" }
GET /auth/me
Returns the currently authenticated user.
Response:
{
"id": "cuid",
"email": "user@example.com",
"name": "User Name",
"teamId": "cuid",
"teamRole": "EDITOR"
}
Possible teamRole values: OWNER, ADMIN, EDITOR, REVIEWER, READONLY
POST /auth/switch-team
Switch the active team context. Returns a new access token scoped to the requested team. The caller must be a member of the target team.
Request body:
{ "teamId": "cuid" }
Response:
{ "accessToken": "string" }
Replace the stored access token with the returned one. All subsequent requests will be scoped to the new team. The refresh token is unchanged.
Note: The response does not include
teamRole. The new role is encoded inside the JWT payload (teamRoleclaim). Clients that need the role without decoding the JWT must callGET /users/meafter switching teams. See the backlog for a possible improvement.
Frontend status: No UI exists for team switching. This endpoint is only reachable via direct API call. Use
GET /teams/mineto enumerate the teams available to switch to.
GET /users/me/preferences
Returns the current user's preferences as a freeform JSON object.
Response: Record<string, unknown>
PATCH /users/me/preferences
Merges new key/value pairs into the user's stored preferences. Existing keys not present in the request body are preserved.
Request body: Record<string, unknown>
Response: Updated preferences object
Notes
- Access tokens are short-lived JWTs signed with
JWT_SECRET. - Refresh tokens are stored encrypted and are invalidated on logout.
- YouTube OAuth tokens (for channel connections) are separate from user auth tokens and are AES-256 encrypted in the database using
TOKEN_ENCRYPTION_KEY. If that key changes, all channel connections must be re-authenticated. - See 06 - Authentication for the full auth flow and guard usage.