[API] Libraries #39069
Copy link
Copy link
Description
Functional Area: Libraries
Endpoints under this functional area:
| Module | API Version | Resource / Endpoint | HTTP Method | Description |
|---|---|---|---|---|
| Home | v1 | /contentstore/v1/home/libraries |
GET | Retrieves all libraries on the home page. Supports optional query parameters: org (filter by organization) and is_migrated (boolean, true or false to filter legacy libraries by migration status). Returns display name, library key, URL, edit permissions, and migration info. Useful for AI systems or external tools managing library content or migration tracking. |
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
Faraz32123 commentedon Oct 15, 2026
Standardization PR open: #39238
PR: #39238 — feat: apply FC-0118 ADRs to legacy libraries API
State: open
What this does
Standardizes the Libraries functional area (#39069, part of #38137). This area has one operation: "list the legacy (v1, modulestore) libraries the requester can read". Today it is served at three addresses across two versions; this PR adds its v4 at
/api/authoring/v4/legacy_libraries/.New addresses
/api/authoring/v4/legacy_libraries/(supersedesGET /api/contentstore/v1/home/libraries,GET /api/contentstore/v3/home/libraries/andGET /api/authoring/v3/home/libraries/, nowdeprecated: truein the CMS schema)ADRs applied
10 of 16 decisions applied on this pass; every one left open carries its reason.
path(..., as_view({"get": "list"})), not registered on a DRF Router, because a router names the routelegacy_library-listand ADR 0038 rule 11 asks for a snake_case name (legacy_library_list, like its siblingcourse_listin the same URLconf); merged feat: apply ADR 0038 (URL structure standardization) across 6 standardized APIs #39078, feat: apply FC-0118 ADRs to youtube transcripts APIs #39100 and feat: apply FC-0118 ADRs to course content APIs #39157 mount their ViewSets the same way. Otherwise met: plainViewSet(modulestore data path) with a service module; bounded query count; see the matrixDeprecated <link>marker is allowed now that [DEPR]: Contentstore and enrollment API versions superseded by FC-0118 #39128 is Plan Accepted, and is deliberately not added. See the matrixget_queryset()forScopedQuerysetMixinto wrap; the three layers are implemented in the service and tested (see the matrix)The evidence for each tick is the compliance matrix in the PR body; nothing is ticked without a named test or gate line.
Backward compatibility
Schema: 0 breaking changes (69 → 70 paths). URLs: every base route keeps its pattern, name and view (2162 → 2163). The 24 legacy tests pass unmodified; v4 responses match v3 field for field (parity test, 20 rows).
Gates
Deprecations
GET /api/contentstore/v1/home/libraries,GET /api/contentstore/v3/home/libraries/andGET /api/authoring/v3/home/libraries/are superseded byGET /api/authoring/v4/legacy_libraries/. They are markeddeprecated: truein the published CMS schema; the v3 contentstore address was already marked through its/api/contentstore/v3/home/prefix. The superseded views are unchanged: no response header, and no deprecation notes in code./api/authoring/v3/home/and/api/authoring/v3/home/courses/remain current.Tracked on the FC-0118 umbrella DEPR ticket, #39128, which removes them one named release after the release this ships in. This area's entry: #39128 (comment)
Migration notes for callers:
{count, num_pages, current_page, start, next, previous, results}, 10 per page by default,page_sizeup to 100. Each item inresultshas the fields of an item in the oldlibrariesarray, under the same names.orgnow filters by the organization in the library key, as an exact, case-sensitive match; v1 and v3 documented it but ignored it.is_migratedbehaves as before. An empty value for either is a 400.{"detail": ...}or a bare list).ENABLE_CREATOR_GROUP, v1 and v3 created anunrequestedcourse-creator record (CourseCreator) as a side effect of this read, for a non-staff user who had none. Two other Studio reads still create it: the Studio home context (get_home_context,cms/djangoapps/contentstore/utils.py:1714, behind the v1 and v3homeendpoints) and the course rerun context (get_course_rerun_context,utils.py:1740).POST /request_course_creatordepends on that record (cms/djangoapps/contentstore/views/user.py:27-31). It callsuser_requested_access, which doesCourseCreator.objects.get(user=user)(cms/djangoapps/course_creators/views.py:89). On a site withENABLE_CREATOR_GROUP, a non-staff author whose client has loaded neither the Studio home nor a course rerun context gets a 500 from that POST. No v4 endpoint creates the record (neither this list nor/api/authoring/v4/courses/), and this PR adds no POST to do it. A client that offers course-creator requests must still load the Studio home for the user first. The fix is tracked with the Studio home standardization, [API] Home Page Data #39068./api/authoring/v3/home/libraries/was added by #39078, merged 2026-10-12 (cc @Abdul-Muqadim-Arbisoft). It is deprecated here because v4 is now this operation's current version.Follow-ups
SDK: the view carries the
openedx-platform-sdktag, so the next openedx-platform-sdk regeneration gainsv4_legacy_libraries_list. The v3 addresses arex-internaland drop out of generators that skip it.frontend-app-authoring:
/api/contentstore/v3/home/libraries/, which is deprecated. It should target v4 instead (to be noted on FAA#3127).Course-creator record, for [API] Home Page Data #39068: standardizing the Studio home endpoints under [API] Home Page Data #39068 would remove one of the two reads that still create the
unrequestedCourseCreatorrecord; the course rerun context is the other. Before that happens,POST /request_course_creatorneeds a write that creates the record: an explicit endpoint, oruser_requested_accesscreating it when it is missing. This PR records the dependency and adds no POST.edx-drf-extensions (library changes, not made here):
DefaultPagination.get_paginated_response_schemadocuments four of the seven keys, and the inheritedpage_sizedescription gives neither the default nor the cap. The library fix should cover both. This PR adds the second local subclass, afterCourseTextbookPagination. The two now differ, since only this one carries thepage_sizetext. Keeping a second copy is an accepted risk for this PR; both subclasses go once the library fix is released. No issue or PR exists for it (searched 2026-10-14).MethodNotAllowedandNotAcceptableare not cataloged, so a 405 or 406 is enveloped asinternal/ "Internal Server Error".ValidationErroris rendered intodetailas the Python repr of the whole error dict.Items 2 to 4 were not searched for existing issues.
CMS JSON 404: an address below
/api/authoring/v4/legacy_libraries/gets the CMS's HTML 404 page, even when the client asked for JSON. Fixing that for unmatched/api/addresses belongs to the CMShandler404, or to a catch-all route under each collection.Shared test helpers: the v4 tests import
PASSWORD,SignalRecorder,generate_cms_schema,logged_in_client,resolve_refandwritesfromcms/djangoapps/contentstore/rest_api/v2/views/tests/helpers.py, a module scoped to the v2 tests. Hoist them next torouted_actionsincms/djangoapps/contentstore/tests/utils.py, and leave a re-export in v2. Then a v2-only edit cannot change what the v4 tests prove, and retiring v2 cannot break them. Not done here, because it edits frozen v2 test code.Later category-2 opt-ins (no version bump needed): an
orderingparameter and a text-search parameter on v4.Test environment: run in a Tutor container (
openedx-dev:23.0.0-main) withopenedx-core1.11.0,openedx-authz1.24.0 andopenedx-forum0.4.8 installed to match the pins (the image ships older releases). CI is the authoritative run.🤖 Generated with Claude Code
Review on the PR, please — this issue stays open until it merges.