Upload pdf as assignment comment with Canvas API

Jump to solution
Community Explorer

I think this question may have been asked before. But I am stuck for over an hour with an annoying 403 error and there is no way for me to step in further and debug it. My code nugget is as below. The first two steps went well with 200 and 201 responses. However, I kept getting stuck for step 3.

Note that if I exclude 'comment[file_ids][]': [file_id] in the payload in Step 3, a comment will be posted successfully. So I believe the problem is with comment[file_ids][], I am not sure whether the variable should be an array or an integer as it is unclear from the API doc. I tried both but they all fail. My current guess is that I am not authorized to access the file I uploaded as when I tried to curl the file with

curl https://canvas.ou.edu/api/v1/files/:file_id -H 'Authorization: Bearer XXXX'

I got the unauthorized error even though I just created the file. 

{"status":"unauthorized","errors":[{"message":"user not authorized to perform that action"}]}

Any insights or suggestions to navigate through this issue would be immensely appreciated.


    # Headers for API requests
    HEADERS = {
        'Authorization': f'Bearer {API_KEY}'

    # Step 1: Request file upload
    payload = {
        'name': 'solution.pdf',
        'size': os.path.getsize(FILE_PATH), 
        'content_type': 'application/pdf',
        'on_duplicate': 'rename'
    # url = f'{CANVAS_DOMAIN}/api/v1/courses/{COURSE_ID}/files'
    url = f'{CANVAS_DOMAIN}/api/v1/courses/{COURSE_ID}/assignments/{ASSIGNMENT_ID}/submissions/{USER_ID}/files' # tried both and didn't work
    response = requests.post(url, headers=HEADERS, data=payload)
    upload_params = response.json()

    # Step 2: Perform file upload
    with open(FILE_PATH, 'rb') as file:
        response = requests.post(
            files={'file': file}
    file_id = response.json()['id']

    # Step 3: Post comment with attached file
    payload = {
        'comment[text_comment]': comment ,
        'comment[file_ids][]': [file_id]   # should it be an array or integer?
    url = f'{CANVAS_DOMAIN}/api/v1/courses/{COURSE_ID}/assignments/{ASSIGNMENT_ID}/submissions/{USER_ID}'
    response = requests.put(url, headers=HEADERS, data=payload)
1 Solution
Community Contributor


I think you're uploading the file to the wrong endpoint. You'll need to upload it to the submissions comments endpoint instead: https://canvas.instructure.com/doc/api/submission_comments.html#method.submission_comments_api.creat...

According to the Canvas REST API documentation, "The endpoint you choose to post files to will change the permissions set on the file. i.e. only files posted to the submissions comments endpoint can be attached to a submissions comment." (https://canvas.instructure.com/doc/api/file.file_uploads.html)

comment[file_ids][] should be an integer as you can only attach one file to a submission comment (at least through the UI)

View solution in original post