The Instructure Community will enter a read-only state on November 22, 2025 as we prepare to migrate to our new Community platform in early December.
Read our blog post for more info about this change.
I am working with the Canvas API to populate Canvas courses with data from a different LMS. We have been able to create the course, populate the membership, and pull in assignments.
Where I'm stuck is in pushing over grade data. I am doing this by creating a submissions for a given assignment for a given student, and setting a grade. I add parameter as_user_id=sis_user_id:xxx where xxx is the sis_user_id of a professor in the course. But I am getting an 'unauthorized' error. I also tried using the sis_user_id of the relevant student, but got the same 'unauthorized' error.
My questions are:
1. What permissions do I need to be aware of, or somehow address to be able to set grades/create submissions via the API?
2. To bring grades over, would the appropriate steps be to just create a Submission via a POST and include the grade, or do I need to create a submission via a POST, and then make a PUT call to update it to set the grade?
3. As an alternative, the update_grades call seemed a good way to potentially make a single bulk call. However I was unable to get this working either -- I'm not even entirely clear in what format that data should be passed -- is it simple text rather than json? I was testing in postman, but got an internal server error, so clearly I am not sending data in the correct format (error_report_id": 1052166532)
curl 'https://<canvas>/api/v1/courses/1/assignments/2/submissions/update_grades' \ -X POST \ -F 'grade_data[3][posted_grade]=88' \ -F 'grade_data[4][posted_grade]=95' \ -H "Authorization: Bearer <token>"Any suggestions would be greatly appreciated!
Robin Colodzin
If you have admin permissions, you don't need to make the call as the instructor. If you have the permissions to masquerade as the user, then you probably have permissions to update the grades.
The unauthorized error is possibly due to you not having the correct IDs. If you are using the 1, 2, 3, or 4, which is what Canvas shows in their grade or comment on multiple submissions endpoint of the Submissions API documentation, then you are almost certainly going to get this error.
If any of the three IDs (course_id, assignment_id, or student_id) are incorrect, then you could be getting the unauthorized error since that course, assignment, or student potentially belongs to some one else. This is especially true when you're not self-hosting (you didn't say whether you were or not).
You also need to make sure to use the instance of your Canvas, not the free for teachers shown in the example.
The call should look something like this:
POST richland.instructure.com/api/v1/courses/896851/assignments/10638275/submissions/update_grades?grade_data[3346297][posted_grade]=2
Of course, this needs changed to your values, you will get an unauthorized error if you try it directly.
The student_id=3346297 (I don't know that you can use the SIS student ID here, but it would look like sis_student_id:123456 if you could), the Canvas assignment ID is 10638275, the Canvas course ID is 896851, and the student received a grade of 2.
You can repeat that form data multiple times, once for each student. The example given in the Canvas API documentation shows updating the grade for two students.
You are welcome to use command line CURL, as shown in the example, but most people use a library for whatever programming language they're using.
You make that POST and include the form data as a query parameter as shown above. Technically, you should probably URI encode the query parameter so that [ becomes %5B and ] becomes %5D, but it works as it is.
I don't use Postman, but the basics are the same no matter what program you use. You should not be sending this as JSON unless you also send the correct headers to tell it that the content-type is application/json. If you are using form-data, then it uses a key=value combination. The key would be grade_data[3346297][posted_grade] and the value would be 2.
If you want to use JSON, then it should look like this (I think, I just typed this up without testing it).
{
"grade_data":{
"3346297":{
"posted_grade":2
}
}
}
Thanks so much, this is very helpful. One more question – does a submission need to already exist to set a grade? Or can I set a grade for a student on an assignment using info below, with no submission yet created?
You can use the API call to update grades for students who are missing an assignment. You do not have to upload a file or submit something for them first. This call is essentially a way to automate what would happen if you were in the gradebook and manually entered a grade for someone, they don't have to have a submission there to put a grade in.
Some explanation:
In Canvas, a submission record exists for any item (student/assignment combination) that's in the gradebook. In fact, the gradebook loads the submission entries to display the gradebook. These records are automatically created when you create assignments or add new students. It's possibly a background task but it should be available almost immediately.
It sounds like you mean submission to be the student actually submitting something. This is not the same as what Canvas considers a submission. Canvas considers this "missing" when a student has not made a submission.
In the case that a student is missing an assignment, Canvas's submission record indicates they haven't submitted an assignment. To Canvas, they still have a submission record that you can modify.
A note on classic quizzes -- setting a grade when there is a quiz submission will adjust the fudge points. I have not tested it for a missing quiz.
Ok, that clears up some of my misunderstanding, thank you.
I am still getting an ‘unauthorized’ error. I’m going in as an admin user – I’m able to create courses, and create assignments as this user, so clearly an admin.
I am hitting our instance, and confirmed that the course and assignment ids are valid – doing a GET with the following returns the expected assignment:
https://mit.test.instructure.com/api/v1/courses/2193/assignments/21251
But, when I try to do the following POST, I am back to ‘unauthorized’. The student id is a valid student in the course. I have tried both the user_id and the sis_user_id. Same result either way.
https://mit.test.instructure.com/api/v1/courses/2193/assignments/21251/submissions/update_grades?grade_data[87384][posted_grade]=40
Could the issue be something to do with permissions on my admin user?
More to the point, are there logs that would help me better understand why this is failing?
Thanks again for your help.
Here are some general troubleshooting ideas, you've covered some of them, but I repeat for others coming along later who may have a similar problem.
Are the course / assignment / and student valid in the test instance of Canvas? The test instance is only updated once a month. The last update was February 15, the next one is March 21. The dates are available on the Canvas Updates Calendar (Google)
If you created the courses in the production instance of Canvas, they will have the same IDs when transferred over to test, but they won't get transferred until the dates above. Similarly, if the student or assignments were added after February 15, they won't be in the test instance yet. Try GET /api/v1/courses/2193/users and make sure the student is in the course. You may need to add ?per_page=100 if you have more than 10 students.
You can try to fetch the submission for the student rather than posting it. Try GET /api/v1/courses/2193/assignments/21251/submissions?include[]=user and see if the student is listed.
Another possibility is that you created an access token in the production instance after February 15. That access token will work in the test instance but only after the test instance has been updated on March 21. For right now, you would need an access token generated in the test instance. I don't think this is the reason since you said were able to create courses.
One other thing I can think of is whether you are a root admin or a subaccount admin? If you are a subaccount admin, then it may not be set up for you to change grades, even though you could create assignments and read them. See What user roles and permissions are available in Canvas? and in particular, the Canvas Course Role Permissions and Canvas Account Role Permissions that is linked in the blue section at the top. There is a section on "Sub-Account Permissions and Settings" in the account one and there are some things that sub-account admins cannot do that root admins cannot do. Permissions are interwoven. For example, the ability to see the grade history may be tied to the ability to edit grades and subaccount admins can't see the grade history.
I suspect it must be an issue with permissions on my account, which is indeed a sub-account.
Checking submission on a single user returns data, so I know student is valid:
https://mit.test.instructure.com/api/v1/courses/2193/assignments/21262/submissions/3815
Thanks again for the help, and thorough documentation of troubleshooting path. I’ve reached out to administrators of our system to explore permissions on our subaccount.
Robin Colodzin
It turns out my issue was due to the assignment not being published.
Had to do an update on the assignment as below, and then call to set grades worked.
PUT https://mit.test.instructure.com/api/v1/courses/2193/assignments/21252?assignment[published]=true
Then did a post with json body with all the grade data.
POST https://mit.test.instructure.com/api/v1/courses/2193/assignments/21252/submissions/update_grades
{
grade_data: {
'3757': { posted_grade: '66.00' },
'3815': { posted_grade: '86.00' },
'11226': { posted_grade: '95.00' },
'20329': { posted_grade: '32.00' },
'57323': { posted_grade: '97.00' },
'57428': { posted_grade: '87.00' },
'57936': { posted_grade: '94.00' },
'59518': { posted_grade: '87.00' }
}
}
Community helpTo interact with Panda Bot, our automated chatbot, you need to sign up or log in:
Sign inTo interact with Panda Bot, our automated chatbot, you need to sign up or log in:
Sign in
This discussion post is outdated and has been archived. Please use the Community question forums and official documentation for the most current and accurate information.