> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lala.ist/llms.txt
> Use this file to discover all available pages before exploring further.

# Profile and onboarding

> Read the student with GET /api/me and write it with PATCH /api/profile.

The profile drives the conversation. Lala reads the profile on every turn and adapts to it. The
onboarding screen of the application writes it with `PATCH /api/profile`.

## Read the student

`GET /api/me` returns the identity and the profile. The first call creates the student row.

| Field                | Type           | Notes                                   |
| -------------------- | -------------- | --------------------------------------- |
| `id`                 | uuid           | The Supabase `auth.users.id`.           |
| `phone`              | string or null | From the token claims.                  |
| `email`              | string or null | From the token claims.                  |
| `profile`            | StudentProfile | The full profile.                       |
| `onboardingComplete` | boolean        | A copy of `profile.onboardingComplete`. |

## Write the profile

`PATCH /api/profile` is a partial update. The server writes only the fields that are present in
the body. A field that you omit keeps its value. A field that you send as `null` becomes null,
where the schema permits null.

```bash theme={null}
curl -X PATCH https://client-api.lala.ist/api/profile \
  -H "Authorization: Bearer $LALA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"examType":"YKS","field":"Sayısal","grade":"12"}'
```

The response is the full profile after the update:

```json theme={null}
{ "profile": { "name": "Zeynep", "examType": "YKS", "...": "..." } }
```

## Fields

| Field                | Type                              | Constraint                                              |
| -------------------- | --------------------------------- | ------------------------------------------------------- |
| `name`               | string                            | 1 to 120 characters.                                    |
| `examType`           | `YKS` or `LGS`                    | —                                                       |
| `field`              | `EA`, `Sayısal`, `Sözel`, or null | The YKS track. Null for LGS.                            |
| `grade`              | string                            | Maximum 32 characters. For example `"12"` or `"mezun"`. |
| `targetRanking`      | string or null                    | Free text. Maximum 120 characters.                      |
| `targetRankingNum`   | integer or null                   | 1 to 1000000.                                           |
| `dailyHours`         | integer or null                   | 1 to 16.                                                |
| `strongSubjects`     | string array                      | Maximum 16 items. Each item 1 to 64 characters.         |
| `weakSubjects`       | string array                      | Maximum 16 items. Each item 1 to 64 characters.         |
| `communicationStyle` | `informal` or `formal`            | Write only. See below.                                  |

A value outside these limits fails schema validation, and the request returns `400`.

<Warning>
  `communicationStyle` is accepted by `PATCH /api/profile`, but it is not part of the profile that
  `GET /api/me` returns. The server stores it with the conversation context, not with the profile.
  Keep the selected value in local application state if the onboarding screen must show it again.
</Warning>

<Note>
  The server trims each subject string and converts it to lower case. `"Matematik "` is stored as
  `"matematik"`. Compare in lower case when you highlight a chip in the user interface.
</Note>

## The onboarding rule

`onboardingComplete` becomes `true` when the profile holds all of these:

* a non-empty `grade`, and
* an `examType`, and
* a `field`, when `examType` is `YKS`.

For LGS, `field` stays null and is not required. The flag never returns to `false`.

Show the onboarding screen while `onboardingComplete` is `false`. The chat works before onboarding
is complete. Lala then collects the same facts in conversation instead.

## Lala also writes the profile

Lala can update the profile itself during a conversation, with an internal tool. If the student
says "aslında sayısaldayım", the profile changes without any client request.

Because of this, the profile is not client-owned state:

1. Read `GET /api/me` when the application starts and when it returns to the foreground.
2. Do not cache the profile across sessions as the source of truth.
3. Do not write back a whole profile object that you read earlier. Send only the fields that the
   student just changed.

<Warning>
  A student cannot command a profile change through the chat text. The system prompt treats a direct
  request such as "profilimi güncelle" as a manipulation attempt and refuses it. Profile edits from
  the user interface must go through `PATCH /api/profile`.
</Warning>
