Users - Profile & Settings
Base path: /api/v1/users
User endpoints allow customers and owners to manage their profiles, update credentials, and preferences.
POST /api/v1/users/email/otp — Send Email Update OTP
Auth: Protected (Authorization: Bearer <accessToken>)
Used by: owner-booki-web-app, customer-booki-web-app · Role: owner, branch-manager, customer
organizationId: From JWT token (not required in request body)
Description: Send a 6-digit OTP to verify email change.
Request
{
"email": "newemail@example.com"
}
Fields:
email(string, required): New email address to send OTP to
Note:
organizationIdis read from the user's JWT token server-side.
Response (200 OK)
{
"message": "Update email OTP sent successfully. Kindly check your email for the OTP."
}
Error Responses
401 Unauthorized — No valid token:
{
"statusCode": 401,
"message": "Access token is required to proceed."
}
cURL Example
curl -X POST http://localhost:4001/api/v1/users/email/otp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGc..." \
-d '{
"email": "newemail@example.com"
}'
POST /api/v1/users/email/otp/:otp/verify — Verify Email Update OTP
Auth: Protected (Authorization: Bearer <accessToken>)
Used by: owner-booki-web-app, customer-booki-web-app · Role: owner, branch-manager, customer
Description: Verify OTP and update email (OTP valid for 10 minutes). The OTP is passed as a URL parameter.
Request
POST /api/v1/users/email/otp/123456/verify
No request body required. The OTP is read from the URL path, and the user identity is derived from the JWT token.
Response (200 OK)
{
"message": "Update email OTP verified successfully."
}
Error Responses
400 Bad Request — Invalid or expired OTP:
{
"statusCode": 400,
"message": "Invalid or expired OTP"
}
cURL Example
curl -X POST "http://localhost:4001/api/v1/users/email/otp/123456/verify" \
-H "Authorization: Bearer eyJhbGc..."
GET /api/v1/users/id/:id — Get User by ID
Auth: Protected (Authorization: Bearer <accessToken>)
Used by: owner-booki-web-app · Role: owner, branch-manager
organizationId: From JWT token
Description: Retrieve a specific user by ID.
Request
GET /api/v1/users/id/507f1f77bcf86cd799439011
Response (200 OK)
{
"_id": "507f1f77bcf86cd799439011",
"email": "jane@example.com",
"firstName": "Jane",
"lastName": "Doe",
"phone": "09171234567",
"userType": "owner",
"organizationId": "507f191e810c19729de860ea",
"status": "active",
"preferredPaymentMethod": "maya",
"createdAt": "2026-03-15T10:30:00Z"
}
cURL Example
curl -X GET http://localhost:4001/api/v1/users/id/507f1f77bcf86cd799439011 \
-H "Authorization: Bearer eyJhbGc..."
GET /api/v1/users/email/:email — Get User by Email
Auth: Protected (Authorization: Bearer <accessToken>)
Used by: owner-booki-web-app · Role: owner, branch-manager
organizationId: From JWT token
Description: Retrieve a user by email address (admin/owner context).
Request
GET /api/v1/users/email/jane@example.com
Response (200 OK)
Same as above.
cURL Example
curl -X GET http://localhost:4001/api/v1/users/email/jane@example.com \
-H "Authorization: Bearer eyJhbGc..."
GET /api/v1/users/payment-preference — Get Payment Preference
Auth: Protected (Authorization: Bearer <accessToken>)
Used by: owner-booki-web-app, customer-booki-web-app · Role: owner, customer
organizationId: From JWT token
Description: Get the user's preferred payment method for bookings.
Response (200 OK)
{
"user": {
"_id": "507f1f77bcf86cd799439011",
"preferredPaymentMethod": "maya"
}
}
cURL Example
curl -X GET http://localhost:4001/api/v1/users/payment-preference \
-H "Authorization: Bearer eyJhbGc..."
GET /api/v1/users — List Users (Admin Only)
Auth: Protected (Authorization: Bearer <accessToken>) · admin only
Used by: admin-booki-web-app · Role: admin
organizationId: Not applicable (admin sees all users)
Description: List all users (super-admin endpoint).
Request
Query Parameters (optional):
page(number, default: 1)limit(number, default: 10, max: 100)search(string): Search by name or emailsort(string, default:_id)order(string, default:desc)
GET /api/v1/users?page=1&limit=20&search=jane
Response (200 OK)
{
"items": [
{
"_id": "507f1f77bcf86cd799439011",
"email": "jane@example.com",
"firstName": "Jane",
"lastName": "Doe",
"userType": "owner",
"status": "active",
"createdAt": "2026-03-15T10:30:00Z"
}
],
"pages": 1,
"pageRange": "1-1"
}
cURL Example
curl -X GET "http://localhost:4001/api/v1/users?page=1&limit=20" \
-H "Authorization: Bearer ADMIN_TOKEN"
PUT /api/v1/users/name — Update Display Name
Auth: Protected (Authorization: Bearer <accessToken>)
Used by: owner-booki-web-app, customer-booki-web-app · Role: owner, branch-manager, customer
organizationId: From JWT token (not required in request body)
Description: Update user's first, middle, or last name (at least one required).
Request
{
"firstName": "Janet",
"lastName": "Smith"
}
Fields (at least one of the following required):
firstName(string, optional): First name (max 255)middleName(string, optional): Middle name (max 255)lastName(string, optional): Last name (max 255)
Note:
idis injected from the JWT token server-side.
Response (200 OK)
{
"message": "Name updated successfully."
}
cURL Example
curl -X PUT http://localhost:4001/api/v1/users/name \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGc..." \
-d '{
"firstName": "Janet",
"lastName": "Smith"
}'
PUT /api/v1/users/:id/password — Update Password
Auth: Protected (Authorization: Bearer <accessToken>)
Used by: owner-booki-web-app, customer-booki-web-app · Role: owner, branch-manager, customer
organizationId: From JWT token
Description: Change user password (requires strong password).
Request
PUT /api/v1/users/507f1f77bcf86cd799439011/password
Body:
{
"password": "NewSecureP@ss123"
}
Fields:
password(string, required): New password (min 8 chars, must include uppercase, lowercase, number, and special character)
Note:
idis read from the URL path parameter.
Response (200 OK)
{
"message": "Password updated successfully."
}
Error Responses
422 Unprocessable Entity — Weak password:
{
"statusCode": 422,
"message": "Password must contain at least one uppercase letter, one lowercase letter, one number, and one special character."
}
cURL Example
curl -X PUT http://localhost:4001/api/v1/users/507f1f77bcf86cd799439011/password \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGc..." \
-d '{
"password": "NewSecureP@ss123"
}'
PUT /api/v1/users/payment-preference — Update Payment Preference
Auth: Protected (Authorization: Bearer <accessToken>)
Used by: owner-booki-web-app, customer-booki-web-app · Role: owner, customer
organizationId: From JWT token
Description: Set the user's preferred payment method for bookings.
Request
{
"preferredPaymentMethod": "cash"
}
Fields:
preferredPaymentMethod(string, required):cashormaya
Note:
idis injected from the JWT token server-side.
Response (200 OK)
{
"message": "Payment method preference updated successfully."
}
cURL Example
curl -X PUT http://localhost:4001/api/v1/users/payment-preference \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGc..." \
-d '{
"preferredPaymentMethod": "cash"
}'
DELETE /api/v1/users/:id — Delete User (Admin Only)
Auth: Protected (Authorization: Bearer <accessToken>)
Used by: admin-booki-web-app · Role: any authenticated user
organizationId: Not applicable
Description: Soft-delete a user account.
Request
DELETE /api/v1/users/507f1f77bcf86cd799439011
Response (200 OK)
{
"message": "User deleted successfully."
}
Error Responses
404 Not Found — User not found:
{
"statusCode": 404,
"message": "User not found"
}
cURL Example
curl -X DELETE http://localhost:4001/api/v1/users/507f1f77bcf86cd799439011 \
-H "Authorization: Bearer ADMIN_TOKEN"
GET /api/v1/subscription/my-payments — Get My Subscription Payment History
Auth: Protected (Authorization: Bearer <accessToken>)
Used by: owner-booki-web-app · Role: owner
organizationId: From JWT token
Description: Retrieve the subscription payment history for the current owner.
Response (200 OK)
{
"items": [
{
"_id": "507f1f77bcf86cd799439091",
"organizationId": "507f191e810c19729de860ea",
"amount": 999.0,
"status": "paid",
"paidAt": "2026-04-01T10:00:00Z",
"planName": "Pro Monthly"
}
],
"total": 10,
"page": 1,
"pages": 1
}
cURL Example
curl -X GET http://localhost:4001/api/v1/subscription/my-payments \
-H "Authorization: Bearer eyJhbGc..."
GET /api/v1/subscription/payments/:id — Get Subscription Payment by ID
Auth: Protected (Authorization: Bearer <accessToken>)
Used by: owner-booki-web-app · Role: owner
organizationId: From JWT token
Description: Retrieve a specific subscription payment by ID.
cURL Example
curl -X GET http://localhost:4001/api/v1/subscription/payments/507f1f77bcf86cd799439091 \
-H "Authorization: Bearer eyJhbGc..."
POST /api/v1/users/payment-methods/setup — Setup Customer Payment Method
Auth: Protected (Authorization: Bearer <accessToken>) · customer only
Used by: customer-booki-web-app · Role: customer
organizationId: From JWT token
Description: Initiate payment method setup for the authenticated customer. No request body required — the user identity is derived from the JWT token.
Response (200 OK)
{
"paymentMethod": {
"_id": "507f1f77bcf86cd799439099",
"userId": "507f1f77bcf86cd799439011",
"type": "maya",
"last4": "1234",
"createdAt": "2026-04-01T10:00:00Z"
},
"message": "Payment method saved successfully"
}
cURL Example
curl -X POST http://localhost:4001/api/v1/users/payment-methods/setup \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGc..." \
-d '{"paymentToken": "tok_live_abc123...", "type": "maya"}'
GET /api/v1/users/payment-methods — List Customer Payment Methods
Auth: Protected (Authorization: Bearer <accessToken>) · customer only
Used by: customer-booki-web-app · Role: customer
organizationId: From JWT token
Description: List all saved payment methods for the current customer.
Response (200 OK)
{
"items": [
{
"_id": "507f1f77bcf86cd799439099",
"type": "maya",
"last4": "1234",
"createdAt": "2026-04-01T10:00:00Z"
}
]
}
cURL Example
curl -X GET http://localhost:4001/api/v1/users/payment-methods \
-H "Authorization: Bearer eyJhbGc..."
DELETE /api/v1/users/payment-methods/:paymentMethodId — Delete Customer Payment Method
Auth: Protected (Authorization: Bearer <accessToken>) · customer only
Used by: customer-booki-web-app · Role: customer
organizationId: From JWT token
Description: Remove a saved payment method.
Response (200 OK)
{
"message": "Payment method removed"
}
cURL Example
curl -X DELETE http://localhost:4001/api/v1/users/payment-methods/507f1f77bcf86cd799439099 \
-H "Authorization: Bearer eyJhbGc..."
User Types
| Type | Role | Access |
|---|---|---|
owner | Business owner | Full organization control |
branch-manager | Branch manager | Branch-level control |
customer | Regular customer | Can book services |
admin | Super-admin | Full platform control |
guest | Temporary user | One-time booking |
User Status
active: User can log in and access featurespending: Account created, not yet verifiedsuspended: Temporary suspensiondeleted: Soft-deleted (marked withdeletedAt)
Notes
- All timestamps are ISO 8601 format.
- Emails are case-insensitive and unique per organization.
- Passwords are BCrypt hashed; never returned.
- See
booki-api/src/validations/user.validation.tsfor field constraints.
