# Authentication

There are three ways to prove who you are, and each is for a different job: people use the dashboard, Anki uses its sync login, and programs use API keys.

## Which one to use

| You are… | Use | Where |
| --- | --- | --- |
| A person in the dashboard | Email and password, a passkey, or GitHub; optionally two-factor | Log in page |
| Anki syncing | Your email and password, or a sync API key as the password | Anki's sync dialog |
| A script or an app | An API key, sent as a Bearer token | The REST API |

## API keys

An API key lets a program act as you without knowing your password, and it can be limited to exactly what that program needs and revoked on its own.

Create one under *API Keys & Devices* in the dashboard. Give it a name you will recognise, choose its scopes, and copy it when it is shown. **The key is shown once**; we store only a hash, so a lost key cannot be looked up, only replaced.

### Scopes

| Scope | Allows | Does not allow |
| --- | --- | --- |
| `sync` | Anki sync: the collection and its media files. | The REST API. |
| `read` | Every GET request in the REST API. | Changing anything. |
| `write` | Every request in the REST API, including reads. | Anki sync, unless the key also has sync. |

A key can carry several scopes. Give each program the fewest it needs: a dashboard that only displays decks wants `read`, not `write`.

## Sending the key

Put the key in the `Authorization` header as a Bearer token. Keep it out of URLs, which end up in logs, and out of source code.

```
# The key comes from the environment, never from the source file.
curl https://ankinize.com/api/v1/decks \
  -H "Authorization: Bearer $ANKINIZE_API_KEY"
```

### When it is refused

| Status | Code | Meaning |
| --- | --- | --- |
| 401 | `unauthorized` | The header is missing or the key is invalid, disabled, expired or revoked. |
| 403 | `forbidden` | The key is real but may not do this: the scope is too small, it only has sync, the account is suspended or its email unverified, or it is a device key. |
| 403 | `over_quota` | The account is over its storage quota. Reading and deleting still work. |

## Two-factor login and Anki

Two-factor adds a code from an authenticator app to dashboard login. Anki's sync dialog has no place for that code, so once two-factor is on, Anki signs in with a `sync` API key as its **password**, and your email as the username. Your own password stops working for syncing, which is the point.

> Backup codes
> 
> When you turn two-factor on you get ten backup codes. Each signs you in once if you lose your phone, and you can make a fresh set at any time under [Settings → Security](https://ankinize.com/dashboard/settings/security).

## Devices

When Anki signs in, Ankinize gives it its own device key, so that one device can be signed out without touching the others. Device keys appear under *Devices*, work for syncing only, and cannot be used with the REST API.

## Sensitive actions ask again

Adding or removing a passkey and deleting your account need a fresh login. If you signed in a while ago you are asked for a code first (from your authenticator, when two-factor is on). A stolen browser session therefore cannot do these things on its own.

## Destructive changes through the API

Removing a field or card template, or deleting a note type, rewrites the collection's schema and is refused unless *Allow destructive schema changes via API* is on under [API Keys & Devices](https://ankinize.com/dashboard/keys#rest-api). It is off by default; turning it on shows a warning first. Deleting decks and notes is not affected by it.
