Register for InstructureCon25 • Passes include access to all sessions, the expo hall, entertainment and networking events, meals, and extraterrestrial encounters.
Found this content helpful? Log in or sign up to leave a like!
I am using the API to list course migrations for my institution. The idea is to see which recently created courses have not had any content migrated into them, and then automatically do the migration.
NB in the Canvas GUI, the procedure I am referring to is Settings > Import Module Content, but as far as I can tell, in the context of the API itself, this is called a "Migration" (the term also seems to be used for transferring content from another LMS, but I don't think that is the meaning in the context of the API).
See my code Python below.
For the particular account I am picking up hundreds of courses using the courses API call, but when I try to list content migrations, there are none. Given that content migrations happen every year, this does not seem right. I am wondering what's happening here.
Thanks
PS thanks to this post which helped me to sort out the pagination issue. It was very hard to wrap my head around. NB I needed to tweak the code to get it to work.
import requests
import json
import os
from dotenv import load_dotenv
from io import BytesIO
import pandas as pd
os.chdir("/path/to/folder")
# GET BASE URL AND ACCESS TOKEN (NB client_id and secret are not needed)
load_dotenv(dotenv_path="/path/to/folder.env")
base_url = os.getenv('XXXX_CANVAS_BASE_URL')
access_token = os.getenv('XXXX_CANVAS_ACCESS_TOKEN') #
headers = {
'Authorization': f'Bearer {access_token}'
}
# CREATE FUNCTION REQUESTS_GET. IT HANDLES THE PAGINATINO
def requests_get(base_url, resource_url, headers, params):
r = requests.get(base_url + resource_url, params=params, headers=headers)
raw = r.json()
data_set = []
for x in raw: # identifies each entry
data_set.append(x)
while not 'last' in r.links:
r = requests.get(r.links['next']['url'], headers=headers, params=params)
raw = r.json()
for x in raw:
data_set.append(x)
return(data_set)
resource_url = "/api/v1/accounts/1/courses" # API call
parameters = {"search_term" : "2025","per_page" : "100"}
courses = requests_get(base_url=base_url,
resource_url=resource_url,
params=parameters,
headers=headers)
resource_url = "/api/v1/accounts/1/content_migrations"
parameters = {"per_page" : "100"}
migrations = requests_get(base_url=base_url,
resource_url=resource_url,
params=parameters,
headers=headers)
Solved! Go to Solution.
Ahhh. I think I've got it. There is a different resource URL: GET /api/v1/audit/course/accounts/:account_id which is described at https://developerdohttps://developerdocs.instructure.com/services/canvas/file.all_resources/course_a... . This seems to provide the information I want. It hangs as I probably need to give a very tight time window, otherwise it tries to access years worth of data!
Ahhh. I think I've got it. There is a different resource URL: GET /api/v1/audit/course/accounts/:account_id which is described at https://developerdohttps://developerdocs.instructure.com/services/canvas/file.all_resources/course_a... . This seems to provide the information I want. It hangs as I probably need to give a very tight time window, otherwise it tries to access years worth of data!
Similar to that endpoint, I have used the Course Audit - Query by Course endpoint to find out which courses received blueprint content and which blueprint it received. This sometimes required a chain of requests if a course was reset to apply a personalized copy of an old course instead of the expected blueprint since I would need to check the old Canvas course ID to get the details about the old version of the course.
I see that in your original code, you are looking at courses in a specific term. In addition to using start and end dates, you may find that making the request by course rather than account might be better to avoid getting results for courses that you don't need.
As a side note, to keep an eye on the status of the requests, you might consider including print statements or using a logger to give updates as the script runs. This can help clarify if it is still making requests (and any details you want to see while it is processing) and helps to let you know that it is still running. By getting the courses and using the course query, you could also include a count (i.e. x of TOTAL) to make it more obvious how many course audit requests have completed so far and how many total requests are expected.
Cheers. I m still learning the ropes, and have so far experimented with only single API calls. I think the endpoint I mentioned gives me all of the data I need, but I'll look into that alternative endpoint. Once I start running more complex queries, I'll think about using a logger.
To interact with Panda Bot in the Instructure Community, you need to sign up or log in:
Sign In