Everything else in this API acts as a propfirm. These endpoints act as a person:
they are what Propper Mail and the other apps use, and what a script would use to
do something on your own behalf rather than on your firm's.

The difference is not cosmetic. An API key belongs to an organisation and does
whatever its scopes allow. A user token belongs to somebody, and what it can do
is the narrower of two things: the scopes on the token, and the permissions that
person has in the environment. Widening the token never widens the person.

## The credential

```
ptat_9f2c1a44_3b8e7d2f5c9a1b4e6d8f0a2c4e6b8d1f
     ^public id  ^secret (shown once, at sign-in)
```

Sent the same way as a key:

```
Authorization: Bearer ptat_9f2c1a44_3b8e7d2f5c9a1b4e6d8f0a2c4e6b8d1f
```

One token per device. Signing in on a second phone does not disturb the first,
and either can be signed out on its own from [Sessions](/docs/api/apps/sessions).

## Three steps to a token

1. [Resolve the environment](/docs/api/apps/workspace). An email address does not
   identify an account on its own, because addresses are unique per propfirm
   rather than across the platform. Ask for the address of the environment first,
   the way a chat app asks which workspace you are joining.
2. [Sign in](/docs/api/apps/sign-in) with that environment, an email address and a
   password. You get a token, or a challenge.
3. [Answer the challenge](/docs/api/apps/two-factor) with a code when the account
   has two-factor authentication.

## Scopes a person can hold

| Scope                 | Allows                                                       |
| --------------------- | ------------------------------------------------------------ |
| `me:read`             | Read your own profile, and list your signed-in devices       |
| `me:write`            | Sign another device out. Also grants `me:read`               |
| `mail:read`           | Read the mailboxes you have access to                        |
| `mail:write`          | Send and file mail. Also grants `mail:read`                  |
| `calendar:read`       | Read the calendars you have access to                        |
| `calendar:write`      | Make and change appointments. Also grants `calendar:read`    |
| `notifications:read`  | Read your notifications                                      |
| `notifications:write` | Mark notifications as read. Also grants `notifications:read` |
| `devices:write`       | Register this device for push notifications                  |

Ask for what your client actually uses. Anything else in the list is dropped
rather than refused, so a client that asks for a scope no person may hold still
signs in and simply does not get it.

The propfirm scopes (`affiliates:*`, `payouts:*`, and the rest) can never be
granted to a person's device. Those belong to an API key.

What `mail:read` opens is described in [Reading mail](/docs/api/mail/overview),
and `calendar:read` in [The calendar](/docs/api/calendar/overview).
`notifications:read` opens [the notification centre](/docs/api/apps/notifications),
and `me:read` also signs an app onto
[a websocket channel](/docs/api/apps/realtime).

## What ends a token

- Signing out on the device, or signing it out from another one.
- Changing the account password, which ends every device except the one that
  changed it.
- Ninety days without a single request.
- The account being deactivated, or losing access to the environment.

A token that has ended answers `401` with `revoked_token` or `expired_token`.
Both mean the same thing to a client: send the person back to the sign-in screen.

## Two-factor

An account with two-factor authentication has to answer a challenge before it
gets a token. Codes from an authenticator app and recovery codes both work.

An account whose only method is a passkey cannot sign in from an app yet, and
says so with `two_factor_method_unavailable` instead of failing at the code step.
Add an authenticator app on the web and try again.