@todd_vernon
Sorry, I missed the "quiz" part the first time around. In the end, it doesn't matter.
I went into SpeedGrader and changed a grade on a quiz to see what it would do. It used a non-API call to make the change.
The AJAX call was to /courses/:course_id/gradebook/update_submission (notice the lack of /api/v1 in front)
It was a POST and the information passed was
{
"submission":{
"assignment_id":"8499046",
"user_id":"3346297",
"graded_anonymously":"false",
"grade":"12"
}
}
Now what we need to do is figure out if there is an API way to replicate that call.
What Canvas is not using is the Update student question scores and comments endpoint of the Quiz Submissions API. The description there is sounds promising:
Update the amount of points a student has scored for questions they've answered, provide comments for the student about their answer(s), or simply fudge the total score by a specific amount of points.
It might be accomplished that way, but the test account I'm using didn't actually submit the quiz, I was just giving them a score. But the 12 stuck.
I then made a PUT to /api/v1/courses/896851/assignments/8499046/submissions/3346297 with a payload of
{
"comment": {
"text_comment": "Great Job"
},
"submission": {
"posted_grade": "5"
}
}
and the grade changed.
That means that the Grade or comment on a submission endpoint of the Submissions API is the one to use and that it works for quizzes that haven't been taken as well as other assignments.
Then I went to a quiz that had been taken. Maybe things were different there? The ability to manually enter a score is grayed out in SpeedGrader. All I can do is adjust the point values for the questions or the fudge points and then it automatically calculates the score. I know from the past that adjusting a grade in the Gradebook will adjust the fudge points, so I went there to see what happened on the backend when I made the call.
The assignment ID is 13300109 and we're looking at the same test account as before (3346297)
This time it actually made an API PUT call: /api/v1/courses/896851/assignments/13300109/submissions/3346297
If you look look at that, you will see it is the exact same call (just with a different assignment ID). In other words, the Grade or comment on a submission is what the gradebook is using to make the change.
What's different, though, is the payload.
{
"submission":{
"assignment_id":"13300109",
"user_id":"3346297",
"posted_grade":1
},
"include":[
"visibility"
]
}
Back in SpeedGrader / Quiz Moderation, it adjusted the fudge points so the score came out to be 1.
The assignment_id and user_id portion aren't documented and they are included in the pathname, so are they redundant? I tried it with just the submission.posted_grade portion (not even the include.visibility) and when I reloaded SpeedGrader, the score had been updated.
In other words, we have the right API call.
Things to check:
- Make sure the API token is for someone who can manage the grades. If you can do it through the web interface but not the API, it might be that you're using the wrong token. You can check this by using POSTMAN to do a GET /api/v1/users/self (no query parameters) and make sure it's who you think it is.
- Make sure POSTMAN is set to PUT and not GET and that you're formatting the body correctly as JSON and that you're including the header for Content-Type: application/json. I use Advanced Rest Client (ARC) instead of Postman. Hopefully POSTMAN will automatically add that content-type header for you when you tell it to use JSON.
- Go to the Canvas live API, which is your base URL + /doc/api/live. Add your access token at the top. Scroll down to Submissions and expand it and pick the course version of Grade of comment on a submission. Fill in the course_id, assignment_id, user_id, and submission[posted_at]. It will show you the call it makes. If it works here, then it's likely a Postman issue or something with the formatting of the JSON.
- You can check your JSON is valid JSON (not the same as something that Canvas will recognize) by going to an online JSON formatter. I use the one at JSON Formatter & Validator at CuriousConcept.com. For example, if I use single quotes around the score, it warns me about incorrect quotes and will fix it for me.
When sending JSON, I have Authorization, Accept, and Content-Type headers. I tell ARC my body content-type is application/json and put in the JSON. It automatically updates the Content-Type for me. It works for me with or without a content-length header.