The header
Send the access token as a bearer token:/api needs this header. Only GET /health works without it.
How the server verifies the token
The server verifies the token withjose, against the JWKS of the Lala Supabase project:
aud claim is
authenticated. A token that is signed with the legacy HS256 shared secret still verifies while
SUPABASE_JWT_SECRET is set on the server. Asymmetric keys are the default, so a normal client
does not need to know this.
The sub claim is the identity. The server uses it as the student id, so id in the /api/me
response is the Supabase auth.users.id.
Nothing keys on a phone number or an email address. The provider can change without a schema
change.
Get a token in the client
The token comes from the Supabase client library, not from this API.Token expiry
A Supabase access token is short-lived. The Supabase client library refreshes it in the background. Read the token from the session immediately before each request. Do not cache the string for the lifetime of the application. If the API returns401, refresh the session once and send the request again. If the second
attempt also returns 401, sign the student out.
The 401 response
A missing header, a malformed header, an expired token, or a bad signature all produce the same response. The server does not say which one failed.First contact creates the student
The student row is created on the firstGET /api/me. The other routes load the student too, so
they also create the row. Call GET /api/me right after sign-in anyway. The response tells you
whether to show the onboarding screen.