The system supports different authentication types based on the authentication method used during registration:
| Code | Name | Description | Set During |
|---|---|---|---|
| EMAI | Traditional email/password authentication | POST /api/auth/register | |
| GOOG | Google OAuth | Google Sign-In authentication | POST /api/auth/google/register |
| APPE | Apple OAuth | Apple Sign-In authentication (future) | Future implementation |
| FACE | Facebook OAuth | Facebook authentication (future) | Future implementation |
| XXXX | X OAuth | X (formerly Twitter) authentication (future) | Future implementation |
| LINK | LinkedIn OAuth | LinkedIn authentication (future) | Future implementation |
Important Notes:
/api/users
List all users (requires authentication)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Query Parameters:
sort - JSON array with field name and direction
["fieldName","ASC|DESC"]
id, username, email, firstName, lastName, createdAt, updatedAt, verifiedAt, typeName, authTypeName, isActive, userTypeCode, authTypeCode, lastLoginAt
sort=["username","ASC"] - Sort by username in ascending order
page - Page number (1-based)
page=1 - Get the first page
perPage - Number of items per page
perPage=10 - Show 10 items per page
filter - JSON object with field name/value pairs for filtering
{"fieldName1":"value1","fieldName2":value2}
filter={"username":"John","isActive":true} - Filter active users with username containing "John"
q - Global search across username, email, first name, last name, user type name, and authentication type nameusername - Filter by username (partial match, case-insensitive)email - Filter by email address (partial match, case-insensitive)firstName - Filter by first name (partial match, case-insensitive)lastName - Filter by last name (partial match, case-insensitive)isActive - Filter by active status (true/false)userTypeCode - Filter by user type code (SUBS, NONS, ADMI)typeName - Filter by user type name (partial match, case-insensitive)authTypeCode - Filter by authentication type (EMAI, GOOG, APPE, FACE, XXXX, LINK)authTypeName - Filter by authentication type name (partial match, case-insensitive)verifiedAt - Filter by verification status
"null" for unverified users
"!null" for verified users
lastLoginAt - Filter by last login
"null" for users who never logged in
"!null" for users who have logged in
legacyUserId - Filter by legacy user ID
"null" for non-legacy users
"!null" for legacy users
subscriptionExemptionStartsAt - Filter by subscription exemption start date (exact date or date range, or "null"/"!null")subscriptionExemptionEndsAt - Filter by subscription exemption end date (exact date or date range, or "null"/"!null")createdAt - Filter by creation date (exact date or date range)updatedAt - Filter by last update date (exact date or date range)q in the filter will search across all text columns:
filter={"q":"John","isActive":true} - Find active users with "John"
in any text field
"null" to find records with NULL values or "!null" to find records with non-NULL values:
filter={"verifiedAt":"null"} - Find unverified users
filter={"lastLoginAt":"!null"} - Find users who have logged in
filter={"legacyUserId":"null"} - Find non-legacy users
filter={"legacyUserId":"!null"} - Find legacy users
Example Requests:
GET /api/users?page=1&perPage=10&sort=["username","ASC"]&filter={"userTypeCode":"SUBS"}
GET /api/users?page=2&perPage=20&filter={"q":"John","isActive":true}
GET /api/users?filter={"email":"gmail.com","verifiedAt":"null"}
GET /api/users?filter={"verifiedAt":"!null","isActive":true}
GET /api/users?filter={"lastLoginAt":"null"}
GET /api/users?filter={"lastLoginAt":"!null","userTypeCode":"SUBS"}
GET /api/users?filter={"legacyUserId":"null"}
GET /api/users?filter={"legacyUserId":"!null","isActive":true}
GET /api/users?filter={"typeName":"Subscribed","isActive":true}
GET /api/users?filter={"authTypeCode":"GOOG","isActive":true}
GET /api/users?filter={"authTypeName":"Google OAuth","isActive":true}
GET /api/users?sort=["authTypeName","ASC"]&filter={"isActive":true}
Response (200 OK):
{
"data": [
{
"id": 1,
"username": "John Doe",
"email": "john@example.com",
"typeCode": "SUBS",
"typeName": "Subscribed",
"firstName": "John",
"lastName": "Doe",
"authTypeCode": "EMAI",
"authTypeName": "Email",
"isActive": true,
"createdAt": "2023-01-15T08:30:00Z",
"updatedAt": "2023-01-15T08:30:00Z",
"verifiedAt": "2023-01-15T08:35:00Z",
"lastLoginAt": "2023-06-15T14:20:00Z",
"subscriptionExemptionStartsAt": null,
"subscriptionExemptionEndsAt": null,
"legacyUserId": null
},
{
"id": 2,
"username": "Jane Smith",
"email": "jane@gmail.com",
"typeCode": "SUBS",
"typeName": "Subscribed",
"firstName": "Jane",
"lastName": "Smith",
"authTypeCode": "GOOG",
"authTypeName": "Google OAuth",
"isActive": true,
"createdAt": "2023-02-20T10:15:00Z",
"updatedAt": "2023-02-20T10:15:00Z",
"verifiedAt": "2023-02-20T10:20:00Z",
"lastLoginAt": "2023-06-14T09:30:00Z",
"subscriptionExemptionStartsAt": null,
"subscriptionExemptionEndsAt": null,
"legacyUserId": 42
}
],
"total": 42
}
Headers:
Content-Range: items 0-9/42 Accept-Range: items Access-Control-Expose-Headers: Content-Range X-Total-Count: 42
Note: The Content-Range header indicates the range of items returned and the total count.
/api/users/me
Get current user profile (requires authentication)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Response (200 OK):
{
"id": 1,
"username": "John Doe",
"email": "john@example.com",
"typeCode": "SUBS",
"typeName": "Subscribed",
"firstName": "John",
"lastName": "Doe",
"authTypeCode": "EMAI",
"authTypeName": "Email",
"isActive": true,
"createdAt": "2023-01-15T08:30:00Z",
"updatedAt": "2023-01-15T08:30:00Z",
"verifiedAt": "2023-01-15T08:35:00Z",
"lastLoginAt": "2023-06-15T14:20:00Z",
"subscriptionExemptionStartsAt": null,
"subscriptionExemptionEndsAt": null,
"legacyUserId": null
}
Error Responses:
{
"message": "User not authenticated"
}
Notes:
/api/users/metrics
Gets a list of overall numbers on user data (requires authentication)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Response (200 OK):
{
"data": [
{
"id": 0,
"totalFreeUsers": 0,
"totalYearlyFreeUsers": 0,
"totalYearlyCreatedUsers": 3,
"monthlyIncompleteRegs": 0,
"totalMonthlyFreeUsers": 0,
"totalMonthlyExpiredUsers": 3,
"totalMonthlyCreatedUsers": 0,
"totalUserswithNoSubscription": 2,
"totalLegacyUsers": 1500,
"totalMigratedLegacyUsers": 1400,
"totalNonMigratedLegacyUsers": 100
}
],
"total": 1
}
Error Responses:
{
"message": "We could not collect any data on the users."
}
Notes:
/api/users/verification-requests
List all user verification requests with filtering, sorting, and pagination (requires authentication)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Query Parameters:
sort - JSON array with field name and direction
["fieldName","ASC|DESC"]
id, userId, requestTypeCode, requestTypeName, verificationCode, createdOn, attempts, username, email, firstName, lastName, isActive
sort=["createdOn","DESC"] - Sort by creation date in descending order
page - Page number (1-based)
page=1 - Get the first page
perPage - Number of items per page
perPage=10 - Show 10 items per page
filter - JSON object with field name/value pairs for filtering
{"fieldName1":"value1","fieldName2":value2}
filter={"requestTypeCode":"RPWR"} - Filter verification requests with type code "RPWR" (password reset)
q - Global search across verification code, request type code, request type name, username, email, first name, and last namerequestTypeCode - Filter by request type code (REGR for registration, RPWR for password reset)requestTypeName - Filter by request type name (partial match, case-insensitive)verificationCode - Filter by verification code (partial match, case-insensitive)username - Filter by username (partial match, case-insensitive)email - Filter by email address (partial match, case-insensitive)firstName - Filter by first name (partial match, case-insensitive)lastName - Filter by last name (partial match, case-insensitive)isActive - Filter by user active status (true/false)userId - Filter by specific user ID (exact match)attempts - Filter by number of verification attempts (exact match)createdOn - Filter by creation date (exact date or date range)q in the filter will search across key text columns:
filter={"q":"reset"} - Find verification requests with "reset" in any
searchable field (verificationCode, requestTypeCode, requestTypeName, username, email,
firstName, lastName)
Example Requests:
GET /api/users/verification-requests?page=1&perPage=10&sort=["createdOn","DESC"]&filter={"requestTypeCode":"RPWR"}
GET /api/users/verification-requests?page=1&perPage=20&filter={"q":"john","isActive":true}
GET /api/users/verification-requests?filter={"requestTypeName":"Password","username":"smith"}
GET /api/users/verification-requests?filter={"userId":42,"attempts":0}
Response (200 OK):
{
"data": [
{
"id": 1,
"userId": 42,
"requestTypeCode": "RPWR",
"requestTypeName": "Reset Password",
"verificationCode": "abc123def456",
"createdOn": "2023-06-15T14:30:00Z",
"attempts": 0,
"username": "johndoe",
"email": "john@example.com",
"firstName": "John",
"lastName": "Doe",
"isActive": true
},
{
"id": 2,
"userId": 37,
"requestTypeCode": "REGR",
"requestTypeName": "Email Verification",
"verificationCode": "xyz789uvw456",
"createdOn": "2023-06-14T10:15:00Z",
"attempts": 1,
"username": "janesmith",
"email": "jane@example.com",
"firstName": "Jane",
"lastName": "Smith",
"isActive": true
}
],
"total": 42
}
Headers:
Content-Range: items 0-9/42 Accept-Range: items Access-Control-Expose-Headers: Content-Range X-Total-Count: 42
Note: This endpoint includes verification codes and user details along with verification request information for improved usability and administration.
Notes:
/api/users/:id
Get a specific user by ID (requires authentication)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr...
Response (200 OK):
{
"id": 2,
"username": "Jane Doe",
"email": "jane@example.com",
"typeCode": "SUBS",
"typeName": "Subscribed",
"firstName": "Jane",
"lastName": "Doe",
"authTypeCode": "GOOG",
"authTypeName": "Google OAuth",
"isActive": true,
"createdAt": "2023-02-20T10:15:00Z",
"updatedAt": "2023-02-20T10:15:00Z",
"verifiedAt": "2023-02-20T10:20:00Z",
"lastLoginAt": "2023-06-14T09:30:00Z",
"subscriptionExemptionStartsAt": null,
"subscriptionExemptionEndsAt": null,
"legacyUserId": null
}
Error Responses:
{
"message": "User not found"
}
{
"message": "User not authenticated"
}
Notes:
/api/users/verification-requests/resend-email
Resends verification email to selected users (requires authentication and CSRF token)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr... x-csrf-token: a8d7f9c6e5b4a3c2d1e0f9a8d7f6c5b4a3
Request Body:
{
"emails": ["john@example.com", "jane@example.com"] // Array of email addresses
}
Response (200 OK):
{
"code": 200,
"message": "Successfully sent verification codes."
}
Error Responses:
{
"message": "One or more users not found."
}
Notes:
/api/users/me
Update current user profile (requires authentication and CSRF token)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr... x-csrf-token: a8d7f9c6e5b4a3c2d1e0f9a8d7f6c5b4a3
Request Body:
{
"username": "johnsmith",
"email": "johnsmith@example.com",
"firstName": "John",
"lastName": "Smith"
}
Response (200 OK):
{
"id": 1,
"username": "johnsmith",
"email": "johnsmith@example.com",
"typeCode": "SUBS",
"typeName": "Subscribed",
"firstName": "John",
"lastName": "Smith",
"isActive": true,
"createdAt": "2023-01-15T08:30:00Z",
"updatedAt": "2023-06-10T14:20:00Z",
"verifiedAt": "2023-01-15T08:35:00Z",
"subscriptionExemptionStartsAt": null,
"subscriptionExemptionEndsAt": null,
"legacyUserId": null
}
Error Responses:
{
"message": "User not authenticated"
}
{
"message": "User not found"
}
Notes:
/api/users/:id
Update any user by ID (requires admin authentication and CSRF token)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr... x-csrf-token: a8d7f9c6e5b4a3c2d1e0f9a8d7f6c5b4a3
Request Body:
{
"username": "johnsmith",
"email": "johnsmith@example.com",
"firstName": "John",
"lastName": "Smith",
"userTypeCode": "SUBS",
"isActive": true,
"subscriptionExemptionStartsAt": "2024-01-01T00:00:00Z",
"subscriptionExemptionEndsAt": "2024-12-31T23:59:59Z"
}
Response (200 OK):
{
"id": 2,
"username": "johnsmith",
"email": "johnsmith@example.com",
"typeCode": "SUBS",
"typeName": "Subscribed",
"firstName": "John",
"lastName": "Smith",
"isActive": true,
"createdAt": "2023-01-15T08:30:00Z",
"updatedAt": "2023-06-10T14:20:00Z",
"verifiedAt": "2023-01-15T08:35:00Z",
"subscriptionExemptionStartsAt": "2024-01-01T00:00:00Z",
"subscriptionExemptionEndsAt": "2024-12-31T23:59:59Z",
"legacyUserId": null
}
Error Responses:
{
"message": "User not authenticated"
}
{
"message": "User not found"
}
Notes:
/api/users/verification-requests/new-request-code
Update verification requests with a new code (requires authentication and CSRF token)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr... x-csrf-token: a8d7f9c6e5b4a3c2d1e0f9a8d7f6c5b4a3
Request Body:
{
"userReqList":[
{
"userId": 3,
"request_type_code": "REGR" // "REGR" for registration, "RPWR" for password reset
},
{
"userId": 5,
"request_type_code": "RPWR"
}
]
}
Response (200 OK):
{
"code": 200,
"message": "Successfully created new verification requests.",
"verificationCodes": [
{
"userId": 3,
"verificationCode": "abc123def456",
"requestType": "REGR"
},
{
"userId": 5,
"verificationCode": "xyz789uvw012",
"requestType": "RPWR"
}
]
}
Error Responses:
{
"message": "One or more users not found."
}
Notes:
/api/users/:id
Delete a user by ID (requires authentication and CSRF token)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr... x-csrf-token: a8d7f9c6e5b4a3c2d1e0f9a8d7f6c5b4a3
Response: 204 No Content
Error Responses:
{
"message": "User not found"
}
{
"message": "User not authenticated"
}
Notes:
/api/users/verification-requests/:id
Delete a verification request by ID (requires admin authentication and CSRF token)
Headers:
Authorization: Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr... x-csrf-token: a8d7f9c6e5b4a3c2d1e0f9a8d7f6c5b4a3
Response: 204 No Content
Error Responses:
{
"message": "Verification request not found"
}
{
"message": "User not authenticated"
}
{
"message": "Administrator access required"
}
Notes: