# Account creation

A tenant key creates app users under its own apps. The same operation is
available as a pure API call and as a URI-style call.

| style | path |
|---|---|
| pure API | `POST /api/v1/accounts` |
| URI style | `POST /api/v1/tenants/{tenant}/accounts` |
| URI style | `POST /api/v1/tenants/{tenant}/apps/{app}/accounts` |

Authenticate with `Authorization: Bearer gtk_...`.

## Pure API

```bash
curl -sS -X POST "$API/accounts" \
  -H "Authorization: Bearer gtk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "app": "app_1a2b3c4d5e6f7a8b",
    "username": "alice",
    "password": "a-long-password",
    "email": "alice@example.com",
    "display_name": "Alice"
  }'
```

`app` accepts an `app_key`, a numeric app id or an app name. Omit it when the
tenant owns exactly one app.

## URI style

```bash
curl -sS -X POST "$API/tenants/c_4m2x9p/accounts" \
  -H "Authorization: Bearer gtk_..." \
  -H "Content-Type: application/json" \
  -d '{"app":"app_1a2b3c4d5e6f7a8b","username":"alice","password":"a-long-password"}'

curl -sS -X POST "$API/tenants/c_4m2x9p/apps/app_1a2b3c4d5e6f7a8b/accounts" \
  -H "Authorization: Bearer gtk_..." \
  -H "Content-Type: application/json" \
  -d '{"username":"alice","password":"a-long-password"}'
```

`{tenant}` accepts a `cid` or a username. A tenant key can only name itself;
any other tenant returns 404.

## Response

```json
{
  "id": 1,
  "uid": "a_9k2m4x",
  "app_id": 1,
  "app_username": "alice",
  "email": "alice@example.com",
  "display_name": "Alice",
  "status": "active",
  "api_key_hint": "gak_abc12345",
  "created_at": 1761200000,
  "updated_at": 1761200000,
  "tenant": "c_4m2x9p",
  "app_key": "app_1a2b3c4d5e6f7a8b",
  "api_key": "gak_...",
  "warning": "Store api_key now; it is not recoverable."
}
```

## Fields

| field | required | notes |
|---|---|---|
| `app` | when the tenant has more than one app | `app_key`, numeric id or name |
| `username` | yes | 3-32 characters: letters, digits, dot, underscore or hyphen |
| `app_username` | no | alias for `username` |
| `password` | yes | at least the server minimum, 10 characters by default |
| `email` | no | |
| `display_name` | no | |

## Behaviour

- A duplicate `app_username` on the same app returns 409.
- A tenant key naming another tenant returns 404, never 403, so tenants cannot
  probe for each other.
- A tenant key cannot create a tenant account; that returns 403.
- Accounts are created on the root app of a family. A user created through a
  sub-app is found by the root app at sign-in time.
- The raw `api_key` is returned once. Only its hash is stored.

## Errors

| status | error | meaning |
|---|---|---|
| 400 | `invalid_request` | a field is missing or malformed |
| 401 | `unauthorized` | missing or invalid credential |
| 403 | `forbidden` | the credential cannot create that kind of account |
| 404 | `not_found` | the tenant or app is not in your scope |
| 409 | `conflict` | the username is already taken |

## Administrator

The service administrator can create tenant accounts and app users through the
same two styles on the internal mount. Those paths are documented in the
operator docs.
