API Reference · Auth
User Guide
Developer
Auth: three routes, one token
Accounts are email + password. Registering or logging in returns a JWT valid for 7 days; send it as a Bearer token to every account-surface route. Passwords are hashed with bcrypt (10 rounds).
/auth/registerNo authCreates an account and signs it in immediately. Email is trimmed and lowercased.
| Field | Type | Description |
|---|---|---|
| email* | string | Valid email shape, max 320 chars. |
| password* | string | 8–128 characters. No strength rules beyond length. |
| name* | string | Display name, 1–120 characters. |
curl -X POST http://localhost/api/auth/register \
-H "Content-Type: application/json" \
-d '{"email":"dev@example.com","password":"s3cure-passphrase","name":"Dev"}'{
"user": {
"id": "cml4k9x2b0000jq8f3h5a1d2e",
"email": "dev@example.com",
"name": "Dev",
"createdAt": "2026-08-06T10:15:30.000Z"
},
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…"
}| Field | Type | Description |
|---|---|---|
| 400 | ApiError | Body failed schema validation (missing field, bad email, password out of range, unknown field). |
| 409 | ApiError | “An account with this email already exists.” |
/auth/loginNo authExchanges credentials for a fresh JWT. Email matching is case-insensitive.
| Field | Type | Description |
|---|---|---|
| email* | string | Registered email. |
| password* | string | Account password. |
curl -X POST http://localhost/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"dev@example.com","password":"s3cure-passphrase"}'{
"user": { "id": "cml4k9x2b0000jq8f3h5a1d2e", "email": "dev@example.com", … },
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…"
}| Field | Type | Description |
|---|---|---|
| 401 | ApiError | “Invalid email or password.” — deliberately identical for unknown emails and wrong passwords. |
/auth/meJWT BearerReturns the account behind a token. Useful as a session check.
curl http://localhost/api/auth/me \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…"{
"user": {
"id": "cml4k9x2b0000jq8f3h5a1d2e",
"email": "dev@example.com",
"name": "Dev",
"createdAt": "2026-08-06T10:15:30.000Z"
}
}| Field | Type | Description |
|---|---|---|
| 401 | ApiError | Missing, malformed, or expired token — or the account no longer exists. |
The JWT contract
Tokens are signed with the api's JWT_SECRET and expire 7 days after issue. The payload is exactly { "sub": "<user id>", "email": "<email>" } plus the standard iat/exp claims. There is no refresh-token flow yet — when a token expires, log in again. The web app stores the token in localStorage; your client should treat it as a bearer secret and never log it.