[API] Update Courses API to Allow More User Enrollment States

Problem statement:

For academic programs I help manage, we use the API to pull in a list of students in specific courses and format the data into a useable format. While I'm currently using Enrollments (https://canvas.instructure.com/doc/api/enrollments.html#method.enrollments_api.index) to create the list of students, there are some inefficacies in using that.

First, I need email addresses for each student but this can't be accessed in Enrollments - so I have to make additional API requests with the user's ID to get the email address.

Second, Enrollments returns the same user if they are enrolled in more than one section, so for some classes this is problematic since I only want the list of users and this effectively creates duplicate entries. While I'd like to use Users (https://canvas.instructure.com/doc/api/courses.html#method.courses.users) to accomplish what I'm looking to do, I'm currently not able to do that because some users have an enrollment state of "deleted" which is not an available enrollment state option under courses/users.

 

Proposed solution:

Enrollments (https://canvas.instructure.com/doc/api/enrollments.html#method.enrollments_api.index) and Course Users (https://canvas.instructure.com/doc/api/courses.html#method.courses.users) both include an option to select enrollment state. I would like to see the Allowed values for both to match.

If this is not an option, then at a minimum, it'd be nice to have Course Users allow the value of "deleted" for enrollment state. This would help solve both of my issues, having access to a complete list of users on a class, along with getting the email address more efficiently. For our program, we manage about 40 courses per term with about 30 students per course. Using Enrollments and having to also make an additional request to get email addresses, I have to make over 1,200 API requests in a short period of time to get a complete list as I need it. This could be reduced to 40 if I can use Course Users since email address is accessible there. Alternatively, email address could be added to Enrollments. I think this was there several years ago but was removed for some reason - and now I can't find the documentation on that but I think I read that several years ago.

 
User role(s):

admin

11 Comments
KristinL
Community Team
Community Team
Status changed to: Open
 
chriscas
Community Coach
Community Coach

Hi @meinhoka,

I would agree that for any api which has an enrollment_state option, we should be able to use any of the Canvas options, not be restricted to certain values for what seems like an arbitrary reason.

I would somewhat disagree with the second proposed solution of including emails in enrollments, as there are no other user attributes returned for an enrollments call right now, just the user_id.

While I have not had tome to investigate it much, I know the long-term future of API-type things in Canvas is going to be GraphQL.  It seems like GraphQL is more customizable and configurable with what it returns, but I don't think it's as fully build out as the REST API is right now.  Could be something for you to investigate though as I think it has the potential to really reduce the number of API calls you make.

-Chris

meinhoka
Community Participant
Author

@chriscas Thanks for the GraphQL idea. I took a look at what I'm hoping to do in there as well and again, enrollment states are limited here too so I still can't pull in the deleted users. I also tried the enrollmentsConnection and get the same problems of the duplicates showing up (which makes sense since users are assigned to multiple sections) but there is also not an option at all to filter by enrollment states so it seems to only return a list of users with pre-determined states - and no one who is deleted. But it will be good to keep an eye on this to see how it evolves over time.

statuses.jpg

James
Community Champion

@meinhoka 

Here are some things to consider. I'm not fully aware of your situation, so not all of them may work for you.

Are your enrollments populated via a student information system? If so, you may be able to get the lists that you need via that system rather than through Canvas.

If you're an admin, you could run the SIS or Provisioning reports and get a list of all of the enrollments  including deleted enrollments, and user information. Then you could join the tables together to get the information that you need.

If you're forced to use the API, then you could fetch the enrollments and the users for the course. That's 80 requests for your 40 courses. Then, you only need additional requests to fetch the user emails for those with deleted enrollments. You may already have those because they're in another course that they're not deleted in. In other words, If you're only talking 1200 users, I would save the data across courses rather than trying to process each course individually. I know could consume a lot of memory if you had huge numbers, but 1200 isn't that bad.

The enrollments API is costly, so I would avoid it. If you don't need the sections the student is in, then I would take the list of course users through the users API (graphQL may be faster than REST). Then I would use the REST API to get the enrollments for just those users that are deleted. Then you have 40 queries to get the course users with their emails, 40 queries to get the list of deleted users, and 1 additional query per deleted user to get the email. You can use graphQL with the legacyNode for users to get the user's email as it might be slightly quicker than using the get users endpoint for the REST API.

You may be lucky on the email. Our login IDs, which are returned with the enrollments API, are the user portion of their email address.

There may be more efficient ways, but it shouldn't take anywhere close to the 1200 API calls to get the information you need.

meinhoka
Community Participant
Author

@James Enrollments are actually populated from six different SISs and Canvas is the only common point where the courses are combined, so this is where we have to get the info from. And good suggestion on the login IDs as well. Our login IDs are just numbers, but I had found a while ago that sometimes our integration_id is the email address and sometimes it's just an actual ID with numbers so I had been using a formula to check that and if it did actually contain an email address, I used that - otherwise I initiated an API call to "Users" to get the email address based on the person's ID.

But anyway, I think I have a good solution now. After I wrote my previous response - I got to thinking along the same lines as your suggestion. I just completed updating my reports and changed it so I'm using "users" to get all the enrollment states I can get there and then I'm only using "enrollments" now for enrollment states of deleted. I'm currently debating if I really need email addresses for deleted users and if I don't, I can take that piece out and save more API calls, although I've improved things greatly by this change. I just did a complete refresh of the data and I used 250 API calls for all the pieces I need for my report. If I don't pull in email addresses of deleted users, I made 190 API calls. I'm also pulling in some course info, quiz scores, etc. into this file so that's where the additional calls are coming from. I don't know why I didn't think of that solution earlier. I guess it helped to talk it out more.

However, I still think it'd make sense that enrollment_state options should be consistent for both the GraphQL and REST API, so hopefully this idea is still considered by the developers.

peremart
Community Explorer

Hi @meinhoka in our implementation when querying Canvas REST API when we need to pull all the enrollment from a course we specify any enrollment state we need on the endpoint as an array as follows:

/enrollments?state[]=deleted&state[]=active etc....

Also, in our implementation, and we use SIS integration, the login_id, present at the enrollment object is the prefix of the student/faculty institution email.

We are currently playing with what we have on GraphQL, still very limited on available options.

Hope this help!

KristinL
Community Team
Community Team
Status changed to: New
 
KristinL
Community Team
Community Team
Status changed to: Added to Theme
 
nathanatkinson
Community Team
Community Team
Status changed to: New
 
nathanatkinson
Community Team
Community Team
Status changed to: New