Skip to content

Activity Log

The Activity Log module provides access to user activity trails stored in MongoDB (the activity_logs collection). The ActivityLogController is mounted at /activities-logs. FE uses it for the “Activity History” / “Activity Timeline” page on the user profile — the endpoints read logs for the currently logged-in user only, with activityType + status filters and pagination.

PropertyValue
Base URL{HOST}/v1
AuthBearer JWT (header Authorization) or cookie access_token
Content-Typeapplication/json
Error envelope{ "message": string | string[], "statusCode": number, "error": string }
ValidationGlobal ValidationPipe · whitelist: true, forbidNonWhitelisted: true · unknown field → 400
Related modulesusers, authentication, withdrawal, saving-goals, security
Document versionv1 · 2026-05-20
AudienceInternal FE devs (mobile + web)

Every user activity (login, withdraw, update saving goal, etc.) is written to MongoDB by an internal log service. FE reads two endpoints: a list of activities (paginated/filtered), and aggregate stats per activityType for the activity chart over the last N days. Both endpoints are always scoped to the currently logged-in user — there is no way to read another user’s logs.

MethodPathAuthSummary
GET/v1/activities-logsbearerList the logged-in user’s activity log (paginated + filter)
GET/v1/activities-logs/statsbearerAggregate stats per activityType over N days

GET /v1/activities-logs bearer

Section titled “GET /v1/activities-logs ”

Reads the logged-in user’s activity log list with activityType/status filters, pagination, and a sort option. Supports activityType as an array (use repeated query-string parameters).

bearer read-activity-log
ParamTypeDefaultNotes
activityTypeenum ActivityType or arrayoptionalFilter by one or many types (e.g. ?activityType=login&activityType=withdrawal_request). Validation IsEnum(..., { each: true })
statusenum ActivityStatusoptionalsuccess, failed, pending, cancelled
pagenumber1Page number · Min(1)
limitnumber20Records per page · Min(1), Max(100)
sortBystringcreatedAtOne of createdAt, activityType, status
sortOrder'asc' | 'desc'descSort order
{
"status": "SUCCESS",
"statusCode": 200,
"message": "Activity logs retrieved successfully",
"data": {
"data": [
{
"_id": "665f1a2b3c4d5e6f7a8b9c0d",
"userId": "770e8400-e29b-41d4-a716-446655440222",
"userEmail": "amal@example.com",
"activityType": "login",
"status": "success",
"description": "User logged in successfully",
"metadata": {},
"deviceInfo": {
"userAgent": "Mozilla/5.0 ...",
"browser": "Chrome",
"os": "Android 14",
"device": "Pixel 7",
"isMobile": true
},
"locationInfo": {
"ipAddress": "103.10.20.30",
"country": "Indonesia",
"region": "DKI Jakarta",
"city": "Jakarta",
"timezone": "Asia/Jakarta",
"coordinates": { "lat": -6.2, "lng": 106.8 }
},
"resourceId": null,
"resourceType": null,
"createdAt": "2026-05-20T08:30:00.000Z",
"updatedAt": "2026-05-20T08:30:00.000Z"
}
],
"total": 124,
"page": 1,
"limit": 20,
"totalPages": 7
}
}
StatusWhen it occurs
400 Bad RequestInvalid query param (e.g. activityType outside the enum, limit > 100)
401 UnauthorizedInvalid Bearer/cookie token
403 ForbiddenMissing read-activity-log permission

If the service throws an exception, the controller catches it and returns a body with status: "ERROR", statusCode: 500, and an error: "..." field. FE should still check statusCode before reading data.


GET /v1/activities-logs/stats bearer

Section titled “GET /v1/activities-logs/stats ”

Aggregate statistics of the logged-in user’s activities over the last N days, grouped by activityType. Good for a summary chart on a profile / security dashboard.

bearer read-activity-log-stats
ParamTypeDefaultNotes
daysnumber30Day range counted backward from today
{
"status": "SUCCESS",
"statusCode": 200,
"message": "Activity statistics retrieved successfully",
"data": [
{
"_id": "login",
"count": 12,
"lastActivity": "2026-05-20T08:30:00.000Z"
},
{
"_id": "withdrawal_request",
"count": 3,
"lastActivity": "2026-05-18T14:20:00.000Z"
}
]
}

The _id field here is the activityType (result of MongoDB’s $group), not an ObjectId. count = number of activities with that type within the days window; lastActivity = timestamp of the most recent activity.

StatusWhen it occurs
400 Bad Requestdays is not a valid number
401 UnauthorizedInvalid Bearer/cookie token
403 ForbiddenMissing read-activity-log-stats permission

  • Authentication & Securitylogin, login_new_device, login_failed, logout, password_change_request, password_changed, two_fa_enabled, two_fa_disabled
  • Account Managementaccount_created, profile_updated, email_verified
  • Financialwithdrawal_request, withdrawal_approved, withdrawal_rejected, withdrawal_completed, deposit, transfer
  • Saving Goalssaving_goal_created, saving_goal_updated, saving_goal_cancelled, saving_goal_contribution, saving_goal_withdrawal_requested, saving_goal_withdrawal_completed
  • Generalapi_access, settings_updated, document_uploaded, suspicious_activity
  • success · failed · pending · cancelled
  • _id — MongoDB ObjectId (string)
  • userId — UUID of the user owning the log
  • userEmail — user’s email (snapshot when the log was created)
  • activityType, status — the enums above
  • description — human-readable narrative
  • metadata — free-form object (context-dependent)
  • deviceInfouserAgent, browser, os, device, isMobile
  • locationInfoipAddress, country, region, city, timezone, coordinates {lat, lng}
  • resourceId, resourceType — optional, references a related entity
  • createdAt, updatedAt — ISO 8601 timestamps
{
"message": "limit must not be greater than 100",
"statusCode": 400,
"error": "Bad Request"
}