docs: instructor ORA api spec (#37775)

* docs: instructor ORA api spec
This commit is contained in:
Daniel Wong
2026-01-08 17:30:26 -06:00
committed by GitHub
parent cd6faeb966
commit 7f1f8767a8
2 changed files with 401 additions and 0 deletions

View File

@@ -0,0 +1,112 @@
Instructor Dashboard Open Response Assessment (ORA) API Specification
======================================================================
Status
======
Accepted
Context
=======
The Instructor Dashboard is being migrated to a Micro-Frontend (MFE) architecture,
which requires stable, well-defined, and RESTful API endpoints.
The existing Open Response Assessment (ORA) functionality exposes summary and
detailed assessment data through legacy endpoints that are tightly coupled to
server-rendered views. These endpoints do not meet the requirements for MFE
consumption, including consistent URL patterns, centralized permission handling,
and standardized API documentation.
Additionally, ORA functionality is implemented in the edx-ora2 library, which
is maintained as a separate Django app from the main platform. Historically,
Instructor Dashboard APIs have been implemented directly in the platform and
coupled to ORA data sources, rather than being owned by or exposed directly from
edx-ora2. While edx-ora2 is expected to be installed in the platform, this
cross-app coupling is not an ideal long-term pattern.
As part of this work, the new versioned ORA APIs will continue to rely on the
existing OraAggregateData interface to retrieve assessment data. This ensures
consistency with current ORA behavior and avoids introducing tighter coupling or
duplicate business logic as part of this migration.
Refactoring or relocating these REST endpoints into the edx-ora2 library
itself—so that the Instructor Dashboard consumes them as an external dependency—
is acknowledged as a potential future improvement. However, this architectural
change is explicitly out of scope for the current effort.
To support the MFE migration in the short term, this work introduces a new
versioned ORA API that follows RESTful principles and aligns with existing
Instructor v2 APIs, while preserving current data access patterns and interfaces.
Decisions
=========
1. RESTful Resource-Oriented Design
----------------------------------
Introduce a versioned API under ``/api/instructor/v2/`` using resource-oriented
URLs and clear HTTP semantics.
**Summary endpoint**
.. code-block:: http
GET /api/instructor/v2/courses/{course_key}/ora/summary/
Returns aggregated ORA statistics for a course, including:
- Total units
- Total assessments
- Total responses
- Counts by assessment type (training, peer, self, waiting, staff)
- Number of final grades received
**Assessments list endpoint**
.. code-block:: http
GET /api/instructor/v2/courses/{course_key}/ora/
Returns a collection of Open Response Assessments (ORAs) for the specified course.
Each item in the response represents a single assessment and includes
per-assessment metrics such as response counts, grading progress, and assessment
state.
2. Permissions Aligned with Instructor Dashboard
------------------------------------
The permission checks for these new API endpoints align with existing
Instructor Dashboard permissions:
- Only users with instructor or staff roles for the course can access these endpoints.
3. Serializer-Based Business Logic
---------------------------------
Use Django REST Framework serializers (``ORASummarySerializer`` and
``ORASerializer``) to encapsulate business logic for data retrieval and formatting.
Views remain thin and focused on request handling.
4. OpenAPI Specification
------------------------
Maintain an OpenAPI specification at ``../references/instructor-v2-ora-api-spec.yaml`` to guide implementation.
This static specification serves as a reference during development, but ``/api-docs/`` is the source of truth for what is actually deployed.
Once implementation is complete and the endpoints are live in ``/api-docs/``, the static spec file will be deleted to avoid maintaining outdated documentation.
Consequences
============
- Reduced the complexity of client-side code by providing structured data
tailored for MFE consumption
- Centralized business logic ensures consistent permission checks and data
formatting
- Simplified client-side logic for the Instructor Dashboard MFE
- OpenAPI documentation enables type-safe client generation and easier
integration
References
==========
- OpenAPI Specification: ``../references/instructor-v2-ora-api-spec.yaml``
- Live API Documentation: ``/api-docs/``

View File

@@ -0,0 +1,289 @@
swagger: '2.0'
info:
title: Instructor Dashboard ORA API v2
version: 2.0.0
description: |
REST API for Open Response Assessment (ORA) operations in the Instructor Dashboard.
Designed to support the Instructor Dashboard Micro-Frontend (MFE).
**Design Principles:**
- RESTful resource-oriented URLs
- Course-scoped endpoints
- Read-only operations
- Centralized permission checks
- Consistent error handling
host: courses.example.com
basePath: /
schemes:
- https
securityDefinitions:
JWTAuth:
type: apiKey
in: header
name: Authorization
description: JWT token authentication (e.g. `JWT <token>`).
security:
- JWTAuth: []
tags:
- name: ORA
description: Open Response Assessment instructor data
paths:
/api/instructor/v2/courses/{course_id}/ora/summary:
get:
tags:
- ORA
summary: Get ORA summary statistics
description: |
Retrieve an overview of Open Response Assessments (ORA) for a course,
including total assessments, responses, and grading state breakdowns.
operationId: getORASummary
produces:
- application/json
parameters:
- $ref: '#/parameters/CourseId'
responses:
200:
description: ORA summary retrieved successfully
schema:
$ref: '#/definitions/ORASummary'
400:
$ref: '#/responses/BadRequest'
401:
$ref: '#/responses/Unauthorized'
403:
$ref: '#/responses/Forbidden'
404:
$ref: '#/responses/NotFound'
/api/instructor/v2/courses/{course_id}/ora:
get:
tags:
- ORA
summary: List ORA assessments with detailed statistics
description: |
Retrieve detailed information for all Open Response Assessments (ORA)
in a course, including response counts and grading states per assessment.
operationId: listORA
produces:
- application/json
parameters:
- $ref: '#/parameters/CourseId'
responses:
200:
description: ORA assessment list retrieved successfully
schema:
$ref: '#/definitions/ORAList'
400:
$ref: '#/responses/BadRequest'
401:
$ref: '#/responses/Unauthorized'
403:
$ref: '#/responses/Forbidden'
404:
$ref: '#/responses/NotFound'
parameters:
CourseId:
name: course_id
in: path
required: true
description: Course identifier in format `course-v1:{org}+{course}+{run}`
type: string
pattern: '^course-v1:[^/+]+(\\+[^/+]+)+(\\+[^/]+)$'
x-example: "course-v1:edX+DemoX+Demo_Course"
responses:
BadRequest:
description: Bad request - Invalid parameters or malformed request
schema:
$ref: '#/definitions/Error'
examples:
application/json:
error: "INVALID_PARAMETER"
message: "Invalid course key format"
Unauthorized:
description: Unauthorized - Authentication required
schema:
$ref: '#/definitions/Error'
examples:
application/json:
error: "AUTHENTICATION_REQUIRED"
message: "You must be authenticated to access this endpoint"
Forbidden:
description: Forbidden - Insufficient permissions
schema:
$ref: '#/definitions/Error'
examples:
application/json:
error: "PERMISSION_DENIED"
message: "You do not have instructor permissions for this course"
NotFound:
description: Not found - Resource does not exist
schema:
$ref: '#/definitions/Error'
examples:
application/json:
error: "RESOURCE_NOT_FOUND"
message: "The specified resource does not exist"
definitions:
ORASummary:
type: object
description: Aggregated ORA statistics for a course
required:
- total_units
- total_assessments
- total_responses
- training
- peer
- self
- waiting
- staff
- final_grade_received
properties:
total_units:
type: integer
minimum: 0
description: Total number of ORA units in the course
example: 12
total_assessments:
type: integer
minimum: 0
description: Total number of ORA assessments
example: 25
total_responses:
type: integer
minimum: 0
description: Total number of learner responses
example: 350
training:
type: integer
minimum: 0
description: Responses in training step
example: 40
peer:
type: integer
minimum: 0
description: Responses in peer grading
example: 120
self:
type: integer
minimum: 0
description: Responses in self assessment
example: 60
waiting:
type: integer
minimum: 0
description: Responses waiting for grading
example: 30
staff:
type: integer
minimum: 0
description: Responses requiring staff grading
example: 20
final_grade_received:
type: integer
minimum: 0
description: Responses with final grade assigned
example: 80
ORAList:
type: object
description: List of ORA assessments with detailed statistics
required:
- assessments
properties:
assessments:
type: array
items:
$ref: '#/definitions/ORAAssessment'
ORAAssessment:
type: object
description: Detailed ORA assessment statistics
required:
- block_id
- unit_name
- display_name
- total_responses
- training
- peer
- self
- waiting
- staff
- final_grade_received
properties:
block_id:
type: string
description: ORA block usage key
example: "block-v1:edX+DemoX+Demo_Course+type@openassessment+block@ora1"
unit_name:
type: string
description: Name of the unit containing the ORA assessment
example: "Week 1: Introduction"
display_name:
type: string
description: Display name of the ORA assessment
example: "Peer Review Assignment 1"
total_responses:
type: integer
minimum: 0
description: Total responses submitted
example: 120
training:
type: integer
minimum: 0
description: Responses in training step
example: 15
peer:
type: integer
minimum: 0
description: Responses in peer grading
example: 50
self:
type: integer
minimum: 0
description: Responses in self assessment
example: 20
waiting:
type: integer
minimum: 0
description: Responses waiting for grading
example: 10
staff:
type: integer
minimum: 0
description: Responses requiring staff grading
example: 5
final_grade_received:
type: integer
minimum: 0
description: Responses with final grade assigned
example: 20
Error:
type: object
description: Error response
required:
- error
- message
properties:
error:
type: string
description: Machine-readable error code
message:
type: string
description: Human-readable error message
field_errors:
type: object
description: Field-specific validation errors
additionalProperties:
type: string