Summary
Five Studio REST APIs on edx-platform have been standardized under FC-0118 (ADRs 0025–0037) and released as new versions. frontend-app-authoring is the sole MFE consumer of all five and needs to migrate its callers.
The old versions remain live (no immediate breakage), but the new versions offer a standardized error envelope, OpenAPI 3.x schemas, ADR 0036 ?view=minimal / field-selection presets, and consistent auth. New Studio features should target the new versions; existing call sites should be migrated opportunistically.
Update — incorporating @bradenmacdonald's feedback:
APIs to migrate
| # |
Old URL |
New URL |
Status |
| 1 |
Legacy /xblock/{usage_key}/ (non-REST) |
/api/contentstore/v1/xblock/{usage_key}/ |
Ready |
| 2 |
/api/contentstore/v1/home/ |
/api/contentstore/v3/home/ |
⏸ On hold (#2540) |
| 3 |
/api/contentstore/v2/home/courses/ |
/api/contentstore/v4/home/courses/ |
⏸ On hold (#2540) |
| 4 |
/api/contentstore/v1/course_details/{course_id} |
/api/contentstore/v3/course_details/{course_id} |
Ready |
| 5 |
/api/contentstore/v1/course_grading/{course_id} (GET+POST) |
/api/contentstore/v3/authoring_grading/{course_id} (single PATCH) |
Ready |
Prerequisite — standardized error wrapper
Before migrating any call site, add a thin React Query wrapper around getAuthenticatedHttpClient() that parses the ADR 0029 standardized error envelope:
{
"error": {
"type": "validation_error",
"detail": "…human-readable message…",
"errors": [
{ "code": "required", "field": "display_name", "detail": "…" }
]
}
}
The wrapper should:
- Read
response.data.error.detail (falling back to response.data.detail so v1 callers keep working during the migration).
- Map
response.data.error.errors[] onto a fieldErrors object keyed by field name, for form UIs (Schedule & Details, Grading Settings).
- Return a normalized
{ detail, fieldErrors, code } shape so consumers never read error.response.data directly.
Landing this first gives one place to add tracing/logging and keeps each per-API PR small. (Envelope shape from ADR 0029; implemented via StandardizedErrorMixin at openedx/core/lib/api/mixins.py.)
Call sites (grepped 2026-07-03)
1. Xblock — legacy /xblock/ → /api/contentstore/v1/xblock/
Every current call goes through the legacy Studio route, not the REST endpoint. Consolidating them behind the new v1 REST viewset also gives us proper OpenAPI schemas for SDK generation.
- Course Unit —
src/course-unit/data/api.ts:22,75,103,127,137
- Course Outline —
src/course-outline/data/api.ts:42,162,177,194,214,267,307,331,347,360,377,394,409,427,443
- Custom Pages —
src/custom-pages/data/api.js:29,41,55
- Course Updates —
src/course-updates/data/api.js:69,81
- XBlock Editors —
src/editors/data/services/cms/urls.ts:44-58,124
- Content Tags Drawer —
src/content-tags-drawer/data/api.js:32,85
2. Course Home v1 → v3 — ⏸ on hold (#2540)
src/studio-home/data/api.ts:6,14,54 (Studio Home landing + libraries tab)
Deferred: #2540 intends to split this endpoint's kitchen-sink payload into smaller queries; bumping the version first would be wasted work.
3. Home Courses v2 → v4 — ⏸ on hold (#2540)
src/studio-home/data/api.ts:20 (v1 fallback — drop), :31 (v2 caller — bump to v4)
Deferred for the same reason as #2.
4. Course Detail v1 → v3
src/schedule-and-details/data/api.js:6,17 (getCourseDetails)
src/schedule-and-details/data/api.js:30 (updateCourseDetails)
5. Author Grading v1 (GET+POST) → v3 PATCH
The v3 endpoint collapses the two-endpoint pattern into a single partial_update.
src/grading-settings/data/api.js:7,17,29 — helpers getGradingSettingsApiUrl, getGradingSettings, sendGradingSettings
src/grading-settings/data/apiHooks.ts:7,21 — React Query hooks
Suggested approach
References
ADRs (on openedx/edx-platform, branch feat/axim-api_improvements pending merge to master):
PRs: #38684 (Home v4), #38694 (Home v3), #38708 (Course Details v3), #38723 (Xblock v1), #38724 (Enrollment v2), #38726 (Author Grading v3), #38773 (ADR 0036 pass), #38796 (ADR 0034 pass), #38834 (Xblock v1 OpenAPI schema).
Related: #2540 (break up Studio Home state).
Summary
Five Studio REST APIs on
edx-platformhave been standardized under FC-0118 (ADRs 0025–0037) and released as new versions.frontend-app-authoringis the sole MFE consumer of all five and needs to migrate its callers.The old versions remain live (no immediate breakage), but the new versions offer a standardized error envelope, OpenAPI 3.x schemas, ADR 0036
?view=minimal/ field-selection presets, and consistent auth. New Studio features should target the new versions; existing call sites should be migrated opportunistically.APIs to migrate
/xblock/{usage_key}/(non-REST)/api/contentstore/v1/xblock/{usage_key}//api/contentstore/v1/home//api/contentstore/v3/home//api/contentstore/v2/home/courses//api/contentstore/v4/home/courses//api/contentstore/v1/course_details/{course_id}/api/contentstore/v3/course_details/{course_id}/api/contentstore/v1/course_grading/{course_id}(GET+POST)/api/contentstore/v3/authoring_grading/{course_id}(single PATCH)Prerequisite — standardized error wrapper
Before migrating any call site, add a thin React Query wrapper around
getAuthenticatedHttpClient()that parses the ADR 0029 standardized error envelope:{ "error": { "type": "validation_error", "detail": "…human-readable message…", "errors": [ { "code": "required", "field": "display_name", "detail": "…" } ] } }The wrapper should:
response.data.error.detail(falling back toresponse.data.detailso v1 callers keep working during the migration).response.data.error.errors[]onto afieldErrorsobject keyed by field name, for form UIs (Schedule & Details, Grading Settings).{ detail, fieldErrors, code }shape so consumers never readerror.response.datadirectly.Landing this first gives one place to add tracing/logging and keeps each per-API PR small. (Envelope shape from ADR 0029; implemented via
StandardizedErrorMixinatopenedx/core/lib/api/mixins.py.)Call sites (grepped 2026-07-03)
1. Xblock — legacy
/xblock/→/api/contentstore/v1/xblock/Every current call goes through the legacy Studio route, not the REST endpoint. Consolidating them behind the new v1 REST viewset also gives us proper OpenAPI schemas for SDK generation.
src/course-unit/data/api.ts:22,75,103,127,137src/course-outline/data/api.ts:42,162,177,194,214,267,307,331,347,360,377,394,409,427,443src/custom-pages/data/api.js:29,41,55src/course-updates/data/api.js:69,81src/editors/data/services/cms/urls.ts:44-58,124src/content-tags-drawer/data/api.js:32,852. Course Home v1 → v3 — ⏸ on hold (#2540)
src/studio-home/data/api.ts:6,14,54(Studio Home landing + libraries tab)Deferred: #2540 intends to split this endpoint's kitchen-sink payload into smaller queries; bumping the version first would be wasted work.
3. Home Courses v2 → v4 — ⏸ on hold (#2540)
src/studio-home/data/api.ts:20(v1 fallback — drop),:31(v2 caller — bump to v4)Deferred for the same reason as #2.
4. Course Detail v1 → v3
src/schedule-and-details/data/api.js:6,17(getCourseDetails)src/schedule-and-details/data/api.js:30(updateCourseDetails)5. Author Grading v1 (GET+POST) → v3 PATCH
The v3 endpoint collapses the two-endpoint pattern into a single
partial_update.src/grading-settings/data/api.js:7,17,29— helpersgetGradingSettingsApiUrl,getGradingSettings,sendGradingSettingssrc/grading-settings/data/apiHooks.ts:7,21— React Query hooksSuggested approach
?view=minimalis opt-in and defaults to the full payload — no changes needed to consumer code unless you want the trimmed payload.References
ADRs (on
openedx/edx-platform, branchfeat/axim-api_improvementspending merge to master):PRs: #38684 (Home v4), #38694 (Home v3), #38708 (Course Details v3), #38723 (Xblock v1), #38724 (Enrollment v2), #38726 (Author Grading v3), #38773 (ADR 0036 pass), #38796 (ADR 0034 pass), #38834 (Xblock v1 OpenAPI schema).
Related: #2540 (break up Studio Home state).