Manage grading periods using the Classroom API

This guide explains how to use the grading periods endpoints in the Google Classroom API.

Overview

Grading periods are created to organize homework, quizzes, and projects into specific date ranges. The Classroom API allows developers to create, modify, and read grading periods in Classroom on behalf of administrators and teachers. You can also use the Classroom API to set grading periods on CourseWork.

The Classroom API offers two endpoints to read and write grading period information in a course:

  • GetGradingPeriodSettings: Lets you read the grading period settings in a course.
  • UpdateGradingPeriodSettings: Lets you manage grading period settings in a course by adding, modifying, and deleting grading periods, and applying the configured grading periods to all existing CourseWork.

Licensing requirements

Modify grading period settings in a course

In order to create, modify, or delete grading periods in a course using the UpdateGradingPeriodSettings endpoint, the following conditions must be met:

Read grading period settings in a course

Domain administrators and teachers of a course can read grading period settings regardless of what license they are assigned. This means that requests to the GetGradingPeriodSettings endpoint are permitted on behalf of any domain administrator or teacher.

Set a grading period ID on CourseWork

Teachers of a course can include the gradingPeriodId when creating or updating CourseWork using the API regardless of what license they are assigned.

Check the eligibility of a user to set up grading periods

Requests to the checkGradingPeriodsSetupEligibility endpoint are permitted on behalf of any administrator or teacher. Use this to determine whether the user can modify grading periods in a course.

Prerequisites

This guide provides code examples in Python, and assumes you have:

  • A Google Cloud project. You can set one up following the instructions in the Python quickstart.
  • Added the following scopes to your project's OAuth consent screen:
    • https://www.googleapis.com/auth/classroom.courses
    • https://www.googleapis.com/auth/classroom.coursework.students
  • An ID of a course in which grading periods should be modified. The course owner must have a Google Workspace for Education Plus license.
  • Access to a teacher's or administrator's credentials with a Google Workspace for Education Plus license. You will need a teacher's credentials to create or modify CourseWork. Administrators cannot create or modify CourseWork if they are not a teacher in the course.

Manage the GradingPeriodSettings resource

The GradingPeriodSettings resource includes a list of individual GradingPeriods and a boolean field called applyToExistingCoursework.

The GradingPeriods list represents all of the individual grading periods in a course. You must specify a title, start date, and end date for each individual grading period in the list. Each grading period in a course must have a unique title, and the start and end dates of different grading periods cannot overlap. Each grading period will have its own Classroom API-assigned identifier.

The applyToExistingCoursework boolean is a persisted setting that lets you organize previously created CourseWork into grading periods without having to make a separate API call to modify the gradingPeriodId for each CourseWork. If it is set to True, Classroom will automatically set the gradingPeriodId on all existing CourseWork if the courseWork.dueDate falls within an existing grading period's start and end dates. If no due date was set on the CourseWork, Classroom will use the courseWork.scheduledTime. If neither field is present or there is no match within an existing grading period's start and end dates, the CourseWork won't be associated with any grading period.

Determine if a user can modify grading period settings in a course

Because the ability to create and modify grading periods in Classroom is only available to users with a specific license, the Classroom API provides the checkGradingPeriodsSetupEligibility endpoint to help you proactively determine whether a user is able to make requests to the UpdateGradingPeriodSettings endpoint.

Python

def check_grading_period_setup_eligibility(classroom, course_id):
    """Checks whether a user is able to create and modify grading periods in a course."""
    try:
        grading_period_eligibility_response = classroom.courses().checkGradingPeriodsSetupEligibility(
          courseId=course_id, previewVersion="V1_20240401_PREVIEW").execute()

        # Retrieve the isGradingPeriodsSetupEligible boolean from the response.
        # If the boolean is `True`, the user is able to modify grading period settings in the course.
        is_grading_periods_eligible = grading_period_eligibility_response.get("isGradingPeriodsSetupEligible")
        return is_grading_periods_eligible
    except HttpError as error:
        # Handle errors as appropriate for your application.
        print(f"An error occurred: {error}")
        return error

Add grading periods

Now that you are certain the user has the required license to modify grading period settings in a course, you can begin issuing requests to the UpdateGradingPeriodSettings endpoint. Any modifications to the GradingPeriodSettings resource are performed using the UpdateGradingPeriodSettings endpoint whether you are adding individual grading periods, modifying existing grading periods, or deleting a grading period.

Python

In the following example, the gradingPeriodSettings resource is modified to include two grading periods. The applyToExistingCoursework boolean is set to True which will modify the gradingPeriodId on any existing CourseWork that falls between one grading period's start and end date. Note that the updateMask includes both fields. Save the IDs for the individual grading periods once they are returned in the response. You'll need to use these IDs to update the grading periods if necessary.

def create_grading_periods(classroom, course_id):
    """
    Create grading periods in a course and apply the grading periods
    to existing courseWork.
    """
    try:
        body = {
          "gradingPeriods": [
            {
              "title": "First Semester",
              "start_date": {
                "day": 1,
                "month": 9,
                "year": 2023
              },
              "end_date": {
                "day": 15,
                "month": 12,
                "year": 2023
              }
            },
            {
              "title": "Second Semester",
              "start_date": {
                "day": 15,
                "month": 1,
                "year": 2024
              },
              "end_date": {
                "day": 31,
                "month": 5,
                "year": 2024
              }
            }
          ],
          "applyToExistingCoursework": True
        }
        gradingPeriodSettingsResponse = classroom.courses().updateGradingPeriodSettings(
          courseId=course_id,
          updateMask='gradingPeriods,applyToExistingCoursework',
          body=body,
          previewVersion="V1_20240401_PREVIEW"
        ).execute();

        print(f"Grading period settings updated.")
        return gradingPeriodSettingsResponse

    except HttpError as error:
        # Handle errors as appropriate for your application.
        print(f"An error occurred: {error}")
        return error

Read grading period settings

GradingPeriodSettings are read using the GetGradingPeriodSettings endpoint. Any user, regardless of license, can read grading periods settings in a course.

Python

def get_grading_period_settings(classroom, course_id):
    """Read grading periods settings in a course."""
    try:
        gradingPeriodSettings = classroom.courses().getGradingPeriodSettings(
          courseId=course_id, previewVersion="V1_20240401_PREVIEW").execute()
        return gradingPeriodSettings
    except HttpError as error:
        # Handle errors as appropriate for your application.
        print(f"An error occurred: {error}")
        return error

Add an individual grading period to the list

Updates to an individual grading period must be done following a read-modify-write pattern. This means you should:

  1. Read the grading periods list within the GradingPeriodSettings resource using the GetGradingPeriodSettings endpoint.
  2. Make the chosen modifications to the grading periods list.
  3. Send the new grading periods list in a request to UpdateGradingPeriodSettings.

This pattern will help you ensure that individual grading period titles in a course are distinct and there is no overlap between start and end dates of grading periods.

Keep in mind the following rules about updating the grading periods list:

  1. Grading periods added to the list without an ID are considered additions.
  2. Grading periods missing in the list are considered deletions.
  3. Grading periods with an existing ID but modified data are considered edits. Unmodified properties are left as is.
  4. Grading periods with new or unknown IDs are considered errors.

Python

The following code will build on the example in this guide. A new grading period is created with the title, "Summer". The applyToExistingCoursework boolean is set to False in the request body.

To do this, the current GradingPeriodSettings is read, a new grading period is added to the list, and the applyToExistingCoursework boolean is set to False. Note that any grading periods that have already been applied to existing CourseWork won't be removed. In the previous example, "Semester 1" and "Semester 2" grading periods were already applied to existing CourseWork and won't be removed from CourseWork if applyToExistingCoursework is set to False in subsequent requests.

def add_grading_period(classroom, course_id):
    """
    A new grading period is added to the list, but it is not applied to existing courseWork.
    """
    try:
        # Use the `GetGradingPeriodSettings` endpoint to retrieve the existing
        # grading period IDs. You will need to include these IDs in the request
        # body to make sure existing grading periods aren't deleted.
        body = {
          "gradingPeriods": [
            {
              # Specify the ID to make sure the grading period is not deleted.
              "id": "FIRST_SEMESTER_GRADING_PERIOD_ID",
              "title": "First Semester",
              "start_date": {
                "day": 1,
                "month": 9,
                "year": 2023
              },
              "end_date": {
                "day": 15,
                "month": 12,
                "year": 2023
              }
            },
            {
              # Specify the ID to make sure the grading period is not deleted.
              "id": "SECOND_SEMESTER_GRADING_PERIOD_ID",
              "title": "Second Semester",
              "start_date": {
                "day": 15,
                "month": 1,
                "year": 2024
              },
              "end_date": {
                "day": 31,
                "month": 5,
                "year": 2024
              }
            },
            {
              # Does not include an ID because this grading period is an addition.
              "title": "Summer",
              "start_date": {
                "day": 1,
                "month": 6,
                "year": 2024
              },
              "end_date": {
                "day": 31,
                "month": 8,
                "year": 2024
              }
            }
          ],
          "applyToExistingCoursework": False
        }

        gradingPeriodSettings = classroom.courses().updateGradingPeriodSettings(
          courseId=course_id, body=body, updateMask='gradingPeriods,applyToExistingCoursework',
          previewVersion="V1_20240401_PREVIEW").execute()
        return gradingPeriodSettings

    except HttpError as error:
        # Handle errors as appropriate for your application.
        print(f"An error occurred: {error}")
        return error

Helpful pointers about the applyToExistingCoursework boolean field

It's important to remember that the applyToExistingCoursework boolean is persisted meaning that if the boolean was set to True in a previous API call and not changed, subsequent updates to grading periods will be applied to existing CourseWork.

Note that if you change this boolean value from True to False in a request to UpdateGradingPeriodSettings, only the new changes you are making to GradingPeriodSettings won't be applied to existing CourseWork. Any grading period information applied to CourseWork in previous API calls when the boolean was set to True won't be removed. A helpful way to think about this boolean setting is that it supports associating existing CourseWork with your configured grading periods, but it doesn't support removing existing associations between CourseWork and configured grading periods.

If you delete or change the title of a grading period, those changes will be propagated through all existing CourseWork, regardless of the setting of the applyToExistingCoursework boolean.

Update an individual grading period in the list

To modify some data associated with an existing grading period, include the ID of the existing grading period in the list with the modified data.

Python

In this example, the "Summer" grading period end date will be modified. The applyToExistingCoursework field will be set to True. Note that setting this boolean to True will apply all configured grading periods on existing CourseWork. In the previous API request, the boolean was set to False so that the "Summer" grading period was not applied to existing CourseWork. Now that this boolean field is set to True, the "Summer" grading period will be applied to all existing CourseWork that match.

def update_existing_grading_period(classroom, course_id):
    """
    An existing grading period is updated.
    """
    try:
        # Use the `GetGradingPeriodSettings` endpoint to retrieve the existing
        # grading period IDs. You will need to include these IDs in the request
        # body to make sure existing grading periods aren't deleted.
        body = {
          "gradingPeriods": [
            {
              "id": "FIRST_SEMESTER_GRADING_PERIOD_ID",
              "title": "First Semester",
              "start_date": {
                "day": 1,
                "month": 9,
                "year": 2023
              },
              "end_date": {
                "day": 15,
                "month": 12,
                "year": 2023
              }
            },
            {
              "id": "SECOND_SEMESTER_GRADING_PERIOD_ID",
              "title": "Second Semester",
              "start_date": {
                "day": 15,
                "month": 1,
                "year": 2024
              },
              "end_date": {
                "day": 31,
                "month": 5,
                "year": 2024
              }
            },
            {
              # The end date for this grading period will be modified from August 31, 2024 to September 10, 2024.
              # Include the grading period ID in the request along with the new data.
              "id": "SUMMER_GRADING_PERIOD_ID",
              "title": "Summer",
              "start_date": {
                "day": 1,
                "month": 6,
                "year": 2024
              },
              "end_date": {
                "day": 10,
                "month": 9,
                "year": 2024
              }
            }
          ],
          "applyToExistingCoursework": True
        }

        gradingPeriodSettings = classroom.courses().updateGradingPeriodSettings(
          courseId=course_id, body=body, updateMask='gradingPeriods,applyToExistingCoursework',
          previewVersion="V1_20240401_PREVIEW").execute()
        return gradingPeriodSettings

    except HttpError as error:
        # Handle errors as appropriate for your application.
        print(f"An error occurred: {error}")
        return error

Delete an individual grading period

To delete a grading period, omit the grading period from the list. Note that if a grading period is deleted, any reference to the grading period on CourseWork will also be deleted regardless of the applyToExistingCoursework setting.

Python

To continue the example in this guide, omit the grading period, "Summer", to delete it.

def delete_grading_period(classroom, course_id):
    """
    An existing grading period is deleted.
    """
    try:
        body = {
          "gradingPeriods": [
            {
              "id": "FIRST_SEMESTER_GRADING_PERIOD_ID",
              "title": "First Semester",
              "start_date": {
                "day": 1,
                "month": 9,
                "year": 2023
              },
              "end_date": {
                "day": 15,
                "month": 12,
                "year": 2023
              }
            },
            {
              "id": "SECOND_SEMESTER_GRADING_PERIOD_ID",
              "title": "Second Semester",
              "start_date": {
                "day": 15,
                "month": 1,
                "year": 2024
              },
              "end_date": {
                "day": 31,
                "month": 5,
                "year": 2024
              }
            }
          ]
        }

        gradingPeriodSettings = classroom.courses().updateGradingPeriodSettings(
          courseId=course_id, body=body, updateMask='gradingPeriods',
          previewVersion="V1_20240401_PREVIEW").execute()
        return gradingPeriodSettings

    except HttpError as error:
        # Handle errors as appropriate for your application.
        print(f"An error occurred: {error}")
        return error

Manage the gradingPeriodId field on CourseWork

The CourseWork resource includes a gradingPeriodId field. You can use CourseWork endpoints to read and write the grading period associated with a CourseWork. There are three ways to manage this association:

  • automatic date-based grading period association
  • custom associated grading period
  • no grading period association

1. Date-based grading period association

When creating CourseWork, you can allow Classroom to handle the grading period association for you. To do this, omit the gradingPeriodId field from the CourseWork request. Then, specify the dueDate or scheduledTime fields in the CourseWork request. If the dueDate falls into an existing grading period date range, Classroom will set that grading period ID on the CourseWork. If the dueDate field is not specified, Classroom will determine the gradingPeriodId based on the scheduledTime field. If neither field is specified, or if there is no grading period date range match, no gradingPeriodId will be set on the CourseWork.

2. Custom associated grading period

If you would like to associate the CourseWork with a different grading period than the one that aligns with the dueDate or scheduledTime, you can manually set the gradingPeriodId field when creating or updating CourseWork. If you manually set the gradingPeriodId, Classroom won't perform the automatic date-based grading period association.

3. No grading period association

If you don't want the CourseWork to be associated with any grading period at all, set the gradingPeriodId field in the CourseWork request to an empty string (gradingPeriodId: "").

What happens to the grading period ID if the due date is updated?

If you are updating the CourseWork dueDate field and you want to preserve a custom or no grading period association, you should include the dueDate and the gradingPeriodId in the updateMask and request body. This will tell Classroom not to override the gradingPeriodId with the grading period that matches the new dueDate.

Python

body = {
  "dueDate": {
    "month": 6,
    "day": 10,
    "year": 2024
  },
  "dueTime": {
    "hours": 7
  },
  "gradingPeriodId": "<INSERT-GRADING-PERIOD-ID-OR-EMPTY-STRING>"
}
courseWork = classroom.courses().courseWork().patch(
  courseId=course_id, id=coursework_id, body=body,
  updateMask='dueDate,dueTime,gradingPeriodId', # include the gradingPeriodId field in the updateMask
  previewVersion="V1_20240401_PREVIEW").execute()