Skip to content

feat: add certificate management v2 API endpoints#38404

Open
wgu-jesse-stewart wants to merge 18 commits intoopenedx:masterfrom
WGU-Open-edX:wgu-jesse-stewart/instructor_dashboard_certificates_v2
Open

feat: add certificate management v2 API endpoints#38404
wgu-jesse-stewart wants to merge 18 commits intoopenedx:masterfrom
WGU-Open-edX:wgu-jesse-stewart/instructor_dashboard_certificates_v2

Conversation

@wgu-jesse-stewart
Copy link
Copy Markdown
Contributor

@wgu-jesse-stewart wgu-jesse-stewart commented Apr 21, 2026

  • Add ToggleCertificateGenerationView endpoint to enable/disable certificate generation
  • Add CertificateExceptionsView endpoint to grant and remove certificate exceptions (allowlist)
  • Add CertificateInvalidationsView endpoint to invalidate and re-validate certificates
  • Update certificate status labels to be more user-friendly (e.g., "Received" instead of "already received")
  • Update certificate generation history labels (e.g., "All Learners" instead of "All learners")
  • Add invalidation notes to IssuedCertificateSerializer
  • Add certificates_enabled flag to CourseInformationSerializerV2

Description

This PR adds comprehensive v2 API endpoints for certificate management in the instructor dashboard, supporting the new React-based instructor dashboard UI.

Changes include:

  • New API Endpoints:

    • POST /api/instructor/v2/courses/{course_id}/certificates/toggle_generation - Enable/disable certificate generation for a course
    • POST /api/instructor/v2/courses/{course_id}/certificates/exceptions - Grant certificate exceptions (allowlist) to learners
    • DELETE /api/instructor/v2/courses/{course_id}/certificates/exceptions - Remove certificate exceptions
    • POST /api/instructor/v2/courses/{course_id}/certificates/invalidations - Invalidate certificates for learners
    • DELETE /api/instructor/v2/courses/{course_id}/certificates/invalidations - Re-validate (remove invalidation) certificates
  • Data Model Updates:

    • Updated certificate status labels to be more user-friendly:
      • "downloadable" → "Received"
      • "notpassing" → "Not Received"
      • "unavailable" → "Invalidated"
      • "error" → "Error State"
      • "audit_passing" → "Audit - Passing"
      • "audit_notpassing" → "Audit - Not Passing"
    • Updated certificate generation history labels:
      • "All learners" → "All Learners"
      • "For exceptions" → "Granted Exceptions"
  • Serializer Enhancements:

    • Added invalidation_note field to IssuedCertificateSerializer to include notes about certificate invalidations
    • Added certificates_enabled flag to CourseInformationSerializerV2 to indicate if certificate management is available

Key Features:

  • Bulk operations support with detailed error handling - returns separate success and error lists
  • Validation checks to prevent invalid operations (e.g., granting exceptions to non-enrolled users, invalidating already-invalidated certificates)
  • Proper permission checks using existing instructor permissions

User Roles Impacted:

  • Instructors/Course Staff - Can manage certificate exceptions and invalidations through the new instructor dashboard UI

Supporting information

Related to the instructor dashboard v2 modernization effort.

Testing instructions

  1. Toggle Certificate Generation:

    curl -X POST /api/instructor/v2/courses/{course_id}/certificates/toggle_generation \
      -H "Authorization: Bearer {token}" \
      -d '{"enabled": false}'

    Expected: Returns {"enabled": false}

  2. Grant Certificate Exceptions (bulk):

    curl -X POST /api/instructor/v2/courses/{course_id}/certificates/exceptions \
      -H "Authorization: Bearer {token}" \
      -d '{"learners": ["user1", "user2@example.com"], "notes": "Test exception"}'

    Expected: Returns success/error lists for each learner

  3. Remove Certificate Exception:

    curl -X DELETE /api/instructor/v2/courses/{course_id}/certificates/exceptions \
      -H "Authorization: Bearer {token}" \
      -d '{"username": "user1"}'

    Expected: Returns success message

  4. Invalidate Certificates (bulk):

    curl -X POST /api/instructor/v2/courses/{course_id}/certificates/invalidations \
      -H "Authorization: Bearer {token}" \
      -d '{"learners": ["user1", "user2@example.com"], "notes": "Reason for invalidation"}'

    Expected: Returns success/error lists for each learner

  5. Remove Certificate Invalidation:

    curl -X DELETE /api/instructor/v2/courses/{course_id}/certificates/invalidations \
      -H "Authorization: Bearer {token}" \
      -d '{"username": "user1"}'

    Expected: Returns success message

Deadline

None

Other information

  • These endpoints follow the same patterns as other v2 instructor API endpoints
  • No database migrations required - uses existing models
  • Backwards compatible - does not modify existing v1 endpoints
  • Frontend PR: [link to frontend-app-instruct PR when created]

- Add ToggleCertificateGenerationView endpoint to enable/disable certificate generation
- Add CertificateExceptionsView endpoint to grant and remove certificate exceptions (allowlist)
- Add CertificateInvalidationsView endpoint to invalidate and re-validate certificates
- Update certificate status labels to be more user-friendly (e.g., "Received" instead of "already received")
- Update certificate generation history labels (e.g., "All Learners" instead of "All learners")
- Add invalidation notes to IssuedCertificateSerializer
- Add certificatesEnabled flag to CourseInformationSerializerV2
@openedx-webhooks openedx-webhooks added open-source-contribution PR author is not from Axim or 2U core contributor PR author is a Core Contributor (who may or may not have write access to this repo). labels Apr 21, 2026
@openedx-webhooks
Copy link
Copy Markdown

openedx-webhooks commented Apr 21, 2026

Thanks for the pull request, @wgu-jesse-stewart!

This repository is currently maintained by @openedx/wg-maintenance-openedx-platform.

Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review.

🔘 Get product approval

If you haven't already, check this list to see if your contribution needs to go through the product review process.

  • If it does, you'll need to submit a product proposal for your contribution, and have it reviewed by the Product Working Group.
    • This process (including the steps you'll need to take) is documented here.
  • If it doesn't, simply proceed with the next step.
🔘 Provide context

To help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:

  • Dependencies

    This PR must be merged before / after / at the same time as ...

  • Blockers

    This PR is waiting for OEP-1234 to be accepted.

  • Timeline information

    This PR must be merged by XX date because ...

  • Partner information

    This is for a course on edx.org.

  • Supporting documentation
  • Relevant Open edX discussion forum threads
🔘 Get a green build

If one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green.

Details
Where can I find more information?

If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources:

When can I expect my changes to be merged?

Our goal is to get community contributions seen and reviewed as efficiently as possible.

However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:

  • The size and impact of the changes that it introduces
  • The need for product review
  • Maintenance status of the parent repository

💡 As a result it may take up to several weeks or months to complete a review and merge your PR.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds new Instructor Dashboard v2 endpoints to manage course certificate generation, exceptions (allowlist), and invalidations, plus updates to certificate-related labels/serialization to support the React-based instructor dashboard UI.

Changes:

  • Introduces v2 API endpoints to toggle certificate generation, manage certificate exceptions, and manage certificate invalidations.
  • Extends v2 serializers to expose certificate-management availability and invalidation notes.
  • Updates certificate status/history “human-readable” labels and adjusts related tests.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
lms/djangoapps/instructor/views/serializers_v2.py Adds certificates_enabled and invalidation_note to v2 serializers.
lms/djangoapps/instructor/views/api_v2.py Adds new v2 certificate management APIViews and extends issued-certs context with invalidation notes.
lms/djangoapps/instructor/views/api_urls.py Wires new v2 certificate management routes.
lms/djangoapps/instructor/tests/test_api_v2.py Updates expected certificate generation history label casing.
lms/djangoapps/certificates/tests/test_models.py Updates expected label strings for generation history candidate rendering.
lms/djangoapps/certificates/models.py Updates generation history candidate strings (“All Learners”, “Granted Exceptions”).
lms/djangoapps/certificates/data.py Updates human-readable certificate status labels and adds mapping for unavailable.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lms/djangoapps/instructor/views/serializers_v2.py Outdated
Comment thread lms/djangoapps/instructor/views/api_v2.py Outdated
Comment thread lms/djangoapps/instructor/views/api_v2.py
Comment thread lms/djangoapps/instructor/views/api_v2.py
Comment thread lms/djangoapps/instructor/views/serializers_v2.py
Comment thread lms/djangoapps/instructor/views/api_v2.py Outdated
Comment thread lms/djangoapps/instructor/views/api_v2.py Outdated
Comment thread lms/djangoapps/instructor/views/api_v2.py Outdated
Comment thread lms/djangoapps/instructor/views/api_v2.py
Comment thread lms/djangoapps/instructor/views/api_v2.py
Copy link
Copy Markdown
Contributor

@dwong2708 dwong2708 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for all the effort. I’ve left my first round of reviews.

Comment thread lms/djangoapps/instructor/views/api_v2.py Outdated
Comment thread lms/djangoapps/instructor/views/api_v2.py Outdated
Comment thread lms/djangoapps/instructor/views/api_v2.py Outdated
Comment thread lms/djangoapps/instructor/views/api_v2.py
Comment thread lms/djangoapps/instructor/views/api_v2.py Outdated
Comment thread lms/djangoapps/instructor/views/api_v2.py Outdated
Comment thread lms/djangoapps/instructor/views/api_v2.py Outdated
Comment thread lms/djangoapps/instructor/views/api_v2.py Outdated
Comment thread lms/djangoapps/instructor/views/api_v2.py Outdated
Comment thread lms/djangoapps/instructor/views/api_v2.py
Comment thread lms/djangoapps/instructor/views/api_v2.py Outdated
@mphilbrick211 mphilbrick211 added the mao-onboarding Reviewing this will help onboard devs from an Axim mission-aligned organization (MAO). label Apr 22, 2026
@mphilbrick211 mphilbrick211 moved this from Needs Triage to Waiting on Author in Contributions Apr 22, 2026
@wgu-jesse-stewart wgu-jesse-stewart marked this pull request as ready for review April 22, 2026 23:36
@wgu-jesse-stewart wgu-jesse-stewart requested a review from a team as a code owner April 22, 2026 23:36
Comment thread lms/djangoapps/instructor/tests/test_certificates_api_v2.py Outdated
Comment thread lms/djangoapps/instructor/views/api_v2.py Outdated
Comment thread lms/djangoapps/instructor/views/serializers_v2.py
Comment thread lms/djangoapps/instructor/views/api_v2.py Outdated
Comment thread lms/djangoapps/instructor/views/api_v2.py Outdated
Comment thread lms/djangoapps/instructor/views/api_v2.py
Comment thread lms/djangoapps/instructor/views/api_v2.py Outdated
Comment thread lms/djangoapps/instructor/views/api_v2.py Outdated
Comment thread lms/djangoapps/instructor/views/api_v2.py Outdated
Comment thread lms/djangoapps/instructor/views/api_v2.py Outdated
Copy link
Copy Markdown
Contributor

@dwong2708 dwong2708 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be the latest suggestions. Thanks!

user.id, course_key
)
try:
task_api.generate_certificates_for_students(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the docstring, this raises an AlreadyRunningError if certificates are currently being generated. It should be handled here and communicated to the user.

"""
Serializer for granting certificate exceptions (bulk).
"""
learners = serializers.ListField(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add max_length= to prevent a large number of learners.

"""
Serializer for invalidating certificates (bulk).
"""
learners = serializers.ListField(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add max_length= to prevent a large number of learners.

for learner, user in exceptions_to_create:
try:
certs_api.create_or_update_certificate_allowlist_entry(user, course_key, notes)
results['success'].append(learner)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we audit (Logging) which learners were affected?

)
# Invalidate the certificate with explicit source for auditability
certificate.invalidate(source='instructor_api_v2')
results['success'].append(learner)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we audit (Logging) which learners were affected?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core contributor PR author is a Core Contributor (who may or may not have write access to this repo). mao-onboarding Reviewing this will help onboard devs from an Axim mission-aligned organization (MAO). open-source-contribution PR author is not from Axim or 2U

Projects

Status: Waiting on Author

Development

Successfully merging this pull request may close these issues.

5 participants