Auth API
Authentication, token management, and password reset endpoints.
These endpoints handle user registration (via invite), login, token verification, and password recovery.
Endpoints
| Method | Path | Description | Auth Required |
|---|---|---|---|
POST | /api/auth/create-user | Create a user from an invitation | No |
POST | /api/auth/login | Login with email and password | No |
POST | /api/auth/forgot-password | Send a password-reset email | No |
POST | /api/auth/reset-password | Reset password with a reset token | No |
GET | /api/auth/verify-token | Verify the main auth token | Yes |
GET | /api/auth/verify-token-forgot | Verify a forgot-password token | No |
GET | /api/auth/verify-token-register | Verify a registration token | No |
GET | /api/auth/verify-token-invite | Verify an invitation token | No |
POST | /api/auth/refresh-token | Refresh an expired access token | No (cookie) |
POST | /api/auth/heartbeat | Report user activity | Yes |
POST /api/auth/create-user
Create a new user account from a valid invitation.
Request Body
{
"email": "john@example.com",
"password": "SecureP@ss123",
"name": "John Doe",
"invitationId": "inv_abc123def456"
}| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Email address (must match invite) |
password | string | Yes | Password (min 8 characters) |
name | string | Yes | Full name of the user |
invitationId | string | Yes | Invitation ID received via email |
Response — 201 Created
{
"success": true,
"message": "User created successfully",
"data": {
"userId": "usr_789xyz",
"email": "john@example.com",
"name": "John Doe"
}
}Error — 400 Bad Request
{
"success": false,
"message": "Invalid or expired invitation"
}POST /api/auth/login
Authenticate with email and password. Returns access and refresh tokens.
Request Body
{
"email": "john@example.com",
"password": "SecureP@ss123"
}| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Registered email address |
password | string | Yes | Account password |
Response — 200 OK
{
"success": true,
"data": {
"token": "v4.public.eyJ...",
"refreshToken": "v4.public.eyJ...",
"user": {
"id": "usr_789xyz",
"email": "john@example.com",
"name": "John Doe",
"role": "manager",
"orgId": "org_abc123"
}
}
}TIP
The refreshToken is also set as an HTTP-only cookie for the /refresh-token endpoint.
Error — 401 Unauthorized
{
"success": false,
"message": "Invalid email or password"
}POST /api/auth/forgot-password
Send a password-reset link to the given email address.
Request Body
{
"email": "john@example.com"
}| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Registered email address |
Response — 200 OK
{
"success": true,
"message": "Password reset email sent"
}Error — 404 Not Found
{
"success": false,
"message": "No account found with this email"
}POST /api/auth/reset-password
Reset a user's password using the token from the reset email.
Request Body
{
"token": "reset_token_value",
"newPassword": "NewSecureP@ss456"
}| Field | Type | Required | Description |
|---|---|---|---|
token | string | Yes | Reset token from the email link |
newPassword | string | Yes | New password (min 8 characters) |
Response — 200 OK
{
"success": true,
"message": "Password reset successfully"
}Error — 400 Bad Request
{
"success": false,
"message": "Invalid or expired reset token"
}GET /api/auth/verify-token
Verify that the caller's access token is valid.
Authentication
Authorization: Bearer <token>Response — 200 OK
{
"success": true,
"data": {
"valid": true,
"userId": "usr_789xyz",
"email": "john@example.com",
"role": "manager"
}
}Error — 401 Unauthorized
{
"success": false,
"message": "Token is invalid or expired"
}GET /api/auth/verify-token-forgot
Verify a forgot-password token is still valid before showing the reset form.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
token | string | Yes | The forgot-password token |
Response — 200 OK
{
"success": true,
"data": {
"valid": true,
"email": "john@example.com"
}
}Error — 400 Bad Request
{
"success": false,
"message": "Invalid or expired token"
}GET /api/auth/verify-token-register
Verify a registration token before showing the registration form.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
token | string | Yes | The registration token |
Response — 200 OK
{
"success": true,
"data": {
"valid": true,
"email": "john@example.com"
}
}Error — 400 Bad Request
{
"success": false,
"message": "Invalid or expired registration token"
}GET /api/auth/verify-token-invite
Verify an invitation token before displaying the accept-invite form.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
token | string | Yes | The invitation token |
Response — 200 OK
{
"success": true,
"data": {
"valid": true,
"email": "john@example.com",
"orgName": "Grand Hotel",
"role": "receptionist"
}
}Error — 400 Bad Request
{
"success": false,
"message": "Invalid or expired invitation token"
}POST /api/auth/refresh-token
Refresh an expired access token using the refresh token stored in an HTTP-only cookie.
Authentication
No Authorization header required. The refresh token is read from the refreshToken cookie set during login.
Response — 200 OK
{
"success": true,
"data": {
"token": "v4.public.eyJ..."
}
}Error — 401 Unauthorized
{
"success": false,
"message": "Refresh token is invalid or expired"
}POST /api/auth/heartbeat
Report user activity to keep the session alive and track online status.
Authentication
Authorization: Bearer <token>Request Body
{
"userid": "usr_789xyz"
}| Field | Type | Required | Description |
|---|---|---|---|
userid | string | Yes | The authenticated user's ID |
Response — 200 OK
{
"success": true,
"message": "Heartbeat received"
}Error — 401 Unauthorized
{
"success": false,
"message": "Token is invalid or expired"
}