# Players and sessions

> Every person arrives signed in as a player of your app, with an id that's only for your app. Session tokens let your server know who is asking. From the Lia developer docs: https://docs.lialabs.org/concepts/players-and-sessions

## Players

People never sign in to your app: Lia does it for them. The first time someone opens your app, Lia makes them a **player** of it. [`Lia.init()`](/reference/sdk-lifecycle#lia-init) gives you:

```json
{
  "player": { "id": "p_3f9c0a6d1b2e4f5a6b7c", "name": "amara" },
  "session": "lias_eyJhcHAiOi…",
  "exp": 1761998400000,
  "mode": "live"
}
```

- **`player.id`** is this person's id in your app. It stays the same every time they open it, on any phone. It's pseudonymous: it's only for your app, never their Lia account, and another app gets a different id for the same person. Use it as the key for everything you keep about a player.
- **`player.name`** is their Lia username, without the @. It's public and can change; Lia keeps it current each time they open your app. Show it, but don't key anything on it.

Lia never gives your app a person's email, phone number, balance or anything else about their account.

## Sessions

Your page can't prove who it is to your server: anyone can send your server a request that claims to be any player. So Lia gives your page a **session token**, signed by Lia, that your server checks with Lia.

- `Lia.init()` answers with a `session` and when it ends, `exp` (milliseconds since 1970).
- A session lasts **15 minutes**. Get a fresh one with [`Lia.session()`](/reference/sdk-lifecycle#lia-session) whenever you need it; it answers `{ session, exp }`.
- A session names your app, the player and the mode (test or live). A token from another app, from the other mode or past its end is not valid.

```js
// In your page: send a fresh session with anything your server must trust.
const { session } = await Lia.session();
await fetch("/api/claim", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ session, chargeId }),
});
```

Your server sends the token to [`POST /session/verify`](/reference/server-api#post-session-verify) with your secret key and gets back the player id:

```json
{ "valid": true, "playerId": "p_3f9c0a6d1b2e4f5a6b7c", "mode": "live", "exp": 1761998400000 }
```

> **Important** Never take a player id from the page on its word. Take it from `/session/verify`. [Verify on your server](/guides/verify-on-your-server) shows the whole pattern, including keeping your own longer session after the first check.

## Modes

Every session is in one **mode**, `test` or `live`, and so is every key. A test key only verifies test sessions and a live key only live ones. See [Test and live](/concepts/test-and-live).

## Lia's own records about a player

Some things Lia keeps per player in your app, so you don't need a server for them:

- Their **best score** and place on your [leaderboard](/guides/scores-and-saves).
- Their [**cloud storage**](/reference/sdk-scores-and-storage#lia-cloudstorage): up to 1024 keys.
- Whether they **allowed your notifications**.
- Their **charges**, **rewards** and **watched videos**, which your server can look up.
