Kona Jones

Assignment Submissions Report Programming

Blog Post created by Kona Jones Champion on Apr 14, 2015


Due to Financial Aid Federal Regulations our College must show the last date of attendance for dropped students. For online students we define attendance as the last date the student submitted any type of assignment in Canvas. The Business office and Financial Aid office need this information but due to the difficulty in obtaining the information from Canvas Online Learning staff was tasked with getting the information. Online Learning staff found it very time consuming to manually locate this information in Canvas, so they worked with the College’s Internet Systems Specialist to create a better way to quickly  and easily access this information. A web interface allows you to select the student and course. “Course Information” image is an example of what shows up once you select a student from the web interface.

The submission report (Example shown below) shows every assignment in the course, whether the student submitted the assignment, and the date of submission if an assignment was submitted or the due date if it wasn’t submitted.

Submission information is now so easy to access that the Business and Financial Aid offices are able to run their own reports, saving Online Learning a lot of time and energy.


What was the need for the submission report?

  • The College needed access to a list of every assignment a student submitted in the course and the date the assignment was submitted.
  • Accessing submission information, including when the assignment was submitted, in Canvas is time consuming and requires multiple clicks for every assignment the student submitted.


Fetch the Data

There are three or four API calls that are used to obtain the report.

  1. Obtain the Canvas User ID and (recommended) Canvas Course ID for the student and course if you don't already have it cached locally. I recommend storing them in your database to speed up processing. If you don't store these locally, use the Enrollments API to obtain both the course ID and student ID in one call. We cache both of these locally, so this step isn't required.
    1. If no data is returned, stop, because you won't be able to do any processing.
    2. If data is returned, then loop through it until you match the SIS ID. Then make note of the Canvas User ID and Canvas Course ID.
  2. Get the student's activity using the Analytics API. This specific call is to the Get user-in-a-course-level assignment data endpoint. This involves the Student ID, which is SISable, but it does not return the Canvas User ID with the data, so you will need to have the Canvas User ID from somewhere else.
    1. If this comes back empty, then stop because there is nothing to process. This could happen when there is a problem getting information back from the API.
    2. If a "status" field exists, make sure it's not "not found". This means there is no information for that student in that course. It also happens when a student has been deleted from a course. Stop processing.
    3. Check to see if an "errors" field exists. If it does, there was a problem. However, this can also happen when a student has been deleted from the course. Stop processing.
  3. Get a list of assignments for the course using the Assignments API. This is done through the List Assignments endpoint. This is necessary so we know what assignments are possible in the class.
  4. Get a list of submissions for that student using the Submissions API. This is done through the List submissions for multiple assignments endpoint. This API calls takes an extra parameter called 'student_ids[]', which contains a list of students IDs -- in this case, just the one. However, this needs to be the Canvas ID for the student, not the SIS ID, which the reason for obtaining that information in step 1.

Process the Data

  1. Assuming that the activities from the analytics call (step 2) doesn't contain a 'status' or 'errors' field, iterate through all of the activities. Each activity is an entry in an array. I generate a sequential integer key for each value so that I can maintain the order. You cannot sort by date because not all assignments have been submitted.
  2. Obtain the date the activity occurred and incorporate this into the key. The first part of the key is the submitted_at date, if it exists, and the second part is the sequence number of the record.
    1. If there is no "submission" field, then the key looks like "-001" or "-002".
    2. If there is a "submission.submitted_at" date, then the key will be a ISO 8061 formatted timestamp with the sequence number appended at the end.
  3. For each activity, store the assignment title, assignment_id, submission date*, score received*, and possible points. (* may not exist)
  4. If there is assignment data (step 3 of the fetch data phase), then loop through them trying to find the one that matches the assignment_id. If you find it, then save the possible submission types into the data structure started in step 3.
  5. If there is submission data (step 4 of the fetch data phase), the loop through them trying to find the one that matches the assignment and record the submission type in the data structure created in step 3.
  6. Check to see if the student has submitted the assignment. Default to "no".
    1. If there is a submission_type (found in step 5) for the assignment submission, then it's a grade due to a submission, not just a grade the faculty put into the system (like a 0 for a missing grade).
    2. If there is no submission_type (missing from step 5) then check to see if "none" is one of the allowed submission types (from step 4).
      1. If "none" is allowed and there the possible points is positive, then look at the score received. If the score greater than 0, then count that as a submission. otherwise mark it as "Unknown" since we don't know whether the 0 came from failing miserably on the assignment or from not completing the assignment at all.
      2. If "none" is allowed and the possible points is 0, then just record it as "Ungraded"
    3. Add the submission summary (step a or b) to the data structure.
    4. If the submission summary is "No", then make the date to put in the key as the due date of the assignment and also record this in the data structure so we can distinguish "due at" from when it was submitted.
  7. Save the data structure into an array, keyed by the date/sequence key.
  8. Repeat steps 1-7 for all activity from the analytics report.
  9. Reverse sort the data based on the key, which is composed of a timestamp and a sequential number. This puts all the the submitted stuff at the top with the newest first and all the unsubmitted assignments at the bottom. This allows the person reading the report to see right away what the student did last.
  10. Generate the report.

API Calls


  1. Enrollments: List Course Enrollments (not needed if you cache Canvas IDs locally)
    GET /api/v1/courses/:course_id/enrollments
  2. Analytics: Get user-in-a-course-level assignment data
    GET /api/v1/courses/:course_id/analytics/users/:student_id/assignments
  3. Assignments: List Assignments
    GET /api/v1/courses/:course_id/assignments
  4. Submissions: List submissions for multiple assignments
    GET /api/v1/courses/:course_id/students/submissions

Contact Information

Kona Jones, Director of Online Learning

James Jones, Internet System Specialist & Professor of Mathematics