How to create multiple-choice questions via the API

414 views
Skip to first unread message

cfbm...@gmail.com

unread,
Feb 16, 2017, 5:34:36 PM2/16/17
to Canvas LMS API Users
Hi all,

I'm new to Canvas and to the API, and I'm tasked with migrating quizzes from another system to our Canvas instance. Mostly these are multiple choice questions. I can create questions via the API, but I haven't been able to do so if I include the answers. Here's an example JSON for a question I created manually, minus the Canvas-created IDs and empty values and null values:


{
 
"points_possible": 10.0,
 
"neutral_comments_html": "<p>mojito ergo sum</p>",
 
"correct_comments_html": "<p>Yea and verily</p>",
 
"question_text": "<p>This is a multiple choice question.</p>",
 
"incorrect_comments_html": "<p>plz no do not want</p>",
 
"question_type": "multiple_choice_question",
 
"quiz_id": 4683,
 
"question_name": "Question",
 
"answers": [
   
{
     
"weight": 100.0,
     
"text": "This is the correct answer.",
     
"comments_html": "<p>Well done!</p>"
   
},
   
{
     
"weight": 0.0,
     
"text": "Nahh.",
     
"comments_html": "<p>Nope. Nuh-uh.</p>"
   
},
   
{
     
"weight": 0.0,
     
"text": "Nacho cheese.",
     
"comments_html": "<p>Not in this lifetime.</p>"
   
},
   
{
     
"weight": 0.0,
     
"text": "Don't even look at it.",
     
"comments_html": "<p>Not now. Not ever.</p>"
   
}
 
],
 
"quiz_group_id": 2766,
 
"assessment_question_id": 109,
 
"position": 1
}



When I adapt it to function as the POST data for an API call to create a question, e.g. by wrapping the object keys in "question[...]", I get an internal server error (500) response from the server. Here's the data I posted:

{
 
"question[incorrect_comments_html]": "<p>plz no do not want</p>",
 
"question[question_text]": "<p>This is a multiple choice question.</p>",
 
"question[quiz_id]": 4683,
 
"question[points_possible]": 10.0,
 
"question[correct_comments_html]": "<p>Yea and verily</p>",
 
"question[neutral_comments_html]": "<p>mojito ergo sum</p>",
 
"question[assessment_question_id]": 109,
 
"question[question_type]": "multiple_choice_question",
 
"question[position]": 1,
 
"question[question_name]": "Question",
 
"question[answers]": [
   
{
     
"text": "This is the correct answer.",
     
"comments_html": "<p>Well done!</p>",
     
"weight": 100.0
   
},
   
{
     
"text": "Nahh.",
     
"comments_html": "<p>Nope. Nuh-uh.</p>",
     
"weight": 0.0
   
},
   
{
     
"text": "Nacho cheese.",
     
"comments_html": "<p>Not in this lifetime.</p>",
     
"weight": 0.0
   
},
   
{
     
"text": "Don't even look at it.",
     
"comments_html": "<p>Not now. Not ever.</p>",
     
"weight": 0.0
   
}
 
],
 
"question[quiz_group_id]": 2766
}



If I leave the `question[answer]` array empty, I can create the question. But with over 18000 multiple choice questions to migrate for just one semester's worth of courses, that leaves a tremendous amount of work to be done manually.

I've found hints in the groups and in the Canvas feature ideas forum that the API doesn't cover this functionality yet:

https://groups.google.com/d/msg/canvas-lms-users/U9XJtmwXLTk/xj0S21K1BIMJ
https://community.canvaslms.com/ideas/2348

This feature idea suggests that it is possible, but I can't make out from its text how it works:

https://community.canvaslms.com/ideas/2348

The API docs themselves are silent on the matter.

Has anyone succeeded in creating multiple choice questions with answers via the API? If so, would you kindly set me straight on how to format the JSON payload to accomplish this?

Many thanks,
Chuck

cfbm...@gmail.com

unread,
Feb 17, 2017, 11:17:32 AM2/17/17
to Canvas LMS API Users
I overlooked a clue in one of the comments on the Canvas Idea #2348. If, instead of using the `data` parameter to the Python requests POST method, I use `json` instead, and package my question/answer data like so:

{
 
"access_token": "for me to know & you to find out",
 
"question": {

   
"question_text": "<p>This is a multiple choice question.</p>",

   
"points_possible": 10.0,
   
"neutral_comments_html": "<p>mojito ergo sum</p>",
   
"incorrect_comments_html": "<p>plz no do not want</p>",
   
"answers": [

     
{
       
"text": "This is the correct answer.",
       
"comments_html": "<p>Well done!</p>",
       
"weight": 100.0
     
},
     
{
       
"text": "Nahh.",
       
"comments_html": "<p>Nope. Nuh-uh.</p>",
       
"weight": 0.0
     
},
     
{
       
"text": "Nacho cheese.",
       
"comments_html": "<p>Not in this lifetime.</p>",
       
"weight": 0.0
     
},
     
{
       
"text": "Don't even look at it.",
       
"comments_html": "<p>Not now. Not ever.</p>",
       
"weight": 0.0
     
}
   
],

   
"correct_comments_html": "<p>Yea and verily</p>",
   
"assessment_question_id": 109,
   
"question_type": "multiple_choice_question",
   
"position": 1,
   
"question_name": "Question",
   
"quiz_group_id": 2766,
   
"quiz_id": 4683
 
}
}

then it works. I have yet to try this model with other question types, but I'm uncharacteristically optimistic.

Thanks to David O'Gwynn and his comment on the Canvas Ideas site:
https://community.canvaslms.com/ideas/2348#comment-72314

All the best,
Chuck

gb8...@gmail.com

unread,
Dec 20, 2018, 8:50:14 PM12/20/18
to Canvas LMS API Users
So I might be a little late to the party, but this is because canvas expects the content-type of the request to be set to application/json in the request headers. When you use data=... with requests.post, it doesn't put that in the headers. When you use json=..., it does that for you. I could be wrong as to your specific case, but I am currently working through this exact problem and using data=... When I specify conetent type in the headers, it works. 
Reply all
Reply to author
Forward
0 new messages