Auth Service API Documentation
Overview
The Auth Service provides authentication, authorization, and member management functionality with support for:
- Authentication: Staff login, token management, session validation
- Staff Management: CRUD operations for staff members
- Service/API Key Management: Generate and manage API keys for service-to-service authentication
- WeChat Member Management: WeChat OAuth login, member profile management, QR code generation
- Consent Management: Privacy policy and terms of service versioning and acceptance tracking
Base URL
baseUrl/auth/api
Authentication
Most endpoints require authentication via JWT token in the Authorization header:
Authorization: Bearer <token>
The token should contain a sub field with the staff/member ID.
Note: Public endpoints like login and password reset do not require authentication.
Authentication API
GET baseUrl/auth/api/check-access-token-session
Check if the current access token session is valid.
Request
Endpoint: GET baseUrl/auth/api/check-access-token-session
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Example Request
GET baseUrl/auth/api/check-access-token-session
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "Access token is valid",
"data": {
"valid": true
}
}
}
POST baseUrl/auth/api/get-new-access-token
Get a new access token using a refresh token.
Request
Endpoint: POST baseUrl/auth/api/get-new-access-token
Headers:
Content-Type: application/json
Request Body:
{
refreshToken?: string; // Optional, if not provided, will use refreshToken from cookie
}
Example Request
{
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
}
Note: The refresh token is also set as an HTTP-only cookie.
Error Response (401 Unauthorized):
{
"statusCode": 401,
"data": {
"message": "Refresh token not found in cookies"
}
}
Staff Actions API
POST baseUrl/auth/api/staffs/login
Staff login with email and password.
Request
Endpoint: POST baseUrl/auth/api/staffs/login
Headers:
Content-Type: application/json
Request Body:
{
email: string; // Required, valid email format
password: string; // Required, minimum 1 character
}
Example Request
{
"email": "staff@example.com",
"password": "securePassword123"
}
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "Login successful",
"data": {
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
}
}
Note: The refresh token is automatically set as an HTTP-only cookie.
Error Response (401 Unauthorized):
{
"statusCode": 401,
"data": {
"message": "Invalid email or password"
}
}
POST baseUrl/auth/api/staffs/request-reset-password
Request password reset for a staff member (admin-initiated).
Request
Endpoint: POST baseUrl/auth/api/staffs/request-reset-password
Headers:
Content-Type: application/json
Request Body:
{
type: "EMAIL" | "SMS"; // Required, reset password session type
staffId: string; // Required, UUID of the staff member
}
Example Request
{
"type": "EMAIL",
"staffId": "550e8400-e29b-41d4-a716-446655440000"
}
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "Reset password request sent successfully"
}
}
POST baseUrl/auth/api/staffs/request-reset-password-by-email
Request password reset by email (self-service).
Request
Endpoint: POST baseUrl/auth/api/staffs/request-reset-password-by-email
Headers:
Content-Type: application/json
Request Body:
{
email: string; // Required, valid email format
locale?: "en" | "th" | "cn"; // Optional, default: "en"
}
Example Request
{
"email": "staff@example.com",
"locale": "en"
}
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "Reset password request sent successfully"
}
}
POST baseUrl/auth/api/staffs/reset-password/:sessionId
Reset password using session ID and verification code.
Request
Endpoint: POST baseUrl/auth/api/staffs/reset-password/:sessionId
Headers:
Content-Type: application/json
Path Parameters:
{
sessionId: string; // UUID of the reset password session
}
Request Body:
{
code: string; // Required, verification code (minimum 1 character)
newPassword: string; // Required, minimum 6 characters
}
Example Request
{
"code": "123456",
"newPassword": "newSecurePassword123"
}
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "Password reset successfully"
}
}
Error Response (400 Bad Request):
{
"statusCode": 400,
"data": {
"message": "Invalid or expired session"
}
}
GET baseUrl/auth/api/staffs/check-session/:sessionId
Check if a reset password session is valid.
Request
Endpoint: GET baseUrl/auth/api/staffs/check-session/:sessionId
Path Parameters:
{
sessionId: string; // UUID of the reset password session
}
Example Request
GET baseUrl/auth/api/staffs/check-session/550e8400-e29b-41d4-a716-446655440000
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "Session check completed",
"data": {
"isValid": true
}
}
}
Staff Management API
GET baseUrl/auth/api/staffs
Get all staff members with pagination and filtering.
Request
Endpoint: GET baseUrl/auth/api/staffs
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Query Parameters:
{
page?: number; // Page number (default: 1)
limit?: number; // Items per page (default: 10)
storeId?: string; // Filter by store ID
roleId?: string; // Filter by role ID (UUID)
status?: "ACTIVE" | "INACTIVE" | "WAIT_FOR_FIRST_ACTIVE"; // Filter by status
search?: string; // Search in name/email
}
Example Request
GET baseUrl/auth/api/staffs?page=1&limit=20&status=ACTIVE&roleId=role-123
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "Staff list retrieved successfully",
"data": {
"meta": {
"page": 1,
"limit": 20,
"total": 45,
"totalPages": 3
},
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "staff@example.com",
"firstname": "John",
"lastname": "Doe",
"phoneNumber": "+66123456789",
"roleId": "role-123",
"storeId": "store-001",
"status": "ACTIVE",
"locale": "en",
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z"
}
]
}
}
}
GET baseUrl/auth/api/staffs/me
Get the current authenticated staff member's information.
Request
Endpoint: GET baseUrl/auth/api/staffs/me
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Example Request
GET baseUrl/auth/api/staffs/me
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "Staff retrieved successfully",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "staff@example.com",
"firstname": "John",
"lastname": "Doe",
"phoneNumber": "+66123456789",
"roleId": "role-123",
"storeId": "store-001",
"status": "ACTIVE",
"locale": "en",
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z"
}
}
}
Error Response (404 Not Found):
{
"statusCode": 404,
"data": {
"message": "Staff not found",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
GET baseUrl/auth/api/staffs/:id
Get a specific staff member by ID.
Request
Endpoint: GET baseUrl/auth/api/staffs/:id
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Path Parameters:
{
id: string; // UUID of the staff member
}
Example Request
GET baseUrl/auth/api/staffs/550e8400-e29b-41d4-a716-446655440000
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "Staff retrieved successfully",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "staff@example.com",
"firstname": "John",
"lastname": "Doe",
"phoneNumber": "+66123456789",
"roleId": "role-123",
"storeId": "store-001",
"status": "ACTIVE",
"locale": "en",
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z"
}
}
}
POST baseUrl/auth/api/staffs
Create a new staff member.
Request
Endpoint: POST baseUrl/auth/api/staffs
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
Request Body:
{
email: string; // Required, valid email format
firstname: string; // Required, max 256 characters
lastname: string; // Required, max 256 characters
phoneNumber?: string; // Optional, max 256 characters
roleId: string; // Required, UUID
storeId?: string; // Optional store ID
status?: "ACTIVE" | "INACTIVE" | "WAIT_FOR_FIRST_ACTIVE"; // Optional, default: "WAIT_FOR_FIRST_ACTIVE"
locale?: "en" | "th" | "cn"; // Optional, default: "en"
}
Example Request
{
"email": "newstaff@example.com",
"firstname": "Jane",
"lastname": "Smith",
"phoneNumber": "+66987654321",
"roleId": "role-123",
"storeId": "store-001",
"status": "WAIT_FOR_FIRST_ACTIVE",
"locale": "en"
}
Response
Success Response (201 Created):
{
"statusCode": 201,
"data": {
"message": "Staff created successfully",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "newstaff@example.com",
"firstname": "Jane",
"lastname": "Smith",
"phoneNumber": "+66987654321",
"roleId": "role-123",
"storeId": "store-001",
"status": "WAIT_FOR_FIRST_ACTIVE",
"locale": "en",
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z"
}
}
}
PUT baseUrl/auth/api/staffs/:id
Update an existing staff member.
Request
Endpoint: PUT baseUrl/auth/api/staffs/:id
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
Path Parameters:
{
id: string; // UUID of the staff member
}
Request Body:
{
email: string; // Required, valid email format
firstname: string; // Required, max 256 characters
lastname: string; // Required, max 256 characters
phoneNumber?: string; // Optional, max 256 characters
roleId: string; // Required, UUID
storeId?: string; // Optional store ID
}
Example Request
{
"email": "updated@example.com",
"firstname": "Jane",
"lastname": "Doe",
"phoneNumber": "+66987654321",
"roleId": "role-456",
"storeId": "store-002"
}
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "Staff updated successfully",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "updated@example.com",
"firstname": "Jane",
"lastname": "Doe",
"phoneNumber": "+66987654321",
"roleId": "role-456",
"storeId": "store-002",
"status": "ACTIVE",
"locale": "en",
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-20T14:30:00.000Z"
}
}
}
DELETE baseUrl/auth/api/staffs/:id
Delete (soft delete) a staff member.
Request
Endpoint: DELETE baseUrl/auth/api/staffs/:id
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Path Parameters:
{
id: string; // UUID of the staff member
}
Example Request
DELETE baseUrl/auth/api/staffs/550e8400-e29b-41d4-a716-446655440000
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "Staff deleted successfully",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
Service/API Key Management API
POST baseUrl/auth/api/services/generate-api-key
Generate a new API key for service-to-service authentication.
Request
Endpoint: POST baseUrl/auth/api/services/generate-api-key
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
Request Body:
{
name: string; // Required, max 256 characters (service name)
roleId: string; // Required, UUID (role for the API key)
expiredIn?: number; // Optional, expiration time in milliseconds
}
Example Request
{
"name": "Point Service API Key",
"roleId": "role-service-point-id",
"expiredIn": 31536000000
}
Response
Success Response (201 Created):
{
"statusCode": 201,
"data": {
"id": "service-key-id",
"name": "Point Service API Key",
"apiKey": "sb_api_abc123def456...",
"roleId": "role-service-point-id",
"expiresAt": "2025-01-15T10:30:00.000Z",
"createdAt": "2024-01-15T10:30:00.000Z"
}
}
GET baseUrl/auth/api/services/me
Get all API keys for the current authenticated staff member.
Request
Endpoint: GET baseUrl/auth/api/services/me
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Query Parameters:
{
page?: number; // Page number (default: 1)
limit?: number; // Items per page (default: 10)
}
Example Request
GET baseUrl/auth/api/services/me?page=1&limit=20
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"meta": {
"page": 1,
"limit": 20,
"total": 3,
"totalPages": 1
},
"data": [
{
"id": "service-key-id-1",
"name": "Point Service API Key",
"roleId": "role-service-point-id",
"expiresAt": "2025-01-15T10:30:00.000Z",
"createdAt": "2024-01-15T10:30:00.000Z"
}
]
}
}
Note: The actual apiKey is only returned when first created for security reasons.
DELETE baseUrl/auth/api/services/revoke/:id
Revoke (delete) an API key.
Request
Endpoint: DELETE baseUrl/auth/api/services/revoke/:id
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Path Parameters:
{
id: string; // UUID of the service/API key
}
Example Request
DELETE baseUrl/auth/api/services/revoke/service-key-id-1
Response
Success Response (204 No Content):
No response body.
POST baseUrl/auth/api/services/get-access-token
Get an access token using an API key (for service-to-service authentication).
Request
Endpoint: POST baseUrl/auth/api/services/get-access-token
Headers:
Content-Type: application/json
Request Body:
{
apiKey: string; // Required, the API key string
}
Example Request
{
"apiKey": "sb_api_abc123def456..."
}
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 3600
}
}
Error Response (401 Unauthorized):
{
"statusCode": 401,
"data": {
"message": "Invalid API key"
}
}
WeChat Member Management API
POST baseUrl/auth/api/members/wechat/login
WeChat OAuth login using WeChat code.
Request
Endpoint: POST baseUrl/auth/api/members/wechat/login
Headers:
Content-Type: application/json
Request Body:
{
code: string; // Required, WeChat authorization code (minimum 1 character)
}
Example Request
{
"code": "wechat_code_abc123..."
}
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "WeChat login successful",
"data": {
"status": "NEW" | "EXISTING",
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
}
}
Note: The refresh token is automatically set as an HTTP-only cookie.
Status values:
NEW- New member createdEXISTING- Existing member logged in
GET baseUrl/auth/api/members/me
Get the current authenticated member's information.
Request
Endpoint: GET baseUrl/auth/api/members/me
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Example Request
GET baseUrl/auth/api/members/me
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "WeChat member retrieved successfully",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"openId": "wechat_openid_abc123",
"nickName": "John Doe",
"avatarUrl": "https://thirdwx.qlogo.cn/...",
"name": "John Doe",
"phoneNumber": "+66123456789",
"gender": "Male",
"birthDate": "1990-01-15T00:00:00.000Z",
"address": {
"address": "123 Main Street",
"subDistrict": "Subdistrict",
"district": "District",
"province": "Bangkok",
"postCode": "10110",
"country": "Thailand",
"latitude": 13.7563,
"longitude": 100.5018
},
"status": "ACTIVE",
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z"
}
}
}
Error Response (404 Not Found):
{
"statusCode": 404,
"data": {
"message": "WeChat member not found",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
PUT baseUrl/auth/api/members/me
Update the current authenticated member's information.
Request
Endpoint: PUT baseUrl/auth/api/members/me
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
Request Body:
{
nickName?: string; // Optional, max 256 characters
avatarUrl?: string; // Optional, valid URL
birthDate?: string; // Optional, ISO 8601 date string
name?: string; // Optional, max 100 characters
gender?: "Male" | "Female" | "Other"; // Optional
phoneNumber?: string; // Optional, max 20 characters
address?: { // Optional
address?: string;
subDistrict?: string;
district?: string;
province?: string;
postCode?: string;
country?: string;
latitude?: number;
longitude?: number;
};
}
Example Request
{
"name": "John Updated",
"phoneNumber": "+66987654321",
"gender": "Male",
"birthDate": "1990-01-15",
"address": {
"address": "456 New Street",
"province": "Bangkok",
"postCode": "10120"
}
}
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "WeChat member updated successfully"
}
}
GET baseUrl/auth/api/members/me/qr-code
Get QR code identity for the authenticated member.
Request
Endpoint: GET baseUrl/auth/api/members/me/qr-code
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Example Request
GET baseUrl/auth/api/members/me/qr-code
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"qrCodeUrl": "https://storage.example.com/qr-codes/550e8400-e29b-41d4-a716-446655440000.png",
"memberId": "550e8400-e29b-41d4-a716-446655440000"
}
}
GET baseUrl/auth/api/members
Get all members with pagination and filtering.
Request
Endpoint: GET baseUrl/auth/api/members
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Query Parameters:
{
page?: number; // Page number (default: 1)
limit?: number; // Items per page (default: 10)
birthdayFrom?: string; // Filter by birthday from date (ISO 8601)
search?: string; // Search in name/nickname/phone/email
includePointBalance?: boolean; // Include point balance (default: false)
includeTier?: boolean; // Include tier information (default: false)
locale?: "en" | "th" | "cn"; // Localize response content
}
Example Request
GET baseUrl/auth/api/members?page=1&limit=20&search=John&includePointBalance=true&includeTier=true&locale=en
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "WeChat members retrieved successfully",
"data": {
"meta": {
"page": 1,
"limit": 20,
"total": 150,
"totalPages": 8
},
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"openId": "wechat_openid_abc123",
"nickName": "John Doe",
"avatarUrl": "https://thirdwx.qlogo.cn/...",
"name": "John Doe",
"phoneNumber": "+66123456789",
"gender": "Male",
"status": "ACTIVE",
"pointBalance": 1250,
"tier": {
"id": "tier-gold-id",
"name_en": "Gold",
"level": 3
},
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z"
}
]
}
}
}
POST baseUrl/auth/api/members/bulk
Get multiple members by their IDs (bulk query).
Request
Endpoint: POST baseUrl/auth/api/members/bulk
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
Request Body:
{
ids: string[]; // Array of member UUIDs
}
Example Request
{
"ids": [
"550e8400-e29b-41d4-a716-446655440000",
"660e8400-e29b-41d4-a716-446655440001"
]
}
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "WeChat members retrieved successfully",
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"nickName": "John Doe",
"name": "John Doe",
"status": "ACTIVE"
},
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"nickName": "Jane Smith",
"name": "Jane Smith",
"status": "ACTIVE"
}
]
}
}
GET baseUrl/auth/api/members/:id
Get a specific member by ID.
Request
Endpoint: GET baseUrl/auth/api/members/:id
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Path Parameters:
{
id: string; // UUID of the member
}
Query Parameters:
{
includeTier?: boolean; // Include tier information (default: false)
locale?: "en" | "th" | "cn"; // Localize response content
}
Example Request
GET baseUrl/auth/api/members/550e8400-e29b-41d4-a716-446655440000?includeTier=true&locale=en
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "WeChat member retrieved successfully",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"openId": "wechat_openid_abc123",
"nickName": "John Doe",
"avatarUrl": "https://thirdwx.qlogo.cn/...",
"name": "John Doe",
"phoneNumber": "+66123456789",
"gender": "Male",
"birthDate": "1990-01-15T00:00:00.000Z",
"status": "ACTIVE",
"tier": {
"id": "tier-gold-id",
"name_en": "Gold",
"level": 3
},
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z"
}
}
}
POST baseUrl/auth/api/members/wechat/sync/:memberId
Sync WeChat member information from WeChat API.
Request
Endpoint: POST baseUrl/auth/api/members/wechat/sync/:memberId
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
Path Parameters:
{
memberId: string; // UUID of the member
}
Request Body:
{
nickName?: string; // Optional, max 256 characters
avatarUrl?: string; // Optional, valid URL
name?: string; // Optional, max 100 characters
phoneNumber?: string; // Optional, max 20 characters
gender?: 0 | 1 | 2; // Optional, WeChat gender (0: unknown, 1: male, 2: female)
province?: string; // Optional, max 100 characters
city?: string; // Optional, max 100 characters
country?: string; // Optional, max 100 characters
}
Example Request
{
"nickName": "Updated Nickname",
"avatarUrl": "https://thirdwx.qlogo.cn/new_avatar.jpg",
"gender": 1
}
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "WeChat info synced successfully"
}
}
PUT baseUrl/auth/api/members/:memberId
Update a member's information (admin).
Request
Endpoint: PUT baseUrl/auth/api/members/:memberId
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
Path Parameters:
{
memberId: string; // UUID of the member
}
Request Body: Same as PUT baseUrl/auth/api/members/me
Example Request
{
"name": "John Updated",
"phoneNumber": "+66987654321"
}
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "WeChat member updated successfully"
}
}
POST baseUrl/auth/api/members/direct
Create a member directly (staff/admin, without WeChat OAuth).
Request
Endpoint: POST baseUrl/auth/api/members/direct
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
Request Body:
{
birthDate?: string; // Optional, ISO 8601 date string
name: string; // Required, max 100 characters
gender?: "Male" | "Female" | "Other"; // Optional
phoneNumber: string; // Required, max 20 characters
address?: { // Optional
address?: string;
subDistrict?: string;
district?: string;
province?: string;
postCode?: string;
country?: string;
latitude?: number;
longitude?: number;
};
}
Example Request
{
"name": "John Doe",
"phoneNumber": "+66123456789",
"gender": "Male",
"birthDate": "1990-01-15",
"address": {
"address": "123 Main Street",
"province": "Bangkok",
"postCode": "10110"
}
}
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "WeChat member created successfully via direct create"
}
}
PUT baseUrl/auth/api/members/:memberId/direct
Update a member directly with full control (staff/admin).
Request
Endpoint: PUT baseUrl/auth/api/members/:memberId/direct
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
Path Parameters:
{
memberId: string; // UUID of the member
}
Request Body:
{
nickName?: string; // Optional, max 256 characters
avatarUrl?: string; // Optional, valid URL
birthDate?: string; // Optional, ISO 8601 date string
name?: string; // Optional, max 100 characters
gender?: "Male" | "Female" | "Other"; // Optional
phoneNumber?: string; // Optional, max 20 characters
address?: { // Optional
address?: string;
subDistrict?: string;
district?: string;
province?: string;
postCode?: string;
country?: string;
latitude?: number;
longitude?: number;
};
status?: "PENDING" | "WECHAT_INFO_SYNCED" | "ACTIVE" | "INACTIVE"; // Optional
}
Example Request
{
"name": "John Updated",
"status": "ACTIVE",
"phoneNumber": "+66987654321"
}
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "WeChat member updated successfully via direct update"
}
}
PATCH baseUrl/auth/api/members/:memberId/set-active
Set the active status of a member.
Request
Endpoint: PATCH baseUrl/auth/api/members/:memberId/set-active
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
Path Parameters:
{
memberId: string; // UUID of the member
}
Request Body:
{
isActive: boolean; // Required
}
Example Request
{
"isActive": false
}
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "WeChat member set active successfully"
}
}
GET baseUrl/auth/api/members/summary/daily
Get daily member registration summary statistics.
Request
Endpoint: GET baseUrl/auth/api/members/summary/daily
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Query Parameters:
{
startDate?: string; // Start date (ISO 8601 format)
endDate?: string; // End date (ISO 8601 format)
}
Example Request
GET baseUrl/auth/api/members/summary/daily?startDate=2024-01-01&endDate=2024-01-31
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "WeChat member summary daily retrieved successfully",
"data": [
{
"date": "2024-01-15",
"newMembers": 25,
"activeMembers": 1500
},
{
"date": "2024-01-16",
"newMembers": 30,
"activeMembers": 1530
}
]
}
}
Consent Management API
GET baseUrl/auth/api/consents/current
Get the current active consent (privacy policy/terms of service).
Request
Endpoint: GET baseUrl/auth/api/consents/current
Query Parameters:
{
locale?: "en" | "th" | "cn"; // Optional, default: "en"
}
Example Request
GET baseUrl/auth/api/consents/current?locale=en
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "Current consent retrieved successfully",
"data": {
"id": "consent-id-123",
"version": "1.2.0",
"versionType": "MINOR",
"title_en": "Privacy Policy",
"title_th": "นโยบายความเป็นส่วนตัว",
"title_cn": "隐私政策",
"content_en": "Privacy policy content...",
"content_th": "เนื้อหานโยบายความเป็นส่วนตัว...",
"content_cn": "隐私政策内容...",
"isCurrent": true,
"publishedAt": "2024-01-01T00:00:00.000Z",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
}
}
GET baseUrl/auth/api/consents
Get all consents with pagination.
Request
Endpoint: GET baseUrl/auth/api/consents
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Query Parameters:
{
page?: number; // Page number (default: 1, min: 1)
limit?: number; // Items per page (default: 10, min: 1, max: 100)
locale?: "en" | "th" | "cn"; // Optional, default: "en"
}
Example Request
GET baseUrl/auth/api/consents?page=1&limit=20&locale=en
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "Consents retrieved successfully",
"data": {
"meta": {
"page": 1,
"limit": 20,
"total": 5,
"totalPages": 1
},
"data": [
{
"id": "consent-id-123",
"version": "1.2.0",
"versionType": "MINOR",
"title_en": "Privacy Policy",
"title_th": "นโยบายความเป็นส่วนตัว",
"title_cn": "隐私政策",
"isCurrent": true,
"createdAt": "2024-01-01T00:00:00.000Z"
}
]
}
}
}
GET baseUrl/auth/api/consents/:id
Get a specific consent by ID.
Request
Endpoint: GET baseUrl/auth/api/consents/:id
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Path Parameters:
{
id: string; // UUID of the consent
}
Query Parameters:
{
locale?: "en" | "th" | "cn"; // Optional, default: "en"
}
Example Request
GET baseUrl/auth/api/consents/consent-id-123?locale=en
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "Consent retrieved successfully",
"data": {
"id": "consent-id-123",
"version": "1.2.0",
"versionType": "MINOR",
"title_en": "Privacy Policy",
"title_th": "นโยบายความเป็นส่วนตัว",
"title_cn": "隐私政策",
"content_en": "Privacy policy content...",
"content_th": "เนื้อหานโยบายความเป็นส่วนตัว...",
"content_cn": "隐私政策内容...",
"isCurrent": true,
"publishedAt": "2024-01-01T00:00:00.000Z",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
}
}
POST baseUrl/auth/api/consents
Create a new consent version.
Request
Endpoint: POST baseUrl/auth/api/consents
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
Request Body:
{
title_en: string; // Required, max 256 characters
title_th: string; // Required, max 256 characters
title_cn: string; // Required, max 256 characters
content_en: string; // Required
content_th: string; // Required
content_cn: string; // Required
versionType?: "MAJOR" | "MINOR"; // Optional, default: "MINOR"
}
Example Request
{
"title_en": "Privacy Policy",
"title_th": "นโยบายความเป็นส่วนตัว",
"title_cn": "隐私政策",
"content_en": "Updated privacy policy content...",
"content_th": "เนื้อหานโยบายความเป็นส่วนตัวที่อัปเดต...",
"content_cn": "更新的隐私政策内容...",
"versionType": "MINOR"
}
Response
Success Response (201 Created):
{
"statusCode": 201,
"data": {
"message": "Consent created successfully",
"data": {
"id": "consent-id-124",
"version": "1.2.1",
"versionType": "MINOR",
"title_en": "Privacy Policy",
"isCurrent": false,
"createdAt": "2024-01-20T10:30:00.000Z"
}
}
}
PUT baseUrl/auth/api/consents/:id
Update consent content.
Request
Endpoint: PUT baseUrl/auth/api/consents/:id
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
Path Parameters:
{
id: string; // UUID of the consent
}
Request Body: All fields optional, but at least one must be provided:
{
title_en?: string; // Optional, max 256 characters
title_th?: string; // Optional, max 256 characters
title_cn?: string; // Optional, max 256 characters
content_en?: string; // Optional
content_th?: string; // Optional
content_cn?: string; // Optional
}
Example Request
{
"content_en": "Updated privacy policy content v2..."
}
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "Consent updated successfully",
"data": {
"id": "consent-id-123",
"version": "1.2.0",
"content_en": "Updated privacy policy content v2...",
"updatedAt": "2024-01-20T14:30:00.000Z"
}
}
}
PATCH baseUrl/auth/api/consents/publish
Publish (set as current) a consent version.
Request
Endpoint: PATCH baseUrl/auth/api/consents/publish
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
Request Body:
{
id: string; // Required, UUID of the consent to publish
}
Example Request
{
"id": "consent-id-124"
}
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "Consent published successfully",
"data": {
"id": "consent-id-124",
"version": "1.2.1",
"isCurrent": true,
"publishedAt": "2024-01-20T15:00:00.000Z"
}
}
}
PATCH baseUrl/auth/api/consents/rollback
Rollback to the previous consent version.
Request
Endpoint: PATCH baseUrl/auth/api/consents/rollback
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Example Request
PATCH baseUrl/auth/api/consents/rollback
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "Consent rolled back successfully",
"data": {
"previousConsentId": "consent-id-123",
"currentConsentId": "consent-id-122"
}
}
}
POST baseUrl/auth/api/consents/members/accept-current
Accept the current active consent for the authenticated member.
Request
Endpoint: POST baseUrl/auth/api/consents/members/accept-current
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Example Request
POST baseUrl/auth/api/consents/members/accept-current
Response
Success Response (201 Created):
{
"statusCode": 201,
"data": {
"message": "Current consent accepted successfully",
"data": {
"id": "acceptance-id-123",
"memberId": "550e8400-e29b-41d4-a716-446655440000",
"consentId": "consent-id-123",
"consentVersion": "1.2.0",
"acceptedAt": "2024-01-15T10:30:00.000Z"
}
}
}
GET baseUrl/auth/api/consents/members/me
Get the current authenticated member's consent acceptance information.
Request
Endpoint: GET baseUrl/auth/api/consents/members/me
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Query Parameters:
{
locale?: "en" | "th" | "cn"; // Optional, default: "en"
}
Example Request
GET baseUrl/auth/api/consents/members/me?locale=en
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "Member consent acceptance retrieved successfully",
"data": {
"memberId": "550e8400-e29b-41d4-a716-446655440000",
"latestAcceptedConsentId": "consent-id-123",
"latestAcceptedConsentVersion": "1.2.0",
"latestAcceptedAt": "2024-01-15T10:30:00.000Z",
"currentConsentId": "consent-id-124",
"currentConsentVersion": "1.2.1",
"needsAcceptance": true
}
}
}
GET baseUrl/auth/api/consents/members/:id
Get consent acceptance information for a specific member.
Request
Endpoint: GET baseUrl/auth/api/consents/members/:id
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Path Parameters:
{
id: string; // UUID of the member
}
Query Parameters:
{
locale?: "en" | "th" | "cn"; // Optional, default: "en"
}
Example Request
GET baseUrl/auth/api/consents/members/550e8400-e29b-41d4-a716-446655440000?locale=en
Response
Success Response (200 OK):
Same structure as GET baseUrl/auth/api/consents/members/me
GET baseUrl/auth/api/consents/members
Get all member consent acceptances with pagination (admin).
Request
Endpoint: GET baseUrl/auth/api/consents/members
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Query Parameters:
{
page?: number; // Page number (default: 1)
limit?: number; // Items per page (default: 10)
}
Example Request
GET baseUrl/auth/api/consents/members?page=1&limit=20
Response
Success Response (200 OK):
{
"statusCode": 200,
"data": {
"message": "Member consent acceptances retrieved successfully",
"data": {
"meta": {
"page": 1,
"limit": 20,
"total": 1500,
"totalPages": 75
},
"data": [
{
"id": "acceptance-id-123",
"memberId": "550e8400-e29b-41d4-a716-446655440000",
"consentId": "consent-id-123",
"consentVersion": "1.2.0",
"acceptedAt": "2024-01-15T10:30:00.000Z"
}
]
}
}
}
Data Types & Enums
Staff Status
ACTIVE- Staff member is activeINACTIVE- Staff member is inactiveWAIT_FOR_FIRST_ACTIVE- Waiting for first password set
Member Status
PENDING- Member created but not yet activatedWECHAT_INFO_SYNCED- WeChat information syncedACTIVE- Member is activeINACTIVE- Member is inactive
Gender
Male- MaleFemale- FemaleOther- Other
WeChat Gender
0- Unknown1- Male2- Female
Consent Version Type
MAJOR- Major version changeMINOR- Minor version change
Reset Password Session Type
EMAIL- Reset via emailSMS- Reset via SMS
Locales
en- Englishth- Thaicn- Chinese (Simplified)
Error Responses
All error responses follow this structure:
{
"statusCode": <HTTP_STATUS_CODE>,
"data": {
"message": "<Error message>",
"errors": [ // Optional, for validation errors
{
"field": "<field_name>",
"message": "<validation message>"
}
]
}
}
Common HTTP Status Codes
200 OK- Request succeeded201 Created- Resource created successfully204 No Content- Request succeeded with no content400 Bad Request- Invalid request data or business rule violation401 Unauthorized- Missing or invalid authentication token403 Forbidden- Insufficient permissions404 Not Found- Resource not found500 Internal Server Error- Server error
Notes
-
Authentication: Most endpoints require a valid JWT token in the
Authorizationheader. The token'ssubfield should contain the staff/member ID. -
Cookies: Refresh tokens are automatically set as HTTP-only cookies for login endpoints. This provides better security than storing tokens in client-side storage.
-
WeChat OAuth: The WeChat login flow uses OAuth 2.0. You need to obtain a WeChat authorization code from the WeChat mini-program or official account, then exchange it for tokens.
-
Member Management:
- Members can be created via WeChat OAuth login
- Members can also be created directly by staff (without WeChat)
- Direct update allows staff to update any field including status
- Regular member update is for self-service profile updates
-
Consent Management:
- Only one consent can be "current" (published) at a time
- Publishing a new consent automatically unpublishes the previous one
- Version numbers are automatically generated based on version type (MAJOR/MINOR)
- Members must accept new consent versions when published
-
API Keys:
- Used for service-to-service authentication
- Can have expiration dates
- Once revoked, cannot be used to obtain access tokens
- The actual API key value is only shown once when created
-
Password Reset:
- Two methods: admin-initiated (with staff ID) or self-service (with email)
- Creates a reset password session with a verification code
- Session must be validated before resetting password
-
Date Formats: All date fields use ISO 8601 format (e.g.,
2024-12-31T23:59:59.000Zor2024-12-31). -
Pagination: Pagination defaults to page 1 with 10 items per page. Maximum limit is 100 items per page.
-
Localization: Use the
localequery parameter to get localized content. If not specified, defaults to "en" for consent endpoints.
Support
For issues or questions, please contact the development team or refer to the main project documentation.