---
title: Authentication
description: Exchange an email and password for a bearer token, and use it on every request to the Ysra API.
---

The API authenticates requests with a signed bearer token. Tokens are valid for
24 hours by default.

## Sign in

`POST`{ .post } `/auth/login`
{ .endpoint }

Exchange credentials for an access token.

### Request body

<div class="params" markdown>

`email` `string`{ .type } **required**{ .required }
:   The account's email address.

`password` `string`{ .type } **required**{ .required }
:   The account's password.

</div>

### Response

<div class="params" markdown>

`access_token` `string`{ .type }
:   The bearer token. Send it as `Authorization: Bearer <token>`.

`token_type` `string`{ .type }
:   Always `bearer`.

`user` `object`{ .type }
:   `id`, `email`, `name` and `is_admin` for the signed-in account.

</div>

=== "curl"

    ```console
    $ curl -sS "$YSRA_API_URL/auth/login" \
        -H 'content-type: application/json' \
        -d '{"email": "you@example.com", "password": "…"}'
    ```

=== "Python"

    ```python
    import httpx

    response = httpx.post(
        f"{api_url}/auth/login",
        json={"email": "you@example.com", "password": password},
    )
    response.raise_for_status()
    token = response.json()["access_token"]
    ```

=== "TypeScript"

    ```typescript
    const response = await fetch(`${apiUrl}/auth/login`, {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ email: "you@example.com", password }),
    });
    if (!response.ok) throw new Error(`Sign-in failed: ${response.status}`);
    const { access_token: token } = await response.json();
    ```

```json title="200 OK"
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…",
  "token_type": "bearer",
  "user": {
    "id": "5b0d3c1e-…",
    "email": "you@example.com",
    "name": "Ada",
    "is_admin": false
  }
}
```

### Errors

| Status | When |
|---|---|
| `401` | The email or password is wrong. |
| `422` | The body is not valid — for example, a malformed email. |

## The current account

`GET`{ .get } `/auth/me`
{ .endpoint }

Returns the account the token belongs to. Useful to validate a stored token on
startup: a `401` means sign in again.

## Keeping tokens safe

- Keep tokens on servers or in platform secure storage. A token in a mobile
  binary or a public repository is compromised.
- Treat `401` from any route as "sign in again", not as a permanent failure.
- On shared machines, `POST /auth/logout` ends the session.
