Owner Abhishek P

V1 API User

Source: OpenAPI 3.1.0 spec + src/api/v1/user/routes.py, src/api/v1/user/schemas.py Tag: User - Profile management, phone verification, reports.

All endpoints require Bearer Token authentication. Response data is encrypted when feature flag is enabled.


GET /users/mcq-daily/sync

Summary: Sync User MCQ Daily Stats

Sync user MCQ daily stats by updated_at. Returns records updated after the cursor, filtered to day_start_epoch_ms >= sync_from_epoch_ms. Use next_cursor for next page.

Parameters

NameInRequiredConstraintsDescription
course_idqueryrequiredCourseEnumCourse ID to fetch stats for
sync_from_epoch_msqueryrequiredinteger (epoch ms)Start of day UTC. Only entries with day_start_epoch_ms >= this value
next_cursorqueryoptionalbase64 stringEncoded cursor (updated_at, id). Omit for first page
limitqueryoptional1-100, default 50Max records to return
x-dev-timeheaderoptional13 digitsEpoch ms

Success Response

{
  "status": "success",
  "is_data_encrypted": 0,
  "data": [
    {
      "id": "507f1f77bcf86cd799439011_1_1714348800000",
      "day_start_epoch_ms": 1714348800000,
      "first_attempt_total": 15,
      "first_attempt_correct": 10,
      "reattempt_total": 5,
      "reattempt_correct": 4,
      "overall_total": 20,
      "overall_correct": 14
    },
    {
      "id": "507f1f77bcf86cd799439011_1_1714262400000",
      "day_start_epoch_ms": 1714262400000,
      "first_attempt_total": 8,
      "first_attempt_correct": 6,
      "reattempt_total": 2,
      "reattempt_correct": 1,
      "overall_total": 10,
      "overall_correct": 7
    }
  ],
  "error": null,
  "app_actions": null,
  "pagination": {
    "next_cursor": "eyJ1cGRhdGVkX2F0IjoxNzE0MzQ4ODAwMDAwLCJpZCI6IjUwN2YxZjc3YmNmODZjZDc5OTQzOTAxMV8xXzE3MTQyNjI0MDAwMDAifQ==",
    "prev_cursor": null,
    "limit": 50,
    "has_more": false
  }
}
FieldDescription
idDocument ID format: {user_id}_{course_id}_{day_start_epoch_ms}
day_start_epoch_msDay start (00:00 UTC) in epoch ms
first_attempt_totalCount of first-time attempts that day
first_attempt_correctCorrect first attempts
reattempt_totalRe-attempt count
reattempt_correctCorrect re-attempts
overall_totalTotal attempts (first + re)
overall_correctTotal correct

DELETE /users

Summary: Delete User

Delete the authenticated user and log them out from all active sessions.

Parameters

NameInRequiredDescription
x-dev-timeheaderoptionalEpoch ms (13 digits)

Success Response

{
  "status": "success",
  "is_data_encrypted": 0,
  "data": {
    "id": "507f1f77bcf86cd799439011",
    "message": "Operation completed successfully."
  },
  "error": null,
  "app_actions": null
}

Error Responses

Error CodeCondition
3507User deletion failed

PATCH /users/info

Summary: Update User Info

Update user info fields. All fields are optional; only provided fields are updated.

Parameters

NameInRequiredDescription
x-dev-timeheaderoptionalEpoch ms (13 digits)

Request Body

{
  "name": {
    "first_name": "John",
    "last_name": "Doe"
  },
  "background_info": "Engineering graduate, preparing for UPSC",
  "attempt_number": 2,
  "attempt_year": 2026
}
FieldTypeConstraintsDescription
nameobjectoptional{ first_name: string, last_name: string }
background_infostringoptional, max 1000 charsEducational/professional background
attempt_numberintegeroptional, >= 1Exam attempt number
attempt_yearintegeroptional, 1900-2100Year of attempt

Conditions:

  • At least one field must be provided; error 1006 (VALIDATION_FAILED) if all fields are null/missing
  • String fields are auto-stripped of whitespace

Success Response

Returns the full UserDetailsResponse (same shape as GET /auth/me response data).


POST /users/profile-picture

Summary: Upload Profile Picture

Upload a profile picture for the authenticated user.

Request Body - multipart/form-data

FieldTypeRequiredConstraints
filebinaryrequiredJPEG, PNG, or WEBP only

Success Response

{
  "status": "success",
  "is_data_encrypted": 0,
  "data": {
    "filename": "profile_507f1f77.jpg",
    "width": 400,
    "height": 400,
    "aspect_ratio": "1:1"
  },
  "error": null,
  "app_actions": null
}

POST /users/send-phone-otp

Summary: Initiate Phone Number Validation

Send an OTP to validate the user’s phone number.

Request Body

{
  "phone_number": {
    "code": "+91",
    "value": "9876543210"
  }
}

Conditions:

  • code must be "+91" (India only)
  • value must be 10-15 digits

Success Response

{
  "status": "success",
  "is_data_encrypted": 0,
  "data": {
    "message": "OTP sent successfully",
    "expiry_time": 1714400300000,
    "oti": "b2c3d4e5-f6a7-8901-bcde-f12345678901"
  },
  "error": null,
  "app_actions": null
}

Error Responses

Error CodeCondition
3708Phone number already registered to another account

POST /users/verify-phone-otp

Summary: Verify Phone Number Validation

Verify the OTP and link the phone number to the user’s account.

Request Body

{
  "phone_number": {
    "code": "+91",
    "value": "9876543210"
  },
  "otp": "123456",
  "oti": "b2c3d4e5-f6a7-8901-bcde-f12345678901"
}

All fields required. otp length must match server-configured OTP length.

Business Logic

  1. Verifies OTP against cache using phone_number, otp, and oti
  2. Revokes the OTI (one-time use)
  3. Updates user’s phone_number and sets is_phone_validated=true

Success Response

Returns the full UserDetailsResponse with updated phone number.

Error Responses

Error CodeCondition
2002OTP is incorrect
2003OTP has expired
2008OTI has expired
3709Phone number already exists on this account

POST /users/report

Summary: Create User Report

Create a user report regarding content issues (MCQ or docket).

Parameters

NameInRequiredDescription
course_idqueryrequiredCourse ID the reported content belongs to
x-dev-timeheaderoptionalEpoch ms (13 digits)

Request Body

{
  "content_id": "60d5ec49f1b2c72e4c8b4567",
  "content_short_uid": "M01234",
  "content_type": 2,
  "issue_type": 1,
  "comments": "The correct answer for this question should be option_2, not option_3. The explanation references the wrong article."
}
FieldRequiredDescription
content_idrequiredMongoDB ObjectId of the MCQ or Docket
content_short_uidoptionalHuman-readable short UID (e.g. “M01234”)
content_typerequiredDOCKET=1, MCQ=2
issue_typerequiredDefault=1
commentsrequiredDetailed description of the issue

Success Response

{
  "status": "success",
  "is_data_encrypted": 0,
  "data": {
    "id": "60d5ec49f1b2c72e4c8baaaa",
    "message": "Operation completed successfully."
  },
  "error": null,
  "app_actions": null
}