These endpoints create accounts, sign users in, and handle email verification and password resets. Authentication, error shapes and rate limits are covered in the REST API overview.
Register
Create a new account. For self-serve signup, a new organization is created and named from organization_name. To join an existing organization instead, pass the invite_token from an invitation email — the account is created as a member of the inviting organization, and because the invite is bound to your email address, no separate email verification is needed.
POST /api/v1/auth/register
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | User email address |
password | string | Yes | Account password (min 8 characters) |
organization_name | string | No | Name for the new organization. Required when not using an invite. |
invite_token | string | No | Invitation token from an organization invite email |
Response:
{
"access_token": "eyJ...",
"token_type": "bearer",
"user_id": 1,
"email": "user@example.com",
"organization_id": 1,
"role": "admin",
"email_verified": false
}
Errors:
409— Email already registered.400— Invalid, expired, or already-redeemed invite, or the invite was sent to a different email address.422—organization_namemissing on a self-serve (non-invite) signup.
Login
Authenticate and receive a JWT token.
POST /api/v1/auth/login
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | User email address |
password | string | Yes | Account password |
Response: Same shape as the register response (including email_verified).
Errors:
401— Invalid credentials.
Change Password
Change the authenticated user’s password.
POST /api/v1/auth/change-password
Auth: Bearer token required.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
current_password | string | Yes | Your current password |
new_password | string | Yes | The new password |
Response:
{
"status": "ok"
}
To reset a forgotten password instead, use POST /api/v1/auth/forgot-password (body: email) to receive a reset link by email, then POST /api/v1/auth/reset-password (body: token, new_password).
Delete Account
Permanently delete the authenticated user’s account.
DELETE /api/v1/auth/account
Auth: Bearer token required.
Response:
{
"status": "account_deleted"
}
Verify Email
Confirm an email address using the token from the verification email sent at registration.
POST /api/v1/auth/verify-email
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
token | string | Yes | Verification token from the emailed link |
Response:
{
"status": "verified"
}
Errors:
400— Invalid or expired verification link.
Resend Verification Email
Request a fresh verification email. Always returns 200 regardless of whether the address exists or is already verified.
POST /api/v1/auth/resend-verification
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | User email address |
Response:
{
"status": "ok"
}
Forgot Password
Request a password-reset email. Always returns 200 regardless of whether the address exists.
POST /api/v1/auth/forgot-password
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | User email address |
Response:
{
"status": "ok"
}
Reset Password
Set a new password using the token from a password-reset email. The token is single-use: it becomes invalid once the password has been changed. Completing a reset also marks the email address as verified.
POST /api/v1/auth/reset-password
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
token | string | Yes | Reset token from the emailed link |
new_password | string | Yes | The new password (min 8 characters) |
Response:
{
"status": "ok"
}
Errors:
400— Invalid, expired, or already-used reset link.