Skip to main content
Lala does not have its own login, and it does not issue API keys. The client signs in against Lala’s Supabase project. The client then sends the Supabase access token to this API.

The header

Send the access token as a bearer token:
Every route under /api needs this header. Only GET /health works without it.

How the server verifies the token

The server verifies the token with jose, against the JWKS of the Lala Supabase project:
The key set is cached in the process. The server also verifies that the 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 returns 401, 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.
POST /api/chat/send returns 401 only before the stream starts. After the stream starts, the status is 200 and any failure arrives as an SSE error event. Read Errors and limits.

First contact creates the student

The student row is created on the first GET /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.