Caret delegates identity and token issuance entirely to Supabase Auth. When a user signs in through the Caret frontend, Supabase issues a JSON Web Token (JWT) that encodes the user’s identity, expiry time, and role claims. Every Caret backend service validates that token server-side before processing a request — no session cookies, no API keys for user-facing calls. Pass the JWT as a Bearer token in theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/arrozet/caret/llms.txt
Use this file to discover all available pages before exploring further.
Authorization header on every request to the API Gateway.
How Authentication Works
User signs in via Supabase Auth
The Caret frontend uses the Supabase JS client to authenticate the user with email/password (or an OAuth provider). Supabase Auth issues a short-lived access token and a longer-lived refresh token, both stored in the browser session managed by the Supabase client.
Frontend attaches the JWT to API requests
Before making any REST call to the Caret API, the frontend reads
session.access_token from the Supabase client and attaches it to the Authorization header as a Bearer token.API Gateway validates the token
The API Gateway’s auth middleware verifies the JWT signature using
SUPABASE_JWT_SECRET. If the token is missing, malformed, or expired, the gateway returns 401 Unauthorized before the request reaches any downstream service.Obtaining a Token
Use the Supabase JS client in your frontend application to sign in and retrieve the access token. Caret uses Google OAuth as its sign-in provider:Backend services validate JWTs server-side using
SUPABASE_JWT_SECRET. The SUPABASE_ANON_KEY is for client-side Supabase calls only — it authorises the frontend to interact with Supabase directly (for example reading user_profiles) but is not the same as the JWT that you send to the Caret API Gateway.Making Authenticated Requests
Once you have the access token, include it in theAuthorization header on every call to the Caret API:
201 Created with the new document:
Token Expiry and Refresh
Supabase JWTs are short-lived. The Supabase JS client handles refresh automatically using theonAuthStateChange listener. Wire this up once in your application bootstrap to ensure tokens are always fresh before being attached to requests:
Authenticating the Collaboration WebSocket
The collaboration service runs separately from the API Gateway and does not use HTTP headers for auth. Instead, pass the JWT as atoken query parameter when opening the WebSocket connection:
The collaboration WebSocket connects directly to
ws.caret.page (or localhost:3003 locally) — it does not route through the API Gateway at api.caret.page. Ensure your firewall and CORS configuration allow the frontend origin to reach both hosts.Environment Variables
The table below lists every environment variable involved in Caret’s authentication flow, who owns it, and what it is used for.| Variable | Scope | Purpose |
|---|---|---|
SUPABASE_URL | Frontend + Backend | Base URL of your Supabase project (e.g. https://xyz.supabase.co) |
SUPABASE_ANON_KEY | Frontend only | Public anon key for client-side Supabase JS calls |
SUPABASE_JWT_SECRET | Backend services | Secret used to verify JWT signatures on incoming requests |
SUPABASE_SERVICE_ROLE_KEY | Backend services only | Privileged service-role key for server-side admin operations |
Summary
REST API
Pass the Supabase JWT as
Authorization: Bearer <token> on every call to https://api.caret.page/api/v1/.... Tokens are validated server-side by the API Gateway.Collaboration WebSocket
Pass the JWT as a query parameter:
wss://ws.caret.page/document/{doc_id}?token={jwt}. Validated by the collab service during the WebSocket handshake.