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

# Authentication

> How to get a token, how long it lives, and what to do when it expires.

The API accepts JWT. You get a pair of tokens with the email and password of your AiGenda account and send `access` with every request.

## Get a token

```bash theme={null}
curl -X POST https://api.aigenda.tech/api/token/ \
  -H "Content-Type: application/json" \
  -d '{"username": "you@example.com", "password": "your-password"}'
```

```json Response 200 theme={null}
{
  "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCJ9.signature",
  "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIn0.signature"
}
```

The field is called `username`, but it holds your email.

## Send the token

Add this header to every request except getting and refreshing a token:

```http theme={null}
Authorization: Bearer <access>
```

## Token lifetime

| Token | Lifetime | How to renew |
| - | - | - |
| `access` | 30 days | Sign in again with email and password, or use `refresh` |
| `refresh` | 1 day | Only by signing in again |

[Refreshing](/en/api-reference/auth/refresh) with `refresh` returns a new `access` but does not issue a new `refresh`. One day after sign-in you can no longer refresh, so the simplest approach is:

1. Store `access` and its expiration time. It is in the `exp` field inside the token (Unix time in seconds).
2. When less than a day is left before `exp`, or the API responds with `401`, get a new pair with email and password.
3. Retry the original request once with the new token.

```python Token expiration theme={null}
import base64, json

def token_expires_at(access: str) -> int:
    payload = access.split(".")[1]
    payload += "=" * (-len(payload) % 4)
    return json.loads(base64.urlsafe_b64decode(payload))["exp"]
```

## Errors

| Response | Body | What to do |
| - | - | - |
| `401` on sign-in | `{"detail": "No active account found with the given credentials"}` | Check the email and password |
| `401` | `{"detail": "Authentication credentials were not provided."}` | Add the `Authorization` header |
| `401` | `{"detail": "Given token not valid for any token type", "code": "token_not_valid", ...}` | The token has expired or is corrupted: sign in again |

<Warning>
  Do not store the password in code or in the repository. Pass it through environment variables or your platform's secret store.
</Warning>

<Note>
  Do you sign in to the cabinet with Google? Such an account may have no password. Set one on the [password recovery](https://personal.aigenda.tech/ru/recovery-password) page, and API sign-in will work.
</Note>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.