Authentication
A route takes one of 3 credentials: none, a Supabase Auth token, or the bank’s read token. The tables on this page are generated from the API’s own route table, so they never drift.
Open routes: no credential
Section titled “Open routes: no credential”A child plays without signing in. These routes take no token:
| Route | What it does |
|---|---|
GET /api/health | Answers when the API is up. |
GET /api/v1/featured-lessons | Lists the featured lessons anyone may play. |
GET /api/v1/playground-examples/{language} | Lists the playground's authored examples in one language, with their keys. |
POST /api/v1/assignments/{id}/attempts | Starts an attempt at an assignment. |
GET /api/v1/attempts/{id} | Reads an attempt: its plan and everything asked so far. |
POST /api/v1/attempts/{id}/answers | Sends one try at the current question, or a skip. |
POST /api/v1/attempts/{id}/questions/{seq}/help | Releases the next rung of help for one question. |
PATCH /api/v1/attempts/{id} | Pauses or resumes an attempt. |
GET /api/v1/attempts/{id}/results | Reads an attempt's results in question order, mid-lesson too. |
GET /api/v1/attempts/{id}/review | Reads a finished attempt's questions again, for the child. |
An attempt route is bound by its attempt id. Whoever holds the id may read and answer that
attempt. Only the reply that starts an attempt carries its id, so keep it safe and never log it.
An unknown id, or one from another pod, is 404.
Parent routes: a Supabase Auth token
Section titled “Parent routes: a Supabase Auth token”An adult signs in to the app, and Supabase Auth runs the sign-in. However the adult signs in, the result is a Supabase session, and its access token is what these routes take:
| Route | What it does |
|---|---|
GET /api/v1/me | Reads the signed-in adult: account, pod and learners. |
POST /api/v1/accounts | Makes the account and pod on the first sign-in. |
POST /api/v1/learners | Adds a child to the caller's pod. |
POST /api/v1/attempts/{id}/claims | Attaches an anonymous attempt to a learner in the caller's pod. |
GET /api/v1/learners/{id}/attempts | Lists a learner's attempts, newest first. |
GET /api/v1/assignments/{id}/attempts | Lists one assignment's attempts the caller's pod may read: the lesson overview. |
GET /api/v1/learners/{id}/attempts/{attempt}/review | Reads a finished attempt of the caller's learner, with every try. |
Send the token as a bearer token:
curl https://app.jadwigo.pl/api/v1/me \ -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN"- The token is a JWT signed with RS256, with the audience
authenticated. - No token, or one that fails verification, is
401NotSignedIn. - A token whose
exphas passed fails verification. Refresh the session and try again. GET /api/v1/mereads the signed-in adult.- On the first sign-in there is no account yet, and the parent routes answer
409AccountMissing. CallPOST /api/v1/accountsonce. It makes the account and its pod. A repeat call returns the same records, so a double tap or a reload is safe.
Bank routes: the bank’s read token
Section titled “Bank routes: the bank’s read token”The bank section of the API reference has both routes.
The question bank is searched and read with a shared read token, not a Supabase token:
| Route | What it does |
|---|---|
POST /api/v1/question-searches | Searches the question bank: a need in, ranked questions out. |
GET /api/v1/questions/{id} | Reads one bank question's body, with its answer key. |
curl -X POST https://app.jadwigo.pl/api/v1/question-searches \ -H "Authorization: Bearer $JADWIGO_BANK_READ_TOKEN" \ -H "Content-Type: application/json" \ -d @need.jsonA question’s body carries its answer key, so it is behind the same token:
curl https://app.jadwigo.pl/api/v1/questions/$QUESTION_ID \ -H "Authorization: Bearer $JADWIGO_BANK_READ_TOKEN"- A missing, malformed or wrong token is
401Unauthorized, whatever the id. - With the token, an unknown question id is
404. - When the server cannot reach the bank, the reply is
502BankUnavailable. Try again later. - The read token is shared. It is a stopgap until each caller gets a token of its own.
No error message ever names a token.