Auth Endpoints
These endpoints handle user authentication, account management, personal access tokens (PATs), sessions, invites, and the OAuth flow for CLI/programmatic clients.
Sessions
Login
POST /api/auth/loginContent-Type: application/jsonNo authentication required. Rate-limited to 10 requests per 15 minutes per IP.
Authenticates with email and password. On success, returns the user object and sets HttpOnly session cookies for use by the web UI.
Request:
{ "email": "user@example.com", "password": "secret123"}Response: 200 OK — returns the user profile. Session cookies are set via Set-Cookie.
Errors: 401 InvalidCredentials, 429 RateLimited.
Logout
POST /api/auth/logoutClears the session cookie. Does not revoke PATs.
Response: 200 OK
Current User
GET /api/auth/meReturns the currently authenticated user (via cookie or Bearer token). Returns 401 MissingAuthentication when unauthenticated.
Signup
POST /api/auth/signupContent-Type: application/jsonNo authentication required. Only works when the server has SIGNUP_ENABLED=true. Rate-limited to 10 / 15 min.
Request:
{ "email": "user@example.com", "displayName": "Jane Doe", "password": "secret123"}Response: 202 Accepted — the account is created (or an invite is issued, depending on server policy).
Account Management
Change Password
POST /api/auth/change-passwordAuthorization: Bearer club_pat_...Content-Type: application/json{ "currentPassword": "old-secret", "newPassword": "new-secret"}On success, all existing sessions for the user are revoked.
Response: 200 OK
Update Profile
PATCH /api/auth/profileAuthorization: Bearer club_pat_...Content-Type: application/json{ "displayName": "Jane D." }Response: 200 OK — returns the updated user.
Upload Avatar
POST /api/auth/avatarAuthorization: Bearer club_pat_...Content-Type: multipart/form-dataUpload an avatar image as a multipart form. Response: 200 OK with the updated user.
Delete Avatar
DELETE /api/auth/avatarAuthorization: Bearer club_pat_...Fetch a User’s Avatar (public)
GET /api/users/<userId>/avatarReturns the image bytes, or 404 NotFound if the user has no avatar.
Invites
When an admin creates a user with mode: "invite", the user receives an invite URL containing a token.
Inspect an Invite
GET /api/invites/<token>No authentication required. Rate-limited to 10 / 15 min.
Returns the invite’s target email and expiry.
Accept an Invite
POST /api/invites/<token>/acceptContent-Type: application/jsonNo authentication required. Rate-limited to 10 / 15 min.
{ "displayName": "Jane Doe", "password": "new-secret"}Response: 200 OK — returns the newly-activated user and establishes a session.
Personal Access Tokens (PATs)
PATs have the prefix club_pat_ and are passed via Authorization: Bearer. The secret is returned once at creation and cannot be retrieved again.
Create a PAT
POST /api/auth/keysAuthorization: Bearer club_pat_...Content-Type: application/json{ "name": "CI/CD Deploy Token", "scopes": ["read", "write"], "expiresInDays": 365}| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Human-readable label |
scopes | string[] | yes | Any subset of read, write, admin; clamped to the caller’s role |
expiresInDays | integer | no | Defaults to the server’s configured expiry |
Response: 201 Created
{ "id": "key_a1b2c3d4", "name": "CI/CD Deploy Token", "secret": "club_pat_x9y8z7w6v5u4t3s2r1q0p9o8n7m6l5k4", "prefix": "club_pat_x9", "scopes": ["read", "write"], "createdAt": "2026-04-09T10:00:00.000Z", "expiresAt": "2027-04-09T10:00:00.000Z"}List PATs
GET /api/auth/keysAuthorization: Bearer club_pat_...Returns all PATs for the caller (without secrets).
Revoke a PAT
DELETE /api/auth/keys/<id>Authorization: Bearer club_pat_...Response: 200 OK.
Sessions
Session records are created on web login.
List Active Sessions
GET /api/auth/sessionsAuthorization: Bearer club_pat_...Revoke a Session
DELETE /api/auth/sessions/<id>Authorization: Bearer club_pat_...Revoke All Other Sessions
POST /api/auth/sessions/revoke-othersAuthorization: Bearer club_pat_...Revokes every session except the one making the call.
OAuth Flow (CLI)
The club CLI acquires a PAT via an OAuth 2.0 authorization-code flow with PKCE. The resulting access_token is a regular PAT and is used in subsequent API calls.
1. Authorize
GET /oauth/authorize ?response_type=code &client_id=cli &redirect_uri=<callback> &code_challenge=<S256 challenge> &code_challenge_method=S256 &state=<random> &scope=read,writeIf unauthenticated, the server redirects the browser to the login page. Once authenticated, it redirects to /oauth/consent?request_id=<id>.
2. Consent (web-only)
GET /oauth/pending/<requestId>Returns the pending authorization’s details for the consent UI. Requires a session cookie.
POST /oauth/approveContent-Type: application/json
{ "request_id": "<id>" }Response: 200 OK
{ "redirect_url": "<redirect_uri>?code=<code>&state=<state>" }3. Token Exchange
POST /oauth/tokenContent-Type: application/x-www-form-urlencodedAccepts either form-encoded or JSON bodies:
grant_type=authorization_codecode=<code>redirect_uri=<same as authorize>code_verifier=<PKCE verifier>Response: 200 OK
{ "access_token": "club_pat_...", "token_type": "Bearer", "scope": "read,write", "email": "user@example.com"}The access_token is a PAT and can be used for any subsequent API call.