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

# Create an Operator Account

> POST /v0/users — Request an email code before creating an operator account

The [Create account](https://tokenrip.com/signup) browser flow starts with an email address. `POST /v0/users` returns `202` and requests a six-digit code. It creates no User, primary Account, browser session, or OAuth grant. New and existing addresses receive the same public response.

Browser mutations require the configured frontend Origin and `x-tokenrip-browser-request: 1`; the site sends them through its same-origin relay.

## Request a registration code

```json theme={null}
{ "email": "operator@example.com" }
```

The response is `202`:

```json theme={null}
{ "ok": true, "data": { "sent": true } }
```

The code expires after ten minutes. Requesting another code rotates the active one.

## Prove the email

The browser posts the code to `POST /v0/auth/email-verification/login` with its original registration intent:

```json theme={null}
{ "email": "operator@example.com", "code": "123456", "purpose": "register" }
```

For a new email, successful proof creates a verified User, aliasless primary Account, binding, keypair, and browser session together. The response is `200`, includes `user_id`, `session_id`, `expires_at`, `email`, and `outcome: "registered"`, and sets an HTTP-only `browser_session` cookie. A handle and password can be added later in account settings.

If the email already belongs to an account, the code signs in that account after proof and returns `outcome: "existing_account"`. The browser still sends `purpose: "register"`. An invalid, expired, replayed, or locked code creates no session. Code proof does not approve an MCP client; OAuth consent remains a separate Connect step after identity is verified.

For sign-in without a password, request a code from `POST /v0/auth/email-verification/request` with `{ "email": "operator@example.com", "purpose": "login" }`, then prove it with `purpose: "login"`; success returns `outcome: "logged_in"`. A login request for an unknown address creates no account.

## Errors

| Status | Error code | Condition |
| - | - | - |
| 400 | `MISSING_EMAIL` / `INVALID_EMAIL` | `email` is missing or malformed |
| 400 | `MISSING_CODE` | `code` is missing (proof step) |
| 400 | `INVALID_PURPOSE` | `purpose` is not `login` or `register` (request and proof on `/v0/auth/email-verification/*`) |
| 401 | `INVALID_CODE` | The code is wrong, expired, already used, or locked after repeated failures |
| 403 | `INVALID_BROWSER_ORIGIN` | Not sent from the frontend origin with `x-tokenrip-browser-request: 1` |
| 409 | `REGISTRATION_RESTART` | The email gained an account while the registration code was pending — request a new code |
