From 161e3560dde9edf1c2bacedf2dd442dc077a8cbf Mon Sep 17 00:00:00 2001
From: Kshitij Sobti <kshitij@sobti.in>
Date: Thu, 6 May 2021 18:05:14 +0000
Subject: [PATCH] feat: Add REST endpoints for problem response report
 generation that can be driven by MFEs. (#27313)

---
 docs/swagger.yaml                           | 4633 ++++++++++++++-----
 lms/djangoapps/instructor/apps.py           |    5 +-
 lms/djangoapps/instructor/tests/test_api.py |  121 +-
 lms/djangoapps/instructor/urls.py           |   17 +
 lms/djangoapps/instructor/views/api.py      |  441 +-
 lms/djangoapps/instructor/views/api_urls.py |   14 +-
 openedx/core/lib/api/serializers.py         |    8 +-
 7 files changed, 3997 insertions(+), 1242 deletions(-)
 create mode 100644 lms/djangoapps/instructor/urls.py

diff --git a/docs/swagger.yaml b/docs/swagger.yaml
index 073d6084814..2a4b4f5fa4f 100644
--- a/docs/swagger.yaml
+++ b/docs/swagger.yaml
@@ -16,18 +16,136 @@ securityDefinitions:
 security:
   - Basic: []
 paths:
+  /badges/v1/assertions/user/{username}/:
+    get:
+      operationId: badges_v1_assertions_user_read
+      summary: '**Use Cases**'
+      description: |-
+        Request a list of assertions for a user, optionally constrained to a course.
+
+        **Example Requests**
+
+            GET /api/badges/v1/assertions/user/{username}/
+
+        **Response Values**
+
+            Body comprised of a list of objects with the following fields:
+
+            * badge_class: The badge class the assertion was awarded for. Represented as an object
+              with the following fields:
+                * slug: The identifier for the badge class
+                * issuing_component: The software component responsible for issuing this badge.
+                * display_name: The display name of the badge.
+                * course_id: The course key of the course this badge is scoped to, or null if it isn't scoped to a course.
+                * description: A description of the award and its significance.
+                * criteria: A description of what is needed to obtain this award.
+                * image_url: A URL to the icon image used to represent this award.
+            * image_url: The baked assertion image derived from the badge_class icon-- contains metadata about the award
+              in its headers.
+            * assertion_url: The URL to the OpenBadges BadgeAssertion object, for verification by compatible tools
+              and software.
+
+        **Params**
+
+            * slug (optional): The identifier for a particular badge class to filter by.
+            * issuing_component (optional): The issuing component for a particular badge class to filter by
+              (requires slug to have been specified, or this will be ignored.) If slug is provided and this is not,
+              assumes the issuing_component should be empty.
+            * course_id (optional): Returns assertions that were awarded as part of a particular course. If slug is
+              provided, and this field is not specified, assumes that the target badge has an empty course_id field.
+              '*' may be used to get all badges with the specified slug, issuing_component combination across all courses.
+
+        **Returns**
+
+            * 200 on success, with a list of Badge Assertion objects.
+            * 403 if a user who does not have permission to masquerade as
+              another user specifies a username other than their own.
+            * 404 if the specified user does not exist
+
+            {
+                "count": 7,
+                "previous": null,
+                "num_pages": 1,
+                "results": [
+                    {
+                        "badge_class": {
+                            "slug": "special_award",
+                            "issuing_component": "openedx__course",
+                            "display_name": "Very Special Award",
+                            "course_id": "course-v1:edX+DemoX+Demo_Course",
+                            "description": "Awarded for people who did something incredibly special",
+                            "criteria": "Do something incredibly special.",
+                            "image": "http://example.com/media/badge_classes/badges/special_xdpqpBv_9FYOZwN.png"
+                        },
+                        "image_url": "http://badges.example.com/media/issued/cd75b69fc1c979fcc1697c8403da2bdf.png",
+                        "assertion_url": "http://badges.example.com/public/assertions/07020647-e772-44dd-98b7-d13d34335ca6"
+                    },
+                ...
+                ]
+            }
+      parameters:
+        - name: page
+          in: query
+          description: A page number within the paginated result set.
+          required: false
+          type: integer
+        - name: page_size
+          in: query
+          description: Number of results to return per page.
+          required: false
+          type: integer
+      responses:
+        '200':
+          description: ''
+          schema:
+            required:
+              - count
+              - results
+            type: object
+            properties:
+              count:
+                type: integer
+              next:
+                type: string
+                format: uri
+                x-nullable: true
+              previous:
+                type: string
+                format: uri
+                x-nullable: true
+              results:
+                type: array
+                items:
+                  $ref: '#/definitions/BadgeAssertion'
+      tags:
+        - badges
+    parameters:
+      - name: username
+        in: path
+        required: true
+        type: string
   /bookmarks/v1/bookmarks/:
     get:
       operationId: bookmarks_v1_bookmarks_list
       summary: Get a paginated list of bookmarks for a user.
-      description: "The list can be filtered by passing parameter \"course_id=<course_id>\"\
-        \nto only include bookmarks from a particular course.\n\nThe bookmarks are\
-        \ always sorted in descending order by creation date.\n\nEach page in the\
-        \ list contains 10 bookmarks by default. The page\nsize can be altered by\
-        \ passing parameter \"page_size=<page_size>\".\n\nTo include the optional\
-        \ fields pass the values in \"fields\" parameter\nas a comma separated list.\
-        \ Possible values are:\n\n* \"display_name\"\n* \"path\"\n\n**Example Requests**\n\
-        \nGET /api/bookmarks/v1/bookmarks/?course_id={course_id1}&fields=display_name,path"
+      description: |-
+        The list can be filtered by passing parameter "course_id=<course_id>"
+        to only include bookmarks from a particular course.
+
+        The bookmarks are always sorted in descending order by creation date.
+
+        Each page in the list contains 10 bookmarks by default. The page
+        size can be altered by passing parameter "page_size=<page_size>".
+
+        To include the optional fields pass the values in "fields" parameter
+        as a comma separated list. Possible values are:
+
+        * "display_name"
+        * "path"
+
+        **Example Requests**
+
+        GET /api/bookmarks/v1/bookmarks/?course_id={course_id1}&fields=display_name,path
       parameters:
         - name: page
           in: query
@@ -55,11 +173,17 @@ paths:
     post:
       operationId: bookmarks_v1_bookmarks_create
       summary: Create a new bookmark for a user.
-      description: "The POST request only needs to contain one parameter \"usage_id\"\
-        .\n\nHttp400 is returned if the format of the request is not correct,\nthe\
-        \ usage_id is invalid or a block corresponding to the usage_id\ncould not\
-        \ be found.\n\n**Example Requests**\n\nPOST /api/bookmarks/v1/bookmarks/\n\
-        Request data: {\"usage_id\": <usage-id>}"
+      description: |-
+        The POST request only needs to contain one parameter "usage_id".
+
+        Http400 is returned if the format of the request is not correct,
+        the usage_id is invalid or a block corresponding to the usage_id
+        could not be found.
+
+        **Example Requests**
+
+        POST /api/bookmarks/v1/bookmarks/
+        Request data: {"usage_id": <usage-id>}
       parameters: []
       responses:
         '201':
@@ -71,7 +195,10 @@ paths:
     get:
       operationId: bookmarks_v1_bookmarks_read
       summary: Get a specific bookmark for a user.
-      description: "**Example Requests**\n\nGET /api/bookmarks/v1/bookmarks/{username},{usage_id}?fields=display_name,path"
+      description: |-
+        **Example Requests**
+
+        GET /api/bookmarks/v1/bookmarks/{username},{usage_id}?fields=display_name,path
       parameters: []
       responses:
         '200':
@@ -96,31 +223,209 @@ paths:
         in: path
         required: true
         type: string
+  /bulk_enroll/v1/bulk_enroll:
+    post:
+      operationId: bulk_enroll_v1_bulk_enroll_create
+      summary: '**Use Case**'
+      description: |-
+        Enroll multiple users in one or more courses.
+
+        **Example Request**
+
+            POST /api/bulk_enroll/v1/bulk_enroll/ {
+                "auto_enroll": true,
+                "email_students": true,
+                "action": "enroll",
+                "courses": "course-v1:edX+Demo+123,course-v1:edX+Demo2+456",
+                "cohorts": "cohortA,cohortA",
+                "identifiers": "brandon@example.com,yamilah@example.com"
+            }
+
+            **POST Parameters**
+
+              A POST request can include the following parameters.
+
+              * auto_enroll: When set to `true`, students will be enrolled as soon
+                as they register.
+              * email_students: When set to `true`, students will be sent email
+                notifications upon enrollment.
+              * action: Can either be set to "enroll" or "unenroll". This determines the behavior
+              * cohorts: Optional. If provided, the number of items in the list should be equal to
+                the number of courses. first cohort coressponds with the first course and so on.
+                The learners will be added to the corresponding cohort.
+
+        **Response Values**
+
+            If the supplied course data is valid and the enrollments were
+            successful, an HTTP 200 "OK" response is returned.
+
+            The HTTP 200 response body contains a list of response data for each
+            enrollment. (See the `instructor.views.api.students_update_enrollment`
+            docstring for the specifics of the response data available for each
+            enrollment)
+
+            If a cohorts list is provided, additional 'cohort' keys will be added
+            to the 'before' and 'after' states.
+      parameters: []
+      responses:
+        '201':
+          description: ''
+      tags:
+        - bulk_enroll
+    parameters: []
+  /ccx/v0/ccx/:
+    get:
+      operationId: ccx_v0_ccx_list
+      summary: Gets a list of CCX Courses for a given Master Course.
+      description: Additional parameters are allowed for pagination purposes.
+      parameters:
+        - name: page
+          in: query
+          description: A page number within the paginated result set.
+          required: false
+          type: integer
+        - name: page_size
+          in: query
+          description: Number of results to return per page.
+          required: false
+          type: integer
+      responses:
+        '200':
+          description: ''
+          schema:
+            required:
+              - count
+              - results
+            type: object
+            properties:
+              count:
+                type: integer
+              next:
+                type: string
+                format: uri
+                x-nullable: true
+              previous:
+                type: string
+                format: uri
+                x-nullable: true
+              results:
+                type: array
+                items:
+                  $ref: '#/definitions/CCXCourse'
+      tags:
+        - ccx
+    post:
+      operationId: ccx_v0_ccx_create
+      description: Creates a new CCX course for a given Master Course.
+      parameters:
+        - name: data
+          in: body
+          required: true
+          schema:
+            $ref: '#/definitions/CCXCourse'
+      responses:
+        '201':
+          description: ''
+          schema:
+            $ref: '#/definitions/CCXCourse'
+      tags:
+        - ccx
+    parameters: []
+  /ccx/v0/ccx/{ccx_course_id}/:
+    get:
+      operationId: ccx_v0_ccx_read
+      description: Gets a CCX Course information.
+      parameters: []
+      responses:
+        '200':
+          description: ''
+          schema:
+            $ref: '#/definitions/CCXCourse'
+      tags:
+        - ccx
+    patch:
+      operationId: ccx_v0_ccx_partial_update
+      description: Modifies a CCX course.
+      parameters:
+        - name: data
+          in: body
+          required: true
+          schema:
+            $ref: '#/definitions/CCXCourse'
+      responses:
+        '200':
+          description: ''
+          schema:
+            $ref: '#/definitions/CCXCourse'
+      tags:
+        - ccx
+    delete:
+      operationId: ccx_v0_ccx_delete
+      description: Deletes a CCX course.
+      parameters: []
+      responses:
+        '204':
+          description: ''
+      tags:
+        - ccx
+    parameters:
+      - name: ccx_course_id
+        in: path
+        required: true
+        type: string
   /certificates/v0/certificates/{username}/:
     get:
       operationId: certificates_v0_certificates_read
       summary: Get a paginated list of bookmarks for a user.
-      description: "**Use Case**\n\nGet the list of viewable course certificates for\
-        \ a specific user.\n\n**Example Request**\n\nGET /api/certificates/v0/certificates/{username}\n\
-        \n**GET Response Values**\n\n    If the request for information about the\
-        \ user's certificates is successful,\n    an HTTP 200 \"OK\" response is returned.\n\
-        \n    The HTTP 200 response contains a list of dicts with the following keys/values.\n\
-        \n    * username: A string representation of an user's username passed in\
-        \ the request.\n\n    * course_id: A string representation of a Course ID.\n\
-        \n    * course_display_name: A string representation of the Course name.\n\
-        \n    * course_organization: A string representation of the organization associated\
-        \ with the Course.\n\n    * certificate_type: A string representation of the\
-        \ certificate type.\n        Can be honor|verified|professional\n\n    * created_date:\
-        \ Date/time the certificate was created, in ISO-8661 format.\n\n    * status:\
-        \ A string representation of the certificate status.\n\n    * is_passing:\
-        \ True if the certificate has a passing status, False if not.\n\n    * download_url:\
-        \ A string representation of the certificate url.\n\n    * grade: A string\
-        \ representation of a float for the user's course grade.\n\n**Example GET\
-        \ Response**\n\n    [{\n        \"username\": \"bob\",\n        \"course_id\"\
-        : \"edX/DemoX/Demo_Course\",\n        \"certificate_type\": \"verified\",\n\
-        \        \"created_date\": \"2015-12-03T13:14:28+0000\",\n        \"status\"\
-        : \"downloadable\",\n        \"is_passing\": true,\n        \"download_url\"\
-        : \"http://www.example.com/cert.pdf\",\n        \"grade\": \"0.98\"\n    }]"
+      description: |-
+        **Use Case**
+
+        Get the list of viewable course certificates for a specific user.
+
+        **Example Request**
+
+        GET /api/certificates/v0/certificates/{username}
+
+        **GET Response Values**
+
+            If the request for information about the user's certificates is successful,
+            an HTTP 200 "OK" response is returned.
+
+            The HTTP 200 response contains a list of dicts with the following keys/values.
+
+            * username: A string representation of an user's username passed in the request.
+
+            * course_id: A string representation of a Course ID.
+
+            * course_display_name: A string representation of the Course name.
+
+            * course_organization: A string representation of the organization associated with the Course.
+
+            * certificate_type: A string representation of the certificate type.
+                Can be honor|verified|professional
+
+            * created_date: Date/time the certificate was created, in ISO-8661 format.
+
+            * status: A string representation of the certificate status.
+
+            * is_passing: True if the certificate has a passing status, False if not.
+
+            * download_url: A string representation of the certificate url.
+
+            * grade: A string representation of a float for the user's course grade.
+
+        **Example GET Response**
+
+            [{
+                "username": "bob",
+                "course_id": "edX/DemoX/Demo_Course",
+                "certificate_type": "verified",
+                "created_date": "2015-12-03T13:14:28+0000",
+                "status": "downloadable",
+                "is_passing": true,
+                "download_url": "http://www.example.com/cert.pdf",
+                "grade": "0.98"
+            }]
       parameters:
         - name: username
           in: path
@@ -267,9 +572,10 @@ paths:
   /cohorts/v1/courses/{course_key_string}/users:
     post:
       operationId: cohorts_v1_courses_users_create
-      description: "View method that accepts an uploaded file (using key \"uploaded-file\"\
-        )\ncontaining cohort assignments for users. This method spawns a celery task\n\
-        to do the assignments, and a CSV file with results is provided via data downloads."
+      description: |-
+        View method that accepts an uploaded file (using key "uploaded-file")
+        containing cohort assignments for users. This method spawns a celery task
+        to do the assignments, and a CSV file with results is provided via data downloads.
       parameters: []
       responses:
         '201':
@@ -426,13 +732,32 @@ paths:
     post:
       operationId: completion_v1_completion-batch_create
       summary: Inserts a batch of completions.
-      description: "REST Endpoint Format:\n```\n{\n  \"username\": \"username\",\n\
-        \  \"course_key\": \"course-key\",\n  \"blocks\": {\n    \"block_key1\": 0.0,\n\
-        \    \"block_key2\": 1.0,\n    \"block_key3\": 1.0,\n  }\n}\n```\n\n**Returns**\n\
-        \nA Response object, with an appropriate status code.\n\nIf successful, status\
-        \ code is 200.\n```\n{\n   \"detail\" : _(\"ok\")\n}\n```\n\nOtherwise, a\
-        \ 400 or 404 may be returned, and the \"detail\" content will explain the\
-        \ error."
+      description: |-
+        REST Endpoint Format:
+        ```
+        {
+          "username": "username",
+          "course_key": "course-key",
+          "blocks": {
+            "block_key1": 0.0,
+            "block_key2": 1.0,
+            "block_key3": 1.0,
+          }
+        }
+        ```
+
+        **Returns**
+
+        A Response object, with an appropriate status code.
+
+        If successful, status code is 200.
+        ```
+        {
+           "detail" : _("ok")
+        }
+        ```
+
+        Otherwise, a 400 or 404 may be returned, and the "detail" content will explain the error.
       parameters: []
       responses:
         '201':
@@ -467,17 +792,28 @@ paths:
   : get:
       operationId: course_experience_v1_course_deadlines_info_+]+api_course_experience_v1_course_deadlines_info_+]+(_|+)[_]+)_read
       summary: '**Use Cases**'
-      description: "Request course deadline info for mobile\n\n**Example Requests**\n\
-        \n    GET api/course_experience/v1/course_deadlines_info/{course_key}\n\n\
-        **Response Values**\n\n    Body consists of the following fields:\n\n    dates_banner_info:\
-        \ (obj)\n        missed_deadlines: (bool) Whether the user has missed any\
-        \ graded content deadlines for the given course.\n        missed_gated_content:\
-        \ (bool) Whether the user has missed any gated content for the given course.\n\
-        \        content_type_gating_enabled: (bool) Whether content type gating is\
-        \ enabled for this enrollment.\n        verified_upgrade_link: (str) The URL\
-        \ to ecommerce IDA for purchasing the verified upgrade.\n\n**Returns**\n\n\
-        \    * 200 on success with above fields.\n    * 401 if the user is not authenticated.\n\
-        \    * 404 if the course is not available or cannot be seen."
+      description: |-
+        Request course deadline info for mobile
+
+        **Example Requests**
+
+            GET api/course_experience/v1/course_deadlines_info/{course_key}
+
+        **Response Values**
+
+            Body consists of the following fields:
+
+            dates_banner_info: (obj)
+                missed_deadlines: (bool) Whether the user has missed any graded content deadlines for the given course.
+                missed_gated_content: (bool) Whether the user has missed any gated content for the given course.
+                content_type_gating_enabled: (bool) Whether content type gating is enabled for this enrollment.
+                verified_upgrade_link: (str) The URL to ecommerce IDA for purchasing the verified upgrade.
+
+        **Returns**
+
+            * 200 on success with above fields.
+            * 401 if the user is not authenticated.
+            * 404 if the course is not available or cannot be seen.
       parameters: []
       responses:
         '200':
@@ -498,7 +834,17 @@ paths:
   /course_experience/v1/reset_course_deadlines:
     post:
       operationId: course_experience_v1_reset_course_deadlines_create
-      description: ''
+      description: |-
+        Set the start_date of a schedule to today, which in turn will adjust due dates for
+        sequentials belonging to a self paced course
+
+        Request Parameters:
+            course_key: course key
+            research_event_data: any data that should be included in the research tracking event
+                Example: sending the location of where the reset deadlines banner (i.e. outline-tab)
+
+        IMPORTANT NOTE: If updates are happening to the logic here, ALSO UPDATE the `reset_course_deadlines`
+        function in common/djangoapps/util/views.py as well.
       parameters: []
       responses:
         '201':
@@ -510,13 +856,20 @@ paths:
     get:
       operationId: course_goals_v0_course_goals_list
       summary: API calls to create and update a course goal.
-      description: "Validates incoming data to ensure that course_key maps to an actual\n\
-        course and that the goal_key is a valid option.\n\n**Use Case**\n    * Create\
-        \ a new goal for a user.\n    * Update an existing goal for a user\n\n**Example\
-        \ Requests**\n    POST /api/course_goals/v0/course_goals/\n        Request\
-        \ data: {\"course_key\": <course-key>, \"goal_key\": \"<goal-key>\", \"user\"\
-        : \"<username>\"}\n\nReturns Http400 response if the course_key does not map\
-        \ to a known\ncourse or if the goal_key does not map to a valid goal key."
+      description: |-
+        Validates incoming data to ensure that course_key maps to an actual
+        course and that the goal_key is a valid option.
+
+        **Use Case**
+            * Create a new goal for a user.
+            * Update an existing goal for a user
+
+        **Example Requests**
+            POST /api/course_goals/v0/course_goals/
+                Request data: {"course_key": <course-key>, "goal_key": "<goal-key>", "user": "<username>"}
+
+        Returns Http400 response if the course_key does not map to a known
+        course or if the goal_key does not map to a valid goal key.
       parameters:
         - name: page
           in: query
@@ -575,13 +928,20 @@ paths:
     get:
       operationId: course_goals_v0_course_goals_read
       summary: API calls to create and update a course goal.
-      description: "Validates incoming data to ensure that course_key maps to an actual\n\
-        course and that the goal_key is a valid option.\n\n**Use Case**\n    * Create\
-        \ a new goal for a user.\n    * Update an existing goal for a user\n\n**Example\
-        \ Requests**\n    POST /api/course_goals/v0/course_goals/\n        Request\
-        \ data: {\"course_key\": <course-key>, \"goal_key\": \"<goal-key>\", \"user\"\
-        : \"<username>\"}\n\nReturns Http400 response if the course_key does not map\
-        \ to a known\ncourse or if the goal_key does not map to a valid goal key."
+      description: |-
+        Validates incoming data to ensure that course_key maps to an actual
+        course and that the goal_key is a valid option.
+
+        **Use Case**
+            * Create a new goal for a user.
+            * Update an existing goal for a user
+
+        **Example Requests**
+            POST /api/course_goals/v0/course_goals/
+                Request data: {"course_key": <course-key>, "goal_key": "<goal-key>", "user": "<username>"}
+
+        Returns Http400 response if the course_key does not map to a known
+        course or if the goal_key does not map to a valid goal key.
       parameters: []
       responses:
         '200':
@@ -593,13 +953,20 @@ paths:
     put:
       operationId: course_goals_v0_course_goals_update
       summary: API calls to create and update a course goal.
-      description: "Validates incoming data to ensure that course_key maps to an actual\n\
-        course and that the goal_key is a valid option.\n\n**Use Case**\n    * Create\
-        \ a new goal for a user.\n    * Update an existing goal for a user\n\n**Example\
-        \ Requests**\n    POST /api/course_goals/v0/course_goals/\n        Request\
-        \ data: {\"course_key\": <course-key>, \"goal_key\": \"<goal-key>\", \"user\"\
-        : \"<username>\"}\n\nReturns Http400 response if the course_key does not map\
-        \ to a known\ncourse or if the goal_key does not map to a valid goal key."
+      description: |-
+        Validates incoming data to ensure that course_key maps to an actual
+        course and that the goal_key is a valid option.
+
+        **Use Case**
+            * Create a new goal for a user.
+            * Update an existing goal for a user
+
+        **Example Requests**
+            POST /api/course_goals/v0/course_goals/
+                Request data: {"course_key": <course-key>, "goal_key": "<goal-key>", "user": "<username>"}
+
+        Returns Http400 response if the course_key does not map to a known
+        course or if the goal_key does not map to a valid goal key.
       parameters:
         - name: data
           in: body
@@ -616,13 +983,20 @@ paths:
     patch:
       operationId: course_goals_v0_course_goals_partial_update
       summary: API calls to create and update a course goal.
-      description: "Validates incoming data to ensure that course_key maps to an actual\n\
-        course and that the goal_key is a valid option.\n\n**Use Case**\n    * Create\
-        \ a new goal for a user.\n    * Update an existing goal for a user\n\n**Example\
-        \ Requests**\n    POST /api/course_goals/v0/course_goals/\n        Request\
-        \ data: {\"course_key\": <course-key>, \"goal_key\": \"<goal-key>\", \"user\"\
-        : \"<username>\"}\n\nReturns Http400 response if the course_key does not map\
-        \ to a known\ncourse or if the goal_key does not map to a valid goal key."
+      description: |-
+        Validates incoming data to ensure that course_key maps to an actual
+        course and that the goal_key is a valid option.
+
+        **Use Case**
+            * Create a new goal for a user.
+            * Update an existing goal for a user
+
+        **Example Requests**
+            POST /api/course_goals/v0/course_goals/
+                Request data: {"course_key": <course-key>, "goal_key": "<goal-key>", "user": "<username>"}
+
+        Returns Http400 response if the course_key does not map to a known
+        course or if the goal_key does not map to a valid goal key.
       parameters:
         - name: data
           in: body
@@ -639,13 +1013,20 @@ paths:
     delete:
       operationId: course_goals_v0_course_goals_delete
       summary: API calls to create and update a course goal.
-      description: "Validates incoming data to ensure that course_key maps to an actual\n\
-        course and that the goal_key is a valid option.\n\n**Use Case**\n    * Create\
-        \ a new goal for a user.\n    * Update an existing goal for a user\n\n**Example\
-        \ Requests**\n    POST /api/course_goals/v0/course_goals/\n        Request\
-        \ data: {\"course_key\": <course-key>, \"goal_key\": \"<goal-key>\", \"user\"\
-        : \"<username>\"}\n\nReturns Http400 response if the course_key does not map\
-        \ to a known\ncourse or if the goal_key does not map to a valid goal key."
+      description: |-
+        Validates incoming data to ensure that course_key maps to an actual
+        course and that the goal_key is a valid option.
+
+        **Use Case**
+            * Create a new goal for a user.
+            * Update an existing goal for a user
+
+        **Example Requests**
+            POST /api/course_goals/v0/course_goals/
+                Request data: {"course_key": <course-key>, "goal_key": "<goal-key>", "user": "<username>"}
+
+        Returns Http400 response if the course_key does not map to a known
+        course or if the goal_key does not map to a valid goal key.
       parameters: []
       responses:
         '204':
@@ -662,22 +1043,39 @@ paths:
   : get:
       operationId: course_home_v1_course_metadata_+]+api_course_home_v1_course_metadata_+]+(_|+)[_]+)_read
       summary: '**Use Cases**'
-      description: "Request Course metadata details for the Course Home MFE that every\
-        \ page needs.\n\n**Example Requests**\n\n    GET api/course_home/v1/course_metadata/{course_key}\n\
-        \n**Response Values**\n\n    Body consists of the following fields:\n\n  \
-        \  course_id: (str) The Course's id (Course Run key)\n    is_enrolled: (bool)\
-        \ Indicates if the user is enrolled in the course\n    is_self_paced: (bool)\
-        \ Indicates if the course is self paced\n    is_staff: (bool) Indicates if\
-        \ the user is staff\n    original_user_is_staff: (bool) Indicates if the original\
-        \ user has staff access\n        Used for when masquerading to distinguish\
-        \ between the original requesting user\n        and the user being masqueraded\
-        \ as.\n    number: (str) The Course's number\n    org: (str) The Course's\
-        \ organization\n    tabs: List of Course Tabs to display. They are serialized\
-        \ as:\n        tab_id: (str) The tab's id\n        title: (str) The title\
-        \ of the tab to display\n        url: (str) The url to view the tab\n    title:\
-        \ (str) The Course's display title\n\n**Returns**\n\n    * 200 on success\
-        \ with above fields.\n    * 404 if the course is not available or cannot be\
-        \ seen."
+      description: |-
+        Request Course metadata details for the Course Home MFE that every page needs.
+
+        **Example Requests**
+
+            GET api/course_home/v1/course_metadata/{course_key}
+
+        **Response Values**
+
+            Body consists of the following fields:
+
+            course_id: (str) The Course's id (Course Run key)
+            username: (str) The requesting (or masqueraded) user. Returns None for an
+                unauthenticated user.
+            is_enrolled: (bool) Indicates if the user is enrolled in the course
+            is_self_paced: (bool) Indicates if the course is self paced
+            is_staff: (bool) Indicates if the user is staff
+            original_user_is_staff: (bool) Indicates if the original user has staff access
+                Used for when masquerading to distinguish between the original requesting user
+                and the user being masqueraded as.
+            number: (str) The Course's number
+            org: (str) The Course's organization
+            tabs: List of Course Tabs to display. They are serialized as:
+                tab_id: (str) The tab's id
+                title: (str) The title of the tab to display
+                url: (str) The url to view the tab
+            title: (str) The Course's display title
+            celebrations: (dict) a dict of celebration data
+
+        **Returns**
+
+            * 200 on success with above fields.
+            * 404 if the course is not available or cannot be seen.
       parameters: []
       responses:
         '200':
@@ -699,29 +1097,41 @@ paths:
   : get:
       operationId: course_home_v1_dates_+]+api_course_home_v1_dates_+]+(_|+)[_]+)_read
       summary: '**Use Cases**'
-      description: "Request details for the Dates Tab\n\n**Example Requests**\n\n\
-        \    GET api/course_home/v1/dates/{course_key}\n\n**Response Values**\n\n\
-        \    Body consists of the following fields:\n\n    course_date_blocks: List\
-        \ of serialized DateSummary objects. Each serialization has the following\
-        \ fields:\n        complete: (bool) Meant to only be used by assignments.\
-        \ Indicates completeness for an\n            assignment.\n        date: (datetime)\
-        \ The date time corresponding for the event\n        date_type: (str) The\
-        \ type of date (ex. course-start-date, assignment-due-date, etc.)\n      \
-        \  description: (str) The description for the date event\n        learner_has_access:\
-        \ (bool) Indicates if the learner has access to the date event\n        link:\
-        \ (str) An absolute link to content related to the date event\n          \
-        \  (ex. verified link or link to assignment)\n        title: (str) The title\
-        \ of the date event\n    dates_banner_info: (obj)\n        content_type_gating_enabled:\
-        \ (bool) Whether content type gating is enabled for this enrollment.\n   \
-        \     missed_deadlines: (bool) Indicates whether the user missed any graded\
-        \ content deadlines\n        missed_gated_content: (bool) Indicates whether\
-        \ the user missed gated content\n        verified_upgrade_link: (str) The\
-        \ link for upgrading to the Verified track in a course\n    has_ended: (bool)\
-        \ Indicates whether course has ended\n    learner_is_full_access: (bool) Indicates\
-        \ if the user is verified in the course\n    user_timezone: (str) The user's\
-        \ preferred timezone\n\n**Returns**\n\n    * 200 on success with above fields.\n\
-        \    * 401 if the user is not authenticated.\n    * 404 if the course is not\
-        \ available or cannot be seen."
+      description: |-
+        Request details for the Dates Tab
+
+        **Example Requests**
+
+            GET api/course_home/v1/dates/{course_key}
+
+        **Response Values**
+
+            Body consists of the following fields:
+
+            course_date_blocks: List of serialized DateSummary objects. Each serialization has the following fields:
+                complete: (bool) Meant to only be used by assignments. Indicates completeness for an
+                    assignment.
+                date: (datetime) The date time corresponding for the event
+                date_type: (str) The type of date (ex. course-start-date, assignment-due-date, etc.)
+                description: (str) The description for the date event
+                learner_has_access: (bool) Indicates if the learner has access to the date event
+                link: (str) An absolute link to content related to the date event
+                    (ex. verified link or link to assignment)
+                title: (str) The title of the date event
+            dates_banner_info: (obj)
+                content_type_gating_enabled: (bool) Whether content type gating is enabled for this enrollment.
+                missed_deadlines: (bool) Indicates whether the user missed any graded content deadlines
+                missed_gated_content: (bool) Indicates whether the user missed gated content
+                verified_upgrade_link: (str) The link for upgrading to the Verified track in a course
+            has_ended: (bool) Indicates whether course has ended
+            learner_is_full_access: (bool) Indicates if the user is verified in the course
+            user_timezone: (str) The user's preferred timezone
+
+        **Returns**
+
+            * 200 on success with above fields.
+            * 401 if the user is not authenticated.
+            * 404 if the course is not available or cannot be seen.
       parameters: []
       responses:
         '200':
@@ -754,54 +1164,83 @@ paths:
   : get:
       operationId: course_home_v1_outline_+]+api_course_home_v1_outline_+]+(_|+)[_]+)_read
       summary: '**Use Cases**'
-      description: "Request details for the Outline Tab\n\n**Example Requests**\n\n\
-        \    GET api/course_home/v1/outline/{course_key}\n\n**Response Values**\n\n\
-        \    Body consists of the following fields:\n\n    course_blocks:\n      \
-        \  blocks: List of serialized Course Block objects. Each serialization has\
-        \ the following fields:\n            id: (str) The usage ID of the block.\n\
-        \            type: (str) The type of block. Possible values the names of any\n\
-        \                XBlock type in the system, including custom blocks. Examples\
-        \ are\n                course, chapter, sequential, vertical, html, problem,\
-        \ video, and\n                discussion.\n            display_name: (str)\
-        \ The display name of the block.\n            lms_web_url: (str) The URL to\
-        \ the navigational container of the\n                xBlock on the web LMS.\n\
-        \            children: (list) If the block has child blocks, a list of IDs\
-        \ of\n                the child blocks.\n            resume_block: (bool)\
-        \ Whether the block is the resume block\n    course_goals:\n        goal_options:\
-        \ (list) A list of goals where each goal is represented as a tuple (goal_key,\
-        \ goal_string)\n        selected_goal:\n            key: (str) The unique\
-        \ id given to the user's selected goal.\n            text: (str) The display\
-        \ text for the user's selected goal.\n    course_tools: List of serialized\
-        \ Course Tool objects. Each serialization has the following fields:\n    \
-        \    analytics_id: (str) The unique id given to the tool.\n        title:\
-        \ (str) The display title of the tool.\n        url: (str) The link to access\
-        \ the tool.\n    dates_banner_info: (obj)\n        content_type_gating_enabled:\
-        \ (bool) Whether content type gating is enabled for this enrollment.\n   \
-        \     missed_deadlines: (bool) Whether the user has missed any graded content\
-        \ deadlines for the given course.\n        missed_gated_content: (bool) Whether\
-        \ the user has missed any gated content for the given course.\n        verified_upgrade_link:\
-        \ (str) The URL to ecommerce IDA for purchasing the verified upgrade.\n  \
-        \  dates_widget:\n        course_date_blocks: List of serialized Course Dates\
-        \ objects. Each serialization has the following fields:\n            complete:\
-        \ (bool) Meant to only be used by assignments. Indicates completeness for\
-        \ an\n            assignment.\n            date: (datetime) The date time\
-        \ corresponding for the event\n            date_type: (str) The type of date\
-        \ (ex. course-start-date, assignment-due-date, etc.)\n            description:\
-        \ (str) The description for the date event\n            learner_has_access:\
-        \ (bool) Indicates if the learner has access to the date event\n         \
-        \   link: (str) An absolute link to content related to the date event\n  \
-        \              (ex. verified link or link to assignment)\n            title:\
-        \ (str) The title of the date event\n        dates_tab_link: (str) The URL\
-        \ to the Dates Tab\n        user_timezone: (str) The timezone of the given\
-        \ user\n    enroll_alert:\n        can_enroll: (bool) Whether the user can\
-        \ enroll in the given course\n        extra_text: (str)\n    handouts_html:\
-        \ (str) Raw HTML for the handouts section of the course info\n    has_ended:\
-        \ (bool) Indicates whether course has ended\n    resume_course:\n        has_visited_course:\
-        \ (bool) Whether the user has ever visited the course\n        url: (str)\
-        \ The display name of the course block to resume\n    welcome_message_html:\
-        \ (str) Raw HTML for the course updates banner\n\n**Returns**\n\n    * 200\
-        \ on success with above fields.\n    * 403 if the user is not authenticated.\n\
-        \    * 404 if the course is not available or cannot be seen."
+      description: |-
+        Request details for the Outline Tab
+
+        **Example Requests**
+
+            GET api/course_home/v1/outline/{course_key}
+
+        **Response Values**
+
+            Body consists of the following fields:
+
+            access_expiration: An object detailing when access to this course will expire
+                expiration_date: (str) When the access expires, in ISO 8601 notation
+                masquerading_expired_course: (bool) Whether this course is expired for the masqueraded user
+                upgrade_deadline: (str) Last chance to upgrade, in ISO 8601 notation (or None if can't upgrade anymore)
+                upgrade_url: (str) Upgrade linke (or None if can't upgrade anymore)
+            course_blocks:
+                blocks: List of serialized Course Block objects. Each serialization has the following fields:
+                    id: (str) The usage ID of the block.
+                    type: (str) The type of block. Possible values the names of any
+                        XBlock type in the system, including custom blocks. Examples are
+                        course, chapter, sequential, vertical, html, problem, video, and
+                        discussion.
+                    display_name: (str) The display name of the block.
+                    lms_web_url: (str) The URL to the navigational container of the
+                        xBlock on the web LMS.
+                    children: (list) If the block has child blocks, a list of IDs of
+                        the child blocks.
+                    resume_block: (bool) Whether the block is the resume block
+            course_goals:
+                goal_options: (list) A list of goals where each goal is represented as a tuple (goal_key, goal_string)
+                selected_goal:
+                    key: (str) The unique id given to the user's selected goal.
+                    text: (str) The display text for the user's selected goal.
+            course_tools: List of serialized Course Tool objects. Each serialization has the following fields:
+                analytics_id: (str) The unique id given to the tool.
+                title: (str) The display title of the tool.
+                url: (str) The link to access the tool.
+            dates_banner_info: (obj)
+                content_type_gating_enabled: (bool) Whether content type gating is enabled for this enrollment.
+                missed_deadlines: (bool) Whether the user has missed any graded content deadlines for the given course.
+                missed_gated_content: (bool) Whether the user has missed any gated content for the given course.
+                verified_upgrade_link: (str) The URL to ecommerce IDA for purchasing the verified upgrade.
+            dates_widget:
+                course_date_blocks: List of serialized Course Dates objects. Each serialization has the following fields:
+                    complete: (bool) Meant to only be used by assignments. Indicates completeness for an
+                    assignment.
+                    date: (datetime) The date time corresponding for the event
+                    date_type: (str) The type of date (ex. course-start-date, assignment-due-date, etc.)
+                    description: (str) The description for the date event
+                    learner_has_access: (bool) Indicates if the learner has access to the date event
+                    link: (str) An absolute link to content related to the date event
+                        (ex. verified link or link to assignment)
+                    title: (str) The title of the date event
+                dates_tab_link: (str) The URL to the Dates Tab
+                user_timezone: (str) The timezone of the given user
+            enroll_alert:
+                can_enroll: (bool) Whether the user can enroll in the given course
+                extra_text: (str)
+            handouts_html: (str) Raw HTML for the handouts section of the course info
+            has_ended: (bool) Indicates whether course has ended
+            offer: An object detailing upgrade discount information
+                code: (str) Checkout code
+                expiration_date: (str) Expiration of offer, in ISO 8601 notation
+                original_price: (str) Full upgrade price without checkout code; includes currency symbol
+                discounted_price: (str) Upgrade price with checkout code; includes currency symbol
+                percentage: (int) Amount of discount
+                upgrade_url: (str) Checkout URL
+            resume_course:
+                has_visited_course: (bool) Whether the user has ever visited the course
+                url: (str) The display name of the course block to resume
+            welcome_message_html: (str) Raw HTML for the course updates banner
+
+        **Returns**
+
+            * 200 on success with above fields.
+            * 404 if the course is not available or cannot be seen.
       parameters: []
       responses:
         '200':
@@ -823,51 +1262,70 @@ paths:
   : get:
       operationId: course_home_v1_progress_+]+api_course_home_v1_progress_+]+(_|+)[_]+)_read
       summary: '**Use Cases**'
-      description: "Request details for the Progress Tab\n\n**Example Requests**\n\
-        \n    GET api/course_home/v1/progress/{course_key}\n\n**Response Values**\n\
-        \n    Body consists of the following fields:\n\n    certificate_data: Object\
-        \ containing information about the user's certificate status\n        cert_web_view_url:\
-        \ (str) the url to view the certificate\n        download_url: (str) the url\
-        \ to download the certificate\n        is_downloadable: (bool) true if the\
-        \ status is downloadable and the download url is not None\n        is_requestable:\
-        \ (bool) true if status is requesting and request_cert_url is not None\n \
-        \       msg: (str) message for the certificate status\n        title: (str)\
-        \ title of the certificate status\n    credit_course_requirements: An object\
-        \ containing the following fields\n        dashboard_url: (str) the url to\
-        \ the user's dashboard\n        eligibility_status: (str) the user's eligibility\
-        \ to receive a course credit\n        requirements: object containing the\
-        \ following fields\n            display_name: (str) the name of the requirement\
-        \ that should be displayed\n            namespace: (str) the type that the\
-        \ requirement is\n            min_grade: (float) the percentage formatted\
-        \ minimum grade needed for this requirement\n            status: (str) the\
-        \ status of the requirement\n            status_date: (str) the date the status\
-        \ was set\n    credit_support_url: (str) the url to the support docs for purchasing\
-        \ a credit\n    courseware_summary: List of serialized Chapters. each Chapter\
-        \ has the following fields:\n        display_name: (str) a str of what the\
-        \ name of the Chapter is for displaying on the site\n        subsections:\
-        \ List of serialized Subsections, each has the following fields:\n       \
-        \     display_name: (str) a str of what the name of the Subsection is for\
-        \ displaying on the site\n            due: (str) a DateTime string for when\
-        \ the Subsection is due\n            format: (str) the format, if any, of\
-        \ the Subsection (Homework, Exam, etc)\n            graded: (bool) whether\
-        \ or not the Subsection is graded\n            graded_total: an object containing\
-        \ the following fields\n                earned: (float) the amount of points\
-        \ the user earned\n                possible: (float) the amount of points\
-        \ the user could have earned\n            percent_graded: (float) the percentage\
-        \ of the points the user received for the subsection\n            show_correctness:\
-        \ (str) a str representing whether to show the problem/practice scores based\
-        \ on due date\n            show_grades: (bool) a bool for whether to show\
-        \ grades based on the access the user has\n            url: (str) the absolute\
-        \ path url to the Subsection\n    enrollment_mode: (str) a str representing\
-        \ the enrollment the user has ('audit', 'verified', ...)\n    studio_url:\
-        \ (str) a str of the link to the grading in studio for the course\n    user_timezone:\
-        \ (str) The user's preferred timezone\n    verification_data: an object containing\n\
-        \        link: (str) the link to either start or retry verification\n    \
-        \    status: (str) the status of the verification\n        status_date: (str)\
-        \ the date time string of when the verification status was set\n\n\n\n**Returns**\n\
-        \n    * 200 on success with above fields.\n    * 302 if the user is not enrolled.\n\
-        \    * 403 if the user is not authenticated.\n    * 404 if the course is not\
-        \ available or cannot be seen."
+      description: |-
+        Request details for the Progress Tab
+
+        **Example Requests**
+
+            GET api/course_home/v1/progress/{course_key}
+
+        **Response Values**
+
+            Body consists of the following fields:
+
+            end: (date) end date of the course
+            user_has_passing_grade: (bool) boolean on if the user has a passing grade in the course
+            has_scheduled_content: (bool) boolean on if the course has content scheduled with a release date in the future
+            certificate_data: Object containing information about the user's certificate status
+                cert_status: (str) the status of a user's certificate (full list of statuses are defined in
+                             lms/djangoapps/certificates/models.py)
+                cert_web_view_url: (str) the url to view the certificate
+                download_url: (str) the url to download the certificate
+            completion_summary: Object containing unit completion counts with the following fields:
+                complete_count: (float) number of complete units
+                incomplete_count: (float) number of incomplete units
+                locked_count: (float) number of units where contains_gated_content is True
+            course_grade: Object containing the following fields:
+                is_passing: (bool) whether the user's grade is above the passing grade cutoff
+                letter_grade: (str) the user's letter grade based on the set grade range.
+                                    If user is passing, value may be 'A', 'B', 'C', 'D', 'Pass', otherwise none
+                percent: (float) the user's total graded percent in the course
+            section_scores: List of serialized Chapters. Each Chapter has the following fields:
+                display_name: (str) a str of what the name of the Chapter is for displaying on the site
+                subsections: List of serialized Subsections, each has the following fields:
+                    assignment_type: (str) the format, if any, of the Subsection (Homework, Exam, etc)
+                    display_name: (str) a str of what the name of the Subsection is for displaying on the site
+                    has_graded_assignment: (bool) whether or not the Subsection is a graded assignment
+                    num_points_earned: (int) the amount of points the user has earned for the given subsection
+                    num_points_possible: (int) the total amount of points possible for the given subsection
+                    percent_graded: (float) the percentage of total points the user has received a grade for in a given subsection
+                    show_correctness: (str) a str representing whether to show the problem/practice scores based on due date
+                                      ('always', 'never', 'past_due', values defined in
+                                       common/lib/xmodule/xmodule/modulestore/inheritance.py)
+                    show_grades: (bool) a bool for whether to show grades based on the access the user has
+                    url: (str) the absolute path url to the Subsection
+            enrollment_mode: (str) a str representing the enrollment the user has ('audit', 'verified', ...)
+            grading_policy:
+                assignment_policies: List of serialized assignment grading policy objects, each has the following fields:
+                    num_droppable: (int) the number of lowest scored assignments that will not be counted towards the final grade
+                    short_label: (str) the abbreviated name given to the assignment type
+                    type: (str) the assignment type
+                    weight: (float) the percent weight the given assigment type has on the overall grade
+                grade_range: an object containing the grade range cutoffs. The exact keys in the object can vary, but they
+                             range from just 'Pass', to a combination of 'A', 'B', 'C', and 'D'. If a letter grade is present,
+                             'Pass' is not included.
+            studio_url: (str) a str of the link to the grading in studio for the course
+            verification_data: an object containing
+                link: (str) the link to either start or retry verification
+                status: (str) the status of the verification
+                status_date: (str) the date time string of when the verification status was set
+
+        **Returns**
+
+            * 200 on success with above fields.
+            * 302 if the user is not enrolled.
+            * 401 if the user is not authenticated.
+            * 404 if the course is not available or cannot be seen.
       parameters: []
       responses:
         '200':
@@ -900,28 +1358,46 @@ paths:
     get:
       operationId: course_modes_v1_courses_read
       summary: View to list or create course modes for a course.
-      description: "**Use Case**\n\n    List all course modes for a course, or create\
-        \ a new\n    course mode.\n\n**Example Requests**\n\n    GET /api/course_modes/v1/courses/{course_id}/\n\
-        \n        Returns a list of all existing course modes for a course.\n\n  \
-        \  POST /api/course_modes/v1/courses/{course_id}/\n\n        Creates a new\
-        \ course mode in a course.\n\n**Response Values**\n\n    For each HTTP verb\
-        \ below, an HTTP 404 \"Not Found\" response is returned if the\n    requested\
-        \ course id does not exist.\n\n    GET: If the request is successful, an HTTP\
-        \ 200 \"OK\" response is returned\n    along with a list of course mode dictionaries\
-        \ within a course.\n    The details are contained in a JSON dictionary as\
-        \ follows:\n\n      * course_id: The course identifier.\n      * mode_slug:\
-        \ The short name for the course mode.\n      * mode_display_name: The verbose\
-        \ name for the course mode.\n      * min_price: The minimum price for which\
-        \ a user can\n        enroll in this mode.\n      * currency: The currency\
-        \ of the listed prices.\n      * expiration_datetime: The date and time after\
-        \ which\n        users cannot enroll in the course in this mode (not required\
-        \ for POST).\n      * expiration_datetime_is_explicit: Whether the expiration_datetime\
-        \ field was\n        explicitly set (not required for POST).\n      * description:\
-        \ A description of this mode (not required for POST).\n      * sku: The SKU\
-        \ for this mode (for ecommerce purposes, not required for POST).\n      *\
-        \ bulk_sku: The bulk SKU for this mode (for ecommerce purposes, not required\
-        \ for POST).\n\n    POST: If the request is successful, an HTTP 201 \"Created\"\
-        \ response is returned."
+      description: |-
+        **Use Case**
+
+            List all course modes for a course, or create a new
+            course mode.
+
+        **Example Requests**
+
+            GET /api/course_modes/v1/courses/{course_id}/
+
+                Returns a list of all existing course modes for a course.
+
+            POST /api/course_modes/v1/courses/{course_id}/
+
+                Creates a new course mode in a course.
+
+        **Response Values**
+
+            For each HTTP verb below, an HTTP 404 "Not Found" response is returned if the
+            requested course id does not exist.
+
+            GET: If the request is successful, an HTTP 200 "OK" response is returned
+            along with a list of course mode dictionaries within a course.
+            The details are contained in a JSON dictionary as follows:
+
+              * course_id: The course identifier.
+              * mode_slug: The short name for the course mode.
+              * mode_display_name: The verbose name for the course mode.
+              * min_price: The minimum price for which a user can
+                enroll in this mode.
+              * currency: The currency of the listed prices.
+              * expiration_datetime: The date and time after which
+                users cannot enroll in the course in this mode (not required for POST).
+              * expiration_datetime_is_explicit: Whether the expiration_datetime field was
+                explicitly set (not required for POST).
+              * description: A description of this mode (not required for POST).
+              * sku: The SKU for this mode (for ecommerce purposes, not required for POST).
+              * bulk_sku: The bulk SKU for this mode (for ecommerce purposes, not required for POST).
+
+            POST: If the request is successful, an HTTP 201 "Created" response is returned.
       parameters: []
       responses:
         '200':
@@ -935,28 +1411,46 @@ paths:
     post:
       operationId: course_modes_v1_courses_create
       summary: View to list or create course modes for a course.
-      description: "**Use Case**\n\n    List all course modes for a course, or create\
-        \ a new\n    course mode.\n\n**Example Requests**\n\n    GET /api/course_modes/v1/courses/{course_id}/\n\
-        \n        Returns a list of all existing course modes for a course.\n\n  \
-        \  POST /api/course_modes/v1/courses/{course_id}/\n\n        Creates a new\
-        \ course mode in a course.\n\n**Response Values**\n\n    For each HTTP verb\
-        \ below, an HTTP 404 \"Not Found\" response is returned if the\n    requested\
-        \ course id does not exist.\n\n    GET: If the request is successful, an HTTP\
-        \ 200 \"OK\" response is returned\n    along with a list of course mode dictionaries\
-        \ within a course.\n    The details are contained in a JSON dictionary as\
-        \ follows:\n\n      * course_id: The course identifier.\n      * mode_slug:\
-        \ The short name for the course mode.\n      * mode_display_name: The verbose\
-        \ name for the course mode.\n      * min_price: The minimum price for which\
-        \ a user can\n        enroll in this mode.\n      * currency: The currency\
-        \ of the listed prices.\n      * expiration_datetime: The date and time after\
-        \ which\n        users cannot enroll in the course in this mode (not required\
-        \ for POST).\n      * expiration_datetime_is_explicit: Whether the expiration_datetime\
-        \ field was\n        explicitly set (not required for POST).\n      * description:\
-        \ A description of this mode (not required for POST).\n      * sku: The SKU\
-        \ for this mode (for ecommerce purposes, not required for POST).\n      *\
-        \ bulk_sku: The bulk SKU for this mode (for ecommerce purposes, not required\
-        \ for POST).\n\n    POST: If the request is successful, an HTTP 201 \"Created\"\
-        \ response is returned."
+      description: |-
+        **Use Case**
+
+            List all course modes for a course, or create a new
+            course mode.
+
+        **Example Requests**
+
+            GET /api/course_modes/v1/courses/{course_id}/
+
+                Returns a list of all existing course modes for a course.
+
+            POST /api/course_modes/v1/courses/{course_id}/
+
+                Creates a new course mode in a course.
+
+        **Response Values**
+
+            For each HTTP verb below, an HTTP 404 "Not Found" response is returned if the
+            requested course id does not exist.
+
+            GET: If the request is successful, an HTTP 200 "OK" response is returned
+            along with a list of course mode dictionaries within a course.
+            The details are contained in a JSON dictionary as follows:
+
+              * course_id: The course identifier.
+              * mode_slug: The short name for the course mode.
+              * mode_display_name: The verbose name for the course mode.
+              * min_price: The minimum price for which a user can
+                enroll in this mode.
+              * currency: The currency of the listed prices.
+              * expiration_datetime: The date and time after which
+                users cannot enroll in the course in this mode (not required for POST).
+              * expiration_datetime_is_explicit: Whether the expiration_datetime field was
+                explicitly set (not required for POST).
+              * description: A description of this mode (not required for POST).
+              * sku: The SKU for this mode (for ecommerce purposes, not required for POST).
+              * bulk_sku: The bulk SKU for this mode (for ecommerce purposes, not required for POST).
+
+            POST: If the request is successful, an HTTP 201 "Created" response is returned.
       parameters:
         - name: data
           in: body
@@ -979,35 +1473,54 @@ paths:
     get:
       operationId: course_modes_v1_courses_read
       summary: View to retrieve, update, or delete a specific course mode for a course.
-      description: "**Use Case**\n\n    Get or update course mode details for a specific\
-        \ course mode on a course.\n    Or you may delete a specific course mode from\
-        \ a course.\n\n**Example Requests**\n\n    GET /api/course_modes/v1/courses/{course_id}/{mode_slug}\n\
-        \n        Returns details on an existing course mode for a course.\n\n   \
-        \ PATCH /api/course_modes/v1/courses/{course_id}/{mode_slug}\n\n        Updates\
-        \ (via merge) details of an existing course mode for a course.\n\n    DELETE\
-        \ /api/course_modes/v1/courses/{course_id}/{mode_slug}\n\n        Deletes\
-        \ an existing course mode for a course.\n\n**Response Values**\n\n    For\
-        \ each HTTP verb below, an HTTP 404 \"Not Found\" response is returned if\
-        \ the\n    requested course id does not exist, or the mode slug does not exist\
-        \ within the course.\n\n    GET: If the request is successful, an HTTP 200\
-        \ \"OK\" response is returned\n    along with a details for a single course\
-        \ mode within a course.  The details are contained\n    in a JSON dictionary\
-        \ as follows:\n\n      * course_id: The course identifier.\n      * mode_slug:\
-        \ The short name for the course mode.\n      * mode_display_name: The verbose\
-        \ name for the course mode.\n      * min_price: The minimum price for which\
-        \ a user can\n        enroll in this mode.\n      * currency: The currency\
-        \ of the listed prices.\n      * expiration_datetime: The date and time after\
-        \ which\n        users cannot enroll in the course in this mode (not required\
-        \ for PATCH).\n      * expiration_datetime_is_explicit: Whether the expiration_datetime\
-        \ field was\n        explicitly set (not required for PATCH).\n      * description:\
-        \ A description of this mode (not required for PATCH).\n      * sku: The SKU\
-        \ for this mode (for ecommerce purposes, not required for PATCH).\n      *\
-        \ bulk_sku: The bulk SKU for this mode (for ecommerce purposes, not required\
-        \ for PATCH).\n\n    PATCH: If the request is successful, an HTTP 204 \"No\
-        \ Content\" response is returned.\n    If \"application/merge-patch+json\"\
-        \ is not the specified content type,\n    a 415 \"Unsupported Media Type\"\
-        \ response is returned.\n\n    DELETE: If the request is successful, an HTTP\
-        \ 204 \"No Content\" response is returned."
+      description: |-
+        **Use Case**
+
+            Get or update course mode details for a specific course mode on a course.
+            Or you may delete a specific course mode from a course.
+
+        **Example Requests**
+
+            GET /api/course_modes/v1/courses/{course_id}/{mode_slug}
+
+                Returns details on an existing course mode for a course.
+
+            PATCH /api/course_modes/v1/courses/{course_id}/{mode_slug}
+
+                Updates (via merge) details of an existing course mode for a course.
+
+            DELETE /api/course_modes/v1/courses/{course_id}/{mode_slug}
+
+                Deletes an existing course mode for a course.
+
+        **Response Values**
+
+            For each HTTP verb below, an HTTP 404 "Not Found" response is returned if the
+            requested course id does not exist, or the mode slug does not exist within the course.
+
+            GET: If the request is successful, an HTTP 200 "OK" response is returned
+            along with a details for a single course mode within a course.  The details are contained
+            in a JSON dictionary as follows:
+
+              * course_id: The course identifier.
+              * mode_slug: The short name for the course mode.
+              * mode_display_name: The verbose name for the course mode.
+              * min_price: The minimum price for which a user can
+                enroll in this mode.
+              * currency: The currency of the listed prices.
+              * expiration_datetime: The date and time after which
+                users cannot enroll in the course in this mode (not required for PATCH).
+              * expiration_datetime_is_explicit: Whether the expiration_datetime field was
+                explicitly set (not required for PATCH).
+              * description: A description of this mode (not required for PATCH).
+              * sku: The SKU for this mode (for ecommerce purposes, not required for PATCH).
+              * bulk_sku: The bulk SKU for this mode (for ecommerce purposes, not required for PATCH).
+
+            PATCH: If the request is successful, an HTTP 204 "No Content" response is returned.
+            If "application/merge-patch+json" is not the specified content type,
+            a 415 "Unsupported Media Type" response is returned.
+
+            DELETE: If the request is successful, an HTTP 204 "No Content" response is returned.
       parameters: []
       responses:
         '200':
@@ -1039,35 +1552,54 @@ paths:
     delete:
       operationId: course_modes_v1_courses_delete
       summary: View to retrieve, update, or delete a specific course mode for a course.
-      description: "**Use Case**\n\n    Get or update course mode details for a specific\
-        \ course mode on a course.\n    Or you may delete a specific course mode from\
-        \ a course.\n\n**Example Requests**\n\n    GET /api/course_modes/v1/courses/{course_id}/{mode_slug}\n\
-        \n        Returns details on an existing course mode for a course.\n\n   \
-        \ PATCH /api/course_modes/v1/courses/{course_id}/{mode_slug}\n\n        Updates\
-        \ (via merge) details of an existing course mode for a course.\n\n    DELETE\
-        \ /api/course_modes/v1/courses/{course_id}/{mode_slug}\n\n        Deletes\
-        \ an existing course mode for a course.\n\n**Response Values**\n\n    For\
-        \ each HTTP verb below, an HTTP 404 \"Not Found\" response is returned if\
-        \ the\n    requested course id does not exist, or the mode slug does not exist\
-        \ within the course.\n\n    GET: If the request is successful, an HTTP 200\
-        \ \"OK\" response is returned\n    along with a details for a single course\
-        \ mode within a course.  The details are contained\n    in a JSON dictionary\
-        \ as follows:\n\n      * course_id: The course identifier.\n      * mode_slug:\
-        \ The short name for the course mode.\n      * mode_display_name: The verbose\
-        \ name for the course mode.\n      * min_price: The minimum price for which\
-        \ a user can\n        enroll in this mode.\n      * currency: The currency\
-        \ of the listed prices.\n      * expiration_datetime: The date and time after\
-        \ which\n        users cannot enroll in the course in this mode (not required\
-        \ for PATCH).\n      * expiration_datetime_is_explicit: Whether the expiration_datetime\
-        \ field was\n        explicitly set (not required for PATCH).\n      * description:\
-        \ A description of this mode (not required for PATCH).\n      * sku: The SKU\
-        \ for this mode (for ecommerce purposes, not required for PATCH).\n      *\
-        \ bulk_sku: The bulk SKU for this mode (for ecommerce purposes, not required\
-        \ for PATCH).\n\n    PATCH: If the request is successful, an HTTP 204 \"No\
-        \ Content\" response is returned.\n    If \"application/merge-patch+json\"\
-        \ is not the specified content type,\n    a 415 \"Unsupported Media Type\"\
-        \ response is returned.\n\n    DELETE: If the request is successful, an HTTP\
-        \ 204 \"No Content\" response is returned."
+      description: |-
+        **Use Case**
+
+            Get or update course mode details for a specific course mode on a course.
+            Or you may delete a specific course mode from a course.
+
+        **Example Requests**
+
+            GET /api/course_modes/v1/courses/{course_id}/{mode_slug}
+
+                Returns details on an existing course mode for a course.
+
+            PATCH /api/course_modes/v1/courses/{course_id}/{mode_slug}
+
+                Updates (via merge) details of an existing course mode for a course.
+
+            DELETE /api/course_modes/v1/courses/{course_id}/{mode_slug}
+
+                Deletes an existing course mode for a course.
+
+        **Response Values**
+
+            For each HTTP verb below, an HTTP 404 "Not Found" response is returned if the
+            requested course id does not exist, or the mode slug does not exist within the course.
+
+            GET: If the request is successful, an HTTP 200 "OK" response is returned
+            along with a details for a single course mode within a course.  The details are contained
+            in a JSON dictionary as follows:
+
+              * course_id: The course identifier.
+              * mode_slug: The short name for the course mode.
+              * mode_display_name: The verbose name for the course mode.
+              * min_price: The minimum price for which a user can
+                enroll in this mode.
+              * currency: The currency of the listed prices.
+              * expiration_datetime: The date and time after which
+                users cannot enroll in the course in this mode (not required for PATCH).
+              * expiration_datetime_is_explicit: Whether the expiration_datetime field was
+                explicitly set (not required for PATCH).
+              * description: A description of this mode (not required for PATCH).
+              * sku: The SKU for this mode (for ecommerce purposes, not required for PATCH).
+              * bulk_sku: The bulk SKU for this mode (for ecommerce purposes, not required for PATCH).
+
+            PATCH: If the request is successful, an HTTP 204 "No Content" response is returned.
+            If "application/merge-patch+json" is not the specified content type,
+            a 415 "Unsupported Media Type" response is returned.
+
+            DELETE: If the request is successful, an HTTP 204 "No Content" response is returned.
       parameters: []
       responses:
         '204':
@@ -1089,22 +1621,41 @@ paths:
     get:
       operationId: courses_v1_blocks_list
       summary: '**Use Case**'
-      description: "Returns the blocks in the course according to the requesting user's\n\
-        \    access level.\n\n**Example requests**:\n\n    GET /api/courses/v1/blocks/?course_id=<course_id>\n\
-        \    GET /api/courses/v1/blocks/?course_id=<course_id>\n        &username=anjali\n\
-        \        &depth=all\n        &requested_fields=graded,format,student_view_multi_device,lti_url\n\
-        \        &block_counts=video\n        &student_view_data=video\n        &block_types_filter=problem,html\n\
-        \n**Parameters**:\n\n    This view redirects to /api/courses/v1/blocks/<root_usage_key>/\
-        \ for the\n    root usage key of the course specified by course_id.  The view\
-        \ accepts\n    all parameters accepted by :class:`BlocksView`, plus the following\n\
-        \    required parameter\n\n    * course_id: (string, required) The ID of the\
-        \ course whose block data\n      we want to return\n\n**Response Values**\n\
-        \n    Responses are identical to those returned by :class:`BlocksView` when\n\
-        \    passed the root_usage_key of the requested course.\n\n    If the course_id\
-        \ is not supplied, a 400: Bad Request is returned, with\n    a message indicating\
-        \ that course_id is required.\n\n    If an invalid course_id is supplied,\
-        \ a 400: Bad Request is returned,\n    with a message indicating that the\
-        \ course_id is not valid."
+      description: |-
+        Returns the blocks in the course according to the requesting user's
+            access level.
+
+        **Example requests**:
+
+            GET /api/courses/v1/blocks/?course_id=<course_id>
+            GET /api/courses/v1/blocks/?course_id=<course_id>
+                &username=anjali
+                &depth=all
+                &requested_fields=graded,format,student_view_multi_device,lti_url
+                &block_counts=video
+                &student_view_data=video
+                &block_types_filter=problem,html
+
+        **Parameters**:
+
+            This view redirects to /api/courses/v1/blocks/<root_usage_key>/ for the
+            root usage key of the course specified by course_id.  The view accepts
+            all parameters accepted by :class:`BlocksView`, plus the following
+            required parameter
+
+            * course_id: (string, required) The ID of the course whose block data
+              we want to return
+
+        **Response Values**
+
+            Responses are identical to those returned by :class:`BlocksView` when
+            passed the root_usage_key of the requested course.
+
+            If the course_id is not supplied, a 400: Bad Request is returned, with
+            a message indicating that course_id is required.
+
+            If an invalid course_id is supplied, a 400: Bad Request is returned,
+            with a message indicating that the course_id is not valid.
       parameters:
         - name: page
           in: query
@@ -1126,100 +1677,180 @@ paths:
   : get:
       operationId: courses_v1_blocks_courses_v1_blocks__[_]+_[_]+_[_]+_[@]+(:@[_read
       summary: '**Use Case**'
-      description: "Returns the blocks within the requested block tree according to\
-        \ the\n    requesting user's access level.\n\n**Example requests**:\n\n  \
-        \  GET /api/courses/v1/blocks/<root_block_usage_id>/?depth=all\n    GET /api/courses/v1/blocks/<usage_id>/?\n\
-        \        username=anjali\n        &depth=all\n        &requested_fields=graded,format,student_view_multi_device,lti_url,due\n\
-        \        &block_counts=video\n        &student_view_data=video\n        &block_types_filter=problem,html\n\
-        \n**Parameters**:\n\n    * all_blocks: (boolean) Provide a value of \"true\"\
-        \ to return all\n      blocks. Returns all blocks only if the requesting user\
-        \ has course\n      staff permissions. Blocks that are visible only to specific\
-        \ learners\n      (for example, based on group membership or randomized content)\
-        \ are\n      all included. If all_blocks is not specified, you must specify\
-        \ the\n      username for the user whose course blocks are requested.\n\n\
-        \    * username: (string) Required, unless ``all_blocks`` is specified.\n\
-        \      Specify the username for the user whose course blocks are requested.\n\
-        \      A blank/empty username can be used to request the blocks accessible\n\
-        \      to anonymous users (for public courses). Only users with course staff\n\
-        \      permissions can specify other users' usernames. If a username is\n\
-        \      specified, results include blocks that are visible to that user,\n\
-        \      including those based on group or cohort membership or randomized\n\
-        \      content assigned to that user.\n\n      Example: username=anjali\n\
-        \               username=''\n               username\n\n    * student_view_data:\
-        \ (list) Indicates for which block types to return\n      student_view_data.\n\
-        \n      Example: student_view_data=video\n\n    * block_counts: (list) Indicates\
-        \ for which block types to return the\n      aggregate count of the blocks.\n\
-        \n      Example: block_counts=video,problem\n\n    * requested_fields: (list)\
-        \ Indicates which additional fields to return\n      for each block.  For\
-        \ a list of available fields see under `Response\n      Values -> blocks`,\
-        \ below.\n\n      The following fields are always returned: id, type, display_name\n\
-        \n      Example: requested_fields=graded,format,student_view_multi_device\n\
-        \n    * depth: (integer or all) Indicates how deep to traverse into the blocks\n\
-        \      hierarchy.  A value of all means the entire hierarchy.\n\n      Default\
-        \ is 0\n\n      Example: depth=all\n\n    * nav_depth: (integer)\n\n     \
-        \ WARNING: nav_depth is not supported, and may be removed at any time.\n\n\
-        \      Indicates how far deep to traverse into the\n      course hierarchy\
-        \ before bundling all the descendants.\n\n      Default is 3 since typical\
-        \ navigational views of the course show a\n      maximum of chapter->sequential->vertical.\n\
-        \n      Example: nav_depth=3\n\n    * return_type (string) Indicates in what\
-        \ data type to return the\n      blocks.\n\n      Default is dict. Supported\
-        \ values are: dict, list\n\n      Example: return_type=dict\n\n    * block_types_filter:\
-        \ (list) Requested types of blocks used to filter the final result\n     \
-        \ of returned blocks. Possible values include sequential, vertical, html,\
-        \ problem,\n      video, and discussion.\n\n      Example: block_types_filter=vertical,html\n\
-        \n**Response Values**\n\n    The following fields are returned with a successful\
-        \ response.\n\n    * root: The ID of the root node of the requested course\
-        \ block\n      structure.\n\n    * blocks: A dictionary or list, based on\
-        \ the value of the\n      \"return_type\" parameter. Maps block usage IDs\
-        \ to a collection of\n      information about each block. Each block contains\
-        \ the following\n      fields.\n\n      * id: (string) The usage ID of the\
-        \ block.\n\n      * type: (string) The type of block. Possible values the\
-        \ names of any\n        XBlock type in the system, including custom blocks.\
-        \ Examples are\n        course, chapter, sequential, vertical, html, problem,\
-        \ video, and\n        discussion.\n\n      * display_name: (string) The display\
-        \ name of the block.\n\n      * children: (list) If the block has child blocks,\
-        \ a list of IDs of\n        the child blocks.  Returned only if \"children\"\
-        \ is included in the\n        \"requested_fields\" parameter.\n\n      * completion:\
-        \ (float or None) The level of completion of the block.\n        Its value\
-        \ can vary between 0.0 and 1.0 or be equal to None\n        if block is not\
-        \ completable. Returned only if \"completion\"\n        is included in the\
-        \ \"requested_fields\" parameter.\n\n      * block_counts: (dict) For each\
-        \ block type specified in the\n        block_counts parameter to the endpoint,\
-        \ the aggregate number of\n        blocks of that type for this block and\
-        \ all of its descendants.\n\n      * graded (boolean) Whether or not the block\
-        \ or any of its descendants\n        is graded.  Returned only if \"graded\"\
-        \ is included in the\n        \"requested_fields\" parameter.\n\n      * format:\
-        \ (string) The assignment type of the block.  Possible values\n        can\
-        \ be \"Homework\", \"Lab\", \"Midterm Exam\", and \"Final Exam\".\n      \
-        \  Returned only if \"format\" is included in the \"requested_fields\"\n \
-        \       parameter.\n\n      * student_view_data: (dict) The JSON data for\
-        \ this block.\n        Returned only if the \"student_view_data\" input parameter\
-        \ contains\n        this block's type.\n\n      * student_view_url: (string)\
-        \ The URL to retrieve the HTML rendering\n        of this block's student\
-        \ view.  The HTML could include CSS and\n        Javascript code. This field\
-        \ can be used in combination with the\n        student_view_multi_device field\
-        \ to decide whether to display this\n        content to the user.\n\n    \
-        \    This URL can be used as a fallback if the student_view_data for\n   \
-        \     this block type is not supported by the client or the block.\n\n   \
-        \   * student_view_multi_device: (boolean) Whether or not the HTML of\n  \
-        \      the student view that is rendered at \"student_view_url\" supports\n\
-        \        responsive web layouts, touch-based inputs, and interactive state\n\
-        \        management for a variety of device sizes and types, including\n \
-        \       mobile and touch devices. Returned only if\n        \"student_view_multi_device\"\
-        \ is included in the \"requested_fields\"\n        parameter.\n\n      * lms_web_url:\
-        \ (string) The URL to the navigational container of the\n        xBlock on\
-        \ the web LMS.  This URL can be used as a further fallback\n        if the\
-        \ student_view_url and the student_view_data fields are not\n        supported.\n\
-        \n      * lti_url: The block URL for an LTI consumer. Returned only if the\n\
-        \        \"ENABLE_LTI_PROVIDER\" Django settign is set to \"True\".\n\n  \
-        \    * due: The due date of the block. Returned only if \"due\" is included\n\
-        \        in the \"requested_fields\" parameter.\n\n      * show_correctness:\
-        \ Whether to show scores/correctness to learners for the current sequence\
-        \ or problem.\n        Returned only if \"show_correctness\" is included in\
-        \ the \"requested_fields\" parameter.\n\n      * Additional XBlock fields\
-        \ can be included in the response if they are\n        configured via the\
-        \ COURSE_BLOCKS_API_EXTRA_FIELDS Django setting and\n        requested via\
-        \ the \"requested_fields\" parameter."
+      description: |-
+        Returns the blocks within the requested block tree according to the
+            requesting user's access level.
+
+        **Example requests**:
+
+            GET /api/courses/v1/blocks/<root_block_usage_id>/?depth=all
+            GET /api/courses/v1/blocks/<usage_id>/?
+                username=anjali
+                &depth=all
+                &requested_fields=graded,format,student_view_multi_device,lti_url,due
+                &block_counts=video
+                &student_view_data=video
+                &block_types_filter=problem,html
+
+        **Parameters**:
+
+            * all_blocks: (boolean) Provide a value of "true" to return all
+              blocks. Returns all blocks only if the requesting user has course
+              staff permissions. Blocks that are visible only to specific learners
+              (for example, based on group membership or randomized content) are
+              all included. If all_blocks is not specified, you must specify the
+              username for the user whose course blocks are requested.
+
+            * username: (string) Required, unless ``all_blocks`` is specified.
+              Specify the username for the user whose course blocks are requested.
+              A blank/empty username can be used to request the blocks accessible
+              to anonymous users (for public courses). Only users with course staff
+              permissions can specify other users' usernames. If a username is
+              specified, results include blocks that are visible to that user,
+              including those based on group or cohort membership or randomized
+              content assigned to that user.
+
+              Example: username=anjali
+                       username=''
+                       username
+
+            * student_view_data: (list) Indicates for which block types to return
+              student_view_data.
+
+              Example: student_view_data=video
+
+            * block_counts: (list) Indicates for which block types to return the
+              aggregate count of the blocks.
+
+              Example: block_counts=video,problem
+
+            * requested_fields: (list) Indicates which additional fields to return
+              for each block.  For a list of available fields see under `Response
+              Values -> blocks`, below.
+
+              The following fields are always returned: id, type, display_name
+
+              Example: requested_fields=graded,format,student_view_multi_device
+
+            * depth: (integer or all) Indicates how deep to traverse into the blocks
+              hierarchy.  A value of all means the entire hierarchy.
+
+              Default is 0
+
+              Example: depth=all
+
+            * nav_depth: (integer)
+
+              WARNING: nav_depth is not supported, and may be removed at any time.
+
+              Indicates how far deep to traverse into the
+              course hierarchy before bundling all the descendants.
+
+              Default is 3 since typical navigational views of the course show a
+              maximum of chapter->sequential->vertical.
+
+              Example: nav_depth=3
+
+            * return_type (string) Indicates in what data type to return the
+              blocks.
+
+              Default is dict. Supported values are: dict, list
+
+              Example: return_type=dict
+
+            * block_types_filter: (list) Requested types of blocks used to filter the final result
+              of returned blocks. Possible values include sequential, vertical, html, problem,
+              video, and discussion.
+
+              Example: block_types_filter=vertical,html
+
+        **Response Values**
+
+            The following fields are returned with a successful response.
+
+            * root: The ID of the root node of the requested course block
+              structure.
+
+            * blocks: A dictionary or list, based on the value of the
+              "return_type" parameter. Maps block usage IDs to a collection of
+              information about each block. Each block contains the following
+              fields.
+
+              * id: (string) The usage ID of the block.
+
+              * type: (string) The type of block. Possible values the names of any
+                XBlock type in the system, including custom blocks. Examples are
+                course, chapter, sequential, vertical, html, problem, video, and
+                discussion.
+
+              * display_name: (string) The display name of the block.
+
+              * children: (list) If the block has child blocks, a list of IDs of
+                the child blocks.  Returned only if "children" is included in the
+                "requested_fields" parameter.
+
+              * completion: (float or None) The level of completion of the block.
+                Its value can vary between 0.0 and 1.0 or be equal to None
+                if block is not completable. Returned only if "completion"
+                is included in the "requested_fields" parameter.
+
+              * block_counts: (dict) For each block type specified in the
+                block_counts parameter to the endpoint, the aggregate number of
+                blocks of that type for this block and all of its descendants.
+
+              * graded (boolean) Whether or not the block or any of its descendants
+                is graded.  Returned only if "graded" is included in the
+                "requested_fields" parameter.
+
+              * format: (string) The assignment type of the block.  Possible values
+                can be "Homework", "Lab", "Midterm Exam", and "Final Exam".
+                Returned only if "format" is included in the "requested_fields"
+                parameter.
+
+              * student_view_data: (dict) The JSON data for this block.
+                Returned only if the "student_view_data" input parameter contains
+                this block's type.
+
+              * student_view_url: (string) The URL to retrieve the HTML rendering
+                of this block's student view.  The HTML could include CSS and
+                Javascript code. This field can be used in combination with the
+                student_view_multi_device field to decide whether to display this
+                content to the user.
+
+                This URL can be used as a fallback if the student_view_data for
+                this block type is not supported by the client or the block.
+
+              * student_view_multi_device: (boolean) Whether or not the HTML of
+                the student view that is rendered at "student_view_url" supports
+                responsive web layouts, touch-based inputs, and interactive state
+                management for a variety of device sizes and types, including
+                mobile and touch devices. Returned only if
+                "student_view_multi_device" is included in the "requested_fields"
+                parameter.
+
+              * lms_web_url: (string) The URL to the navigational container of the
+                xBlock on the web. This URL can be used as a further fallback
+                if the student_view_url and the student_view_data fields are not
+                supported. Will direct to either the "New" (micro-frontend) or
+                "Legacy" (Django-template-rendered) frontend experience depending
+                on which experience is active.
+
+              * legacy_web_url: (string) Like `lms_web_url`, but always directs to
+                the "Legacy" frontend experience. Should only be used for
+                transitional purposes; will be removed as part of DEPR-109.
+
+              * lti_url: The block URL for an LTI consumer. Returned only if the
+                "ENABLE_LTI_PROVIDER" Django settign is set to "True".
+
+              * due: The due date of the block. Returned only if "due" is included
+                in the "requested_fields" parameter.
+
+              * show_correctness: Whether to show scores/correctness to learners for the current sequence or problem.
+                Returned only if "show_correctness" is included in the "requested_fields" parameter.
+
+              * Additional XBlock fields can be included in the response if they are
+                configured via the COURSE_BLOCKS_API_EXTRA_FIELDS Django setting and
+                requested via the "requested_fields" parameter.
       parameters:
         - name: page
           in: query
@@ -1249,26 +1880,54 @@ paths:
     get:
       operationId: courses_v1_course_ids_list
       summary: '**Use Cases**'
-      description: "Request a list of course IDs for all courses the specified user\
-        \ can\n    access based on the provided parameters.\n\n**Example Requests**\n\
-        \n    GET /api/courses/v1/courses_ids/\n\n**Response Values**\n\n    Body\
-        \ comprises a list of course ids and pagination details.\n\n**Parameters**\n\
-        \n    username (optional):\n        The username of the specified user whose\
-        \ visible courses we\n        want to see.\n\n    role (required):\n     \
-        \   Course ids are filtered such that only those for which the\n        user\
-        \ has the specified role are returned. Role can be \"staff\"\n        or \"\
-        instructor\".\n        Case-insensitive.\n\n**Returns**\n\n    * 200 on success,\
-        \ with a list of course ids and pagination details\n    * 400 if an invalid\
-        \ parameter was sent or the username was not provided\n      for an authenticated\
-        \ request.\n    * 403 if a user who does not have permission to masquerade\
-        \ as\n      another user who specifies a username other than their own.\n\
-        \    * 404 if the specified user does not exist, or the requesting user does\n\
-        \      not have permission to view their courses.\n\n    Example response:\n\
-        \n        {\n            \"results\":\n                [\n               \
-        \     \"course-v1:edX+DemoX+Demo_Course\"\n                ],\n          \
-        \  \"pagination\": {\n                \"previous\": null,\n              \
-        \  \"num_pages\": 1,\n                \"next\": null,\n                \"\
-        count\": 1\n            }\n        }"
+      description: |-
+        Request a list of course IDs for all courses the specified user can
+            access based on the provided parameters.
+
+        **Example Requests**
+
+            GET /api/courses/v1/courses_ids/
+
+        **Response Values**
+
+            Body comprises a list of course ids and pagination details.
+
+        **Parameters**
+
+            username (optional):
+                The username of the specified user whose visible courses we
+                want to see.
+
+            role (required):
+                Course ids are filtered such that only those for which the
+                user has the specified role are returned. Role can be "staff"
+                or "instructor".
+                Case-insensitive.
+
+        **Returns**
+
+            * 200 on success, with a list of course ids and pagination details
+            * 400 if an invalid parameter was sent or the username was not provided
+              for an authenticated request.
+            * 403 if a user who does not have permission to masquerade as
+              another user who specifies a username other than their own.
+            * 404 if the specified user does not exist, or the requesting user does
+              not have permission to view their courses.
+
+            Example response:
+
+                {
+                    "results":
+                        [
+                            "course-v1:edX+DemoX+Demo_Course"
+                        ],
+                    "pagination": {
+                        "previous": null,
+                        "num_pages": 1,
+                        "next": null,
+                        "count": 1
+                    }
+                }
       parameters:
         - name: page
           in: query
@@ -1310,36 +1969,68 @@ paths:
     get:
       operationId: courses_v1_courses_list
       summary: '**Use Cases**'
-      description: "Request information on all courses visible to the specified user.\n\
-        \n**Example Requests**\n\n    GET /api/courses/v1/courses/\n\n**Response Values**\n\
-        \n    Body comprises a list of objects as returned by `CourseDetailView`.\n\
-        \n**Parameters**\n\n    search_term (optional):\n        Search term to filter\
-        \ courses (used by ElasticSearch).\n\n    username (optional):\n        The\
-        \ username of the specified user whose visible courses we\n        want to\
-        \ see. The username is not required only if the API is\n        requested\
-        \ by an Anonymous user.\n\n    org (optional):\n        If specified, visible\
-        \ `CourseOverview` objects are filtered\n        such that only those belonging\
-        \ to the organization with the\n        provided org code (e.g., \"HarvardX\"\
-        ) are returned.\n        Case-insensitive.\n\n**Returns**\n\n    * 200 on\
-        \ success, with a list of course discovery objects as returned\n      by `CourseDetailView`.\n\
-        \    * 400 if an invalid parameter was sent or the username was not provided\n\
-        \      for an authenticated request.\n    * 403 if a user who does not have\
-        \ permission to masquerade as\n      another user specifies a username other\
-        \ than their own.\n    * 404 if the specified user does not exist, or the\
-        \ requesting user does\n      not have permission to view their courses.\n\
-        \n    Example response:\n\n        [\n          {\n            \"blocks_url\"\
-        : \"/api/courses/v1/blocks/?course_id=edX%2Fexample%2F2012_Fall\",\n     \
-        \       \"media\": {\n              \"course_image\": {\n                \"\
-        uri\": \"/c4x/edX/example/asset/just_a_test.jpg\",\n                \"name\"\
-        : \"Course Image\"\n              }\n            },\n            \"description\"\
-        : \"An example course.\",\n            \"end\": \"2015-09-19T18:00:00Z\",\n\
-        \            \"enrollment_end\": \"2015-07-15T00:00:00Z\",\n            \"\
-        enrollment_start\": \"2015-06-15T00:00:00Z\",\n            \"course_id\":\
-        \ \"edX/example/2012_Fall\",\n            \"name\": \"Example Course\",\n\
-        \            \"number\": \"example\",\n            \"org\": \"edX\",\n   \
-        \         \"start\": \"2015-07-17T12:00:00Z\",\n            \"start_display\"\
-        : \"July 17, 2015\",\n            \"start_type\": \"timestamp\"\n        \
-        \  }\n        ]"
+      description: |-
+        Request information on all courses visible to the specified user.
+
+        **Example Requests**
+
+            GET /api/courses/v1/courses/
+
+        **Response Values**
+
+            Body comprises a list of objects as returned by `CourseDetailView`.
+
+        **Parameters**
+
+            search_term (optional):
+                Search term to filter courses (used by ElasticSearch).
+
+            username (optional):
+                The username of the specified user whose visible courses we
+                want to see. The username is not required only if the API is
+                requested by an Anonymous user.
+
+            org (optional):
+                If specified, visible `CourseOverview` objects are filtered
+                such that only those belonging to the organization with the
+                provided org code (e.g., "HarvardX") are returned.
+                Case-insensitive.
+
+        **Returns**
+
+            * 200 on success, with a list of course discovery objects as returned
+              by `CourseDetailView`.
+            * 400 if an invalid parameter was sent or the username was not provided
+              for an authenticated request.
+            * 403 if a user who does not have permission to masquerade as
+              another user specifies a username other than their own.
+            * 404 if the specified user does not exist, or the requesting user does
+              not have permission to view their courses.
+
+            Example response:
+
+                [
+                  {
+                    "blocks_url": "/api/courses/v1/blocks/?course_id=edX%2Fexample%2F2012_Fall",
+                    "media": {
+                      "course_image": {
+                        "uri": "/c4x/edX/example/asset/just_a_test.jpg",
+                        "name": "Course Image"
+                      }
+                    },
+                    "description": "An example course.",
+                    "end": "2015-09-19T18:00:00Z",
+                    "enrollment_end": "2015-07-15T00:00:00Z",
+                    "enrollment_start": "2015-06-15T00:00:00Z",
+                    "course_id": "edX/example/2012_Fall",
+                    "name": "Example Course",
+                    "number": "example",
+                    "org": "edX",
+                    "start": "2015-07-17T12:00:00Z",
+                    "start_display": "July 17, 2015",
+                    "start_type": "timestamp"
+                  }
+                ]
       parameters:
         - name: page
           in: query
@@ -1381,51 +2072,88 @@ paths:
   : get:
       operationId: courses_v1_courses_+]+api_courses_v1_courses_+]+(_|+)[_]+)_read
       summary: '**Use Cases**'
-      description: "Request details for a course\n\n**Example Requests**\n\n    GET\
-        \ /api/courses/v1/courses/{course_key}/\n\n**Response Values**\n\n    Body\
-        \ consists of the following fields:\n\n    * effort: A textual description\
-        \ of the weekly hours of effort expected\n        in the course.\n    * end:\
-        \ Date the course ends, in ISO 8601 notation\n    * enrollment_end: Date enrollment\
-        \ ends, in ISO 8601 notation\n    * enrollment_start: Date enrollment begins,\
-        \ in ISO 8601 notation\n    * id: A unique identifier of the course; a serialized\
-        \ representation\n        of the opaque key identifying the course.\n    *\
-        \ media: An object that contains named media items.  Included here:\n    \
-        \    * course_image: An image to show for the course.  Represented\n     \
-        \     as an object with the following fields:\n            * uri: The location\
-        \ of the image\n    * name: Name of the course\n    * number: Catalog number\
-        \ of the course\n    * org: Name of the organization that owns the course\n\
-        \    * overview: A possibly verbose HTML textual description of the course.\n\
-        \        Note: this field is only included in the Course Detail view, not\n\
-        \        the Course List view.\n    * short_description: A textual description\
-        \ of the course\n    * start: Date the course begins, in ISO 8601 notation\n\
-        \    * start_display: Readably formatted start of the course\n    * start_type:\
-        \ Hint describing how `start_display` is set. One of:\n        * `\"string\"\
-        `: manually set by the course author\n        * `\"timestamp\"`: generated\
-        \ from the `start` timestamp\n        * `\"empty\"`: no start date is specified\n\
-        \    * pacing: Course pacing. Possible values: instructor, self\n\n    Deprecated\
-        \ fields:\n\n    * blocks_url: Used to fetch the course blocks\n    * course_id:\
-        \ Course key (use 'id' instead)\n\n**Parameters:**\n\n    username (optional):\n\
-        \        The username of the specified user for whom the course data\n   \
-        \     is being accessed. The username is not only required if the API is\n\
-        \        requested by an Anonymous user.\n\n**Returns**\n\n    * 200 on success\
-        \ with above fields.\n    * 400 if an invalid parameter was sent or the username\
-        \ was not provided\n      for an authenticated request.\n    * 403 if a user\
-        \ who does not have permission to masquerade as\n      another user specifies\
-        \ a username other than their own.\n    * 404 if the course is not available\
-        \ or cannot be seen.\n\n    Example response:\n\n        {\n            \"\
-        blocks_url\": \"/api/courses/v1/blocks/?course_id=edX%2Fexample%2F2012_Fall\"\
-        ,\n            \"media\": {\n                \"course_image\": {\n       \
-        \             \"uri\": \"/c4x/edX/example/asset/just_a_test.jpg\",\n     \
-        \               \"name\": \"Course Image\"\n                }\n          \
-        \  },\n            \"description\": \"An example course.\",\n            \"\
-        end\": \"2015-09-19T18:00:00Z\",\n            \"enrollment_end\": \"2015-07-15T00:00:00Z\"\
-        ,\n            \"enrollment_start\": \"2015-06-15T00:00:00Z\",\n         \
-        \   \"course_id\": \"edX/example/2012_Fall\",\n            \"name\": \"Example\
-        \ Course\",\n            \"number\": \"example\",\n            \"org\": \"\
-        edX\",\n            \"overview: \"<p>A verbose description of the course.</p>\"\
-        \n            \"start\": \"2015-07-17T12:00:00Z\",\n            \"start_display\"\
-        : \"July 17, 2015\",\n            \"start_type\": \"timestamp\",\n       \
-        \     \"pacing\": \"instructor\"\n        }"
+      description: |-
+        Request details for a course
+
+        **Example Requests**
+
+            GET /api/courses/v1/courses/{course_key}/
+
+        **Response Values**
+
+            Body consists of the following fields:
+
+            * effort: A textual description of the weekly hours of effort expected
+                in the course.
+            * end: Date the course ends, in ISO 8601 notation
+            * enrollment_end: Date enrollment ends, in ISO 8601 notation
+            * enrollment_start: Date enrollment begins, in ISO 8601 notation
+            * id: A unique identifier of the course; a serialized representation
+                of the opaque key identifying the course.
+            * media: An object that contains named media items.  Included here:
+                * course_image: An image to show for the course.  Represented
+                  as an object with the following fields:
+                    * uri: The location of the image
+            * name: Name of the course
+            * number: Catalog number of the course
+            * org: Name of the organization that owns the course
+            * overview: A possibly verbose HTML textual description of the course.
+                Note: this field is only included in the Course Detail view, not
+                the Course List view.
+            * short_description: A textual description of the course
+            * start: Date the course begins, in ISO 8601 notation
+            * start_display: Readably formatted start of the course
+            * start_type: Hint describing how `start_display` is set. One of:
+                * `"string"`: manually set by the course author
+                * `"timestamp"`: generated from the `start` timestamp
+                * `"empty"`: no start date is specified
+            * pacing: Course pacing. Possible values: instructor, self
+
+            Deprecated fields:
+
+            * blocks_url: Used to fetch the course blocks
+            * course_id: Course key (use 'id' instead)
+
+        **Parameters:**
+
+            username (optional):
+                The username of the specified user for whom the course data
+                is being accessed. The username is not only required if the API is
+                requested by an Anonymous user.
+
+        **Returns**
+
+            * 200 on success with above fields.
+            * 400 if an invalid parameter was sent or the username was not provided
+              for an authenticated request.
+            * 403 if a user who does not have permission to masquerade as
+              another user specifies a username other than their own.
+            * 404 if the course is not available or cannot be seen.
+
+            Example response:
+
+                {
+                    "blocks_url": "/api/courses/v1/blocks/?course_id=edX%2Fexample%2F2012_Fall",
+                    "media": {
+                        "course_image": {
+                            "uri": "/c4x/edX/example/asset/just_a_test.jpg",
+                            "name": "Course Image"
+                        }
+                    },
+                    "description": "An example course.",
+                    "end": "2015-09-19T18:00:00Z",
+                    "enrollment_end": "2015-07-15T00:00:00Z",
+                    "enrollment_start": "2015-06-15T00:00:00Z",
+                    "course_id": "edX/example/2012_Fall",
+                    "name": "Example Course",
+                    "number": "example",
+                    "org": "edX",
+                    "overview: "<p>A verbose description of the course.</p>"
+                    "start": "2015-07-17T12:00:00Z",
+                    "start_display": "July 17, 2015",
+                    "start_type": "timestamp",
+                    "pacing": "instructor"
+                }
       parameters: []
       responses:
         '200':
@@ -1447,22 +2175,41 @@ paths:
     get:
       operationId: courses_v2_blocks_list
       summary: '**Use Case**'
-      description: "Returns the blocks in the course according to the requesting user's\n\
-        \    access level.\n\n**Example requests**:\n\n    GET /api/courses/v1/blocks/?course_id=<course_id>\n\
-        \    GET /api/courses/v1/blocks/?course_id=<course_id>\n        &username=anjali\n\
-        \        &depth=all\n        &requested_fields=graded,format,student_view_multi_device,lti_url\n\
-        \        &block_counts=video\n        &student_view_data=video\n        &block_types_filter=problem,html\n\
-        \n**Parameters**:\n\n    This view redirects to /api/courses/v1/blocks/<root_usage_key>/\
-        \ for the\n    root usage key of the course specified by course_id.  The view\
-        \ accepts\n    all parameters accepted by :class:`BlocksView`, plus the following\n\
-        \    required parameter\n\n    * course_id: (string, required) The ID of the\
-        \ course whose block data\n      we want to return\n\n**Response Values**\n\
-        \n    Responses are identical to those returned by :class:`BlocksView` when\n\
-        \    passed the root_usage_key of the requested course.\n\n    If the course_id\
-        \ is not supplied, a 400: Bad Request is returned, with\n    a message indicating\
-        \ that course_id is required.\n\n    If an invalid course_id is supplied,\
-        \ a 400: Bad Request is returned,\n    with a message indicating that the\
-        \ course_id is not valid."
+      description: |-
+        Returns the blocks in the course according to the requesting user's
+            access level.
+
+        **Example requests**:
+
+            GET /api/courses/v1/blocks/?course_id=<course_id>
+            GET /api/courses/v1/blocks/?course_id=<course_id>
+                &username=anjali
+                &depth=all
+                &requested_fields=graded,format,student_view_multi_device,lti_url
+                &block_counts=video
+                &student_view_data=video
+                &block_types_filter=problem,html
+
+        **Parameters**:
+
+            This view redirects to /api/courses/v1/blocks/<root_usage_key>/ for the
+            root usage key of the course specified by course_id.  The view accepts
+            all parameters accepted by :class:`BlocksView`, plus the following
+            required parameter
+
+            * course_id: (string, required) The ID of the course whose block data
+              we want to return
+
+        **Response Values**
+
+            Responses are identical to those returned by :class:`BlocksView` when
+            passed the root_usage_key of the requested course.
+
+            If the course_id is not supplied, a 400: Bad Request is returned, with
+            a message indicating that course_id is required.
+
+            If an invalid course_id is supplied, a 400: Bad Request is returned,
+            with a message indicating that the course_id is not valid.
       parameters:
         - name: page
           in: query
@@ -1484,100 +2231,180 @@ paths:
   : get:
       operationId: courses_v2_blocks_courses_v2_blocks__[_]+_[_]+_[_]+_[@]+(:@[_read
       summary: '**Use Case**'
-      description: "Returns the blocks within the requested block tree according to\
-        \ the\n    requesting user's access level.\n\n**Example requests**:\n\n  \
-        \  GET /api/courses/v1/blocks/<root_block_usage_id>/?depth=all\n    GET /api/courses/v1/blocks/<usage_id>/?\n\
-        \        username=anjali\n        &depth=all\n        &requested_fields=graded,format,student_view_multi_device,lti_url,due\n\
-        \        &block_counts=video\n        &student_view_data=video\n        &block_types_filter=problem,html\n\
-        \n**Parameters**:\n\n    * all_blocks: (boolean) Provide a value of \"true\"\
-        \ to return all\n      blocks. Returns all blocks only if the requesting user\
-        \ has course\n      staff permissions. Blocks that are visible only to specific\
-        \ learners\n      (for example, based on group membership or randomized content)\
-        \ are\n      all included. If all_blocks is not specified, you must specify\
-        \ the\n      username for the user whose course blocks are requested.\n\n\
-        \    * username: (string) Required, unless ``all_blocks`` is specified.\n\
-        \      Specify the username for the user whose course blocks are requested.\n\
-        \      A blank/empty username can be used to request the blocks accessible\n\
-        \      to anonymous users (for public courses). Only users with course staff\n\
-        \      permissions can specify other users' usernames. If a username is\n\
-        \      specified, results include blocks that are visible to that user,\n\
-        \      including those based on group or cohort membership or randomized\n\
-        \      content assigned to that user.\n\n      Example: username=anjali\n\
-        \               username=''\n               username\n\n    * student_view_data:\
-        \ (list) Indicates for which block types to return\n      student_view_data.\n\
-        \n      Example: student_view_data=video\n\n    * block_counts: (list) Indicates\
-        \ for which block types to return the\n      aggregate count of the blocks.\n\
-        \n      Example: block_counts=video,problem\n\n    * requested_fields: (list)\
-        \ Indicates which additional fields to return\n      for each block.  For\
-        \ a list of available fields see under `Response\n      Values -> blocks`,\
-        \ below.\n\n      The following fields are always returned: id, type, display_name\n\
-        \n      Example: requested_fields=graded,format,student_view_multi_device\n\
-        \n    * depth: (integer or all) Indicates how deep to traverse into the blocks\n\
-        \      hierarchy.  A value of all means the entire hierarchy.\n\n      Default\
-        \ is 0\n\n      Example: depth=all\n\n    * nav_depth: (integer)\n\n     \
-        \ WARNING: nav_depth is not supported, and may be removed at any time.\n\n\
-        \      Indicates how far deep to traverse into the\n      course hierarchy\
-        \ before bundling all the descendants.\n\n      Default is 3 since typical\
-        \ navigational views of the course show a\n      maximum of chapter->sequential->vertical.\n\
-        \n      Example: nav_depth=3\n\n    * return_type (string) Indicates in what\
-        \ data type to return the\n      blocks.\n\n      Default is dict. Supported\
-        \ values are: dict, list\n\n      Example: return_type=dict\n\n    * block_types_filter:\
-        \ (list) Requested types of blocks used to filter the final result\n     \
-        \ of returned blocks. Possible values include sequential, vertical, html,\
-        \ problem,\n      video, and discussion.\n\n      Example: block_types_filter=vertical,html\n\
-        \n**Response Values**\n\n    The following fields are returned with a successful\
-        \ response.\n\n    * root: The ID of the root node of the requested course\
-        \ block\n      structure.\n\n    * blocks: A dictionary or list, based on\
-        \ the value of the\n      \"return_type\" parameter. Maps block usage IDs\
-        \ to a collection of\n      information about each block. Each block contains\
-        \ the following\n      fields.\n\n      * id: (string) The usage ID of the\
-        \ block.\n\n      * type: (string) The type of block. Possible values the\
-        \ names of any\n        XBlock type in the system, including custom blocks.\
-        \ Examples are\n        course, chapter, sequential, vertical, html, problem,\
-        \ video, and\n        discussion.\n\n      * display_name: (string) The display\
-        \ name of the block.\n\n      * children: (list) If the block has child blocks,\
-        \ a list of IDs of\n        the child blocks.  Returned only if \"children\"\
-        \ is included in the\n        \"requested_fields\" parameter.\n\n      * completion:\
-        \ (float or None) The level of completion of the block.\n        Its value\
-        \ can vary between 0.0 and 1.0 or be equal to None\n        if block is not\
-        \ completable. Returned only if \"completion\"\n        is included in the\
-        \ \"requested_fields\" parameter.\n\n      * block_counts: (dict) For each\
-        \ block type specified in the\n        block_counts parameter to the endpoint,\
-        \ the aggregate number of\n        blocks of that type for this block and\
-        \ all of its descendants.\n\n      * graded (boolean) Whether or not the block\
-        \ or any of its descendants\n        is graded.  Returned only if \"graded\"\
-        \ is included in the\n        \"requested_fields\" parameter.\n\n      * format:\
-        \ (string) The assignment type of the block.  Possible values\n        can\
-        \ be \"Homework\", \"Lab\", \"Midterm Exam\", and \"Final Exam\".\n      \
-        \  Returned only if \"format\" is included in the \"requested_fields\"\n \
-        \       parameter.\n\n      * student_view_data: (dict) The JSON data for\
-        \ this block.\n        Returned only if the \"student_view_data\" input parameter\
-        \ contains\n        this block's type.\n\n      * student_view_url: (string)\
-        \ The URL to retrieve the HTML rendering\n        of this block's student\
-        \ view.  The HTML could include CSS and\n        Javascript code. This field\
-        \ can be used in combination with the\n        student_view_multi_device field\
-        \ to decide whether to display this\n        content to the user.\n\n    \
-        \    This URL can be used as a fallback if the student_view_data for\n   \
-        \     this block type is not supported by the client or the block.\n\n   \
-        \   * student_view_multi_device: (boolean) Whether or not the HTML of\n  \
-        \      the student view that is rendered at \"student_view_url\" supports\n\
-        \        responsive web layouts, touch-based inputs, and interactive state\n\
-        \        management for a variety of device sizes and types, including\n \
-        \       mobile and touch devices. Returned only if\n        \"student_view_multi_device\"\
-        \ is included in the \"requested_fields\"\n        parameter.\n\n      * lms_web_url:\
-        \ (string) The URL to the navigational container of the\n        xBlock on\
-        \ the web LMS.  This URL can be used as a further fallback\n        if the\
-        \ student_view_url and the student_view_data fields are not\n        supported.\n\
-        \n      * lti_url: The block URL for an LTI consumer. Returned only if the\n\
-        \        \"ENABLE_LTI_PROVIDER\" Django settign is set to \"True\".\n\n  \
-        \    * due: The due date of the block. Returned only if \"due\" is included\n\
-        \        in the \"requested_fields\" parameter.\n\n      * show_correctness:\
-        \ Whether to show scores/correctness to learners for the current sequence\
-        \ or problem.\n        Returned only if \"show_correctness\" is included in\
-        \ the \"requested_fields\" parameter.\n\n      * Additional XBlock fields\
-        \ can be included in the response if they are\n        configured via the\
-        \ COURSE_BLOCKS_API_EXTRA_FIELDS Django setting and\n        requested via\
-        \ the \"requested_fields\" parameter."
+      description: |-
+        Returns the blocks within the requested block tree according to the
+            requesting user's access level.
+
+        **Example requests**:
+
+            GET /api/courses/v1/blocks/<root_block_usage_id>/?depth=all
+            GET /api/courses/v1/blocks/<usage_id>/?
+                username=anjali
+                &depth=all
+                &requested_fields=graded,format,student_view_multi_device,lti_url,due
+                &block_counts=video
+                &student_view_data=video
+                &block_types_filter=problem,html
+
+        **Parameters**:
+
+            * all_blocks: (boolean) Provide a value of "true" to return all
+              blocks. Returns all blocks only if the requesting user has course
+              staff permissions. Blocks that are visible only to specific learners
+              (for example, based on group membership or randomized content) are
+              all included. If all_blocks is not specified, you must specify the
+              username for the user whose course blocks are requested.
+
+            * username: (string) Required, unless ``all_blocks`` is specified.
+              Specify the username for the user whose course blocks are requested.
+              A blank/empty username can be used to request the blocks accessible
+              to anonymous users (for public courses). Only users with course staff
+              permissions can specify other users' usernames. If a username is
+              specified, results include blocks that are visible to that user,
+              including those based on group or cohort membership or randomized
+              content assigned to that user.
+
+              Example: username=anjali
+                       username=''
+                       username
+
+            * student_view_data: (list) Indicates for which block types to return
+              student_view_data.
+
+              Example: student_view_data=video
+
+            * block_counts: (list) Indicates for which block types to return the
+              aggregate count of the blocks.
+
+              Example: block_counts=video,problem
+
+            * requested_fields: (list) Indicates which additional fields to return
+              for each block.  For a list of available fields see under `Response
+              Values -> blocks`, below.
+
+              The following fields are always returned: id, type, display_name
+
+              Example: requested_fields=graded,format,student_view_multi_device
+
+            * depth: (integer or all) Indicates how deep to traverse into the blocks
+              hierarchy.  A value of all means the entire hierarchy.
+
+              Default is 0
+
+              Example: depth=all
+
+            * nav_depth: (integer)
+
+              WARNING: nav_depth is not supported, and may be removed at any time.
+
+              Indicates how far deep to traverse into the
+              course hierarchy before bundling all the descendants.
+
+              Default is 3 since typical navigational views of the course show a
+              maximum of chapter->sequential->vertical.
+
+              Example: nav_depth=3
+
+            * return_type (string) Indicates in what data type to return the
+              blocks.
+
+              Default is dict. Supported values are: dict, list
+
+              Example: return_type=dict
+
+            * block_types_filter: (list) Requested types of blocks used to filter the final result
+              of returned blocks. Possible values include sequential, vertical, html, problem,
+              video, and discussion.
+
+              Example: block_types_filter=vertical,html
+
+        **Response Values**
+
+            The following fields are returned with a successful response.
+
+            * root: The ID of the root node of the requested course block
+              structure.
+
+            * blocks: A dictionary or list, based on the value of the
+              "return_type" parameter. Maps block usage IDs to a collection of
+              information about each block. Each block contains the following
+              fields.
+
+              * id: (string) The usage ID of the block.
+
+              * type: (string) The type of block. Possible values the names of any
+                XBlock type in the system, including custom blocks. Examples are
+                course, chapter, sequential, vertical, html, problem, video, and
+                discussion.
+
+              * display_name: (string) The display name of the block.
+
+              * children: (list) If the block has child blocks, a list of IDs of
+                the child blocks.  Returned only if "children" is included in the
+                "requested_fields" parameter.
+
+              * completion: (float or None) The level of completion of the block.
+                Its value can vary between 0.0 and 1.0 or be equal to None
+                if block is not completable. Returned only if "completion"
+                is included in the "requested_fields" parameter.
+
+              * block_counts: (dict) For each block type specified in the
+                block_counts parameter to the endpoint, the aggregate number of
+                blocks of that type for this block and all of its descendants.
+
+              * graded (boolean) Whether or not the block or any of its descendants
+                is graded.  Returned only if "graded" is included in the
+                "requested_fields" parameter.
+
+              * format: (string) The assignment type of the block.  Possible values
+                can be "Homework", "Lab", "Midterm Exam", and "Final Exam".
+                Returned only if "format" is included in the "requested_fields"
+                parameter.
+
+              * student_view_data: (dict) The JSON data for this block.
+                Returned only if the "student_view_data" input parameter contains
+                this block's type.
+
+              * student_view_url: (string) The URL to retrieve the HTML rendering
+                of this block's student view.  The HTML could include CSS and
+                Javascript code. This field can be used in combination with the
+                student_view_multi_device field to decide whether to display this
+                content to the user.
+
+                This URL can be used as a fallback if the student_view_data for
+                this block type is not supported by the client or the block.
+
+              * student_view_multi_device: (boolean) Whether or not the HTML of
+                the student view that is rendered at "student_view_url" supports
+                responsive web layouts, touch-based inputs, and interactive state
+                management for a variety of device sizes and types, including
+                mobile and touch devices. Returned only if
+                "student_view_multi_device" is included in the "requested_fields"
+                parameter.
+
+              * lms_web_url: (string) The URL to the navigational container of the
+                xBlock on the web. This URL can be used as a further fallback
+                if the student_view_url and the student_view_data fields are not
+                supported. Will direct to either the "New" (micro-frontend) or
+                "Legacy" (Django-template-rendered) frontend experience depending
+                on which experience is active.
+
+              * legacy_web_url: (string) Like `lms_web_url`, but always directs to
+                the "Legacy" frontend experience. Should only be used for
+                transitional purposes; will be removed as part of DEPR-109.
+
+              * lti_url: The block URL for an LTI consumer. Returned only if the
+                "ENABLE_LTI_PROVIDER" Django settign is set to "True".
+
+              * due: The due date of the block. Returned only if "due" is included
+                in the "requested_fields" parameter.
+
+              * show_correctness: Whether to show scores/correctness to learners for the current sequence or problem.
+                Returned only if "show_correctness" is included in the "requested_fields" parameter.
+
+              * Additional XBlock fields can be included in the response if they are
+                configured via the COURSE_BLOCKS_API_EXTRA_FIELDS Django setting and
+                requested via the "requested_fields" parameter.
       parameters:
         - name: page
           in: query
@@ -1626,47 +2453,92 @@ paths:
   : get:
       operationId: courseware_course_+]+api_courseware_course_+]+(_|+)[_]+)_read
       summary: '**Use Cases**'
-      description: "Request details for a course\n\n**Example Requests**\n\n    GET\
-        \ /api/courseware/course/{course_key}\n\n**Response Values**\n\n    Body consists\
-        \ of the following fields:\n\n    * effort: A textual description of the weekly\
-        \ hours of effort expected\n        in the course.\n    * end: Date the course\
-        \ ends, in ISO 8601 notation\n    * enrollment_end: Date enrollment ends,\
-        \ in ISO 8601 notation\n    * enrollment_start: Date enrollment begins, in\
-        \ ISO 8601 notation\n    * id: A unique identifier of the course; a serialized\
-        \ representation\n        of the opaque key identifying the course.\n    *\
-        \ media: An object that contains named media items.  Included here:\n    \
-        \    * course_image: An image to show for the course.  Represented\n     \
-        \     as an object with the following fields:\n            * uri: The location\
-        \ of the image\n    * name: Name of the course\n    * number: Catalog number\
-        \ of the course\n    * org: Name of the organization that owns the course\n\
-        \    * short_description: A textual description of the course\n    * start:\
-        \ Date the course begins, in ISO 8601 notation\n    * start_display: Readably\
-        \ formatted start of the course\n    * start_type: Hint describing how `start_display`\
-        \ is set. One of:\n        * `\"string\"`: manually set by the course author\n\
-        \        * `\"timestamp\"`: generated from the `start` timestamp\n       \
-        \ * `\"empty\"`: no start date is specified\n    * pacing: Course pacing.\
-        \ Possible values: instructor, self\n    * tabs: Course tabs\n    * enrollment:\
-        \ Enrollment status of authenticated user\n        * mode: `audit`, `verified`,\
-        \ etc\n        * is_active: boolean\n    * can_load_course: Whether the user\
-        \ can view the course (AccessResponse object)\n    * is_staff: Whether the\
-        \ effective user has staff access to the course\n    * original_user_is_staff:\
-        \ Whether the original user has staff access to the course\n    * user_has_passing_grade:\
-        \ Whether or not the effective user's grade is equal to or above the courses\
-        \ minimum\n        passing grade\n    * course_exit_page_is_active: Flag for\
-        \ the learning mfe on whether or not the course exit page should display\n\
-        \    * certificate_data: data regarding the effective user's certificate for\
-        \ the given course\n    * verify_identity_url: URL for a learner to verify\
-        \ their identity. Only returned for learners enrolled in a\n        verified\
-        \ mode. Will update to reverify URL if necessary.\n    * linkedin_add_to_profile_url:\
-        \ URL to add the effective user's certificate to a LinkedIn Profile.\n\n**Parameters:**\n\
-        \n    requested_fields (optional) comma separated list:\n        If set, then\
-        \ only those fields will be returned.\n    username (optional) username to\
-        \ masquerade as (if requesting user is staff)\n\n**Returns**\n\n    * 200\
-        \ on success with above fields.\n    * 400 if an invalid parameter was sent\
-        \ or the username was not provided\n      for an authenticated request.\n\
-        \    * 403 if a user who does not have permission to masquerade as\n     \
-        \ another user specifies a username other than their own.\n    * 404 if the\
-        \ course is not available or cannot be seen."
+      description: |-
+        Request details for a course
+
+        **Example Requests**
+
+            GET /api/courseware/course/{course_key}
+
+        **Response Values**
+
+            Body consists of the following fields:
+
+            * access_expiration: An object detailing when access to this course will expire
+                * expiration_date: (str) When the access expires, in ISO 8601 notation
+                * masquerading_expired_course: (bool) Whether this course is expired for the masqueraded user
+                * upgrade_deadline: (str) Last chance to upgrade, in ISO 8601 notation (or None if can't upgrade anymore)
+                * upgrade_url: (str) Upgrade linke (or None if can't upgrade anymore)
+            * effort: A textual description of the weekly hours of effort expected
+                in the course.
+            * end: Date the course ends, in ISO 8601 notation
+            * enrollment: Enrollment status of authenticated user
+                * mode: `audit`, `verified`, etc
+                * is_active: boolean
+            * enrollment_end: Date enrollment ends, in ISO 8601 notation
+            * enrollment_start: Date enrollment begins, in ISO 8601 notation
+            * id: A unique identifier of the course; a serialized representation
+                of the opaque key identifying the course.
+            * media: An object that contains named media items.  Included here:
+                * course_image: An image to show for the course.  Represented
+                  as an object with the following fields:
+                    * uri: The location of the image
+            * name: Name of the course
+            * number: Catalog number of the course
+            * offer: An object detailing upgrade discount information
+                * code: (str) Checkout code
+                * expiration_date: (str) Expiration of offer, in ISO 8601 notation
+                * original_price: (str) Full upgrade price without checkout code; includes currency symbol
+                * discounted_price: (str) Upgrade price with checkout code; includes currency symbol
+                * percentage: (int) Amount of discount
+                * upgrade_url: (str) Checkout URL
+            * org: Name of the organization that owns the course
+            * related_programs: A list of objects that contains program data related to the given course including:
+                * progress: An object containing program progress:
+                    * complete: (int) Number of complete courses in the program (a course is completed if the user has
+                        earned a certificate for any of the nested course runs)
+                    * in_progress: (int) Number of courses in the program that are in progress (a course is in progress if
+                        the user has enrolled in any of the nested course runs)
+                    * not_started: (int) Number of courses in the program that have not been started
+                * slug: (str) The program type
+                * title: (str) The title of the program
+                * url: (str) The link to the program's landing page
+                * uuid: (str) A unique identifier of the program
+            * short_description: A textual description of the course
+            * start: Date the course begins, in ISO 8601 notation
+            * start_display: Readably formatted start of the course
+            * start_type: Hint describing how `start_display` is set. One of:
+                * `"string"`: manually set by the course author
+                * `"timestamp"`: generated from the `start` timestamp
+                * `"empty"`: no start date is specified
+            * pacing: Course pacing. Possible values: instructor, self
+            * tabs: Course tabs
+            * user_timezone: User's chosen timezone setting (or null for browser default)
+            * can_load_course: Whether the user can view the course (AccessResponse object)
+            * is_staff: Whether the effective user has staff access to the course
+            * original_user_is_staff: Whether the original user has staff access to the course
+            * user_has_passing_grade: Whether or not the effective user's grade is equal to or above the courses minimum
+                passing grade
+            * course_exit_page_is_active: Flag for the learning mfe on whether or not the course exit page should display
+            * certificate_data: data regarding the effective user's certificate for the given course
+            * verify_identity_url: URL for a learner to verify their identity. Only returned for learners enrolled in a
+                verified mode. Will update to reverify URL if necessary.
+            * linkedin_add_to_profile_url: URL to add the effective user's certificate to a LinkedIn Profile.
+
+        **Parameters:**
+
+            requested_fields (optional) comma separated list:
+                If set, then only those fields will be returned.
+            username (optional) username to masquerade as (if requesting user is staff)
+
+        **Returns**
+
+            * 200 on success with above fields.
+            * 400 if an invalid parameter was sent or the username was not provided
+              for an authenticated request.
+            * 403 if a user who does not have permission to masquerade as
+              another user specifies a username other than their own.
+            * 404 if the course is not available or cannot be seen.
       parameters: []
       responses:
         '200':
@@ -1971,8 +2843,9 @@ paths:
   /discussion/v1/comments/:
     get:
       operationId: discussion_v1_comments_list
-      description: "Implements the GET method for the list endpoint as described in\
-        \ the\nclass docstring."
+      description: |-
+        Implements the GET method for the list endpoint as described in the
+        class docstring.
       parameters: []
       responses:
         '200':
@@ -1984,8 +2857,9 @@ paths:
         - discussion
     post:
       operationId: discussion_v1_comments_create
-      description: "Implements the POST method for the list endpoint as described\
-        \ in the\nclass docstring."
+      description: |-
+        Implements the POST method for the list endpoint as described in the
+        class docstring.
       parameters: []
       responses:
         '201':
@@ -2011,8 +2885,9 @@ paths:
         - discussion
     patch:
       operationId: discussion_v1_comments_partial_update
-      description: "Implements the PATCH method for the instance endpoint as described\
-        \ in\nthe class docstring."
+      description: |-
+        Implements the PATCH method for the instance endpoint as described in
+        the class docstring.
       parameters: []
       responses:
         '200':
@@ -2024,8 +2899,9 @@ paths:
         - discussion
     delete:
       operationId: discussion_v1_comments_delete
-      description: "Implements the DELETE method for the instance endpoint as described\
-        \ in\nthe class docstring"
+      description: |-
+        Implements the DELETE method for the instance endpoint as described in
+        the class docstring
       parameters: []
       responses:
         '204':
@@ -2139,8 +3015,9 @@ paths:
   /discussion/v1/threads/:
     get:
       operationId: discussion_v1_threads_list
-      description: "Implements the GET method for the list endpoint as described in\
-        \ the\nclass docstring."
+      description: |-
+        Implements the GET method for the list endpoint as described in the
+        class docstring.
       parameters: []
       responses:
         '200':
@@ -2152,8 +3029,9 @@ paths:
         - discussion
     post:
       operationId: discussion_v1_threads_create
-      description: "Implements the POST method for the list endpoint as described\
-        \ in the\nclass docstring."
+      description: |-
+        Implements the POST method for the list endpoint as described in the
+        class docstring.
       parameters: []
       responses:
         '201':
@@ -2179,8 +3057,9 @@ paths:
         - discussion
     patch:
       operationId: discussion_v1_threads_partial_update
-      description: "Implements the PATCH method for the instance endpoint as described\
-        \ in\nthe class docstring."
+      description: |-
+        Implements the PATCH method for the instance endpoint as described in
+        the class docstring.
       parameters: []
       responses:
         '200':
@@ -2192,8 +3071,9 @@ paths:
         - discussion
     delete:
       operationId: discussion_v1_threads_delete
-      description: "Implements the DELETE method for the instance endpoint as described\
-        \ in\nthe class docstring"
+      description: |-
+        Implements the DELETE method for the instance endpoint as described in
+        the class docstring
       parameters: []
       responses:
         '204':
@@ -2267,8 +3147,9 @@ paths:
   /edx_proctoring/v1/proctored_exam/allowance:
     get:
       operationId: edx_proctoring_v1_proctored_exam_allowance_list
-      description: "HTTP GET handler. Get all allowances for a course.\nCourse and\
-        \ Global staff can view both timed and proctored exam allowances."
+      description: |-
+        HTTP GET handler. Get all allowances for a course.
+        Course and Global staff can view both timed and proctored exam allowances.
       parameters: []
       responses:
         '200':
@@ -2314,11 +3195,10 @@ paths:
       tags:
         - edx_proctoring
     parameters: []
-  /edx_proctoring/v1/proctored_exam/attempt/course_id/{course_id}:
+  /edx_proctoring/v1/proctored_exam/attempt/grouped/course_id/{course_id}:
     get:
-      operationId: edx_proctoring_v1_proctored_exam_attempt_course_id_read
-      description: "HTTP GET Handler. Returns the status of the exam attempt.\nCourse\
-        \ and Global staff can view both timed and proctored exam attempts."
+      operationId: edx_proctoring_v1_proctored_exam_attempt_grouped_course_id_read
+      description: HTTP GET Handler.
       parameters: []
       responses:
         '200':
@@ -2330,11 +3210,10 @@ paths:
         in: path
         required: true
         type: string
-  /edx_proctoring/v1/proctored_exam/attempt/course_id/{course_id}/search/{search_by}:
+  /edx_proctoring/v1/proctored_exam/attempt/grouped/course_id/{course_id}/search/{search_by}:
     get:
-      operationId: edx_proctoring_v1_proctored_exam_attempt_course_id_search_read
-      description: "HTTP GET Handler. Returns the status of the exam attempt.\nCourse\
-        \ and Global staff can view both timed and proctored exam attempts."
+      operationId: edx_proctoring_v1_proctored_exam_attempt_grouped_course_id_search_read
+      description: HTTP GET Handler.
       parameters: []
       responses:
         '200':
@@ -2362,7 +3241,7 @@ paths:
         - edx_proctoring
     put:
       operationId: edx_proctoring_v1_proctored_exam_attempt_update
-      description: HTTP POST handler. To stop an exam.
+      description: HTTP PUT handler to update exam attempt status based on an action.
       parameters: []
       responses:
         '200':
@@ -2386,7 +3265,7 @@ paths:
   /edx_proctoring/v1/proctored_exam/attempt/{attempt_id}/review_status:
     put:
       operationId: edx_proctoring_v1_proctored_exam_attempt_review_status_update
-      description: Update the is_status_acknowledge flag for the specific attempt
+      description: Update the is_status_acknowledged flag for the specific attempt
       parameters: []
       responses:
         '200':
@@ -2416,8 +3295,9 @@ paths:
   /edx_proctoring/v1/proctored_exam/attempt/{external_id}/reviewed:
     post:
       operationId: edx_proctoring_v1_proctored_exam_attempt_reviewed_create
-      description: "Called when 3rd party proctoring service has finished its review\
-        \ of\nan attempt."
+      description: |-
+        Called when 3rd party proctoring service has finished its review of
+        an attempt.
       parameters: []
       responses:
         '201':
@@ -2432,8 +3312,11 @@ paths:
   /edx_proctoring/v1/proctored_exam/exam:
     get:
       operationId: edx_proctoring_v1_proctored_exam_exam_list
-      description: "HTTP GET handler.\n    Scenarios:\n        by exam_id: calls get_exam_by_id()\n\
-        \        by course_id, content_id: get_exam_by_content_id()"
+      description: |-
+        HTTP GET handler.
+            Scenarios:
+                by exam_id: calls get_exam_by_id()
+                by course_id, content_id: get_exam_by_content_id()
       parameters: []
       responses:
         '200':
@@ -2451,7 +3334,9 @@ paths:
         - edx_proctoring
     put:
       operationId: edx_proctoring_v1_proctored_exam_exam_update
-      description: "HTTP PUT handler. To update an exam.\ncalls the update_exam"
+      description: |-
+        HTTP PUT handler. To update an exam.
+        calls the update_exam
       parameters: []
       responses:
         '200':
@@ -2462,8 +3347,11 @@ paths:
   /edx_proctoring/v1/proctored_exam/exam/course_id/{course_id}:
     get:
       operationId: edx_proctoring_v1_proctored_exam_exam_course_id_read
-      description: "HTTP GET handler.\n    Scenarios:\n        by exam_id: calls get_exam_by_id()\n\
-        \        by course_id, content_id: get_exam_by_content_id()"
+      description: |-
+        HTTP GET handler.
+            Scenarios:
+                by exam_id: calls get_exam_by_id()
+                by course_id, content_id: get_exam_by_content_id()
       parameters: []
       responses:
         '200':
@@ -2481,7 +3369,9 @@ paths:
         - edx_proctoring
     put:
       operationId: edx_proctoring_v1_proctored_exam_exam_course_id_update
-      description: "HTTP PUT handler. To update an exam.\ncalls the update_exam"
+      description: |-
+        HTTP PUT handler. To update an exam.
+        calls the update_exam
       parameters: []
       responses:
         '200':
@@ -2496,8 +3386,11 @@ paths:
   /edx_proctoring/v1/proctored_exam/exam/course_id/{course_id}/content_id/{content_id}:
     get:
       operationId: edx_proctoring_v1_proctored_exam_exam_course_id_content_id_read
-      description: "HTTP GET handler.\n    Scenarios:\n        by exam_id: calls get_exam_by_id()\n\
-        \        by course_id, content_id: get_exam_by_content_id()"
+      description: |-
+        HTTP GET handler.
+            Scenarios:
+                by exam_id: calls get_exam_by_id()
+                by course_id, content_id: get_exam_by_content_id()
       parameters: []
       responses:
         '200':
@@ -2515,7 +3408,9 @@ paths:
         - edx_proctoring
     put:
       operationId: edx_proctoring_v1_proctored_exam_exam_course_id_content_id_update
-      description: "HTTP PUT handler. To update an exam.\ncalls the update_exam"
+      description: |-
+        HTTP PUT handler. To update an exam.
+        calls the update_exam
       parameters: []
       responses:
         '200':
@@ -2534,8 +3429,11 @@ paths:
   /edx_proctoring/v1/proctored_exam/exam/exam_id/{exam_id}:
     get:
       operationId: edx_proctoring_v1_proctored_exam_exam_exam_id_read
-      description: "HTTP GET handler.\n    Scenarios:\n        by exam_id: calls get_exam_by_id()\n\
-        \        by course_id, content_id: get_exam_by_content_id()"
+      description: |-
+        HTTP GET handler.
+            Scenarios:
+                by exam_id: calls get_exam_by_id()
+                by course_id, content_id: get_exam_by_content_id()
       parameters: []
       responses:
         '200':
@@ -2553,7 +3451,9 @@ paths:
         - edx_proctoring
     put:
       operationId: edx_proctoring_v1_proctored_exam_exam_exam_id_update
-      description: "HTTP PUT handler. To update an exam.\ncalls the update_exam"
+      description: |-
+        HTTP PUT handler. To update an exam.
+        calls the update_exam
       parameters: []
       responses:
         '200':
@@ -2565,11 +3465,32 @@ paths:
         in: path
         required: true
         type: string
+  /edx_proctoring/v1/proctored_exam/exam_id/{exam_id}/user_id/{user_id}/reset_attempts:
+    delete:
+      operationId: edx_proctoring_v1_proctored_exam_exam_id_user_id_reset_attempts_delete
+      description: HTTP DELETE handler, deletes all attempts for a given exam and
+        username
+      parameters: []
+      responses:
+        '204':
+          description: ''
+      tags:
+        - edx_proctoring
+    parameters:
+      - name: exam_id
+        in: path
+        required: true
+        type: string
+      - name: user_id
+        in: path
+        required: true
+        type: string
   /edx_proctoring/v1/proctored_exam/{course_id}/allowance:
     get:
       operationId: edx_proctoring_v1_proctored_exam_allowance_list
-      description: "HTTP GET handler. Get all allowances for a course.\nCourse and\
-        \ Global staff can view both timed and proctored exam allowances."
+      description: |-
+        HTTP GET handler. Get all allowances for a course.
+        Course and Global staff can view both timed and proctored exam allowances.
       parameters: []
       responses:
         '200':
@@ -2602,8 +3523,9 @@ paths:
   /edx_proctoring/v1/retire_backend_user/{user_id}/:
     post:
       operationId: edx_proctoring_v1_retire_backend_user_create
-      description: "Deletes all user data for the particular user_id\nfrom all configured\
-        \ backends"
+      description: |-
+        Deletes all user data for the particular user_id
+        from all configured backends
       parameters: []
       responses:
         '201':
@@ -2630,6 +3552,32 @@ paths:
         in: path
         required: true
         type: string
+  /edx_proctoring/v1/user_onboarding/status:
+    get:
+      operationId: edx_proctoring_v1_user_onboarding_status_list
+      description: HTTP GET handler. Returns the learner's onboarding status.
+      parameters: []
+      responses:
+        '200':
+          description: ''
+      tags:
+        - edx_proctoring
+    parameters: []
+  /edx_proctoring/v1/user_onboarding/status/course_id/{course_id}:
+    get:
+      operationId: edx_proctoring_v1_user_onboarding_status_course_id_read
+      description: HTTP GET handler.
+      parameters: []
+      responses:
+        '200':
+          description: ''
+      tags:
+        - edx_proctoring
+    parameters:
+      - name: course_id
+        in: path
+        required: true
+        type: string
   /edxnotes/v1/retire_user/:
     post:
       operationId: edxnotes_v1_retire_user_create
@@ -2641,6 +3589,17 @@ paths:
       tags:
         - edxnotes
     parameters: []
+  /embargo/v1/course_access/:
+    get:
+      operationId: embargo_v1_course_access_list
+      description: GET /api/embargo/v1/course_access/
+      parameters: []
+      responses:
+        '200':
+          description: ''
+      tags:
+        - embargo
+    parameters: []
   /enrollment/v1/course/{course_id}:
     get:
       operationId: enrollment_v1_course_read
@@ -2661,17 +3620,20 @@ paths:
     get:
       operationId: enrollment_v1_enrollment_list
       summary: Gets a list of all course enrollments for a user.
-      description: "Returns a list for the currently logged in user, or for the user\
-        \ named by the 'user' GET\nparameter. If the username does not match that\
-        \ of the currently logged in user, only\ncourses for which the currently logged\
-        \ in user has the Staff or Admin role are listed.\nAs a result, a course team\
-        \ member can find out which of their own courses a particular\nlearner is\
-        \ enrolled in.\n\nOnly the Staff or Admin role (granted on the Django administrative\
-        \ console as the staff\nor instructor permission) in individual courses gives\
-        \ the requesting user access to\nenrollment data. Permissions granted at the\
-        \ organizational level do not give a user\naccess to enrollment data for all\
-        \ of that organization's courses.\n\nUsers who have the global staff permission\
-        \ can access all enrollment data for all\ncourses."
+      description: |-
+        Returns a list for the currently logged in user, or for the user named by the 'user' GET
+        parameter. If the username does not match that of the currently logged in user, only
+        courses for which the currently logged in user has the Staff or Admin role are listed.
+        As a result, a course team member can find out which of their own courses a particular
+        learner is enrolled in.
+
+        Only the Staff or Admin role (granted on the Django administrative console as the staff
+        or instructor permission) in individual courses gives the requesting user access to
+        enrollment data. Permissions granted at the organizational level do not give a user
+        access to enrollment data for all of that organization's courses.
+
+        Users who have the global staff permission can access all enrollment data for all
+        courses.
       parameters: []
       responses:
         '200':
@@ -2681,9 +3643,9 @@ paths:
     post:
       operationId: enrollment_v1_enrollment_create
       summary: Enrolls the currently logged-in user in a course.
-      description: "Server-to-server calls may deactivate or modify the mode of existing\
-        \ enrollments. All other requests\ngo through `add_enrollment()`, which allows\
-        \ creation of new and reactivation of old enrollments."
+      description: |-
+        Server-to-server calls may deactivate or modify the mode of existing enrollments. All other requests
+        go through `add_enrollment()`, which allows creation of new and reactivation of old enrollments.
       parameters: []
       responses:
         '201':
@@ -2695,9 +3657,9 @@ paths:
     get:
       operationId: enrollment_v1_enrollment_read
       summary: Create, read, or update enrollment information for a user.
-      description: "HTTP Endpoint for all CRUD operations for a user course enrollment.\
-        \ Allows creation, reading, and\nupdates of the current enrollment for a particular\
-        \ course."
+      description: |-
+        HTTP Endpoint for all CRUD operations for a user course enrollment. Allows creation, reading, and
+        updates of the current enrollment for a particular course.
       parameters: []
       responses:
         '200':
@@ -2713,9 +3675,9 @@ paths:
     get:
       operationId: enrollment_v1_enrollment_read
       summary: Create, read, or update enrollment information for a user.
-      description: "HTTP Endpoint for all CRUD operations for a user course enrollment.\
-        \ Allows creation, reading, and\nupdates of the current enrollment for a particular\
-        \ course."
+      description: |-
+        HTTP Endpoint for all CRUD operations for a user course enrollment. Allows creation, reading, and
+        updates of the current enrollment for a particular course.
       parameters: []
       responses:
         '200':
@@ -2735,35 +3697,66 @@ paths:
     get:
       operationId: enrollment_v1_enrollments_list
       summary: '**Use Cases**'
-      description: "Get a list of all course enrollments, optionally filtered by a\
-        \ course ID or list of usernames.\n\n**Example Requests**\n\n    GET /api/enrollment/v1/enrollments\n\
-        \n    GET /api/enrollment/v1/enrollments?course_id={course_id}\n\n    GET\
-        \ /api/enrollment/v1/enrollments?username={username},{username},{username}\n\
-        \n    GET /api/enrollment/v1/enrollments?course_id={course_id}&username={username}\n\
-        \n**Query Parameters for GET**\n\n    * course_id: Filters the result to course\
-        \ enrollments for the course corresponding to the\n      given course ID.\
-        \ The value must be URL encoded. Optional.\n\n    * username: List of comma-separated\
-        \ usernames. Filters the result to the course enrollments\n      of the given\
-        \ users. Optional.\n\n    * page_size: Number of results to return per page.\
-        \ Optional.\n\n    * page: Page number to retrieve. Optional.\n\n**Response\
-        \ Values**\n\n    If the request for information about the course enrollments\
-        \ is successful, an HTTP 200 \"OK\" response\n    is returned.\n\n    The\
-        \ HTTP 200 response has the following values.\n\n    * results: A list of\
-        \ the course enrollments matching the request.\n\n        * created: Date\
-        \ and time when the course enrollment was created.\n\n        * mode: Mode\
-        \ for the course enrollment.\n\n        * is_active: Whether the course enrollment\
-        \ is active or not.\n\n        * user: Username of the user in the course\
-        \ enrollment.\n\n        * course_id: Course ID of the course in the course\
-        \ enrollment.\n\n    * next: The URL to the next page of results, or null\
-        \ if this is the\n      last page.\n\n    * previous: The URL to the next\
-        \ page of results, or null if this\n      is the first page.\n\n    If the\
-        \ user is not logged in, a 401 error is returned.\n\n    If the user is not\
-        \ global staff, a 403 error is returned.\n\n    If the specified course_id\
-        \ is not valid or any of the specified usernames\n    are not valid, a 400\
-        \ error is returned.\n\n    If the specified course_id does not correspond\
-        \ to a valid course or if all the specified\n    usernames do not correspond\
-        \ to valid users, an HTTP 200 \"OK\" response is returned with an\n    empty\
-        \ 'results' field."
+      description: |-
+        Get a list of all course enrollments, optionally filtered by a course ID or list of usernames.
+
+        **Example Requests**
+
+            GET /api/enrollment/v1/enrollments
+
+            GET /api/enrollment/v1/enrollments?course_id={course_id}
+
+            GET /api/enrollment/v1/enrollments?username={username},{username},{username}
+
+            GET /api/enrollment/v1/enrollments?course_id={course_id}&username={username}
+
+        **Query Parameters for GET**
+
+            * course_id: Filters the result to course enrollments for the course corresponding to the
+              given course ID. The value must be URL encoded. Optional.
+
+            * username: List of comma-separated usernames. Filters the result to the course enrollments
+              of the given users. Optional.
+
+            * page_size: Number of results to return per page. Optional.
+
+            * page: Page number to retrieve. Optional.
+
+        **Response Values**
+
+            If the request for information about the course enrollments is successful, an HTTP 200 "OK" response
+            is returned.
+
+            The HTTP 200 response has the following values.
+
+            * results: A list of the course enrollments matching the request.
+
+                * created: Date and time when the course enrollment was created.
+
+                * mode: Mode for the course enrollment.
+
+                * is_active: Whether the course enrollment is active or not.
+
+                * user: Username of the user in the course enrollment.
+
+                * course_id: Course ID of the course in the course enrollment.
+
+            * next: The URL to the next page of results, or null if this is the
+              last page.
+
+            * previous: The URL to the next page of results, or null if this
+              is the first page.
+
+            If the user is not logged in, a 401 error is returned.
+
+            If the user is not global staff, a 403 error is returned.
+
+            If the specified course_id is not valid or any of the specified usernames
+            are not valid, a 400 error is returned.
+
+            If the specified course_id does not correspond to a valid course or if all the specified
+            usernames do not correspond to valid users, an HTTP 200 "OK" response is returned with an
+            empty 'results' field.
       parameters:
         - name: cursor
           in: query
@@ -2819,8 +3812,9 @@ paths:
   /entitlements/v1/entitlements/:
     get:
       operationId: entitlements_v1_entitlements_list
-      description: "Override the list method to expire records that are past the\n\
-        policy and requested via the API before returning those records."
+      description: |-
+        Override the list method to expire records that are past the
+        policy and requested via the API before returning those records.
       parameters:
         - name: uuid
           in: query
@@ -2887,8 +3881,9 @@ paths:
   /entitlements/v1/entitlements/{uuid}/:
     get:
       operationId: entitlements_v1_entitlements_read
-      description: "Override the retrieve method to expire a record that is past the\n\
-        policy and is requested via the API before returning that record."
+      description: |-
+        Override the retrieve method to expire a record that is past the
+        policy and is requested via the API before returning that record.
       parameters: []
       responses:
         '200':
@@ -2947,12 +3942,15 @@ paths:
   /entitlements/v1/entitlements/{uuid}/enrollments:
     post:
       operationId: entitlements_v1_entitlements_enrollments_create
-      description: "On POST this method will be called and will handle enrolling a\
-        \ user in the\nprovided course_run_id from the data. This is called on a specific\
-        \ entitlement\nUUID so the course_run_id has to correspond to the Course that\
-        \ is assigned to\nthe Entitlement.\n\nWhen this API is called for a user who\
-        \ is already enrolled in a run that User\nwill be unenrolled from their current\
-        \ run and enrolled in the new run if it is\navailable."
+      description: |-
+        On POST this method will be called and will handle enrolling a user in the
+        provided course_run_id from the data. This is called on a specific entitlement
+        UUID so the course_run_id has to correspond to the Course that is assigned to
+        the Entitlement.
+
+        When this API is called for a user who is already enrolled in a run that User
+        will be unenrolled from their current run and enrolled in the new run if it is
+        available.
       parameters: []
       responses:
         '201':
@@ -2963,8 +3961,9 @@ paths:
       operationId: entitlements_v1_entitlements_enrollments_delete
       summary: On DELETE call to this API we will unenroll the course enrollment for
         the provided uuid
-      description: "If is_refund parameter is provided then unenroll the user, set\
-        \ Entitlement expiration, and issue\na refund"
+      description: |-
+        If is_refund parameter is provided then unenroll the user, set Entitlement expiration, and issue
+        a refund
       parameters: []
       responses:
         '204':
@@ -3316,8 +4315,9 @@ paths:
   /grades/v1/gradebook/{course_id}/:
     get:
       operationId: grades_v1_gradebook_read
-      description: "Checks for course author access for the given course by the requesting\
-        \ user.\nCalls the view function if has access, otherwise raises a 403."
+      description: |-
+        Checks for course author access for the given course by the requesting user.
+        Calls the view function if has access, otherwise raises a 403.
       parameters: []
       responses:
         '200':
@@ -3332,8 +4332,9 @@ paths:
   /grades/v1/gradebook/{course_id}/bulk-update:
     post:
       operationId: grades_v1_gradebook_bulk-update_create
-      description: "Checks for course author access for the given course by the requesting\
-        \ user.\nCalls the view function if has access, otherwise raises a 403."
+      description: |-
+        Checks for course author access for the given course by the requesting user.
+        Calls the view function if has access, otherwise raises a 403.
       parameters: []
       responses:
         '201':
@@ -3348,8 +4349,9 @@ paths:
   /grades/v1/gradebook/{course_id}/grading-info:
     get:
       operationId: grades_v1_gradebook_grading-info_list
-      description: "Checks for course author access for the given course by the requesting\
-        \ user.\nCalls the view function if has access, otherwise raises a 403."
+      description: |-
+        Checks for course author access for the given course by the requesting user.
+        Calls the view function if has access, otherwise raises a 403.
       parameters:
         - name: page
           in: query
@@ -3375,14 +4377,25 @@ paths:
     get:
       operationId: grades_v1_policy_courses_read
       summary: '**Use Case**'
-      description: "Get the course grading policy.\n\n**Example requests**:\n\n  \
-        \  GET /api/grades/v1/policy/courses/{course_id}/\n\n**Response Values**\n\
-        \n    * assignment_type: The type of the assignment, as configured by course\n\
-        \      staff. For example, course staff might make the assignment types Homework,\n\
-        \      Quiz, and Exam.\n\n    * count: The number of assignments of the type.\n\
-        \n    * dropped: Number of assignments of the type that are dropped.\n\n \
-        \   * weight: The weight, or effect, of the assignment type on the learner's\n\
-        \      final grade."
+      description: |-
+        Get the course grading policy.
+
+        **Example requests**:
+
+            GET /api/grades/v1/policy/courses/{course_id}/
+
+        **Response Values**
+
+            * assignment_type: The type of the assignment, as configured by course
+              staff. For example, course staff might make the assignment types Homework,
+              Quiz, and Exam.
+
+            * count: The number of assignments of the type.
+
+            * dropped: Number of assignments of the type that are dropped.
+
+            * weight: The weight, or effect, of the assignment type on the learner's
+              final grade.
       parameters:
         - name: page
           in: query
@@ -3407,8 +4420,9 @@ paths:
   /grades/v1/subsection/{subsection_id}/:
     get:
       operationId: grades_v1_subsection_read
-      description: "Returns subection grade data, override grade data and a history\
-        \ of changes made to\na specific users specific subsection grade."
+      description: |-
+        Returns subection grade data, override grade data and a history of changes made to
+        a specific users specific subsection grade.
       parameters: []
       responses:
         '200':
@@ -3420,82 +4434,782 @@ paths:
         in: path
         required: true
         type: string
-  /learning_sequences/v1/course_outline/{course_key_str}:
+  /instructor/v1/reports/{course_id}:
     get:
-      operationId: learning_sequences_v1_course_outline_read
-      summary: The CourseOutline, customized for a given user.
-      description: Currently restricted to global staff.
-      parameters: []
+      operationId: instructor_v1_reports_read
+      summary: List report CSV files that are available for download for this course.
+      description: |-
+        **Use Cases**
+
+        Lists reports available for download
+
+        **Example Requests**:
+
+            GET /api/instructor/v1/reports/{course_id}
+
+        **Response Values**
+        ```json
+        {
+            "downloads": [
+                {
+                    "url": "https://1.mock.url",
+                    "link": "<a href="https://1.mock.url">mock_file_name_1</a>",
+                    "name": "mock_file_name_1"
+                }
+            ]
+        }
+        ```
+
+        The report name will depend on the type of report generated. For example a
+        problem responses report for an entire course might be called:
+
+            edX_DemoX_Demo_Course_student_state_from_block-v1_edX+DemoX+Demo_Course+type@course+block@course_2021-04-30-0918.csv
+      parameters:
+        - name: course_id
+          in: path
+          description: ID for the course whose reports need to be listed.
+          type: string
+          required: true
+        - name: report_name
+          in: query
+          description: Filter results to only return details of for the report with
+            the specified name.
+          type: string
       responses:
         '200':
           description: ''
+          schema:
+            $ref: '#/definitions/ReportDownloadsList'
+        '401':
+          description: The requesting user is not authenticated.
+        '403':
+          description: The requesting user lacks access to the course.
+        '404':
+          description: The requested course does not exist.
       tags:
-        - learning_sequences
+        - instructor
     parameters:
-      - name: course_key_str
+      - name: course_id
         in: path
         required: true
         type: string
-  /organizations/v0/organizations/:
-    get:
-      operationId: organizations_v0_organizations_list
-      description: "Organization view to:\n    - fetch list organization data or single\
-        \ organization using organization short name.\n    - create or update an organization\
-        \ via the PUT endpoint."
+  /instructor/v1/reports/{course_id}/generate/problem_responses:
+    post:
+      operationId: instructor_v1_reports_generate_problem_responses_create
+      summary: Initiate generation of a CSV file containing all student answers
+      description: |-
+        to a given problem.
+
+        **Example requests**
+
+            POST /api/instructor/v1/reports/{course_id}/generate/problem_responses {
+                "problem_locations": [
+                    "{usage_key1}",
+                    "{usage_key2}",
+                    "{usage_key3}"
+                ]
+            }
+            POST /api/instructor/v1/reports/{course_id}/generate/problem_responses {
+                "problem_locations": ["{usage_key}"],
+                "problem_types_filter": ["problem"]
+            }
+
+        **POST Parameters**
+
+        A POST request can include the following parameters:
+
+        * problem_location: A list of usage keys for the blocks to include in
+          the report. If the location is a block that contains other blocks,
+          (such as the course, section, subsection, or unit blocks) then all
+          blocks under that block will be included in the report.
+        * problem_types_filter: Optional. A comma-separated list of block types
+          to include in the report. If set, only blocks of the specified types
+          will be included in the report.
+
+        To get data on all the poll and survey blocks in a course, you could
+        POST the usage key of the course for `problem_location`, and
+        "poll, survey" as the value for `problem_types_filter`.
+
+
+        **Example Response:**
+        If initiation is successful (or generation task is already running):
+        ```json
+        {
+            "status": "The problem responses report is being created. ...",
+            "task_id": "4e49522f-31d9-431a-9cff-dd2a2bf4c85a"
+        }
+        ```
+
+        Responds with BadRequest if any of the provided problem locations are faulty.
       parameters:
-        - name: page
-          in: query
-          description: A page number within the paginated result set.
-          required: false
-          type: integer
-        - name: page_size
-          in: query
-          description: Number of results to return per page.
-          required: false
-          type: integer
+        - name: data
+          in: body
+          required: true
+          schema:
+            $ref: '#/definitions/ProblemResponseReportPostParams'
+        - name: course_id
+          in: path
+          description: ID of the course for which report is to be generate.
+          type: string
+          required: true
       responses:
         '200':
           description: ''
           schema:
-            required:
-              - count
-              - results
-            type: object
-            properties:
-              count:
-                type: integer
-              next:
-                type: string
-                format: uri
-                x-nullable: true
-              previous:
-                type: string
-                format: uri
-                x-nullable: true
-              results:
-                type: array
-                items:
-                  $ref: '#/definitions/Organization'
+            $ref: '#/definitions/ProblemResponsesReportStatus'
+        '400':
+          description: The provided parameters were invalid. Make sure you've provided
+            at least one valid usage key for `problem_locations`.
+        '401':
+          description: The requesting user is not authenticated.
+        '403':
+          description: The requesting user lacks access to the course.
       tags:
-        - organizations
-    parameters: []
-  /organizations/v0/organizations/{short_name}/:
+        - instructor
+    parameters:
+      - name: course_id
+        in: path
+        required: true
+        type: string
+  /instructor/v1/tasks/{course_id}:
     get:
-      operationId: organizations_v0_organizations_read
-      description: "Organization view to:\n    - fetch list organization data or single\
-        \ organization using organization short name.\n    - create or update an organization\
-        \ via the PUT endpoint."
-      parameters: []
+      operationId: instructor_v1_tasks_read
+      summary: List instructor tasks filtered by `course_id`.
+      description: |-
+        **Use Cases**
+
+        Lists currently running instructor tasks
+
+        **Parameters**
+           - With no arguments, lists running tasks.
+           - `problem_location_str` lists task history for problem
+           - `problem_location_str` and `unique_student_identifier` lists task
+               history for problem AND student (intersection)
+
+        **Example Requests**:
+
+            GET /courses/{course_id}/instructor/api/v0/tasks
+
+        **Response Values**
+        ```json
+            {
+              "tasks": [
+                {
+                  "status": "Incomplete",
+                  "task_type": "grade_problems",
+                  "task_id": "2519ff31-22d9-4a62-91e2-55495895b355",
+                  "created": "2019-01-15T18:00:15.902470+00:00",
+                  "task_input": "{}",
+                  "duration_sec": "unknown",
+                  "task_message": "No status information available",
+                  "requester": "staff",
+                  "task_state": "PROGRESS"
+                }
+              ]
+            }
+        ```
+      parameters:
+        - name: course_id
+          in: path
+          description: ID for the course whose tasks need to be listed.
+          type: string
+          required: true
+        - name: problem_location_str
+          in: query
+          description: Filter instructor tasks to this problem location.
+          type: string
+        - name: unique_student_identifier
+          in: query
+          description: Filter tasks to a singe problem and a single student. Must
+            be used in combination with `problem_location_str`.
+          type: string
       responses:
         '200':
           description: ''
           schema:
-            $ref: '#/definitions/Organization'
+            $ref: '#/definitions/InstructorTasksList'
+        '401':
+          description: The requesting user is not authenticated.
+        '403':
+          description: The requesting user lacks access to the course.
+        '404':
+          description: The requested course does not exist.
       tags:
-        - organizations
-    put:
-      operationId: organizations_v0_organizations_update
-      description: We perform both Update and Create action via the PUT method.
+        - instructor
+    parameters:
+      - name: course_id
+        in: path
+        required: true
+        type: string
+  /learning_sequences/v1/course_outline/{course_key_str}:
+    get:
+      operationId: learning_sequences_v1_course_outline_read
+      summary: The CourseOutline, customized for a given user.
+      description: Currently restricted to global staff.
+      parameters: []
+      responses:
+        '200':
+          description: ''
+      tags:
+        - learning_sequences
+    parameters:
+      - name: course_key_str
+        in: path
+        required: true
+        type: string
+  /lti_consumer/v1/lti/{lti_config_id}/lti-ags:
+    get:
+      operationId: lti_consumer_v1_lti_lti-ags_list
+      summary: LineItem endpoint implementation from LTI Advantage.
+      description: 'See full documentation at:'
+      parameters: []
+      responses:
+        '200':
+          description: ''
+          schema:
+            type: array
+            items:
+              $ref: '#/definitions/LtiAgsLineItem'
+      consumes:
+        - application/vnd.ims.lis.v2.lineitem+json
+      produces:
+        - application/vnd.ims.lis.v2.lineitemcontainer+json
+        - application/vnd.ims.lis.v2.lineitem+json
+      tags:
+        - lti_consumer
+    post:
+      operationId: lti_consumer_v1_lti_lti-ags_create
+      summary: LineItem endpoint implementation from LTI Advantage.
+      description: 'See full documentation at:'
+      parameters:
+        - name: data
+          in: body
+          required: true
+          schema:
+            $ref: '#/definitions/LtiAgsLineItem'
+      responses:
+        '201':
+          description: ''
+          schema:
+            $ref: '#/definitions/LtiAgsLineItem'
+      consumes:
+        - application/vnd.ims.lis.v2.lineitem+json
+      produces:
+        - application/vnd.ims.lis.v2.lineitemcontainer+json
+        - application/vnd.ims.lis.v2.lineitem+json
+      tags:
+        - lti_consumer
+    parameters:
+      - name: lti_config_id
+        in: path
+        required: true
+        type: string
+  /lti_consumer/v1/lti/{lti_config_id}/lti-ags/{id}:
+    get:
+      operationId: lti_consumer_v1_lti_lti-ags_read
+      summary: LineItem endpoint implementation from LTI Advantage.
+      description: 'See full documentation at:'
+      parameters: []
+      responses:
+        '200':
+          description: ''
+          schema:
+            $ref: '#/definitions/LtiAgsLineItem'
+      consumes:
+        - application/vnd.ims.lis.v2.lineitem+json
+      produces:
+        - application/vnd.ims.lis.v2.lineitemcontainer+json
+        - application/vnd.ims.lis.v2.lineitem+json
+      tags:
+        - lti_consumer
+    put:
+      operationId: lti_consumer_v1_lti_lti-ags_update
+      summary: LineItem endpoint implementation from LTI Advantage.
+      description: 'See full documentation at:'
+      parameters:
+        - name: data
+          in: body
+          required: true
+          schema:
+            $ref: '#/definitions/LtiAgsLineItem'
+      responses:
+        '200':
+          description: ''
+          schema:
+            $ref: '#/definitions/LtiAgsLineItem'
+      consumes:
+        - application/vnd.ims.lis.v2.lineitem+json
+      produces:
+        - application/vnd.ims.lis.v2.lineitemcontainer+json
+        - application/vnd.ims.lis.v2.lineitem+json
+      tags:
+        - lti_consumer
+    patch:
+      operationId: lti_consumer_v1_lti_lti-ags_partial_update
+      summary: LineItem endpoint implementation from LTI Advantage.
+      description: 'See full documentation at:'
+      parameters:
+        - name: data
+          in: body
+          required: true
+          schema:
+            $ref: '#/definitions/LtiAgsLineItem'
+      responses:
+        '200':
+          description: ''
+          schema:
+            $ref: '#/definitions/LtiAgsLineItem'
+      consumes:
+        - application/vnd.ims.lis.v2.lineitem+json
+      produces:
+        - application/vnd.ims.lis.v2.lineitemcontainer+json
+        - application/vnd.ims.lis.v2.lineitem+json
+      tags:
+        - lti_consumer
+    delete:
+      operationId: lti_consumer_v1_lti_lti-ags_delete
+      summary: LineItem endpoint implementation from LTI Advantage.
+      description: 'See full documentation at:'
+      parameters: []
+      responses:
+        '204':
+          description: ''
+      consumes:
+        - application/vnd.ims.lis.v2.lineitem+json
+      produces:
+        - application/vnd.ims.lis.v2.lineitemcontainer+json
+        - application/vnd.ims.lis.v2.lineitem+json
+      tags:
+        - lti_consumer
+    parameters:
+      - name: id
+        in: path
+        required: true
+        type: string
+      - name: lti_config_id
+        in: path
+        required: true
+        type: string
+  /lti_consumer/v1/lti/{lti_config_id}/lti-ags/{id}/results/{user_id}:
+    get:
+      operationId: lti_consumer_v1_lti_lti-ags_results
+      summary: Return a Result list for an LtiAgsLineItem
+      description: |-
+        URL Parameters:
+          * user_id (string): String external user id representation.
+
+        Query Parameters:
+          * limit (integer): The maximum number of records to return. Records are
+                sorted with most recent timestamp first
+      parameters: []
+      responses:
+        '200':
+          description: ''
+          schema:
+            $ref: '#/definitions/LtiAgsLineItem'
+      consumes:
+        - application/vnd.ims.lis.v2.lineitem+json
+      produces:
+        - application/vnd.ims.lis.v2.resultcontainer+json
+      tags:
+        - lti_consumer
+    parameters:
+      - name: id
+        in: path
+        required: true
+        type: string
+      - name: lti_config_id
+        in: path
+        required: true
+        type: string
+      - name: user_id
+        in: path
+        required: true
+        type: string
+  /lti_consumer/v1/lti/{lti_config_id}/lti-ags/{id}/scores:
+    post:
+      operationId: lti_consumer_v1_lti_lti-ags_scores
+      description: Create a Score record for an LtiAgsLineItem
+      parameters:
+        - name: data
+          in: body
+          required: true
+          schema:
+            $ref: '#/definitions/LtiAgsLineItem'
+      responses:
+        '201':
+          description: ''
+          schema:
+            $ref: '#/definitions/LtiAgsLineItem'
+      consumes:
+        - application/vnd.ims.lis.v1.score+json
+      produces:
+        - application/vnd.ims.lis.v1.score+json
+      tags:
+        - lti_consumer
+    parameters:
+      - name: id
+        in: path
+        required: true
+        type: string
+      - name: lti_config_id
+        in: path
+        required: true
+        type: string
+  /mfe_context:
+    get:
+      operationId: mfe_context_list
+      description: |-
+        Returns the context for third party auth providers, user country code
+        and the currently running pipeline.
+      parameters: []
+      responses:
+        '200':
+          description: ''
+      tags:
+        - mfe_context
+    parameters: []
+  /mobile/{api_version}/course_info/{course_id}/handouts:
+    get:
+      operationId: mobile_course_info_handouts_list
+      summary: '**Use Case**'
+      description: |-
+        Get the HTML for course handouts.
+
+        **Example Request**
+
+            GET /api/mobile/v0.5/course_info/{course_id}/handouts
+
+        **Response Values**
+
+            If the request is successful, the request returns an HTTP 200 "OK"
+            response along with the following value.
+
+            * handouts_html: The HTML for course handouts.
+      parameters:
+        - name: page
+          in: query
+          description: A page number within the paginated result set.
+          required: false
+          type: integer
+        - name: page_size
+          in: query
+          description: Number of results to return per page.
+          required: false
+          type: integer
+      responses:
+        '200':
+          description: ''
+      tags:
+        - mobile
+    parameters:
+      - name: api_version
+        in: path
+        required: true
+        type: string
+      - name: course_id
+        in: path
+        required: true
+        type: string
+  /mobile/{api_version}/course_info/{course_id}/updates:
+    get:
+      operationId: mobile_course_info_updates_list
+      summary: '**Use Case**'
+      description: |-
+        Get the content for course updates.
+
+        **Example Request**
+
+            GET /api/mobile/v0.5/course_info/{course_id}/updates
+
+        **Response Values**
+
+            If the request is successful, the request returns an HTTP 200 "OK"
+            response along with an array of course updates. Each course update
+            contains the following values.
+
+                * content: The content, as an HTML string, of the course update.
+                * date: The date of the course update.
+                * id: The unique identifier of the update.
+                * status: Whether the update is visible or not.
+      parameters:
+        - name: page
+          in: query
+          description: A page number within the paginated result set.
+          required: false
+          type: integer
+        - name: page_size
+          in: query
+          description: Number of results to return per page.
+          required: false
+          type: integer
+      responses:
+        '200':
+          description: ''
+      tags:
+        - mobile
+    parameters:
+      - name: api_version
+        in: path
+        required: true
+        type: string
+      - name: course_id
+        in: path
+        required: true
+        type: string
+  /mobile/{api_version}/my_user_info:
+    get:
+      operationId: mobile_my_user_info_list
+      description: Redirect to the currently-logged-in user's info page
+      parameters: []
+      responses:
+        '200':
+          description: ''
+      tags:
+        - mobile
+    parameters:
+      - name: api_version
+        in: path
+        required: true
+        type: string
+  /mobile/{api_version}/users/{username}:
+    get:
+      operationId: mobile_users_read
+      summary: '**Use Case**'
+      description: |-
+        Get information about the specified user and access other resources
+            the user has permissions for.
+
+            Users are redirected to this endpoint after they sign in.
+
+            You can use the **course_enrollments** value in the response to get a
+            list of courses the user is enrolled in.
+
+        **Example Request**
+
+            GET /api/mobile/{version}/users/{username}
+
+        **Response Values**
+
+            If the request is successful, the request returns an HTTP 200 "OK" response.
+
+            The HTTP 200 response has the following values.
+
+            * course_enrollments: The URI to list the courses the currently signed
+              in user is enrolled in.
+            * email: The email address of the currently signed in user.
+            * id: The ID of the user.
+            * name: The full name of the currently signed in user.
+            * username: The username of the currently signed in user.
+      parameters: []
+      responses:
+        '200':
+          description: ''
+          schema:
+            $ref: '#/definitions/mobile_api.User'
+      tags:
+        - mobile
+    parameters:
+      - name: api_version
+        in: path
+        required: true
+        type: string
+      - name: username
+        in: path
+        description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_
+          only.
+        required: true
+        type: string
+        pattern: ^[\w.@+-]+$
+  /mobile/{api_version}/users/{username}/course_enrollments/:
+    get:
+      operationId: mobile_users_course_enrollments_list
+      summary: '**Use Case**'
+      description: |-
+        Get information about the courses that the currently signed in user is
+            enrolled in.
+
+            v1 differs from v0.5 version by returning ALL enrollments for
+            a user rather than only the enrollments the user has access to (that haven't expired).
+            An additional attribute "expiration" has been added to the response, which lists the date
+            when access to the course will expire or null if it doesn't expire.
+
+        **Example Request**
+
+            GET /api/mobile/v1/users/{username}/course_enrollments/
+
+        **Response Values**
+
+            If the request for information about the user is successful, the
+            request returns an HTTP 200 "OK" response.
+
+            The HTTP 200 response has the following values.
+
+            * expiration: The course expiration date for given user course pair
+              or null if the course does not expire.
+            * certificate: Information about the user's earned certificate in the
+              course.
+            * course: A collection of the following data about the course.
+
+            * courseware_access: A JSON representation with access information for the course,
+              including any access errors.
+
+              * course_about: The URL to the course about page.
+              * course_sharing_utm_parameters: Encoded UTM parameters to be included in course sharing url
+              * course_handouts: The URI to get data for course handouts.
+              * course_image: The path to the course image.
+              * course_updates: The URI to get data for course updates.
+              * discussion_url: The URI to access data for course discussions if
+                it is enabled, otherwise null.
+              * end: The end date of the course.
+              * id: The unique ID of the course.
+              * name: The name of the course.
+              * number: The course number.
+              * org: The organization that created the course.
+              * start: The date and time when the course starts.
+              * start_display:
+                If start_type is a string, then the advertised_start date for the course.
+                If start_type is a timestamp, then a formatted date for the start of the course.
+                If start_type is empty, then the value is None and it indicates that the course has not yet started.
+              * start_type: One of either "string", "timestamp", or "empty"
+              * subscription_id: A unique "clean" (alphanumeric with '_') ID of
+                the course.
+              * video_outline: The URI to get the list of all videos that the user
+                can access in the course.
+
+            * created: The date the course was created.
+            * is_active: Whether the course is currently active. Possible values
+              are true or false.
+            * mode: The type of certificate registration for this course (honor or
+              certified).
+            * url: URL to the downloadable version of the certificate, if exists.
+      parameters: []
+      responses:
+        '200':
+          description: ''
+          schema:
+            type: array
+            items:
+              $ref: '#/definitions/CourseEnrollment'
+      tags:
+        - mobile
+    parameters:
+      - name: api_version
+        in: path
+        required: true
+        type: string
+      - name: username
+        in: path
+        required: true
+        type: string
+  ? /mobile/{api_version}/users/{username}/course_status_info/(P{course_id}[/+]+{var}[/+]+api/mobile/{api_version}/users/{username}/course_status_info/(P{course_id}[/+]+(/|+)[/+]+{var}[/]+)
+  : get:
+      operationId: mobile_users_course_status_info_+]+api_mobile_users_course_status_info_+]+(_|+)[_]+)_list
+      description: Get the ID of the module that the specified user last visited in
+        the specified course.
+      parameters: []
+      responses:
+        '200':
+          description: ''
+      tags:
+        - mobile
+    patch:
+      operationId: mobile_users_course_status_info_+]+api_mobile_users_course_status_info_+]+(_|+)[_]+)_partial_update
+      description: Update the ID of the module that the specified user last visited
+        in the specified course.
+      parameters: []
+      responses:
+        '200':
+          description: ''
+      tags:
+        - mobile
+    parameters:
+      - name: api_version
+        in: path
+        required: true
+        type: string
+      - name: course_id
+        in: path
+        required: true
+        type: string
+      - name: username
+        in: path
+        required: true
+        type: string
+      - name: var
+        in: path
+        required: true
+        type: string
+  /organizations/v0/organizations/:
+    get:
+      operationId: organizations_v0_organizations_list
+      description: |-
+        Organization view to:
+            - list organization data (GET .../)
+            - retrieve single organization (GET .../<short_name>)
+            - create or update an organization via the PUT endpoint (PUT .../<short_name>)
+      parameters:
+        - name: page
+          in: query
+          description: A page number within the paginated result set.
+          required: false
+          type: integer
+        - name: page_size
+          in: query
+          description: Number of results to return per page.
+          required: false
+          type: integer
+      responses:
+        '200':
+          description: ''
+          schema:
+            required:
+              - count
+              - results
+            type: object
+            properties:
+              count:
+                type: integer
+              next:
+                type: string
+                format: uri
+                x-nullable: true
+              previous:
+                type: string
+                format: uri
+                x-nullable: true
+              results:
+                type: array
+                items:
+                  $ref: '#/definitions/Organization'
+      tags:
+        - organizations
+    parameters: []
+  /organizations/v0/organizations/{short_name}/:
+    get:
+      operationId: organizations_v0_organizations_read
+      description: |-
+        Organization view to:
+            - list organization data (GET .../)
+            - retrieve single organization (GET .../<short_name>)
+            - create or update an organization via the PUT endpoint (PUT .../<short_name>)
+      parameters: []
+      responses:
+        '200':
+          description: ''
+          schema:
+            $ref: '#/definitions/Organization'
+      tags:
+        - organizations
+    put:
+      operationId: organizations_v0_organizations_update
+      summary: We perform both Update and Create action via the PUT method.
+      description: |-
+        The 'active' field may not be specified via the HTTP API, since it
+        is always assumed to be True. So:
+            (1) new organizations created through the API are always Active, and
+            (2) existing organizations updated through the API always end up Active,
+                regardless of whether or not they were previously active.
       parameters:
         - name: data
           in: body
@@ -3529,8 +5243,9 @@ paths:
     parameters:
       - name: short_name
         in: path
-        description: Please do not use spaces or special characters. Only allowed
-          special characters are period (.), hyphen (-) and underscore (_).
+        description: Unique, short string identifier for organization. Please do not
+          use spaces or special characters. Only allowed special characters are period
+          (.), hyphen (-) and underscore (_).
         required: true
         type: string
   /profile_images/v1/{username}/remove:
@@ -3739,8 +5454,9 @@ paths:
   /program_enrollments/v1/programs/{program_uuid}/overview/:
     get:
       operationId: program_enrollments_v1_programs_overview_read
-      description: "A view for getting data associated with a user's course enrollments\n\
-        as part of a program enrollment."
+      description: |-
+        A view for getting data associated with a user's course enrollments
+        as part of a program enrollment.
       parameters: []
       responses:
         '200':
@@ -3759,41 +5475,66 @@ paths:
       operationId: program_enrollments_v1_users_programs_courses_list
       summary: Get an overview of each of a user's course enrollments associated with
         a program.
-      description: "This endpoint exists to get an overview of each course-run enrollment\n\
-        that a user has for course-runs within a given program.\nFields included are\
-        \ the title, upcoming due dates, etc.\nThis API endpoint is intended for use\
-        \ with the\n[Program Learner Portal MFE](https://github.com/edx/frontend-app-learner-portal-programs).\n\
-        \nIt is important to note that the set of enrollments that this endpoint returns\n\
-        is different than a user's set of *program-course-run enrollments*.\nSpecifically,\
-        \ this endpoint may include course runs that are *within*\nthe specified program\
-        \ but were not *enrolled in* via the specified program.\n\n**Example Response:**\n\
-        ```json\n{\n    \"next\": null,\n    \"previous\": null,\n    \"results\"\
-        : [\n        {\n            \"course_run_id\": \"edX+AnimalsX+Aardvarks\"\
-        ,\n            \"display_name\": \"Astonishing Aardvarks\",\n            \"\
-        course_run_url\": \"https://courses.edx.org/courses/course-v1:edX+AnimalsX+Aardvarks/course/\"\
-        ,\n            \"start_date\": \"2017-02-05T05:00:00Z\",\n            \"end_date\"\
-        : \"2018-02-05T05:00:00Z\",\n            \"course_run_status\": \"completed\"\
-        \n            \"emails_enabled\": true,\n            \"due_dates\": [\n  \
-        \              {\n                    \"name\": \"Introduction: What even\
-        \ is an aardvark?\",\n                    \"url\": \"https://courses.edx.org/courses/course-v1:edX+AnimalsX+Aardvarks/jump_to/\n\
-        \                          block-v1:edX+AnimalsX+Aardvarks+type@chapter+block@1414ffd5143b4b508f739b563ab468b7\"\
-        ,\n                    \"date\": \"2017-05-01T05:00:00Z\"\n              \
-        \  },\n                {\n                    \"name\": \"Quiz: Aardvark or\
-        \ Anteater?\",\n                    \"url\": \"https://courses.edx.org/courses/course-v1:edX+AnimalsX+Aardvarks/jump_to/\n\
-        \                            block-v1:edX+AnimalsX+Aardvarks+type@sequential+block@edx_introduction\"\
-        ,\n                    \"date\": \"2017-03-05T00:00:00Z\"\n              \
-        \  }\n            ],\n            \"micromasters_title\": \"Animals\",\n \
-        \           \"certificate_download_url\": \"https://courses.edx.org/certificates/123\"\
-        \n        },\n        {\n            \"course_run_id\": \"edX+AnimalsX+Baboons\"\
-        ,\n            \"display_name\": \"Breathtaking Baboons\",\n            \"\
-        course_run_url\": \"https://courses.edx.org/courses/course-v1:edX+AnimalsX+Baboons/course/\"\
-        ,\n            \"start_date\": \"2018-02-05T05:00:00Z\",\n            \"end_date\"\
-        : null,\n            \"course_run_status\": \"in_progress\"\n            \"\
-        emails_enabled\": false,\n            \"due_dates\": [],\n            \"micromasters_title\"\
-        : \"Animals\",\n            \"certificate_download_url\": \"https://courses.edx.org/certificates/123\"\
-        ,\n            \"resume_course_run_url\": \"https://courses.edx.org/courses/course-v1:edX+AnimalsX+Baboons/jump_to/\n\
-        \                                       block-v1:edX+AnimalsX+Baboons+type@sequential+block@edx_introduction\"\
-        \n        }\n    ]\n}\n```"
+      description: |-
+        This endpoint exists to get an overview of each course-run enrollment
+        that a user has for course-runs within a given program.
+        Fields included are the title, upcoming due dates, etc.
+        This API endpoint is intended for use with the
+        [Program Learner Portal MFE](https://github.com/edx/frontend-app-learner-portal-programs).
+
+        It is important to note that the set of enrollments that this endpoint returns
+        is different than a user's set of *program-course-run enrollments*.
+        Specifically, this endpoint may include course runs that are *within*
+        the specified program but were not *enrolled in* via the specified program.
+
+        **Example Response:**
+        ```json
+        {
+            "next": null,
+            "previous": null,
+            "results": [
+                {
+                    "course_run_id": "edX+AnimalsX+Aardvarks",
+                    "display_name": "Astonishing Aardvarks",
+                    "course_run_url": "https://courses.edx.org/courses/course-v1:edX+AnimalsX+Aardvarks/course/",
+                    "start_date": "2017-02-05T05:00:00Z",
+                    "end_date": "2018-02-05T05:00:00Z",
+                    "course_run_status": "completed"
+                    "emails_enabled": true,
+                    "due_dates": [
+                        {
+                            "name": "Introduction: What even is an aardvark?",
+                            "url": "https://courses.edx.org/courses/course-v1:edX+AnimalsX+Aardvarks/jump_to/
+                                  block-v1:edX+AnimalsX+Aardvarks+type@chapter+block@1414ffd5143b4b508f739b563ab468b7",
+                            "date": "2017-05-01T05:00:00Z"
+                        },
+                        {
+                            "name": "Quiz: Aardvark or Anteater?",
+                            "url": "https://courses.edx.org/courses/course-v1:edX+AnimalsX+Aardvarks/jump_to/
+                                    block-v1:edX+AnimalsX+Aardvarks+type@sequential+block@edx_introduction",
+                            "date": "2017-03-05T00:00:00Z"
+                        }
+                    ],
+                    "micromasters_title": "Animals",
+                    "certificate_download_url": "https://courses.edx.org/certificates/123"
+                },
+                {
+                    "course_run_id": "edX+AnimalsX+Baboons",
+                    "display_name": "Breathtaking Baboons",
+                    "course_run_url": "https://courses.edx.org/courses/course-v1:edX+AnimalsX+Baboons/course/",
+                    "start_date": "2018-02-05T05:00:00Z",
+                    "end_date": null,
+                    "course_run_status": "in_progress"
+                    "emails_enabled": false,
+                    "due_dates": [],
+                    "micromasters_title": "Animals",
+                    "certificate_download_url": "https://courses.edx.org/certificates/123",
+                    "resume_course_run_url": "https://courses.edx.org/courses/course-v1:edX+AnimalsX+Baboons/jump_to/
+                                               block-v1:edX+AnimalsX+Baboons+type@sequential+block@edx_introduction"
+                }
+            ]
+        }
+        ```
       parameters:
         - name: cursor
           in: query
@@ -4064,10 +5805,18 @@ paths:
     get:
       operationId: third_party_auth_v0_providers_user_status_list
       summary: GET /api/third_party_auth/v0/providers/user_status/
-      description: "**GET Response Values**\n```\n{\n    \"accepts_logins\": true,\n\
-        \    \"name\": \"Google\",\n    \"disconnect_url\": \"/auth/disconnect/google-oauth2/?\"\
-        ,\n    \"connect_url\": \"/auth/login/google-oauth2/?auth_entry=account_settings&next=%2Faccount%2Fsettings\"\
-        ,\n    \"connected\": false,\n    \"id\": \"oa2-google-oauth2\"\n}\n```"
+      description: |-
+        **GET Response Values**
+        ```
+        {
+            "accepts_logins": true,
+            "name": "Google",
+            "disconnect_url": "/auth/disconnect/google-oauth2/?",
+            "connect_url": "/auth/login/google-oauth2/?auth_entry=account_settings&next=%2Faccount%2Fsettings",
+            "connected": false,
+            "id": "oa2-google-oauth2"
+        }
+        ```
       parameters: []
       responses:
         '200':
@@ -4079,39 +5828,73 @@ paths:
     get:
       operationId: third_party_auth_v0_providers_users_list
       summary: Map between the third party auth account IDs (remote_id) and EdX username.
-      description: "This API is intended to be a server-to-server endpoint. An on-campus\
-        \ middleware or system should consume this.\n\n**Use Case**\n\n    Get a paginated\
-        \ list of mappings between edX users and remote user IDs for all users currently\n\
-        \    linked to the given backend.\n\n    The list can be filtered by edx username\
-        \ or third party ids. The filter is limited by the max length of URL.\n  \
-        \  It is suggested to query no more than 50 usernames or remote_ids in each\
-        \ request to stay within above\n    limitation\n\n    The page size can be\
-        \ changed by specifying `page_size` parameter in the request.\n\n**Example\
-        \ Requests**\n\n      GET /api/third_party_auth/v0/providers/{provider_id}/users\n\
-        \n      GET /api/third_party_auth/v0/providers/{provider_id}/users?username={username1},{username2}\n\
-        \n      GET /api/third_party_auth/v0/providers/{provider_id}/users?username={username1}&usernames={username2}\n\
-        \n      GET /api/third_party_auth/v0/providers/{provider_id}/users?remote_id={remote_id1},{remote_id2}\n\
-        \n      GET /api/third_party_auth/v0/providers/{provider_id}/users?remote_id={remote_id1}&remote_id={remote_id2}\n\
-        \n      GET /api/third_party_auth/v0/providers/{provider_id}/users?username={username1}&remote_id={remote_id1}\n\
-        \n**URL Parameters**\n\n    * provider_id: The unique identifier of third_party_auth\
-        \ provider (e.g. \"saml-ubc\", \"oa2-google\", etc.\n      This is not the\
-        \ same thing as the backend_name.). (Optional/future: We may also want to\
-        \ allow\n      this to be an 'external domain' like 'ssl:MIT' so that this\
-        \ API can also search the legacy\n      ExternalAuthMap table used by Standford/MIT)\n\
-        \n**Query Parameters**\n\n    * remote_ids: Optional. List of comma separated\
-        \ remote (third party) user IDs to filter the result set.\n      e.g. ?remote_ids=8721384623\n\
-        \n    * usernames: Optional. List of comma separated edX usernames to filter\
-        \ the result set.\n      e.g. ?usernames=bob123,jane456\n\n    * page, page_size:\
-        \ Optional. Used for paging the result set, especially when getting\n    \
-        \  an unfiltered list.\n\n**Response Values**\n\n    If the request for information\
-        \ about the user is successful, an HTTP 200 \"OK\" response\n    is returned.\n\
-        \n    The HTTP 200 response has the following values:\n\n    * count: The\
-        \ number of mappings for the backend.\n\n    * next: The URI to the next page\
-        \ of the mappings.\n\n    * previous: The URI to the previous page of the\
-        \ mappings.\n\n    * num_pages: The number of pages listing the mappings.\n\
-        \n    * results:  A list of mappings returned. Each collection in the list\n\
-        \      contains these fields.\n\n        * username: The edx username\n\n\
-        \        * remote_id: The Id from third party auth provider"
+      description: |-
+        This API is intended to be a server-to-server endpoint. An on-campus middleware or system should consume this.
+
+        **Use Case**
+
+            Get a paginated list of mappings between edX users and remote user IDs for all users currently
+            linked to the given backend.
+
+            The list can be filtered by edx username or third party ids. The filter is limited by the max length of URL.
+            It is suggested to query no more than 50 usernames or remote_ids in each request to stay within above
+            limitation
+
+            The page size can be changed by specifying `page_size` parameter in the request.
+
+        **Example Requests**
+
+              GET /api/third_party_auth/v0/providers/{provider_id}/users
+
+              GET /api/third_party_auth/v0/providers/{provider_id}/users?username={username1},{username2}
+
+              GET /api/third_party_auth/v0/providers/{provider_id}/users?username={username1}&usernames={username2}
+
+              GET /api/third_party_auth/v0/providers/{provider_id}/users?remote_id={remote_id1},{remote_id2}
+
+              GET /api/third_party_auth/v0/providers/{provider_id}/users?remote_id={remote_id1}&remote_id={remote_id2}
+
+              GET /api/third_party_auth/v0/providers/{provider_id}/users?username={username1}&remote_id={remote_id1}
+
+        **URL Parameters**
+
+            * provider_id: The unique identifier of third_party_auth provider (e.g. "saml-ubc", "oa2-google", etc.
+              This is not the same thing as the backend_name.). (Optional/future: We may also want to allow
+              this to be an 'external domain' like 'ssl:MIT' so that this API can also search the legacy
+              ExternalAuthMap table used by Standford/MIT)
+
+        **Query Parameters**
+
+            * remote_ids: Optional. List of comma separated remote (third party) user IDs to filter the result set.
+              e.g. ?remote_ids=8721384623
+
+            * usernames: Optional. List of comma separated edX usernames to filter the result set.
+              e.g. ?usernames=bob123,jane456
+
+            * page, page_size: Optional. Used for paging the result set, especially when getting
+              an unfiltered list.
+
+        **Response Values**
+
+            If the request for information about the user is successful, an HTTP 200 "OK" response
+            is returned.
+
+            The HTTP 200 response has the following values:
+
+            * count: The number of mappings for the backend.
+
+            * next: The URI to the next page of the mappings.
+
+            * previous: The URI to the previous page of the mappings.
+
+            * num_pages: The number of pages listing the mappings.
+
+            * results:  A list of mappings returned. Each collection in the list
+              contains these fields.
+
+                * username: The edx username
+
+                * remote_id: The Id from third party auth provider
       parameters:
         - name: page
           in: query
@@ -4188,8 +5971,9 @@ paths:
   /third_party_auth_context:
     get:
       operationId: third_party_auth_context_list
-      description: Returns the context for third party auth providers and the currently
-        running pipeline.
+      description: |-
+        Returns the context for third party auth providers, user country code
+        and the currently running pipeline.
       parameters: []
       responses:
         '200':
@@ -4200,7 +5984,7 @@ paths:
   /toggles/v0/state/:
     get:
       operationId: toggles_v0_state_list
-      description: An endpoint for displaying the state of toggles in edx-platform.
+      description: Expose toggle state report dict as a view.
       parameters: []
       responses:
         '200':
@@ -4221,8 +6005,15 @@ paths:
     post:
       operationId: user_v1_account_login_session_create
       summary: Log in a user.
-      description: "See `login_user` for details.\n\nExample Usage:\n\n    POST /api/user/v1/login_session\n\
-        \    with POST params `email`, `password`.\n\n    200 {'success': true}"
+      description: |-
+        See `login_user` for details.
+
+        Example Usage:
+
+            POST /api/user/v1/login_session
+            with POST params `email`, `password`.
+
+            200 {'success': true}
       parameters: []
       responses:
         '201':
@@ -4242,6 +6033,17 @@ paths:
       tags:
         - user
     parameters: []
+  /user/v1/account/password_reset/token/validate/:
+    post:
+      operationId: user_v1_account_password_reset_token_validate_create
+      description: HTTP end-point to validate password reset token.
+      parameters: []
+      responses:
+        '201':
+          description: ''
+      tags:
+        - user
+    parameters: []
   /user/v1/account/registration/:
     get:
       operationId: user_v1_account_registration_list
@@ -4255,9 +6057,11 @@ paths:
     post:
       operationId: user_v1_account_registration_create
       summary: Create the user's account.
-      description: "You must send all required form fields with the request.\n\nYou\
-        \ can optionally send a \"course_id\" param to indicate in analytics\nevents\
-        \ that the user registered while enrolling in a particular course."
+      description: |-
+        You must send all required form fields with the request.
+
+        You can optionally send a "course_id" param to indicate in analytics
+        events that the user registered while enrolling in a particular course.
       parameters: []
       responses:
         '201':
@@ -4268,13 +6072,15 @@ paths:
   /user/v1/accounts:
     get:
       operationId: user_v1_accounts_list
-      description: "GET /api/user/v1/accounts?username={username1,username2}\nGET\
-        \ /api/user/v1/accounts?email={user_email}"
+      description: |-
+        GET /api/user/v1/accounts?username={username1},{username2}
+        GET /api/user/v1/accounts?email={user_email1},{user_email2}
       parameters: []
       responses:
         '200':
           description: ''
       consumes:
+        - application/json
         - application/merge-patch+json
       tags:
         - user
@@ -4283,8 +6089,9 @@ paths:
     post:
       operationId: user_v1_accounts_deactivate_logout_create
       summary: POST /api/user/v1/accounts/deactivate_logout/
-      description: "Marks the user as having no password set for deactivation purposes,\n\
-        and logs the user out."
+      description: |-
+        Marks the user as having no password set for deactivation purposes,
+        and logs the user out.
       parameters: []
       responses:
         '201':
@@ -4295,17 +6102,39 @@ paths:
   /user/v1/accounts/replace_usernames/:
     post:
       operationId: user_v1_accounts_replace_usernames_create
-      description: "POST /api/user/v1/accounts/replace_usernames/\n```\n{\n    \"\
-        username_mappings\": [\n        {\"current_username_1\": \"desired_username_1\"\
-        },\n        {\"current_username_2\": \"desired_username_2\"}\n    ]\n}\n```\n\
-        \n**POST Parameters**\n\nA POST request must include the following parameter.\n\
-        \n* username_mappings: Required. A list of objects that map the current username\
-        \ (key)\n  to the desired username (value)\n\n**POST Response Values**\n\n\
-        As long as data validation passes, the request will return a 200 with a new\
-        \ mapping\nof old usernames (key) to new username (value)\n\n```\n{\n    \"\
-        successful_replacements\": [\n        {\"old_username_1\": \"new_username_1\"\
-        }\n    ],\n    \"failed_replacements\": [\n        {\"old_username_2\": \"\
-        new_username_2\"}\n    ]\n}\n```"
+      description: |-
+        POST /api/user/v1/accounts/replace_usernames/
+        ```
+        {
+            "username_mappings": [
+                {"current_username_1": "desired_username_1"},
+                {"current_username_2": "desired_username_2"}
+            ]
+        }
+        ```
+
+        **POST Parameters**
+
+        A POST request must include the following parameter.
+
+        * username_mappings: Required. A list of objects that map the current username (key)
+          to the desired username (value)
+
+        **POST Response Values**
+
+        As long as data validation passes, the request will return a 200 with a new mapping
+        of old usernames (key) to new username (value)
+
+        ```
+        {
+            "successful_replacements": [
+                {"old_username_1": "new_username_1"}
+            ],
+            "failed_replacements": [
+                {"old_username_2": "new_username_2"}
+            ]
+        }
+        ```
       parameters: []
       responses:
         '201':
@@ -4317,9 +6146,16 @@ paths:
     post:
       operationId: user_v1_accounts_post
       summary: POST /api/user/v1/accounts/retire/
-      description: "```\n{\n    'username': 'user_to_retire'\n}\n```\n\nRetires the\
-        \ user with the given username.  This includes\nretiring this username, the\
-        \ associated email address, and\nany other PII associated with this user."
+      description: |-
+        ```
+        {
+            'username': 'user_to_retire'
+        }
+        ```
+
+        Retires the user with the given username.  This includes
+        retiring this username, the associated email address, and
+        any other PII associated with this user.
       parameters: []
       responses:
         '201':
@@ -4331,8 +6167,14 @@ paths:
     post:
       operationId: user_v1_accounts_post
       summary: POST /api/user/v1/accounts/retire_misc/
-      description: "```\n{\n    'username': 'user_to_retire'\n}\n```\n\nRetires the\
-        \ user with the given username in the LMS."
+      description: |-
+        ```
+        {
+            'username': 'user_to_retire'
+        }
+        ```
+
+        Retires the user with the given username in the LMS.
       parameters: []
       responses:
         '201':
@@ -4344,8 +6186,14 @@ paths:
     post:
       operationId: user_v1_accounts_cleanup
       summary: POST /api/user/v1/accounts/retirement_cleanup/
-      description: "```\n{\n    'usernames': ['user1', 'user2', ...]\n}\n```\n\nDeletes\
-        \ a batch of retirement requests by username."
+      description: |-
+        ```
+        {
+            'usernames': ['user1', 'user2', ...]
+        }
+        ```
+
+        Deletes a batch of retirement requests by username.
       parameters: []
       responses:
         '201':
@@ -4357,9 +6205,10 @@ paths:
     post:
       operationId: user_v1_accounts_retirement_partner_report_create
       summary: POST /api/user/v1/accounts/retirement_partner_report/
-      description: "Returns the list of UserRetirementPartnerReportingStatus users\n\
-        that are not already being processed and updates their status\nto indicate\
-        \ they are currently being processed."
+      description: |-
+        Returns the list of UserRetirementPartnerReportingStatus users
+        that are not already being processed and updates their status
+        to indicate they are currently being processed.
       parameters: []
       responses:
         '201':
@@ -4369,9 +6218,15 @@ paths:
     put:
       operationId: user_v1_accounts_retirement_partner_report_update
       summary: PUT /api/user/v1/accounts/retirement_partner_report/
-      description: "```\n{\n    'username': 'user_to_retire'\n}\n```\n\nCreates a\
-        \ UserRetirementPartnerReportingStatus object for the given user\nas part\
-        \ of the retirement pipeline."
+      description: |-
+        ```
+        {
+            'username': 'user_to_retire'
+        }
+        ```
+
+        Creates a UserRetirementPartnerReportingStatus object for the given user
+        as part of the retirement pipeline.
       parameters: []
       responses:
         '200':
@@ -4383,9 +6238,11 @@ paths:
     post:
       operationId: user_v1_accounts_retirement_partner_cleanup
       summary: POST /api/user/v1/accounts/retirement_partner_report_cleanup/
-      description: "[{'original_username': 'user1'}, {'original_username': 'user2'},\
-        \ ...]\n\nDeletes UserRetirementPartnerReportingStatus objects for a list\
-        \ of users\nthat have been reported on."
+      description: |-
+        [{'original_username': 'user1'}, {'original_username': 'user2'}, ...]
+
+        Deletes UserRetirementPartnerReportingStatus objects for a list of users
+        that have been reported on.
       parameters: []
       responses:
         '201':
@@ -4396,10 +6253,12 @@ paths:
   /user/v1/accounts/retirement_queue/:
     get:
       operationId: user_v1_accounts_retirement_queue
-      summary: "GET /api/user/v1/accounts/retirement_queue/\n{'cool_off_days': 7,\
-        \ 'states': ['PENDING', 'COMPLETE']}"
-      description: "Returns the list of RetirementStatus users in the given states\
-        \ that were\ncreated in the retirement queue at least `cool_off_days` ago."
+      summary: |-
+        GET /api/user/v1/accounts/retirement_queue/
+        {'cool_off_days': 7, 'states': ['PENDING', 'COMPLETE']}
+      description: |-
+        Returns the list of RetirementStatus users in the given states that were
+        created in the retirement queue at least `cool_off_days` ago.
       parameters: []
       responses:
         '200':
@@ -4410,11 +6269,14 @@ paths:
   /user/v1/accounts/retirements_by_status_and_date/:
     get:
       operationId: user_v1_accounts_retirements_by_status_and_date
-      summary: "GET /api/user/v1/accounts/retirements_by_status_and_date/\n?start_date=2018-09-05&end_date=2018-09-07&state=COMPLETE"
-      description: "Returns a list of UserRetirementStatusSerializer serialized\n\
-        RetirementStatus rows in the given state that were created in the\nretirement\
-        \ queue between the dates given. Date range is inclusive,\nso to get one day\
-        \ you would set both dates to that day."
+      summary: |-
+        GET /api/user/v1/accounts/retirements_by_status_and_date/
+        ?start_date=2018-09-05&end_date=2018-09-07&state=COMPLETE
+      description: |-
+        Returns a list of UserRetirementStatusSerializer serialized
+        RetirementStatus rows in the given state that were created in the
+        retirement queue between the dates given. Date range is inclusive,
+        so to get one day you would set both dates to that day.
       parameters: []
       responses:
         '200':
@@ -4422,17 +6284,45 @@ paths:
       tags:
         - user
     parameters: []
+  /user/v1/accounts/search_emails:
+    post:
+      operationId: user_v1_accounts_search_emails
+      description: |-
+        POST /api/user/v1/accounts/search_emails
+        Content Type: "application/json"
+        {
+            "emails": ["edx@example.com", "staff@example.com"]
+        }
+      parameters: []
+      responses:
+        '201':
+          description: ''
+      consumes:
+        - application/json
+        - application/merge-patch+json
+      tags:
+        - user
+    parameters: []
   /user/v1/accounts/update_retirement_status/:
     patch:
       operationId: user_v1_accounts_update_retirement_status_partial_update
       summary: PATCH /api/user/v1/accounts/update_retirement_status/
-      description: "```\n{\n    'username': 'user_to_retire',\n    'new_state': 'LOCKING_COMPLETE',\n\
-        \    'response': 'User account locked and logged out.'\n}\n```\n\nUpdates\
-        \ the RetirementStatus row for the given user to the new\nstatus, and append\
-        \ any messages to the message log.\n\nNote that this implementation DOES NOT\
-        \ use the \"merge patch\"\nimplementation seen in AccountViewSet. Slumber,\
-        \ the project\nwe use to power edx-rest-api-client, does not currently support\n\
-        it. The content type for this request is 'application/json'."
+      description: |-
+        ```
+        {
+            'username': 'user_to_retire',
+            'new_state': 'LOCKING_COMPLETE',
+            'response': 'User account locked and logged out.'
+        }
+        ```
+
+        Updates the RetirementStatus row for the given user to the new
+        status, and append any messages to the message log.
+
+        Note that this implementation DOES NOT use the "merge patch"
+        implementation seen in AccountViewSet. Slumber, the project
+        we use to power edx-rest-api-client, does not currently support
+        it. The content type for this request is 'application/json'.
       parameters: []
       responses:
         '200':
@@ -4449,6 +6339,7 @@ paths:
         '200':
           description: ''
       consumes:
+        - application/json
         - application/merge-patch+json
       tags:
         - user
@@ -4462,6 +6353,7 @@ paths:
         '200':
           description: ''
       consumes:
+        - application/json
         - application/merge-patch+json
       tags:
         - user
@@ -4519,8 +6411,10 @@ paths:
   /user/v1/accounts/{username}/retirement_status/:
     get:
       operationId: user_v1_accounts_retirement_status_read
-      description: "GET /api/user/v1/accounts/{username}/retirement_status/\nReturns\
-        \ the RetirementStatus of a given user, or 404 if that row\ndoesn't exist."
+      description: |-
+        GET /api/user/v1/accounts/{username}/retirement_status/
+        Returns the RetirementStatus of a given user, or 404 if that row
+        doesn't exist.
       parameters: []
       responses:
         '200':
@@ -4534,8 +6428,8 @@ paths:
         type: string
   /user/v1/accounts/{username}/verification_status/:
     get:
-      operationId: user_v1_accounts_verification_status_read
-      description: IDVerificationStatus detail endpoint.
+      operationId: user_v1_accounts_verification_status_list
+      description: IDVerification Status endpoint
       parameters: []
       responses:
         '200':
@@ -4621,6 +6515,7 @@ paths:
         '200':
           description: ''
       consumes:
+        - application/json
         - application/merge-patch+json
       tags:
         - user
@@ -4629,8 +6524,9 @@ paths:
     post:
       operationId: user_v1_preferences_email_opt_in_create
       summary: Post function for updating the email opt in preference.
-      description: "Allows the modification or creation of the email opt in preference\
-        \ at an\norganizational level."
+      description: |-
+        Allows the modification or creation of the email opt in preference at an
+        organizational level.
       parameters: []
       responses:
         '201':
@@ -4642,17 +6538,28 @@ paths:
     get:
       operationId: user_v1_preferences_time_zones_list
       summary: '**Use Cases**'
-      description: "Retrieves a list of all time zones, by default, or common time\
-        \ zones for country, if given\n\n    The country is passed in as its ISO 3166-1\
-        \ Alpha-2 country code as an\n    optional 'country_code' argument. The country\
-        \ code is also case-insensitive.\n\n**Example Requests**\n\n    GET /api/user/v1/preferences/time_zones/\n\
-        \n    GET /api/user/v1/preferences/time_zones/?country_code=FR\n\n**Example\
-        \ GET Response**\n\n    If the request is successful, an HTTP 200 \"OK\" response\
-        \ is returned along with a\n    list of time zone dictionaries for all time\
-        \ zones or just for time zones commonly\n    used in a country, if given.\n\
-        \n    Each time zone dictionary contains the following values.\n\n       \
-        \ * time_zone: The name of the time zone.\n        * description: The display\
-        \ version of the time zone"
+      description: |-
+        Retrieves a list of all time zones, by default, or common time zones for country, if given
+
+            The country is passed in as its ISO 3166-1 Alpha-2 country code as an
+            optional 'country_code' argument. The country code is also case-insensitive.
+
+        **Example Requests**
+
+            GET /api/user/v1/preferences/time_zones/
+
+            GET /api/user/v1/preferences/time_zones/?country_code=FR
+
+        **Example GET Response**
+
+            If the request is successful, an HTTP 200 "OK" response is returned along with a
+            list of time zone dictionaries for all time zones or just for time zones commonly
+            used in a country, if given.
+
+            Each time zone dictionary contains the following values.
+
+                * time_zone: The name of the time zone.
+                * description: The display version of the time zone
       parameters: []
       responses:
         '200':
@@ -4906,13 +6813,22 @@ paths:
     post:
       operationId: user_v1_validation_registration_create
       summary: POST /api/user/v1/validation/registration/
-      description: "Expects request of the form\n```\n{\n    \"name\": \"Dan the Validator\"\
-        ,\n    \"username\": \"mslm\",\n    \"email\": \"mslm@gmail.com\",\n    \"\
-        confirm_email\": \"mslm@gmail.com\",\n    \"password\": \"password123\",\n\
-        \    \"country\": \"PK\"\n}\n```\nwhere each key is the appropriate form field\
-        \ name and the value is\nuser input. One may enter individual inputs if needed.\
-        \ Some inputs\ncan get extra verification checks if entered along with others,\n\
-        like when the password may not equal the username."
+      description: |-
+        Expects request of the form
+        ```
+        {
+            "name": "Dan the Validator",
+            "username": "mslm",
+            "email": "mslm@gmail.com",
+            "confirm_email": "mslm@gmail.com",
+            "password": "password123",
+            "country": "PK"
+        }
+        ```
+        where each key is the appropriate form field name and the value is
+        user input. One may enter individual inputs if needed. Some inputs
+        can get extra verification checks if entered along with others,
+        like when the password may not equal the username.
       parameters: []
       responses:
         '201':
@@ -4933,9 +6849,11 @@ paths:
     post:
       operationId: user_v2_account_registration_create
       summary: Create the user's account.
-      description: "You must send all required form fields with the request.\n\nYou\
-        \ can optionally send a \"course_id\" param to indicate in analytics\nevents\
-        \ that the user registered while enrolling in a particular course."
+      description: |-
+        You must send all required form fields with the request.
+
+        You can optionally send a "course_id" param to indicate in analytics
+        events that the user registered while enrolling in a particular course.
       parameters: []
       responses:
         '201':
@@ -5005,18 +6923,34 @@ paths:
       operationId: val_v0_videos_missing-hls_create
       summary: 'Retrieve video IDs that are missing HLS profiles. This endpoint supports
         2 types of input data:'
-      description: "1. If we want a batch of video ids which are missing HLS profile\
-        \ irrespective of their courses, the request\n   data should be in following\
-        \ format:\n        {\n            'batch_size': 50,\n            'offset':\
-        \ 0\n        }\n   And response will be in following format:\n        {\n\
-        \            'videos': ['video_id1', 'video_id2', 'video_id3', ... , video_id50],\n\
-        \            'total': 300,\n            'offset': 50,\n            'batch_size':\
-        \ 50\n        }\n\n2. If we want all the videos which are missing HLS profiles\
-        \ in a set of specific courses, the request data\n   should be in following\
-        \ format:\n        {\n            'courses': [\n                'course_id1',\n\
-        \                'course_id2',\n                ...\n            ]\n     \
-        \   }\n   And response will be in following format:\n        {\n         \
-        \   'videos': ['video_id1', 'video_id2', 'video_id3', ...]\n        }"
+      description: |-
+        1. If we want a batch of video ids which are missing HLS profile irrespective of their courses, the request
+           data should be in following format:
+                {
+                    'batch_size': 50,
+                    'offset': 0
+                }
+           And response will be in following format:
+                {
+                    'videos': ['video_id1', 'video_id2', 'video_id3', ... , video_id50],
+                    'total': 300,
+                    'offset': 50,
+                    'batch_size': 50
+                }
+
+        2. If we want all the videos which are missing HLS profiles in a set of specific courses, the request data
+           should be in following format:
+                {
+                    'courses': [
+                        'course_id1',
+                        'course_id2',
+                        ...
+                    ]
+                }
+           And response will be in following format:
+                {
+                    'videos': ['video_id1', 'video_id2', 'video_id3', ...]
+                }
       parameters: []
       responses:
         '201':
@@ -5026,10 +6960,19 @@ paths:
     put:
       operationId: val_v0_videos_missing-hls_update
       summary: Update a single profile for a given video.
-      description: "Example request data:\n    ```\n    {\n        'edx_video_id':\
-        \ '1234'\n        'profile': 'hls',\n        'encode_data': {\n          \
-        \  'url': 'foo.com/qwe.m3u8'\n            'file_size': 34\n            'bitrate':\
-        \ 12\n        }\n    }\n    ```"
+      description: |-
+        Example request data:
+            ```
+            {
+                'edx_video_id': '1234'
+                'profile': 'hls',
+                'encode_data': {
+                    'url': 'foo.com/qwe.m3u8'
+                    'file_size': 34
+                    'bitrate': 12
+                }
+            }
+            ```
       parameters: []
       responses:
         '200':
@@ -5134,9 +7077,9 @@ paths:
     get:
       operationId: xblock_v2_xblocks_read
       summary: Get metadata about the specified block.
-      description: "Accepts an \"include\" query parameter which must be a comma separated\
-        \ list of keys to include. Valid keys are\n\"index_dictionary\" and \"student_view_data\"\
-        ."
+      description: |-
+        Accepts an "include" query parameter which must be a comma separated list of keys to include. Valid keys are
+        "index_dictionary" and "student_view_data".
       parameters: []
       responses:
         '200':
@@ -5151,8 +7094,9 @@ paths:
   /xblock/v2/xblocks/{usage_key_str}/handler_url/{handler_name}/:
     get:
       operationId: xblock_v2_xblocks_handler_url_read
-      summary: "Get an absolute URL which can be used (without any authentication)\
-        \ to call\nthe given XBlock handler."
+      summary: |-
+        Get an absolute URL which can be used (without any authentication) to call
+        the given XBlock handler.
       description: The URL will expire but is guaranteed to be valid for a minimum
         of 2 days.
       parameters: []
@@ -5189,7 +7133,116 @@ paths:
         in: path
         required: true
         type: string
-definitions:
+definitions:
+  BadgeClass:
+    required:
+      - slug
+      - display_name
+      - description
+      - criteria
+    type: object
+    properties:
+      slug:
+        title: Slug
+        type: string
+        format: slug
+        pattern: ^[-a-zA-Z0-9_]+$
+        maxLength: 255
+        minLength: 1
+      issuing_component:
+        title: Issuing component
+        type: string
+        format: slug
+        pattern: ^[-a-zA-Z0-9_]+$
+        default: ''
+        maxLength: 50
+      display_name:
+        title: Display name
+        type: string
+        maxLength: 255
+        minLength: 1
+      course_id:
+        title: Course id
+        type: string
+        maxLength: 255
+      description:
+        title: Description
+        type: string
+        minLength: 1
+      criteria:
+        title: Criteria
+        type: string
+        minLength: 1
+      image_url:
+        title: Image url
+        type: string
+        readOnly: true
+        format: uri
+  BadgeAssertion:
+    required:
+      - image_url
+      - assertion_url
+    type: object
+    properties:
+      badge_class:
+        $ref: '#/definitions/BadgeClass'
+      image_url:
+        title: Image url
+        type: string
+        format: uri
+        maxLength: 200
+        minLength: 1
+      assertion_url:
+        title: Assertion url
+        type: string
+        format: uri
+        maxLength: 200
+        minLength: 1
+      created:
+        title: Created
+        type: string
+        format: date-time
+        readOnly: true
+  CCXCourse:
+    required:
+      - master_course_id
+      - display_name
+      - coach_email
+      - start
+      - due
+      - max_students_allowed
+    type: object
+    properties:
+      ccx_course_id:
+        title: Ccx course id
+        type: string
+        readOnly: true
+      master_course_id:
+        title: Master course id
+        type: string
+        minLength: 1
+      display_name:
+        title: Display name
+        type: string
+        minLength: 1
+      coach_email:
+        title: Coach email
+        type: string
+        format: email
+        minLength: 1
+      start:
+        title: Start
+        type: string
+      due:
+        title: Due
+        type: string
+      max_students_allowed:
+        title: Max students allowed
+        type: integer
+      course_modules:
+        title: Course modules
+        type: string
+        readOnly: true
   CohortUsersAPI:
     required:
       - username
@@ -5328,6 +7381,7 @@ definitions:
   CourseHomeMetadata:
     required:
       - course_id
+      - username
       - is_enrolled
       - is_self_paced
       - is_staff
@@ -5336,12 +7390,18 @@ definitions:
       - original_user_is_staff
       - tabs
       - title
+      - can_load_courseware
+      - celebrations
     type: object
     properties:
       course_id:
         title: Course id
         type: string
         minLength: 1
+      username:
+        title: Username
+        type: string
+        minLength: 1
       is_enrolled:
         title: Is enrolled
         type: boolean
@@ -5370,6 +7430,15 @@ definitions:
         title: Title
         type: string
         minLength: 1
+      can_load_courseware:
+        title: Can load courseware
+        type: boolean
+      celebrations:
+        title: Celebrations
+        type: object
+        additionalProperties:
+          type: string
+          x-nullable: true
   DateSummary:
     required:
       - complete
@@ -5388,6 +7457,7 @@ definitions:
       complete:
         title: Complete
         type: boolean
+        x-nullable: true
       date:
         title: Date
         type: string
@@ -5420,6 +7490,10 @@ definitions:
         title: Extra info
         type: string
         minLength: 1
+      first_component_block_id:
+        title: First component block id
+        type: string
+        readOnly: true
   DatesTab:
     required:
       - course_date_blocks
@@ -5447,7 +7521,6 @@ definitions:
         type: string
         minLength: 1
   CourseBlock:
-    title: Course blocks
     type: object
     properties:
       blocks:
@@ -5455,7 +7528,6 @@ definitions:
         type: string
         readOnly: true
   CourseGoals:
-    title: Course goals
     required:
       - goal_options
       - selected_goal
@@ -5465,11 +7537,13 @@ definitions:
         type: array
         items:
           type: string
+          x-nullable: true
       selected_goal:
         title: Selected goal
         type: object
         additionalProperties:
           type: string
+          x-nullable: true
   CourseTool:
     required:
       - analytics_id
@@ -5489,7 +7563,6 @@ definitions:
         type: string
         readOnly: true
   DatesWidget:
-    title: Dates widget
     required:
       - course_date_blocks
       - dates_tab_link
@@ -5509,7 +7582,6 @@ definitions:
         type: string
         minLength: 1
   EnrollAlert:
-    title: Enroll alert
     required:
       - can_enroll
       - extra_text
@@ -5523,7 +7595,6 @@ definitions:
         type: string
         minLength: 1
   ResumeCourse:
-    title: Resume course
     required:
       - has_visited_course
       - url
@@ -5539,15 +7610,15 @@ definitions:
         minLength: 1
   OutlineTab:
     required:
+      - access_expiration
       - course_blocks
-      - course_expired_html
       - course_goals
       - course_tools
       - dates_widget
       - enroll_alert
       - handouts_html
       - has_ended
-      - offer_html
+      - offer
       - resume_course
       - welcome_message_html
     type: object
@@ -5556,12 +7627,22 @@ definitions:
         title: Dates banner info
         type: string
         readOnly: true
+      can_show_upgrade_sock:
+        title: Can show upgrade sock
+        type: string
+        readOnly: true
+      verified_mode:
+        title: Verified mode
+        type: string
+        readOnly: true
+      access_expiration:
+        title: Access expiration
+        type: object
+        additionalProperties:
+          type: string
+          x-nullable: true
       course_blocks:
         $ref: '#/definitions/CourseBlock'
-      course_expired_html:
-        title: Course expired html
-        type: string
-        minLength: 1
       course_goals:
         $ref: '#/definitions/CourseGoals'
       course_tools:
@@ -5579,10 +7660,12 @@ definitions:
       has_ended:
         title: Has ended
         type: boolean
-      offer_html:
-        title: Offer html
-        type: string
-        minLength: 1
+      offer:
+        title: Offer
+        type: object
+        additionalProperties:
+          type: string
+          x-nullable: true
       resume_course:
         $ref: '#/definitions/ResumeCourse'
       welcome_message_html:
@@ -5590,13 +7673,10 @@ definitions:
         type: string
         minLength: 1
   CertificateData:
-    title: Certificate data
     required:
       - cert_status
       - cert_web_view_url
       - download_url
-      - msg
-      - title
     type: object
     properties:
       cert_status:
@@ -5611,104 +7691,54 @@ definitions:
         title: Download url
         type: string
         minLength: 1
-      msg:
-        title: Msg
-        type: string
-        minLength: 1
-      title:
-        title: Title
-        type: string
-        minLength: 1
-  CreditRequirement:
-    required:
-      - display_name
-      - status
-      - status_date
-    type: object
-    properties:
-      display_name:
-        title: Display name
-        type: string
-        minLength: 1
-      min_grade:
-        title: Min grade
-        type: string
-        readOnly: true
-      status:
-        title: Status
-        type: string
-        minLength: 1
-      status_date:
-        title: Status date
-        type: string
-        format: date-time
-  CreditCourseRequirements:
-    title: Credit course requirements
+  CourseGrade:
     required:
-      - eligibility_status
-      - requirements
+      - letter_grade
+      - percent
+      - is_passing
     type: object
     properties:
-      dashboard_url:
-        title: Dashboard url
-        type: string
-        readOnly: true
-      eligibility_status:
-        title: Eligibility status
+      letter_grade:
+        title: Letter grade
         type: string
         minLength: 1
-      requirements:
-        type: array
-        items:
-          $ref: '#/definitions/CreditRequirement'
-  GradedTotal:
-    title: Graded total
-    required:
-      - earned
-      - possible
-    type: object
-    properties:
-      earned:
-        title: Earned
-        type: number
-      possible:
-        title: Possible
+      percent:
+        title: Percent
         type: number
-  Subsection:
+      is_passing:
+        title: Is passing
+        type: boolean
+  SubsectionScores:
     required:
+      - assignment_type
       - display_name
-      - due
-      - format
-      - graded
-      - graded_total
+      - has_graded_assignment
+      - num_points_earned
+      - num_points_possible
       - percent_graded
       - show_correctness
     type: object
     properties:
-      display_name:
-        title: Display name
+      assignment_type:
+        title: Assignment type
         type: string
         minLength: 1
-      due:
-        title: Due
-        type: string
-        format: date-time
-      format:
-        title: Format
+      display_name:
+        title: Display name
         type: string
         minLength: 1
-      graded:
-        title: Graded
+      has_graded_assignment:
+        title: Has graded assignment
         type: boolean
-      graded_total:
-        $ref: '#/definitions/GradedTotal'
+      num_points_earned:
+        title: Num points earned
+        type: integer
+      num_points_possible:
+        title: Num points possible
+        type: integer
       percent_graded:
         title: Percent graded
         type: number
-      problem_scores:
-        title: Problem scores
-        type: string
-        readOnly: true
       show_correctness:
         title: Show correctness
         type: string
@@ -5721,7 +7751,7 @@ definitions:
         title: Url
         type: string
         readOnly: true
-  Chapter:
+  SectionScores:
     required:
       - display_name
       - subsections
@@ -5734,9 +7764,23 @@ definitions:
       subsections:
         type: array
         items:
-          $ref: '#/definitions/Subsection'
+          $ref: '#/definitions/SubsectionScores'
+  GradingPolicy:
+    required:
+      - grade_range
+    type: object
+    properties:
+      assignment_policies:
+        title: Assignment policies
+        type: string
+        readOnly: true
+      grade_range:
+        title: Grade range
+        type: object
+        additionalProperties:
+          type: string
+          x-nullable: true
   VerificationData:
-    title: Verification data
     required:
       - link
       - status
@@ -5759,40 +7803,52 @@ definitions:
   ProgressTab:
     required:
       - certificate_data
-      - credit_course_requirements
-      - credit_support_url
-      - courseware_summary
+      - completion_summary
+      - course_grade
+      - end
+      - user_has_passing_grade
+      - has_scheduled_content
+      - section_scores
       - enrollment_mode
+      - grading_policy
       - studio_url
-      - user_timezone
       - verification_data
     type: object
     properties:
       certificate_data:
         $ref: '#/definitions/CertificateData'
-      credit_course_requirements:
-        $ref: '#/definitions/CreditCourseRequirements'
-      credit_support_url:
-        title: Credit support url
+      completion_summary:
+        title: Completion summary
+        type: object
+        additionalProperties:
+          type: string
+          x-nullable: true
+      course_grade:
+        $ref: '#/definitions/CourseGrade'
+      end:
+        title: End
         type: string
-        format: uri
-        minLength: 1
-      courseware_summary:
+        format: date-time
+      user_has_passing_grade:
+        title: User has passing grade
+        type: boolean
+      has_scheduled_content:
+        title: Has scheduled content
+        type: boolean
+      section_scores:
         type: array
         items:
-          $ref: '#/definitions/Chapter'
+          $ref: '#/definitions/SectionScores'
       enrollment_mode:
         title: Enrollment mode
         type: string
         minLength: 1
+      grading_policy:
+        $ref: '#/definitions/GradingPolicy'
       studio_url:
         title: Studio url
         type: string
         minLength: 1
-      user_timezone:
-        title: User timezone
-        type: string
-        minLength: 1
       verification_data:
         $ref: '#/definitions/VerificationData'
   course_modes.CourseMode:
@@ -5841,8 +7897,18 @@ definitions:
         title: Bulk sku
         type: string
         minLength: 1
+  _AbsolutMedia:
+    type: object
+    properties:
+      uri:
+        title: Uri
+        type: string
+        readOnly: true
+      uri_absolute:
+        title: Uri absolute
+        type: string
+        readOnly: true
   _Media:
-    title: Course image
     type: object
     properties:
       uri:
@@ -5850,7 +7916,6 @@ definitions:
         type: string
         readOnly: true
   Image:
-    title: Image
     required:
       - raw
       - small
@@ -5873,13 +7938,15 @@ definitions:
         format: uri
         minLength: 1
   _CourseApiMediaCollection:
-    title: Media
     required:
+      - banner_image
       - course_image
       - course_video
       - image
     type: object
     properties:
+      banner_image:
+        $ref: '#/definitions/_AbsolutMedia'
       course_image:
         $ref: '#/definitions/_Media'
       course_video:
@@ -6361,6 +8428,247 @@ definitions:
         type: string
         format: date-time
         readOnly: true
+  ReportDownload:
+    description: Report Download
+    required:
+      - url
+      - name
+      - link
+    type: object
+    properties:
+      url:
+        title: Url
+        description: URL from which report can be downloaded.
+        type: string
+        format: uri
+        minLength: 1
+      name:
+        title: Name
+        description: Name of report.
+        type: string
+        minLength: 1
+      link:
+        title: Link
+        description: HTML anchor tag that contains the name and link.
+        type: string
+        minLength: 1
+  ReportDownloadsList:
+    required:
+      - downloads
+    type: object
+    properties:
+      downloads:
+        description: List of report downloads
+        type: array
+        items:
+          $ref: '#/definitions/ReportDownload'
+  ProblemResponseReportPostParams:
+    required:
+      - problem_locations
+    type: object
+    properties:
+      problem_locations:
+        description: 'A list of usage keys for the blocks to include in the report. '
+        type: array
+        items:
+          description: A usage key location for a section or a problem. If the location
+            is a block that contains other blocks, (such as the course, section, subsection,
+            or unit blocks) then all blocks under that block will be included in the
+            report.
+          type: string
+          minLength: 1
+      problem_types_filter:
+        description: 'A list of problem/block types to generate the report for. This
+          field can be omitted if the report should include details of allblock types. '
+        type: array
+        items:
+          type: string
+          minLength: 1
+  ProblemResponsesReportStatus:
+    required:
+      - status
+      - task_id
+    type: object
+    properties:
+      status:
+        title: Status
+        description: User-friendly text describing current status of report generation.
+        type: string
+        minLength: 1
+      task_id:
+        title: Task id
+        description: A unique id for the report generation task. It can be used to
+          query the latest report generation status.
+        type: string
+        format: uuid
+  InstructorTask:
+    required:
+      - status
+      - task_type
+      - task_id
+      - created
+      - task_input
+      - requester
+      - task_state
+      - duration_sec
+      - task_message
+    type: object
+    properties:
+      status:
+        title: Status
+        description: Current status of task.
+        type: string
+        minLength: 1
+      task_type:
+        title: Task type
+        description: Identifies the kind of task being performed, e.g. rescoring.
+        type: string
+        minLength: 1
+      task_id:
+        title: Task id
+        description: The celery ID for the task.
+        type: string
+        minLength: 1
+      created:
+        title: Created
+        description: The date and time when the task was created.
+        type: string
+        format: date-time
+      task_input:
+        title: Task input
+        description: The input parameters for the task. The format and content of
+          this data will depend on the kind of task being performed. For instanceit
+          may contain the problem locations for a problem resources task.
+        type: object
+        additionalProperties:
+          type: string
+          x-nullable: true
+      requester:
+        title: Requester
+        description: The username of the user who initiated this task.
+        type: string
+        minLength: 1
+      task_state:
+        title: Task state
+        description: The last knows state of the celery task.
+        type: string
+        minLength: 1
+      duration_sec:
+        title: Duration sec
+        description: Task duration information, if known
+        type: string
+        minLength: 1
+      task_message:
+        title: Task message
+        description: User-friendly task status information, if available.
+        type: string
+        minLength: 1
+  InstructorTasksList:
+    required:
+      - tasks
+    type: object
+    properties:
+      tasks:
+        description: List of instructor tasks.
+        type: array
+        items:
+          $ref: '#/definitions/InstructorTask'
+  LtiAgsLineItem:
+    required:
+      - resourceId
+      - scoreMaximum
+      - label
+    type: object
+    properties:
+      id:
+        title: Id
+        type: string
+        readOnly: true
+      resourceId:
+        title: Resourceid
+        type: string
+        minLength: 1
+      scoreMaximum:
+        title: Scoremaximum
+        type: integer
+      label:
+        title: Label
+        type: string
+        maxLength: 100
+        minLength: 1
+      tag:
+        title: Tag
+        type: string
+        maxLength: 50
+      resourceLinkId:
+        title: Resourcelinkid
+        type: string
+      startDateTime:
+        title: Startdatetime
+        type: string
+        format: date-time
+      endDateTime:
+        title: Enddatetime
+        type: string
+        format: date-time
+  mobile_api.User:
+    required:
+      - username
+    type: object
+    properties:
+      id:
+        title: ID
+        type: integer
+        readOnly: true
+      username:
+        title: Username
+        description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_
+          only.
+        type: string
+        pattern: ^[\w.@+-]+$
+        maxLength: 150
+        minLength: 1
+      email:
+        title: Email address
+        type: string
+        format: email
+        maxLength: 254
+      name:
+        title: Name
+        type: string
+        readOnly: true
+      course_enrollments:
+        title: Course enrollments
+        type: string
+        readOnly: true
+  CourseEnrollment:
+    type: object
+    properties:
+      audit_access_expires:
+        title: Audit access expires
+        type: string
+        readOnly: true
+      created:
+        title: Created
+        type: string
+        format: date-time
+        readOnly: true
+      mode:
+        title: Mode
+        type: string
+        maxLength: 100
+        minLength: 1
+      is_active:
+        title: Is active
+        type: boolean
+      course:
+        title: Course
+        type: string
+        readOnly: true
+      certificate:
+        title: Certificate
+        type: string
+        readOnly: true
   Organization:
     required:
       - name
@@ -6388,8 +8696,9 @@ definitions:
         minLength: 1
       short_name:
         title: Short Name
-        description: Please do not use spaces or special characters. Only allowed
-          special characters are period (.), hyphen (-) and underscore (_).
+        description: Unique, short string identifier for organization. Please do not
+          use spaces or special characters. Only allowed special characters are period
+          (.), hyphen (-) and underscore (_).
         type: string
         maxLength: 255
         minLength: 1
@@ -6576,6 +8885,10 @@ definitions:
         title: Updated at
         type: string
         format: date-time
+      receipt_id:
+        title: Receipt id
+        type: string
+        readOnly: true
   user_api.User:
     type: object
     properties:
diff --git a/lms/djangoapps/instructor/apps.py b/lms/djangoapps/instructor/apps.py
index 6b7b05bd23f..898416585f3 100644
--- a/lms/djangoapps/instructor/apps.py
+++ b/lms/djangoapps/instructor/apps.py
@@ -8,7 +8,6 @@ from django.conf import settings
 from edx_django_utils.plugins import PluginSettings, PluginURLs
 from edx_proctoring.runtime import set_runtime_service
 
-from openedx.core.constants import COURSE_ID_PATTERN
 from openedx.core.djangoapps.plugins.constants import ProjectType, SettingsType
 
 
@@ -22,8 +21,8 @@ class InstructorConfig(AppConfig):
         PluginURLs.CONFIG: {
             ProjectType.LMS: {
                 PluginURLs.NAMESPACE: '',
-                PluginURLs.REGEX: f'^courses/{COURSE_ID_PATTERN}/instructor/api/',
-                PluginURLs.RELATIVE_PATH: 'views.api_urls',
+                PluginURLs.REGEX: '',
+                PluginURLs.RELATIVE_PATH: 'urls',
             }
         },
         PluginSettings.CONFIG: {
diff --git a/lms/djangoapps/instructor/tests/test_api.py b/lms/djangoapps/instructor/tests/test_api.py
index 04ca0fea417..0a6e872a577 100644
--- a/lms/djangoapps/instructor/tests/test_api.py
+++ b/lms/djangoapps/instructor/tests/test_api.py
@@ -19,6 +19,7 @@ from django.core import mail
 from django.core.files.uploadedfile import SimpleUploadedFile
 from django.http import HttpRequest, HttpResponse
 from django.test import RequestFactory, TestCase
+from django.test.client import MULTIPART_CONTENT
 from django.urls import reverse as django_reverse
 from django.utils.translation import ugettext as _
 from edx_when.api import get_dates_for_course, get_overrides_for_user, set_date_for_block
@@ -140,6 +141,8 @@ REPORTS_DATA = (
 INSTRUCTOR_GET_ENDPOINTS = {
     'get_anon_ids',
     'get_issued_certificates',
+    'instructor_api_v1:list_instructor_tasks',
+    'instructor_api_v1:list_report_downloads',
 }
 INSTRUCTOR_POST_ENDPOINTS = {
     'add_users_to_cohorts',
@@ -177,6 +180,7 @@ INSTRUCTOR_POST_ENDPOINTS = {
     'students_update_enrollment',
     'update_forum_role_membership',
     'override_problem_score',
+    'instructor_api_v1:generate_problem_responses'
 }
 
 
@@ -412,13 +416,15 @@ class TestInstructorAPIDenyLevels(SharedModuleStoreTestCase, LoginEnrollmentTest
             ('list_forum_members', {'rolename': FORUM_ROLE_COMMUNITY_TA}),
             ('send_email', {'send_to': '["staff"]', 'subject': 'test', 'message': 'asdf'}),
             ('list_instructor_tasks', {}),
+            ('instructor_api_v1:list_instructor_tasks', {}),
             ('list_background_email_tasks', {}),
-            ('list_report_downloads', {}),
+            ('instructor_api_v1:list_report_downloads', {}),
             ('calculate_grades_csv', {}),
             ('get_students_features', {}),
             ('get_students_who_may_enroll', {}),
             ('get_proctored_exam_results', {}),
             ('get_problem_responses', {}),
+            ('instructor_api_v1:generate_problem_responses', {"problem_locations": [str(self.problem.location)]}),
             ('export_ora2_data', {}),
             ('export_ora2_submission_files', {}),
             ('export_ora2_summary', {}),
@@ -446,7 +452,7 @@ class TestInstructorAPIDenyLevels(SharedModuleStoreTestCase, LoginEnrollmentTest
             ('reset_student_attempts', {'problem_to_reset': self.problem_urlname, 'all_students': True}),
         ]
 
-    def _access_endpoint(self, endpoint, args, status_code, msg):
+    def _access_endpoint(self, endpoint, args, status_code, msg, content_type=MULTIPART_CONTENT):
         """
         Asserts that accessing the given `endpoint` gets a response of `status_code`.
 
@@ -459,7 +465,7 @@ class TestInstructorAPIDenyLevels(SharedModuleStoreTestCase, LoginEnrollmentTest
         if endpoint in INSTRUCTOR_GET_ENDPOINTS:
             response = self.client.get(url, args)
         else:
-            response = self.client.post(url, args)
+            response = self.client.post(url, args, content_type=content_type)
         assert response.status_code == status_code, msg
 
     def test_student_level(self):
@@ -484,7 +490,7 @@ class TestInstructorAPIDenyLevels(SharedModuleStoreTestCase, LoginEnrollmentTest
                 "Student should not be allowed to access endpoint " + endpoint
             )
 
-    def _access_problem_responses_endpoint(self, msg):
+    def _access_problem_responses_endpoint(self, endpoint, msg):
         """
         Access endpoint for problem responses report, ensuring that
         UsageKey.from_string returns a problem key that the endpoint
@@ -496,7 +502,7 @@ class TestInstructorAPIDenyLevels(SharedModuleStoreTestCase, LoginEnrollmentTest
         mock_problem_key.course_key = self.course.id
         with patch.object(UsageKey, 'from_string') as patched_method:
             patched_method.return_value = mock_problem_key
-            self._access_endpoint('get_problem_responses', {}, 200, msg)
+            self._access_endpoint(endpoint, {"problem_locations": ["test"]}, 200, msg, content_type="application/json")
 
     def test_staff_level(self):
         """
@@ -516,8 +522,9 @@ class TestInstructorAPIDenyLevels(SharedModuleStoreTestCase, LoginEnrollmentTest
             # TODO: make these work
             if endpoint in ['update_forum_role_membership', 'list_forum_members']:
                 continue
-            elif endpoint == 'get_problem_responses':
+            elif endpoint in ('get_problem_responses', 'instructor_api_v1:generate_problem_responses'):
                 self._access_problem_responses_endpoint(
+                    endpoint,
                     "Staff member should be allowed to access endpoint " + endpoint
                 )
                 continue
@@ -553,8 +560,9 @@ class TestInstructorAPIDenyLevels(SharedModuleStoreTestCase, LoginEnrollmentTest
             # TODO: make these work
             if endpoint in ['update_forum_role_membership']:
                 continue
-            elif endpoint == 'get_problem_responses':
+            elif endpoint in ('get_problem_responses', 'instructor_api_v1:generate_problem_responses'):
                 self._access_problem_responses_endpoint(
+                    endpoint,
                     "Instructor should be allowed to access endpoint " + endpoint
                 )
                 continue
@@ -2486,18 +2494,22 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
                 email=student.email, course_id=self.course.id
             )
 
-    def test_get_problem_responses_invalid_location(self):
+    @ddt.data(
+        ('get_problem_responses', {'problem_location': ""}),
+        ('instructor_api_v1:generate_problem_responses', {"problem_locations": ["abc"]}),
+    )
+    @ddt.unpack
+    def test_get_problem_responses_invalid_location(self, endpoint, post_data):
         """
         Test whether get_problem_responses returns an appropriate status
         message when users submit an invalid problem location.
         """
         url = reverse(
-            'get_problem_responses',
+            endpoint,
             kwargs={'course_id': str(self.course.id)}
         )
-        problem_location = ''
 
-        response = self.client.post(url, {'problem_location': problem_location})
+        response = self.client.post(url, post_data, content_type="application/json")
         res_json = json.loads(response.content.decode('utf-8'))
         assert res_json == 'Could not find problem with this location.'
 
@@ -2521,18 +2533,22 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
         return wrapper
 
     @valid_problem_location
-    def test_get_problem_responses_successful(self):
+    @ddt.data(
+        ('get_problem_responses', {'problem_location': "test"}),
+        ('instructor_api_v1:generate_problem_responses', {'problem_locations': ["test"]}),
+    )
+    @ddt.unpack
+    def test_get_problem_responses_successful(self, endpoint, post_data):
         """
         Test whether get_problem_responses returns an appropriate status
         message if CSV generation was started successfully.
         """
         url = reverse(
-            'get_problem_responses',
+            endpoint,
             kwargs={'course_id': str(self.course.id)}
         )
-        problem_location = ''
 
-        response = self.client.post(url, {'problem_location': problem_location})
+        response = self.client.post(url, post_data, content_type="application/json")
         res_json = json.loads(response.content.decode('utf-8'))
         assert 'status' in res_json
         status = res_json['status']
@@ -2541,13 +2557,14 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
         assert 'task_id' in res_json
 
     @valid_problem_location
-    def test_get_problem_responses_already_running(self):
+    @ddt.data('get_problem_responses', 'instructor_api_v1:generate_problem_responses')
+    def test_get_problem_responses_already_running(self, endpoint):
         """
         Test whether get_problem_responses returns an appropriate status
         message if CSV generation is already in progress.
         """
         url = reverse(
-            'get_problem_responses',
+            endpoint,
             kwargs={'course_id': str(self.course.id)}
         )
         task_type = 'problem_responses_csv'
@@ -2555,7 +2572,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
         with patch('lms.djangoapps.instructor_task.api.submit_calculate_problem_responses_csv') as submit_task_function:
             error = AlreadyRunningError(already_running_status)
             submit_task_function.side_effect = error
-            response = self.client.post(url, {})
+            response = self.client.post(url, {"problem_locations": ["test"]}, content_type="application/json")
 
         self.assertContains(response, already_running_status, status_code=400)
 
@@ -2732,15 +2749,19 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
 
     @patch('lms.djangoapps.instructor_task.models.logger.error')
     @patch.dict(settings.GRADES_DOWNLOAD, {'STORAGE_TYPE': 's3', 'ROOT_PATH': 'tmp/edx-s3/grades'})
-    def test_list_report_downloads_error(self, mock_error):
+    @ddt.data('list_report_downloads', 'instructor_api_v1:list_report_downloads')
+    def test_list_report_downloads_error(self, endpoint, mock_error):
         """
         Tests the Rate-Limit exceeded is handled and does not raise 500 error.
         """
         ex_status = 503
         ex_reason = 'Slow Down'
-        url = reverse('list_report_downloads', kwargs={'course_id': str(self.course.id)})
+        url = reverse(endpoint, kwargs={'course_id': str(self.course.id)})
         with patch('storages.backends.s3boto.S3BotoStorage.listdir', side_effect=BotoServerError(ex_status, ex_reason)):
-            response = self.client.post(url, {})
+            if endpoint in INSTRUCTOR_GET_ENDPOINTS:
+                response = self.client.get(url)
+            else:
+                response = self.client.post(url, {})
         mock_error.assert_called_with(
             'Fetching files failed for course: %s, status: %s, reason: %s',
             self.course.id,
@@ -2751,14 +2772,18 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
         res_json = json.loads(response.content.decode('utf-8'))
         assert res_json == {'downloads': []}
 
-    def test_list_report_downloads(self):
-        url = reverse('list_report_downloads', kwargs={'course_id': str(self.course.id)})
+    @ddt.data('list_report_downloads', 'instructor_api_v1:list_report_downloads')
+    def test_list_report_downloads(self, endpoint):
+        url = reverse(endpoint, kwargs={'course_id': str(self.course.id)})
         with patch('lms.djangoapps.instructor_task.models.DjangoStorageReportStore.links_for') as mock_links_for:
             mock_links_for.return_value = [
                 ('mock_file_name_1', 'https://1.mock.url'),
                 ('mock_file_name_2', 'https://2.mock.url'),
             ]
-            response = self.client.post(url, {})
+            if endpoint in INSTRUCTOR_GET_ENDPOINTS:
+                response = self.client.get(url)
+            else:
+                response = self.client.post(url, {})
 
         expected_response = {
             "downloads": [
@@ -3456,6 +3481,7 @@ class MockCompletionInfo:
         return False, 'Task Errored In Some Way'
 
 
+@ddt.ddt
 class TestInstructorAPITaskLists(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
     """
     Test instructor task list endpoint.
@@ -3535,16 +3561,20 @@ class TestInstructorAPITaskLists(SharedModuleStoreTestCase, LoginEnrollmentTestC
         self.tasks[-1].make_invalid_output()
 
     @patch('lms.djangoapps.instructor_task.api.get_running_instructor_tasks')
-    def test_list_instructor_tasks_running(self, act):
+    @ddt.data('instructor_api_v1:list_instructor_tasks', 'list_instructor_tasks')
+    def test_list_instructor_tasks_running(self, endpoint, act):
         """ Test list of all running tasks. """
         act.return_value = self.tasks
-        url = reverse('list_instructor_tasks', kwargs={'course_id': str(self.course.id)})
+        url = reverse(endpoint, kwargs={'course_id': str(self.course.id)})
         mock_factory = MockCompletionInfo()
         with patch(
             'lms.djangoapps.instructor.views.instructor_task_helpers.get_task_completion_info'
         ) as mock_completion_info:
             mock_completion_info.side_effect = mock_factory.mock_get_task_completion_info
-            response = self.client.post(url, {})
+            if endpoint in INSTRUCTOR_GET_ENDPOINTS:
+                response = self.client.get(url)
+            else:
+                response = self.client.post(url, {})
         assert response.status_code == 200
 
         # check response
@@ -3577,18 +3607,24 @@ class TestInstructorAPITaskLists(SharedModuleStoreTestCase, LoginEnrollmentTestC
         assert actual_tasks == expected_tasks
 
     @patch('lms.djangoapps.instructor_task.api.get_instructor_task_history')
-    def test_list_instructor_tasks_problem(self, act):
+    @ddt.data('instructor_api_v1:list_instructor_tasks', 'list_instructor_tasks')
+    def test_list_instructor_tasks_problem(self, endpoint, act):
         """ Test list task history for problem. """
         act.return_value = self.tasks
-        url = reverse('list_instructor_tasks', kwargs={'course_id': str(self.course.id)})
+        url = reverse(endpoint, kwargs={'course_id': str(self.course.id)})
         mock_factory = MockCompletionInfo()
         with patch(
             'lms.djangoapps.instructor.views.instructor_task_helpers.get_task_completion_info'
         ) as mock_completion_info:
             mock_completion_info.side_effect = mock_factory.mock_get_task_completion_info
-            response = self.client.post(url, {
-                'problem_location_str': self.problem_urlname,
-            })
+            if endpoint in INSTRUCTOR_GET_ENDPOINTS:
+                response = self.client.get(url, {
+                    'problem_location_str': self.problem_urlname,
+                })
+            else:
+                response = self.client.post(url, {
+                    'problem_location_str': self.problem_urlname,
+                })
         assert response.status_code == 200
 
         # check response
@@ -3600,19 +3636,26 @@ class TestInstructorAPITaskLists(SharedModuleStoreTestCase, LoginEnrollmentTestC
         assert actual_tasks == expected_tasks
 
     @patch('lms.djangoapps.instructor_task.api.get_instructor_task_history')
-    def test_list_instructor_tasks_problem_student(self, act):
+    @ddt.data('list_instructor_tasks', 'instructor_api_v1:list_instructor_tasks')
+    def test_list_instructor_tasks_problem_student(self, endpoint, act):
         """ Test list task history for problem AND student. """
         act.return_value = self.tasks
-        url = reverse('list_instructor_tasks', kwargs={'course_id': str(self.course.id)})
+        url = reverse(endpoint, kwargs={'course_id': str(self.course.id)})
         mock_factory = MockCompletionInfo()
         with patch(
             'lms.djangoapps.instructor.views.instructor_task_helpers.get_task_completion_info'
         ) as mock_completion_info:
             mock_completion_info.side_effect = mock_factory.mock_get_task_completion_info
-            response = self.client.post(url, {
-                'problem_location_str': self.problem_urlname,
-                'unique_student_identifier': self.student.email,
-            })
+            if endpoint in INSTRUCTOR_GET_ENDPOINTS:
+                response = self.client.get(url, {
+                    'problem_location_str': self.problem_urlname,
+                    'unique_student_identifier': self.student.email,
+                })
+            else:
+                response = self.client.post(url, {
+                    'problem_location_str': self.problem_urlname,
+                    'unique_student_identifier': self.student.email,
+                })
         assert response.status_code == 200
 
         # check response
@@ -3663,7 +3706,7 @@ class TestInstructorEmailContentList(SharedModuleStoreTestCase, LoginEnrollmentT
         return self.emails[email_id]
 
     def get_email_content_response(self, num_emails, task_history_request, with_failures=False):
-        """ Calls the list_email_content endpoint and returns the repsonse """
+        """ Calls the list_email_content endpoint and returns the respsonse """
         self.setup_fake_email_info(num_emails, with_failures)
         task_history_request.return_value = list(self.tasks.values())
         url = reverse('list_email_content', kwargs={'course_id': str(self.course.id)})
diff --git a/lms/djangoapps/instructor/urls.py b/lms/djangoapps/instructor/urls.py
new file mode 100644
index 00000000000..17db7f600eb
--- /dev/null
+++ b/lms/djangoapps/instructor/urls.py
@@ -0,0 +1,17 @@
+"""
+Instructor API endpoint urls.
+"""
+
+from django.conf.urls import url, include
+
+from openedx.core.constants import COURSE_ID_PATTERN
+from .views import api_urls
+
+
+urlpatterns = [
+    url(rf'^courses/{COURSE_ID_PATTERN}/instructor/api/', include(api_urls.urlpatterns)),
+    url(
+        r'^api/instructor/v1/',
+        include((api_urls.v1_api_urls, 'lms.djangoapps.instructor'), namespace='instructor_api_v1'),
+    ),
+]
diff --git a/lms/djangoapps/instructor/views/api.py b/lms/djangoapps/instructor/views/api.py
index 0cb63769d31..c2a2e0bbe2a 100644
--- a/lms/djangoapps/instructor/views/api.py
+++ b/lms/djangoapps/instructor/views/api.py
@@ -9,10 +9,11 @@ Many of these GETs may become PUTs in the future.
 import csv
 import json
 import logging
+import string
 import random
 import re
-import string
 
+import edx_api_doc_tools as apidocs
 from django.conf import settings
 from django.contrib.auth.models import User  # lint-amnesty, pylint: disable=imported-auth-user
 from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist, PermissionDenied, ValidationError
@@ -26,17 +27,18 @@ from django.utils.html import strip_tags
 from django.utils.translation import ugettext as _
 from django.views.decorators.cache import cache_control
 from django.views.decorators.csrf import ensure_csrf_cookie
-from django.views.decorators.http import require_http_methods, require_POST
+from django.views.decorators.http import require_POST, require_http_methods
 from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication
 from edx_rest_framework_extensions.auth.session.authentication import SessionAuthenticationAllowInactiveUser
 from edx_when.api import get_date_for_block
 from opaque_keys import InvalidKeyError
 from opaque_keys.edx.keys import CourseKey, UsageKey
-from rest_framework import status
+from rest_framework import serializers, status
 from rest_framework.permissions import IsAdminUser, IsAuthenticated
 from rest_framework.response import Response
 from rest_framework.views import APIView
 from submissions import api as sub_api  # installed from the edx-submissions repository
+from xmodule.modulestore.django import modulestore
 
 from common.djangoapps.course_modes.models import CourseMode
 from common.djangoapps.student import auth
@@ -44,17 +46,17 @@ from common.djangoapps.student.api import is_user_enrolled_in_course
 from common.djangoapps.student.models import (
     ALLOWEDTOENROLL_TO_ENROLLED,
     ALLOWEDTOENROLL_TO_UNENROLLED,
+    CourseEnrollment,
+    CourseEnrollmentAllowed,
     DEFAULT_TRANSITION_STATE,
     ENROLLED_TO_ENROLLED,
     ENROLLED_TO_UNENROLLED,
-    UNENROLLED_TO_ALLOWEDTOENROLL,
-    UNENROLLED_TO_ENROLLED,
-    UNENROLLED_TO_UNENROLLED,
-    CourseEnrollment,
-    CourseEnrollmentAllowed,
     EntranceExamConfiguration,
     ManualEnrollmentAudit,
     Registration,
+    UNENROLLED_TO_ALLOWEDTOENROLL,
+    UNENROLLED_TO_ENROLLED,
+    UNENROLLED_TO_UNENROLLED,
     UserProfile,
     get_user_by_username_or_email,
     is_email_retired,
@@ -63,7 +65,7 @@ from common.djangoapps.student.roles import CourseFinanceAdminRole, CourseSalesA
 from common.djangoapps.util.file import (
     FileValidationException,
     course_and_time_based_filename_generator,
-    store_uploaded_file
+    store_uploaded_file,
 )
 from common.djangoapps.util.json_request import JsonResponse, JsonResponseBadRequest
 from common.djangoapps.util.views import require_global_staff
@@ -79,7 +81,7 @@ from lms.djangoapps.courseware.models import StudentModule
 from lms.djangoapps.discussion.django_comment_client.utils import (
     get_group_id_for_user,
     get_group_name,
-    has_forum_access
+    has_forum_access,
 )
 from lms.djangoapps.instructor import enrollment
 from lms.djangoapps.instructor.access import ROLES, allow_access, list_with_level, revoke_access, update_forum_role
@@ -89,13 +91,11 @@ from lms.djangoapps.instructor.enrollment import (
     get_user_email_language,
     send_beta_role_email,
     send_mail_to_student,
-    unenroll_email
+    unenroll_email,
 )
 from lms.djangoapps.instructor.views import INVOICE_KEY
 from lms.djangoapps.instructor.views.instructor_task_helpers import extract_email_features, extract_task_features
-from lms.djangoapps.instructor_analytics import basic as instructor_analytics_basic
-from lms.djangoapps.instructor_analytics import csvs as instructor_analytics_csvs
-from lms.djangoapps.instructor_analytics import distributions as instructor_analytics_distributions  # lint-amnesty, pylint: disable=unused-import
+from lms.djangoapps.instructor_analytics import basic as instructor_analytics_basic, csvs as instructor_analytics_csvs
 from lms.djangoapps.instructor_task import api as task_api
 from lms.djangoapps.instructor_task.api_helper import AlreadyRunningError, QueueConnectionError
 from lms.djangoapps.instructor_task.models import ReportStore
@@ -107,17 +107,14 @@ from openedx.core.djangoapps.django_comment_common.models import (
     FORUM_ROLE_COMMUNITY_TA,
     FORUM_ROLE_GROUP_MODERATOR,
     FORUM_ROLE_MODERATOR,
-    Role
+    Role,
 )
 from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
 from openedx.core.djangoapps.user_api.preferences.api import get_user_preference
 from openedx.core.djangolib.markup import HTML, Text
 from openedx.core.lib.api.authentication import BearerAuthenticationAllowInactiveUser
-from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin
+from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin, view_auth_classes
 from openedx.core.lib.courses import get_course_by_id
-from xmodule.modulestore.django import modulestore
-
-from .. import permissions
 from .tools import (
     dump_module_extensions,
     dump_student_extensions,
@@ -127,8 +124,9 @@ from .tools import (
     parse_datetime,
     require_student_from_identifier,
     set_due_date_extension,
-    strip_if_string
+    strip_if_string,
 )
+from .. import permissions
 
 log = logging.getLogger(__name__)
 
@@ -971,12 +969,144 @@ def list_course_role_members(request, course_id):
     return JsonResponse(response_payload)
 
 
+class ProblemResponseReportPostParamsSerializer(serializers.Serializer):  # pylint: disable=abstract-method
+    """
+    Serializer that describes that POST parameters for the report generation API.
+    """
+    problem_locations = serializers.ListSerializer(
+        child=serializers.CharField(
+            help_text=_(
+                "A usage key location for a section or a problem. "
+                "If the location is a block that contains other blocks, (such as the course, "
+                "section, subsection, or unit blocks) then all blocks under that block will be "
+                "included in the report."
+            ),
+        ),
+        required=True,
+        allow_empty=False,
+        help_text=_(
+            "A list of usage keys for the blocks to include in the report. "
+        )
+    )
+    problem_types_filter = serializers.ListSerializer(
+        child=serializers.CharField(),
+        required=False,
+        allow_empty=True,
+        help_text=_(
+            "A list of problem/block types to generate the report for. "
+            "This field can be omitted if the report should include details of all"
+            "block types. "
+        ),
+    )
+
+
+class ProblemResponsesReportStatusSerializer(serializers.Serializer):  # pylint: disable=abstract-method
+    """
+    Serializer that describes the response of the problem response report generation API.
+    """
+    status = serializers.CharField(help_text=_("User-friendly text describing current status of report generation."))
+    task_id = serializers.UUIDField(
+        help_text=_(
+            "A unique id for the report generation task. "
+            "It can be used to query the latest report generation status."
+        )
+    )
+
+
+@view_auth_classes()
+@method_decorator(transaction.non_atomic_requests, name='dispatch')
+class ProblemResponseReportInitiate(DeveloperErrorViewMixin, APIView):
+    """
+    Initiate generation of a CSV file containing all student answers
+    to a given problem.
+    """
+
+    @apidocs.schema(
+        parameters=[
+            apidocs.path_parameter(
+                'course_id',
+                str,
+                description="ID of the course for which report is to be generate.",
+            ),
+        ],
+        body=ProblemResponseReportPostParamsSerializer,
+        responses={
+            200: ProblemResponsesReportStatusSerializer,
+            400: _(
+                "The provided parameters were invalid. Make sure you've provided at least "
+                "one valid usage key for `problem_locations`."
+            ),
+            401: _("The requesting user is not authenticated."),
+            403: _("The requesting user lacks access to the course."),
+        }
+    )
+    @transaction.non_atomic_requests
+    @method_decorator(require_course_permission(permissions.CAN_RESEARCH))
+    def post(self, request, course_id):
+        """
+        Initiate generation of a CSV file containing all student answers
+        to a given problem.
+
+        **Example requests**
+
+            POST /api/instructor/v1/reports/{course_id}/generate/problem_responses {
+                "problem_locations": [
+                    "{usage_key1}",
+                    "{usage_key2}",
+                    "{usage_key3}"
+                ]
+            }
+            POST /api/instructor/v1/reports/{course_id}/generate/problem_responses {
+                "problem_locations": ["{usage_key}"],
+                "problem_types_filter": ["problem"]
+            }
+
+        **POST Parameters**
+
+        A POST request can include the following parameters:
+
+        * problem_location: A list of usage keys for the blocks to include in
+          the report. If the location is a block that contains other blocks,
+          (such as the course, section, subsection, or unit blocks) then all
+          blocks under that block will be included in the report.
+        * problem_types_filter: Optional. A comma-separated list of block types
+          to include in the report. If set, only blocks of the specified types
+          will be included in the report.
+
+        To get data on all the poll and survey blocks in a course, you could
+        POST the usage key of the course for `problem_location`, and
+        "poll, survey" as the value for `problem_types_filter`.
+
+
+        **Example Response:**
+        If initiation is successful (or generation task is already running):
+        ```json
+        {
+            "status": "The problem responses report is being created. ...",
+            "task_id": "4e49522f-31d9-431a-9cff-dd2a2bf4c85a"
+        }
+        ```
+
+        Responds with BadRequest if any of the provided problem locations are faulty.
+        """
+        params = ProblemResponseReportPostParamsSerializer(data=request.data)
+        params.is_valid(raise_exception=True)
+        problem_locations = params.validated_data.get('problem_locations')
+        problem_types_filter = params.validated_data.get('problem_types_filter')
+        if problem_types_filter:
+            problem_types_filter = ','.join(problem_types_filter)
+        return _get_problem_responses(
+            request,
+            course_id=course_id,
+            problem_locations=problem_locations,
+            problem_types_filter=problem_types_filter,
+        )
+
+
 @transaction.non_atomic_requests
 @require_POST
 @ensure_csrf_cookie
-@cache_control(no_cache=True, no_store=True, must_revalidate=True)
 @require_course_permission(permissions.CAN_RESEARCH)
-@common_exceptions_400
 def get_problem_responses(request, course_id):
     """
     Initiate generation of a CSV file containing all student answers
@@ -1020,24 +1150,38 @@ def get_problem_responses(request, course_id):
 
     Responds with BadRequest if any of the provided problem locations are faulty.
     """
-    course_key = CourseKey.from_string(course_id)
     # A comma-separated list of problem locations
     # The name of the POST parameter is `problem_location` (not pluralised) in
     # order to preserve backwards compatibility with existing third-party
     # scripts.
-    problem_locations = request.POST.get('problem_location', '')
+    problem_locations = request.POST.get('problem_location', '').split(',')
     # A comma-separated list of block types
-    problem_types_filter = request.POST.get('problem_types_filter', '')
+    problem_types_filter = request.POST.get('problem_types_filter')
+    return _get_problem_responses(
+        request,
+        course_id=course_id,
+        problem_locations=problem_locations,
+        problem_types_filter=problem_types_filter,
+    )
+
+
+@cache_control(no_cache=True, no_store=True, must_revalidate=True)
+@common_exceptions_400
+def _get_problem_responses(request, *, course_id, problem_locations, problem_types_filter):
+    """
+    Shared code for new DRF and old APIS for problem response report generation.
+    """
+    course_key = CourseKey.from_string(course_id)
     report_type = _('problem responses')
 
     try:
-        for problem_location in problem_locations.split(','):
-            problem_key = UsageKey.from_string(problem_location).map_into_course(course_key)  # lint-amnesty, pylint: disable=unused-variable
+        for problem_location in problem_locations:
+            UsageKey.from_string(problem_location).map_into_course(course_key)
     except InvalidKeyError:
         return JsonResponseBadRequest(_("Could not find problem with this location."))
 
     task = task_api.submit_calculate_problem_responses_csv(
-        request, course_key, problem_locations, problem_types_filter,
+        request, course_key, ','.join(problem_locations), problem_types_filter,
     )
     success_status = SUCCESS_MESSAGE_TEMPLATE.format(report_type=report_type)
 
@@ -1852,10 +1996,139 @@ def list_email_content(request, course_id):
     return JsonResponse(response_payload)
 
 
+class InstructorTaskSerializer(serializers.Serializer):  # pylint: disable=abstract-method
+    """
+    Serializer that describes the format of a single instructor task.
+    """
+    status = serializers.CharField(help_text=_("Current status of task."))
+    task_type = serializers.CharField(help_text=_("Identifies the kind of task being performed, e.g. rescoring."))
+    task_id = serializers.CharField(help_text=_("The celery ID for the task."))
+    created = serializers.DateTimeField(help_text=_("The date and time when the task was created."))
+    task_input = serializers.DictField(
+        help_text=_(
+            "The input parameters for the task. The format and content of this "
+            "data will depend on the kind of task being performed. For instance"
+            "it may contain the problem locations for a problem resources task.")
+    )
+    requester = serializers.CharField(help_text=_("The username of the user who initiated this task."))
+    task_state = serializers.CharField(help_text=_("The last knows state of the celery task."))
+    duration_sec = serializers.CharField(help_text=_("Task duration information, if known"))
+    task_message = serializers.CharField(help_text=_("User-friendly task status information, if available."))
+
+
+class InstructorTasksListSerializer(serializers.Serializer):  # pylint: disable=abstract-method
+    """
+    Serializer to describe the response of the instructor tasks list API.
+    """
+    tasks = serializers.ListSerializer(
+        child=InstructorTaskSerializer(),
+        help_text=_("List of instructor tasks.")
+    )
+
+
+@view_auth_classes()
+class InstructorTasks(DeveloperErrorViewMixin, APIView):
+    """
+    **Use Cases**
+
+        Lists currently running instructor tasks
+
+    **Parameters**
+       - With no arguments, lists running tasks.
+       - `problem_location_str` lists task history for problem
+       - `problem_location_str` and `unique_student_identifier` lists task
+           history for problem AND student (intersection)
+
+    **Example Requests**:
+
+        GET /courses/{course_id}/instructor/api/v0/tasks
+
+    **Response Values**
+        {
+          "tasks": [
+            {
+              "status": "Incomplete",
+              "task_type": "grade_problems",
+              "task_id": "2519ff31-22d9-4a62-91e2-55495895b355",
+              "created": "2019-01-15T18:00:15.902470+00:00",
+              "task_input": "{}",
+              "duration_sec": "unknown",
+              "task_message": "No status information available",
+              "requester": "staff",
+              "task_state": "PROGRESS"
+            }
+          ]
+        }
+    """
+
+    @apidocs.schema(
+        parameters=[
+            apidocs.string_parameter(
+                'course_id',
+                apidocs.ParameterLocation.PATH,
+                description="ID for the course whose tasks need to be listed.",
+            ),
+            apidocs.string_parameter(
+                'problem_location_str',
+                apidocs.ParameterLocation.QUERY,
+                description="Filter instructor tasks to this problem location.",
+            ),
+            apidocs.string_parameter(
+                'unique_student_identifier',
+                apidocs.ParameterLocation.QUERY,
+                description="Filter tasks to a singe problem and a single student. "
+                            "Must be used in combination with `problem_location_str`.",
+            ),
+        ],
+        responses={
+            200: InstructorTasksListSerializer,
+            401: _("The requesting user is not authenticated."),
+            403: _("The requesting user lacks access to the course."),
+            404: _("The requested course does not exist."),
+        }
+    )
+    def get(self, request, course_id):
+        """
+        List instructor tasks filtered by `course_id`.
+
+        **Use Cases**
+
+        Lists currently running instructor tasks
+
+        **Parameters**
+           - With no arguments, lists running tasks.
+           - `problem_location_str` lists task history for problem
+           - `problem_location_str` and `unique_student_identifier` lists task
+               history for problem AND student (intersection)
+
+        **Example Requests**:
+
+            GET /courses/{course_id}/instructor/api/v0/tasks
+
+        **Response Values**
+        ```json
+            {
+              "tasks": [
+                {
+                  "status": "Incomplete",
+                  "task_type": "grade_problems",
+                  "task_id": "2519ff31-22d9-4a62-91e2-55495895b355",
+                  "created": "2019-01-15T18:00:15.902470+00:00",
+                  "task_input": "{}",
+                  "duration_sec": "unknown",
+                  "task_message": "No status information available",
+                  "requester": "staff",
+                  "task_state": "PROGRESS"
+                }
+              ]
+            }
+        ```
+        """
+        return _list_instructor_tasks(request=request, course_id=course_id)
+
+
 @require_POST
 @ensure_csrf_cookie
-@cache_control(no_cache=True, no_store=True, must_revalidate=True)
-@require_course_permission(permissions.SHOW_TASKS)
 def list_instructor_tasks(request, course_id):
     """
     List instructor tasks.
@@ -1866,9 +2139,21 @@ def list_instructor_tasks(request, course_id):
         - `problem_location_str` and `unique_student_identifier` lists task
             history for problem AND student (intersection)
     """
+    return _list_instructor_tasks(request=request, course_id=course_id)
+
+
+@cache_control(no_cache=True, no_store=True, must_revalidate=True)
+@require_course_permission(permissions.SHOW_TASKS)
+def _list_instructor_tasks(request, course_id):
+    """
+    List instructor tasks.
+
+    Internal function with common code for both DRF and and tradition views.
+    """
     course_id = CourseKey.from_string(course_id)
-    problem_location_str = strip_if_string(request.POST.get('problem_location_str', False))
-    student = request.POST.get('unique_student_identifier', None)
+    params = getattr(request, 'query_params', request.POST)
+    problem_location_str = strip_if_string(params.get('problem_location_str', False))
+    student = params.get('unique_student_identifier', None)
     if student is not None:
         student = get_student_from_identifier(student)
 
@@ -1940,10 +2225,85 @@ def list_entrance_exam_instructor_tasks(request, course_id):
     return JsonResponse(response_payload)
 
 
+class ReportDownloadSerializer(serializers.Serializer):  # pylint: disable=abstract-method
+    """
+    Serializer that describes a single report download.
+    """
+    url = serializers.URLField(help_text=_("URL from which report can be downloaded."))
+    name = serializers.CharField(help_text=_("Name of report."))
+    link = serializers.CharField(help_text=_("HTML anchor tag that contains the name and link."))
+
+
+class ReportDownloadsListSerializer(serializers.Serializer):  # pylint: disable=abstract-method
+    """
+    Serializer that describes the response of the report downloads list API.
+    """
+    downloads = serializers.ListSerializer(
+        child=ReportDownloadSerializer(help_text="Report Download"),
+        help_text=_("List of report downloads"),
+    )
+
+
+@view_auth_classes()
+class ReportDownloads(DeveloperErrorViewMixin, APIView):
+    """
+    API view to list report downloads for a course.
+    """
+
+    @apidocs.schema(parameters=[
+        apidocs.string_parameter(
+            'course_id',
+            apidocs.ParameterLocation.PATH,
+            description=_("ID for the course whose reports need to be listed."),
+        ),
+        apidocs.string_parameter(
+            'report_name',
+            apidocs.ParameterLocation.QUERY,
+            description=_(
+                "Filter results to only return details of for the report with the specified name."
+            ),
+        ),
+    ], responses={
+        200: ReportDownloadsListSerializer,
+        401: _("The requesting user is not authenticated."),
+        403: _("The requesting user lacks access to the course."),
+        404: _("The requested course does not exist."),
+    })
+    def get(self, request, course_id):
+        """
+        List report CSV files that are available for download for this course.
+
+        **Use Cases**
+
+        Lists reports available for download
+
+        **Example Requests**:
+
+            GET /api/instructor/v1/reports/{course_id}
+
+        **Response Values**
+        ```json
+        {
+            "downloads": [
+                {
+                    "url": "https://1.mock.url",
+                    "link": "<a href=\"https://1.mock.url\">mock_file_name_1</a>",
+                    "name": "mock_file_name_1"
+                }
+            ]
+        }
+        ```
+
+        The report name will depend on the type of report generated. For example a
+        problem responses report for an entire course might be called:
+
+            edX_DemoX_Demo_Course_student_state_from_block-v1_edX+DemoX+Demo_Course+type@course+block@course_2021-04-30-0918.csv
+        """  # pylint: disable=line-too-long
+        return _list_report_downloads(request=request, course_id=course_id)
+
+
 @require_POST
 @ensure_csrf_cookie
-@cache_control(no_cache=True, no_store=True, must_revalidate=True)
-@require_course_permission(permissions.CAN_RESEARCH)
 def list_report_downloads(request, course_id):
     """
     List grade CSV files that are available for download for this course.
@@ -1951,9 +2311,20 @@ def list_report_downloads(request, course_id):
     Takes the following query parameters:
     - (optional) report_name - name of the report
     """
+    return _list_report_downloads(request=request, course_id=course_id)
+
+
+@cache_control(no_cache=True, no_store=True, must_revalidate=True)
+@require_course_permission(permissions.CAN_RESEARCH)
+def _list_report_downloads(request, course_id):
+    """
+    List grade CSV files that are available for download for this course.
+
+    Internal function with common code shared between DRF and functional views.
+    """
     course_id = CourseKey.from_string(course_id)
     report_store = ReportStore.from_config(config_name='GRADES_DOWNLOAD')
-    report_name = request.POST.get("report_name", None)
+    report_name = getattr(request, 'query_params', request.POST).get("report_name", None)
 
     response_payload = {
         'downloads': [
diff --git a/lms/djangoapps/instructor/views/api_urls.py b/lms/djangoapps/instructor/views/api_urls.py
index 8fc74f80dfb..6a0b7d1e8e6 100644
--- a/lms/djangoapps/instructor/views/api_urls.py
+++ b/lms/djangoapps/instructor/views/api_urls.py
@@ -2,10 +2,22 @@
 Instructor API endpoint urls.
 """
 
-
 from django.conf.urls import url
 
 from lms.djangoapps.instructor.views import api, gradebook_api
+from openedx.core.constants import COURSE_ID_PATTERN
+
+# These endpoints are exposing existing views in a way that can be used by MFEs
+# or other API clients. They are currently versioned at `v1` since they have
+# been around without major changes for a while and will probably not be changed
+# in incompatible ways. If they do need incompatible changes for use via MFEs
+# then new v2 endpoints can be introduced.
+v1_api_urls = [
+    url(rf'^tasks/{COURSE_ID_PATTERN}$', api.InstructorTasks.as_view(), name='list_instructor_tasks', ),
+    url(rf'^reports/{COURSE_ID_PATTERN}$', api.ReportDownloads.as_view(), name='list_report_downloads', ),
+    url(rf'^reports/{COURSE_ID_PATTERN}/generate/problem_responses$', api.ProblemResponseReportInitiate.as_view(),
+        name='generate_problem_responses', ),
+]
 
 urlpatterns = [
     url(r'^students_update_enrollment$', api.students_update_enrollment, name='students_update_enrollment'),
diff --git a/openedx/core/lib/api/serializers.py b/openedx/core/lib/api/serializers.py
index c620599d50b..01be9077806 100644
--- a/openedx/core/lib/api/serializers.py
+++ b/openedx/core/lib/api/serializers.py
@@ -53,8 +53,8 @@ class CourseKeyField(serializers.Field):
         """Convert unicode to a course key. """
         try:
             return CourseKey.from_string(data)
-        except InvalidKeyError as ex:
-            raise serializers.ValidationError(f"Invalid course key: {ex.msg}")  # lint-amnesty, pylint: disable=no-member
+        except InvalidKeyError as err:
+            raise serializers.ValidationError("Invalid course key") from err
 
 
 class UsageKeyField(serializers.Field):
@@ -68,5 +68,5 @@ class UsageKeyField(serializers.Field):
         """Convert unicode to a usage key. """
         try:
             return UsageKey.from_string(data)
-        except InvalidKeyError as ex:
-            raise serializers.ValidationError(f"Invalid usage key: {ex.msg}")  # lint-amnesty, pylint: disable=no-member
+        except InvalidKeyError as err:
+            raise serializers.ValidationError("Invalid course key") from err
-- 
GitLab