Use API to Copy specific Assignments from one course to multiple courses

Jump to solution
Community Explorer

Hi Everyone - i'm a definite API novice and I'm hoping someone might be able to give me some tips.

I have used Postman in the past to bulk migrate a source course into multiple courses using a simple POST URL with a "course" variable and a CSV with the list of the Canvas IDs for the destination courses. 

What I want to do this time is a little more involved. I would like to copy one specific assignment into multiple other courses. But ideally set this up so I could use "assignment ID" and "destination id" variables to do this en masse for several different assignment that will go into multiple courses. 

For a better illustration, let's say in a single source course I have a whole bunch of assignments, each one corresponding with a different academic course. 

MATH 101  - Final Exam (Canvas Assignment ID: 0000001)
MATH 201 - Final Exam (Canvas Assignment ID: 0000002)

We use a 1-to-1 courses/sections setup at our campus, so let's say for the Fall 23 term there are three separate course shells for each:

Fall23 MATH 101 #34567 (Canvas Course ID: 987654)
Fall23 MATH 101 #34568 (Canvas Course ID: 876543)
Fall23 MATH 101 #34569 (Canvas Course ID: 765432)
Fall23 MATH 201 #34570 (Canvas Course ID: 654321)
Fall23 MATH 201 #34571 (Canvas Course ID:  543210)
Fall23 MATH 201 #34572 (Canvas Course ID: 432109)

My hope is that I can create a POST function that will copy Assignment ID 0000001 into the first three courses, and so on.  So i Imagine the data CSV would end up look something like:

assignment_id, destination_course_id
0000001, 987654
0000001, 876543
0000001, 765432
0000002, 654321
0000002, 543210
0000002, 432109

However, I can't seem to find any info about how to create a command to actually process this. 

Would love any thoughts or ideas or resources that might help. Thanks so much!

1 Solution
Community Champion


I don't use PostMan, so I cannot help with the CSV portion, but you will also need the source course ID and potentially the destination module ID and destination assignment group ID.

One trick I use a lot when I cannot figure out something from the documentation is to look at what Canvas does and then recreate that request. I'll describe how to do this within Chrome.

Go the page where you want to initiate the assignment copy (either the assignments page or the assignment itself). Press F`12 to open the Developer Tools and then switch to the Network tab. Normally you're safe to select Fetch/XHR and it cuts down on the number of requests, but you can also clear the requests lists right before you make the new request.

Now click on the more options (three vertical dots) button and choose Copy To. Type in the name of the first destination course and then select it after Canvas finds it. Fill in the module information and where to place it if appropriate.

At this point, I may clear the requests before hitting the Copy button. This clears out any extraneous information so I can focus on what is important. It's the circle with the slash through it at the top next to the red circle for record.

Now I hit Copy.

Look for the new request that was made. In this case, it is content_migrations. Select it from the Name column.

Now click on Headers on the right side. The Request URL will tell you what URL to use and the Request Method will tell you whether it is a GET or POST. We already knew this one would be a POST since we were creating new content. The Request URL is instance/api/courses/:course_id/content_migrations. The :course_id, is the destination course ID, not the source course ID.

Sometimes knowing the URL is enough to find the documentation and figure things out. That particular URL is for the Create a content migration endpoint, but the options may not be clear.

Now click on Payload. We have a JSON object that shows what Canvas sends. The documentation can help you understand what it is doing and possible lead you to a more intelligent copy.


  "migration_type": "course_copy_importer",
  "select": {
    "assignments": [
  "settings": {
    "source_course_id": "3646256",
    "insert_into_module_id": "834172",
    "insert_into_module_type": "assignments",
    "insert_into_module_position": null


For me, the assignment number that I am copying is is 39452860. This would be your assignment_id parameter. Under the settings, the source_course_id is the ID for the course that you are copying from. That's why I said you would need to add the source course ID to your CSV file.

The module information is optional if you just want to copy the assignment to the course and then later go through and clean it up. This is fairly well defined in the API documentation.

  • insert_into_module_id is the ID of the destination module.
  • insert_into_module_type is not necessary according to the documentation. It allows you to copy just assignments, discussions, files, content pages, or quizzes. Since you are selecting an individual assignment to copy, you wouldn't need to filter the type.
  • insert_into_module_position is an index (starting with 1) of where to place it into the module. This may be tricky if not first (1) or last (null). If it varies by destination course, then the position may need to be another parameter that you need.

What you don't get from the request Canvas made is that there are other options you may want to use.

By default, Canvas dumps everything into the "Imported Assignments" assignment category. I use descriptive assignment group names and "Imported Assignments" is not one of them. There is a move_to_assignment_group_id setting that controls where the assignment ends up. If you want to place it into a specific assignment group, then this is another parameter that you would have to include in your CSV file.

If you already had a Final Exam in your destination course that was created by copying the original course, then you may not need to do any clean-up. Canvas will override the existing assignment rather than creating a duplicate. If there was no Final Exam in the destination course or if it was created manually and not copied from the same source, then you will probably end up with some clean-up tasks.

Here are some parting thoughts.

I teach math at a small institution where each faculty develops their own content. For people like me, copying assignments from one course to another is rare. About the only time I use it is when I need to grab an assignment from years ago to reuse it in the current term. It's quicker for me to use the web interface than try to automate it -- even though I'm a person who hates repetitive clicks.

Some institutions have enough courses that they would want to automate this (or use blueprint courses). Those institutions are are going to want to do something other than use a REST client. REST clients are great for testing, but there is a lot of looking up of items to populate your CSV file. If this is a major or recurring process and you have so many of those that you have want to automate it, then you will also want to write a program that does all the looking up of the information so you don't have to manually create the CSV. If you're writing a program to look up the information, you might as well use that program to initiate the requests and handle the clean-up work rather than trying to use a REST client.

View solution in original post