# Getting a token, from nothing or from an existing journal

> Prove an address, get a journal made, and get a token for it.

## Getting a code

Two calls, whatever you are asking for — a fresh journal, or write access to one that already exists:

```http
POST /api/auth/codes
Content-Type: application/json

{"email": "them@example.com", "for": "signup"}
```

`for` is one of `signup` (a new journal), `write` (an agent token on a journal that exists — send `user` too), `read` (a guest cookie, browser-only) or `identity` (proves an address, authorises nothing). The answer is `202 {"status": "accepted"}` for almost every address — a mail either lands or it does not, and the response cannot say which without letting a caller enumerate addresses. Two exceptions actually answer differently: an invite-only instance answers `403 signup_not_invited` to `for: "signup"` from an address its operator has not named, and `for: "write"` to an address that neither owns the journal nor is named on any of its trips answers `403 not_authorised` — naming a `scope: {"trip": "<trip-id>"}` the address actually belongs to is the fix, not a retry.

```http
POST /api/auth/codes/redeem
Content-Type: application/json

{"email": "them@example.com", "code": "123456", "for": "signup"}
```

`for: "write"`/`"signup"` answer with the token itself, in the body — never a cookie, since an agent has no cookie jar. `for: "write"` on somebody already on one trip takes `"scope": {"trip": "<trip-id>"}` at the code request and answers a token scoped to that trip alone; leaving it out is the journal's own owner asking for the whole journal.

**A signup token creates exactly one journal, and is spent by doing so:**

```http
POST /api/v2/journals
Content-Type: application/json
Authorization: Bearer fs_signup_…

| Field | | Type |
| --- | --- | --- |
| `username` | **required** | string — permanent — never invent or illustrate one, ask |
| `title` | **required** | string — what the journal is called |
| `ownerName` | **required** | string — their real name |
| `ownerNickname` | **required** | string — what the site should call them — never derived from `ownerName` |
| `tagline` | optional | string |
| `visibility` | optional | string — `public` or `guest` — no default, ask which |
| `defaultLocale` | optional | string — the owner's own language — sets the welcome mail's |
| `locales` | optional | a list of {string} — which languages a reader may switch into; must include `defaultLocale` |
| `baseCurrency` | optional | string — **permanent** — every cost in the journal is added up in it |
| `displayCurrencies` | optional | a list of {string} |
| `units` | optional | one of `metric`, `imperial` |
| `tips` | optional | boolean |
```

**A `400 phone_required` here means the signup token has no proven phone number yet.** This server also asks for one before it will create a journal — `message` names the mode (`sms` or `whatsapp-inbound`). Prove it with `POST /api/auth/signup/phone` (the signup token, and the number) and `POST /api/auth/signup/phone/redeem` (the code), then retry this same call.

The reply carries the journal's own agent token — no second code — plus a one-time sign-in link for the person, never for you.

## If you were handed a handover code instead

An owner can copy one out of their own journal's access page: twenty minutes, single use, spent for a seven-day token of your own.

```http
POST /api/auth/{user}/handover   (owner's cookie, mints the code)
POST /api/auth/handover                (you spend it)
Authorization: Bearer fs_handover_…
```

## First, get your bearings

Before anything else, two free reads:

```http
GET /api/v2/status              — this instance: capabilities, limits, pricing. No auth.
GET /api/v2/{user}/status       — this journal and this token: drafts waiting, trips you may write to, storage, inbox counts, and whether your token is journal-wide or scoped to one trip.
```

A `401` on the second one means go and get a code. A `200` is your bearings in one call — read it before writing anything.

The full contract is generated from the schemas at /api/v2/openapi.json. The rest of this journal's guide is indexed at /documentation.txt.
