Owner Abhishek P

V1 API MCQ

Source: OpenAPI 3.1.0 spec + src/api/v1/mcq/routes.py, src/api/v1/mcq/schemas.py Tag: MCQ - MCQ questions and operations.

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


GET /mcqs/sync

Summary: List PYQ MCQs by Updated At (sync)

Retrieve a paginated list of PYQ MCQs with forward-only pagination by updated_at. Only PYQs are returned (DQ/EQ excluded). Filter by year or taxonomy_id, not both.

Parameters

NameInRequiredConstraintsDescription
course_idqueryrequiredCourseEnumCourse ID
limitqueryoptional1-120, default 10Number of results to return
yearqueryoptionalintegerFilter MCQs by year (e.g. 2023). Mutually exclusive with taxonomy_id
taxonomy_idqueryoptionalObjectId stringFilter MCQs by taxonomy ID. Mutually exclusive with year
next_cursorqueryoptionalbase64 stringForward pagination cursor from previous response
prev_cursorqueryoptionalbase64 stringBackward pagination cursor
x-dev-timeheaderoptional13 digitsEpoch ms

Conditions:

  • year and taxonomy_id are mutually exclusive. If both provided: error 1003 (INVALID_PARAMETERS) with message “Use either year or taxonomy_id, not both.”
  • taxonomy_id is converted to PydanticObjectId internally; invalid format raises error

Business Logic

  1. Decodes cursor (if provided) to get last updated_at + id
  2. Queries MCQs with: course_id, year or taxonomy_id filter, updated_at > cursor.updated_at
  3. Fetches associated blocks for each MCQ via BlockService.get_blocks_for_mcqs()
  4. Builds response with next_cursor from last item’s (updated_at, id)

Success Response

{
  "status": "success",
  "is_data_encrypted": 0,
  "data": [
    {
      "id": "60d5ec49f1b2c72e4c8b4567",
      "display_uid": "UPSC-POL-001",
      "short_uid": "M00123",
      "question": "Which article of the Indian Constitution deals with the Right to Equality?",
      "question_format": 1,
      "q_pview": "Which article of the Indian Constitution deals with the Right to Equality?",
      "option_1": "Article 12",
      "selected_option_1_count": 245,
      "option_2": "Article 14",
      "selected_option_2_count": 1893,
      "option_3": "Article 19",
      "selected_option_3_count": 312,
      "option_4": "Article 21",
      "selected_option_4_count": 189,
      "correct_option": "option_2",
      "question_type": 1,
      "year": 2023,
      "root_taxonomy_id": "60d5ec49f1b2c72e4c8b0001",
      "taxonomy_ids": [
        "60d5ec49f1b2c72e4c8b0001",
        "60d5ec49f1b2c72e4c8b0002",
        "60d5ec49f1b2c72e4c8b0003"
      ],
      "sole": "U2FsdGVkX1+abc123encrypted...",
      "sort_order": 15,
      "tag_ids": [
        "60d5ec49f1b2c72e4c8baaaa"
      ],
      "docket_id": "60d5ec49f1b2c72e4c8bdddd",
      "is_deleted": false,
      "ordered_block_ids": ["B001", "B002"],
      "block_details": [
        {
          "id": "60d5ec49f1b2c72e4c8beeee",
          "short_uid": "B001",
          "docket_id": "60d5ec49f1b2c72e4c8bdddd",
          "title": "Right to Equality - Key Provisions",
          "conte": "U2FsdGVkX1+xyz789encrypted...",
          "is_deleted": false
        }
      ]
    }
  ],
  "error": null,
  "app_actions": null,
  "pagination": {
    "next_cursor": "eyJ1cGRhdGVkX2F0IjoxNzE0NDAwMDAwMDAwLCJpZCI6IjYwZDVlYzQ5ZjFiMmM3MmU0YzhiNDU2NyJ9",
    "prev_cursor": null,
    "limit": 10,
    "has_more": true
  }
}

Field Details

FieldTypeDescription
question_formatintegerSIMPLE_MCQ=1 (plain string), ADVANCED_MCQ=2 (PlateJS JSON)
q_pviewstringPlain text preview. Simple MCQ: question with newlines as spaces. Advanced: extracted plain text
correct_optionstring"option_1", "option_2", "option_3", or "option_4"
question_typeintegerPYQ=1, DQ=2, EQ=3
taxonomy_idsarrayHierarchical order: [L1_root, L2_parent, L3_leaf]
solestring/nullAt-rest encrypted solution. Clients decrypt using short_uid-derived keys. null if no solution
docket_idObjectId/nullL4 taxonomy leaf docket. Same taxonomy_ids as this MCQ
block_details[].contestring/nullAt-rest encrypted block content (CryptoV2.1, short_uid-derived keys)
selected_option_N_countintegerHow many users selected this option (community stats)

Error Response Example

{
  "status": "failure",
  "is_data_encrypted": 0,
  "data": null,
  "error": {
    "code": 1003,
    "message": "Use either year or taxonomy_id, not both."
  },
  "app_actions": null
}

GET /mcqs/batch

Summary: Get MCQs by IDs

Retrieve up to 100 MCQs by MongoDB ObjectId or short_uid. Missing IDs are silently omitted (no error per ID).

Parameters

NameInRequiredConstraintsDescription
course_idqueryrequiredCourseEnumCourse ID
idsqueryrequiredmin 1 charComma-separated list of MCQ IDs or short UIDs
x-dev-timeheaderoptional13 digitsEpoch ms

Conditions:

  • Maximum 100 IDs per request; error 1003 if exceeded
  • Minimum 1 ID required; error 1003 if empty
  • Each ID must be <= 25 characters; error 1003 if longer
  • IDs are auto-stripped of whitespace
  • Can mix ObjectIds and short_uid values in the same request

Success Response

Same MCQDetailsListResponse[] shape as /mcqs/sync response data, but without pagination. Returns only MCQs that were found; missing IDs are omitted silently.

{
  "status": "success",
  "is_data_encrypted": 0,
  "data": [
    {
      "id": "60d5ec49f1b2c72e4c8b4567",
      "short_uid": "M00123",
      "question": "Which article of the Indian Constitution...",
      "option_1": "Article 12",
      "option_2": "Article 14",
      "option_3": "Article 19",
      "option_4": "Article 21",
      "correct_option": "option_2",
      "question_type": 1,
      "year": 2023,
      "taxonomy_ids": ["60d5ec49f1b2c72e4c8b0001", "60d5ec49f1b2c72e4c8b0002", "60d5ec49f1b2c72e4c8b0003"],
      "block_details": [ ... ]
    }
  ],
  "error": null,
  "app_actions": null
}

Error Response Example

{
  "status": "failure",
  "is_data_encrypted": 0,
  "data": null,
  "error": {
    "code": 1003,
    "message": "Maximum 100 IDs allowed per request."
  },
  "app_actions": null
}