Are your users using Classroom with Google Meet? Check out the Apps Script quickstart covering how to check student attendence in Google Meet courses.

Manage Classwork

Classroom has five types of Classwork: Assignments, Quiz Assignments, Questions (short answer and multiple choice), Materials, and Topics. The Classroom API currently allows developers to read and write two of these types: Assignments and Questions.

To access this functionality, you can use the CourseWork resource, which represents an Assignment or Question that has been assigned to students in a particular course, including any additional materials and details, like due date or max score.

In addition to the CourseWork resource, you can manage completed assignments with the StudentSubmission resource. The following sections describe these in more detail.

Create assignments

Assignments can only be created on behalf of the course's teacher(s) and attempting to create assignments in a course on behalf of a student will result in a 403 PERMISSION_DENIED error. Likewise, domain admins also cannot create assignments for courses they do not teach and attempting to do so through the API will also result in a 403 PERMISSION_DENIED error.

When creating assignments you can attach links as materials, shown in the sample code below:

Python

classroom/snippets/classroom_snippets.py
coursework = {
    'title': 'Ant colonies',
    'description': '''Read the article about ant colonies
                      and complete the quiz.''',
    'materials': [
        {'link': {'url': 'http://example.com/ant-colonies'}},
        {'link': {'url': 'http://example.com/ant-quiz'}}
    ],
    'workType': 'ASSIGNMENT',
    'state': 'PUBLISHED',
}
coursework = service.courses().courseWork().create(
    courseId=course_id, body=coursework).execute()
print('Assignment created with ID {%s}' % coursework.get('id'))

The result includes a server-assigned identifier that can be used to reference the assignment in other API requests.

To include linked materials in an assignment created via the Classroom API, use a Link resource, specifying the target URL. Classroom automatically fetches the title and thumbnail image. The Classroom API also natively supports Drive and YouTube materials, which can included with a DriveFile resource or YouTubeVideo resource in a similar way.

To specify a due date, set the dueDate and dueTime fields to the corresponding UTC time. The due date must be in the future.

Retrieve assignments and questions

You can retrieve assignments and questions for students and teachers of the corresponding course or by a domain administrator. To retrieve a specific assignment or question, use courses.courseWork.get. To retrieve all assignments or questions (optionally matching some criteria), use courses.courseWork.list.

The required scope depends on the role that the requesting user has in the course. If the user is a student, use one of the following scopes:

  • https://www.googleapis.com/auth/classroom.coursework.me.readonly
  • https://www.googleapis.com/auth/classroom.coursework.me

If the user is a teacher or a domain administrator, use one of the following scopes:

  • https://www.googleapis.com/auth/classroom.coursework.students.readonly
  • https://www.googleapis.com/auth/classroom.coursework.students

Having permission to retrieve an assignment or question does not imply permissions to access materials or material metadata. In practice, this means that an administrator may not see the title of an attached Drive file if they're not a member of the course. If you want to allow administrators access to user files, see the domain-wide delegation guide.

Manage student responses

A StudentSubmission resource represents the work done and grade of a student for an assignment or question. A StudentSubmission resource is implicitly created for each student when a new question or assignment is created.

The following sections explain common actions that manage student responses.

Retrieve student responses

Students can retrieve their own submissions, teachers can retrieve submissions for all students in their courses, and domain administrators can retrieve all submissions for all students in their domain. Each student submission is assigned an identifier; if you know the identifier, use courses.courseWork.studentSubmissions.get to retrieve it.

Use courses.courseWork.studentSubmissions.list to get StudentSubmission that match some criteria, as shown in the following sample:

Python

classroom/snippets/classroom_snippets.py
submissions = []
page_token = None

while True:
    coursework = service.courses().courseWork()
    response = coursework.studentSubmissions().list(
        pageToken=page_token,
        courseId=course_id,
        courseWorkId=coursework_id,
        pageSize=10).execute()
    submissions.extend(response.get('studentSubmissions', []))
    page_token = response.get('nextPageToken', None)
    if not page_token:
        break

if not submissions:
    print('No student submissions found.')
else:
    print('Student Submissions:')
    for submission in submissions:
        print("%s was submitted at %s" %
              (submission.get('id'),
               submission.get('creationTime')))
submissions = []
page_token = None

while True:
    coursework = service.courses().courseWork()
    response = coursework.studentSubmissions().list(
        pageToken=page_token,
        courseId=course_id,
        courseWorkId="-",
        userId=user_id).execute()
    submissions.extend(response.get('studentSubmissions', []))
    page_token = response.get('nextPageToken', None)
    if not page_token:
        break

if not submissions:
    print('No student submissions found.')
else:
    print('Complete list of student Submissions:')
    for submission in submissions:
        print("%s was submitted at %s" %
              (submission.get('id'),
               submission.get('creationTime')))

Retrieve student submissions that belong to a particular student by specifying the userId parameter, as shown in the following sample:

Python

classroom/snippets/classroom_snippets.py
submissions = []
page_token = None

while True:
    coursework = service.courses().courseWork()
    response = coursework.studentSubmissions().list(
        pageToken=page_token,
        courseId=course_id,
        courseWorkId=coursework_id,
        userId=user_id).execute()
    submissions.extend(response.get('studentSubmissions', []))
    page_token = response.get('nextPageToken', None)
    if not page_token:
        break

if not submissions:
    print('No student submissions found.')
else:
    print('Student Submissions:')
    for submission in submissions:
        print("%s was submitted at %s" %
              (submission.get('id'),
               submission.get('creationTime')))

Students are identified by the unique ID or email address of the user, as returned by the Google Admin SDK. The current user may also refer to their own ID using the "me" shorthand.

It's also possible to get student submissions for all assignments within a course. To do so, use the literal "-" as the courseWorkId, as shown in the following sample:

Python

service.courses().courseWork().studentSubmissions().list(
    courseId=<course ID or alias>,
    courseWorkId='-',
    userId=<user ID>).execute()

The required scope depends on the role that the requesting user has in the course. Use the following scope if the user is a teacher or a domain administrator:

  • https://www.googleapis.com/auth/classroom.coursework.students.readonly
  • https://www.googleapis.com/auth/classroom.coursework.students

Use the following scope if the user is a student:

  • https://www.googleapis.com/auth/classroom.coursework.me.readonly
  • https://www.googleapis.com/auth/classroom.coursework.me

Having permission to retrieve a student submission does not imply permissions to access attachments or attachment metadata. In practice, this means that an administrator may not see the title of an attached Drive file if they're not a member of the course. If you want to allow administrators access to user files, see the domain-wide delegation guide.

Adding attachments to a student response

You can attach links to a student submission by attaching a Link, DriveFile, or YouTubeVideo resource. This is done with courses.courseWork.studentSubmissions.modifyAttachments, as shown in the following sample:

Python

classroom/snippets/classroom_snippets.py
request = {
    'addAttachments': [
        {'link': {'url': 'http://example.com/quiz-results'}},
        {'link': {'url': 'http://example.com/quiz-reading'}}
    ]
}
coursework = service.courses().courseWork()
coursework.studentSubmissions().modifyAttachments(
    courseId=course_id,
    courseWorkId=coursework_id,
    id=submission_id,
    body=request).execute()
guardian_invitation = {
    'invitedEmailAddress': 'guardian@gmail.com',
}
guardian_invitations = service.userProfiles().guardianInvitations()
guardian_invitation = guardian_invitations.create(
    # You can use a user ID or an email address.
    studentId='student@mydomain.edu',
    body=guardian_invitation).execute()
print("Invitation created with id: {%s}"
      % guardian_invitation.get('invitationId'))

A Link attachment is defined by the target URL; Classroom will automatically fetch the title and thumbnail image. You can learn about the other materials at their respective reference pages.

Materials can be created by a course teacher or by the student that owns the corresponding student submission, but only for student submissions with a courseWorkType of "ASSIGNMENT".

The required scope depends on the role that the requesting user has in the course. Use the following scope if the user is a teacher:

  • https://www.googleapis.com/auth/classroom.coursework.students

Use the following scope if the user is a student:

  • https://www.googleapis.com/auth/classroom.coursework.me

Manage student response state

A student response may be unsubmitted, turned in, or returned. The state field in StudentSubmission indicates the current state. To change the state, call one of the following methods:

All of these methods take an empty body. Example:

Python

service.courses().courseWork().studentSubmission().turnIn(
    courseId=<course ID or alias>,
    courseWorkId=<courseWork ID>,
    id=<studentSubmission ID>,
    body={}).execute()

Only the student that owns a StudentSubmission may turn it in or reclaim it. Only a turned in submission may be reclaimed. Course teachers can only return a StudentSubmission that is in the turned in state.

Grade student responses

The StudentSubmission resource has two fields to store grades: assignedGrade, which is the grade reported to students, and draftGrade, which is a tentative grade visible only to teachers. These fields are updated using courses.courseWork.studentSubmissions.patch with a field mask containing the appropriate fields, as shown in the following sample.

Python

studentSubmission = {
  'assignedGrade': 99,
  'draftGrade': 80
}
service.courses().courseWork().studentSubmissions().patch(
    courseId=<course ID or alias>,
    courseWorkId=<courseWork ID>,
    id=<studentSubmission ID>,
    updateMask='assignedGrade,draftGrade',
    body=studentSubmission).execute()

When working with the Classroom UI, teachers can't assign a grade until they have first saved a draft grade. The assigned grade can then be returned to a student. Applications need to emulate this behavior. Your application can grade a student's assignment in one of two ways:

  • Assign just the draftGrade. This is useful, for example, to let the teacher manually review grades before finalizing them. Students cannot see draft grades.

  • Assign both the draftGrade and assignedGrade to fully grade an assignment.