Get Access Token

  • Endpoint: /api/v3/tokens?grant_type=client_credentials&user_id=<client defined user id>&user_firstname=<client defined user first name>&user_lastname=<client defined user last name>
  • Note: The parameters grant_type and user_id are mandatory.  The parameters user_firstname and user_lastname are optional. The OAuth access token returned will carry the user_id that was passed in upon token creation. If the user is not recognized (if there is no user account for given user_id), a new user is created.
  • Security Note: We use HTTPS protocol for secure communication over a computer network. All communication is encrypted and there's no need to encrypt the user credentials again.
  • Role restriction: instructor, student
  • Request: type POST
  • Req. Header: {Authorization: Basic <Base64 encoded string "username:password">}
  • Response status code:
    • If everything is OK then HTTP STATUS CODE 200 (OK)
    • If username or password is incorrect then HTTP STATUS CODE 401 (Unauthorized)
    • If any parameter is missing then HTTP STATUS CODE 400 (Bad Request)
  • Response body:

{
    "access_token": "<OAuth access token>",
    "token_type": "bearer", # The SA REST API issues bearer tokens so this value will always be 'bearer',
    "expires_in": "<token expiration time in seconds>",
    "scope": "read write trust" # according what scope the user has,
    "user_id": "<user id set by client in the request>"
}

The input credentials for this endpoint (basic auth. username and password) are the role credentials obtained upon client's registration. As the credentials are tied up with a role (instructor or student), the returned access token is tied up with the same role.

There is no special protocol to refresh an access token using the client credentials authorization flow. The client application simply requests a new token once the previous token has expired.


Create Submission

  • Note: SafeAssign generates UUID for every uploaded file and every submission and returns the UUIDs in the response. One submission can contain multiple files. We check the uploaded file content type and skip the file if it is not supported. Skipped files are listed under unprocessed_file_names and they don't have UUIDs. If the user isn't registered in the course, he is enrolled in as a student. The maximum size of the files being uploaded is 10 MB.
  • Endpoint: /api/v3/courses/<course_uuid>/assignments/<assignment_uuid>/submissions
  • Role restriction:  student
  • Request: type POST with MULTIPART body:

{
"global_check" : "<true/false>", # Optional, default is false. Whether to add the file(s) to the global search index. It only goes into the global search index if it's allowed in client settings and here (both flags must be set to true). Otherwise it goes into the institutional search index.
"group_submission" : "<true/false>" # Whether to submit all files grouped as a single submission (single originality report) or to create a submission per file
}

files you want to submit

  • Example Request:

Content-Type: multipart/form-data; boundary=AaB03x

   --AaB03x
 Content-Disposition: form-data; name="attributes"
 Content-Type: application/json; charset=UTF-8
 {
  "global_check" : "<true/false>", # Whether to add this file to the global search index
  "group_submission" : "<true/false>" # Whether to submit all files grouped as a single submission (single originality report) or to create a submission per file
 }


   --AaB03x
   Content-Disposition: form-data; name="files"
   Content-Type: multipart/mixed; boundary=BbC04y

   --BbC04y
   Content-Disposition: file; filename="file1.txt"
   Content-Type: text/plain

   ... contents of file1.txt ...
   --BbC04y
   Content-Disposition: file; filename="file2.pdf"
   Content-Type: application/pdf
   ...contents of file2.pdf...
   --BbC04y--
   --AaB03x--

  • Req. Header: {Content-Type=[multipart/form-data], Accept=[application/json],  Authorization = Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response status code:
    • If everything is OK then HTTP STATUS CODE 200 (OK)
    • If files are missing or empty or sum of their size exceed the limit then HTTP STATUS CODE 400 (Bad Request)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If the role restriction is not met then 403 (Forbidden)
    • If course or assignment doesn't exist in SA then HTTP STATUS CODE 404 (Not found)
  • Response body:

# group_submission (single originality report) = TRUE


{
    "submissions": [
        {
            "submission_uuid": "<safe_assign_generated_UUID>",
            "submission_files": [
                {
                    "file_name": "<supported_file_name_1>",
                    "file_uuid": "<safe_assign_generated_UUID>"
                },
                {
                    "file_name": "<supported_file_name_2>",
                    "file_uuid": "<safe_assign_generated_UUID>"
                }
            ]
        }
    ],
    "unprocessed_file_names": [
        "<unsupported_file_name_1>",  # e.g. datafile.json
        "<unsupported_file_name_2>",  # e.g. packed.zip
    ]
}


# group_submission (originality report per each file) = FALSE


{
    "submissions": [
        {
            "submission_uuid": "<safe_assign_generated_UUID>",
            "submission_files": [
                {
                    "file_name": "<supported_file_name_1>",
                    "file_uuid": "<safe_assign_generated_UUID>"
                }
            ]
        },
        {
            "submission_uuid": "<safe_assign_generated_UUID>",
            "submission_files": [
                {
                    "file_name": "<supported_file_name_2>",
                    "file_uuid": "<safe_assign_generated_UUID>"
                }
            ]
        }
    ],
    "unprocessed_file_names": [
        "<unsupported_file_name_1>",  # e.g. datafile.json
        "<unsupported_file_name_2>",  # e.g. packed.zip
    ]
}

Question

Moodle & other 3rd parties

Learn

Shall we support ZIP archives i.e. put all of the files uploaded in one archive? No Implied
Will we support global flag? Yes Implied
Will we share the same global index with Learn or will we create a new global index for SA-REST-API? Yes Implied
Will we support paper re-submission? Yes Implied

How are we going to identify submissions so it won't match against the same user's submission.

 

A same structure will be used to model paper matching.

Implied

How it works in Learn:

  • Identical files are not checked against each other for plagiarism when the user submits them into different assignments within the same course. However, the plagiarism gets performed for user files inside different courses.

 

If we want to force 3rd parties to follow Learn attributes they must have similar data structures as in Learn (course, assignment, user). Do 3rd parties also have the same set of attributes as Learn? If not, should we let the party define its own set of filtering attributes?

Moodle has similar data structures

Implied
Are we going to support draft submissions, i.e. the paper won't be added to the search index and it's only going to be checked for plagiarism.

I think this would be a useful feature for Moodle as it does support draft submissions. Allowing a student to see the plagiarism score prior to submission would potential save time for themselves and the tutor.

Implied

3. Get Originality Report Basic Data (Score)

  • Endpoint: /api/v3/submissions/<submission_uuid>/report/metadata
  • Role restriction:  instructor,student
  • Request: type GET
  • Req. Header: {Content-Type=[application/json], Accept=[application/json],  Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response status code:
    • If everything is OK then HTTP STATUS CODE 200 (OK) 
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If any student requests a submission which contains files from different submitters than himself (i.e. students can only see their submissions/files) 403 (Forbidden)
    • If submission doesn't exist in SA then HTTP STATUS CODE 404 (Not found)
    • If the files have not been processed yet i.e. the report is not created then HTTP STATUS CODE 404 (Not Found)
    • If the role restriction is not met then 403 (Forbidden)
    • Response body:

{
  "highest_score": "<the highest plagiarism score in percent>",
  "average_score": "<the average plagiarism score in percent>",
  "submission_files": {
    "<file1_uuid>": "<the plagiarism score in percent>",
    "<file2_uuid>": "<the plagiarism score in percent>",
    ...
    "<fileN_uuid>": "<the plagiarism score in percent>"
  }
}

Question

Answer

How does highest/avg score get computed?

One submission can have multiple files. The highest/avg score is a number calculated as aggregation function from all files attached to one submission.

This endpoint is basically the same as the next one. The only different thing, except the URL of course, is the response (just score vs. full report).


Get Originality Report

  • Endpoint: /api/v3/submissions/<submission_uuid>/report
  • Role restriction: instructor, student
  • Request: type GET
  • Req. Header: {Content-Type=[application/json],  Authorization=Bearer [<OAUTH_ACCESS_TOKEN>], Accept-Language = <language>}
  • Req. Params: Optional query parameters:
    • print=true to return a print version of the report
    • css_url=<url_to_some_css_file> to add some custom report styling
    • logo_url=<url_to_some_logo_file> to use custom logo
    • text_only=true to return a text only version of the report
    • include_deleted=true to show report despite file was deleted
  • Response status code:
    • If everything is OK then HTTP STATUS CODE 200 (OK)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If any student requests a submission which contains files from different submitters than himself (i.e. students can only see their submissions/files) 403 (Forbidden)
    • If submission doesn't exist in SA  then HTTP STATUS CODE 404 (Not found)
    • If the files have not been processed yet i.e. the report is not created then HTTP STATUS CODE 404 (Not Found)
    • If the role restriction is not met then 403 (Forbidden)
  • Response Header: {Content-Type=[?],  Authorization=[<OAUTH_ACCESS_TOKEN>]
  • Response body: An originality report in HTML UTF-8 encoded.

Get Originality Report for Legacy Papers/Direct Submit Papers

  • Endpoint: /api/v3/papers/<paper_uuid>/report
  • Role restriction: instructor, student
  • Request: type GET
  • Req. Header: {Content-Type=[application/json],  Authorization=Bearer [<OAUTH_ACCESS_TOKEN>]
  • Req. Params: Optional query parameters:
    • print=true to return a print version of the report
    • css_url=<url_to_some_css_file> to add some custom report styling
    • logo_url=<url_to_some_logo_file> to use custom logo
    • text_only=true to return a text only version of the report
    • include_deleted=true to show report despite file was deleted
  • Response status code:
    • If everything is OK then HTTP STATUS CODE 200 (OK)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If any student requests a submission which contains files from different submitters than himself (i.e. students can only see their submissions/files) 403 (Forbidden)
    • If submission doesn't exist in SA  then HTTP STATUS CODE 404 (Not found)
    • If the files have not been processed yet i.e. the report is not created then HTTP STATUS CODE 404 (Not Found)
    • If the role restriction is not met then 403 (Forbidden)
  • Response Header: {Content-Type=[?],  Authorization=[<OAUTH_ACCESS_TOKEN>]
  • Response body: An originality report in HTML UTF-8 encoded.

Delete Submission

  • Note: The submission and all attached files will not be deleted physically. It will be only marked as deleted and excluded from any plagiarism check processed after the deletion is finished.
  • Endpoint:  /api/v3/submissions/<submission_uuid>
  • Role restriction:  instructor
  • Request: type DELETE
  • Req. Header: {Content-Type=[application/json], Accept=[application/json],  Authorization=Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response status code:
    • If everything is OK then HTTP STATUS CODE 204 (No Content)
    • If submission_uuid parameter is missing then HTTP STATUS CODE 400 (Bad Request)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If the submission identified by id provided in request doesn't exist then HTTP STATUS CODE 404 (Not Found)
    • If the role restriction is not met then 403 (Forbidden)
  • Response body: Empty in case everything is OK. Error message in case of 400, 401, 403 or 404.

Resubmit File

  • Endpoint: /api/v3/submissions/<submission_uuid>
  • Role restriction:  instructor
  • Req. Header: Content-Type=[application/x-www-form-urlencoded], Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Request: type POST

<input type="text" name="file_uuid" value="<safe_assign_generated_UUID>" />
<input type="text" name="skipped_urls[]" value="<url_1>" />
<input type="text" name="skipped_urls[]" value="<url_2>" />
<input type="text" name="skipped_engine_names[]" value="<engine_name_1>" />
<input type="text" name="skipped_engine_names[]" value="<engine_name_2>" />

  • Req. Header: Content-Type=[application/json], Accept=[application/json],  Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Request: type PUT

{
    "file_uuid": "<safe_assign_generated_UUID>",
    "skipped_citations": [
        {
            "url": "<url_1>",
            "engine_name": "<engine_name_1>"
        },
        {
            "url": "<url_2>",
            "engine_name": "<engine_name_2>"
        }
    ]
}

Response:

{
    "status": "SUCCESS"
}

  • Response status code:
    • If everything is OK then HTTP STATUS CODE 202 (ACCEPTED)
    • If some of the request parameters don't match then HTTP STATUS CODE 400 (BAD REQUEST)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If the role restriction is not met then 403 (Forbidden)
    • If submission or submission attachment don't exist in SA then HTTP STATUS CODE 404 (Not found)

Create Course

  • Endpoint: /api/v3/courses
  • Note: The user becomes an instructor of the course.
  • DevNote: the newly created UUID will be stored in COURSE table in both BBID and BB_COURSE_MAIN_UUID columns
  • Role restriction: instructor
  • Request: type POST with body:

{
  "id":"<course id 255 chars>",
  "title":"<course title 255 chars>"
}

  • Req. Header: Content-Type=[application/json], Accept=[application/json],  Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response body:

{
  "id":"<course id (echoing request parameter)>",
  "uuid":"<course uuid (universally unique identifier)>",
  "title":"<course title (echoing request parameter)>"
}

  • Response status code:
    • If everything is OK then HTTP STATUS CODE 201 (Created)
    • If id or title parameter is missing then HTTP STATUS CODE 400 (Bad Request)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If course identified by the same id already exists then 409 (Conflict)
    • If the role restriction is not met then 403 (Forbidden)

Create Assignment

  • Endpoint: /api/v3/courses/<course_uuid>/assignments
  • Role restriction: instructor
  • Request: type POST with body:

{
  "id":"<assignment id 255 chars>",
  "title":"<assignment title 255 chars>",
  "draft" : "<true/false>" # Optional, default is false. If set to true, submissions are excluded from both institutional and global search indices (aka Institutional and Global References Databases). It has priority over the "global_check" flag.
}

  • Req. Header: Content-Type=[application/json], Accept=[application/json],  Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response body:

{
 "id":"<assignment id (echoing request parameter)>" ,
 "uuid":"<assignment uuid (universally unique identifier)>",
 "title":"<assignment title (echoing request parameter)>",
 "draft":"<draft flag (echoing request parameter)>"
}

  • Response status code:
    • If everything is OK then HTTP STATUS CODE 201 (Created)
    • If course_uuid, id or title parameter is missing then HTTP STATUS CODE 400 (Bad Request)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If the role restriction is not met then 403 (Forbidden)
    • If assignment identified by the same id already exists then 409 (Conflict)
    • If course doesn't exist in SA then HTTP STATUS CODE 404 (Not found)

Check Course Exists

  • Endpoint: /api/v3/courses
  • Role restriction: instructor
  • Request: type GET
  • Request params: id=123456
  • Req. Header: Accept=[application/json],  Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response body:

{
  "id": "<original id provided by the caller>",
  "uuid":"<course uuid (universally unique identifier)>",
  "title":"<course title>"
}

  • Response status code:
    • If everything is OK then HTTP STATUS CODE 200 (OK)
    • If id parameter is missing then HTTP STATUS CODE 400 (Bad Request)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If course doesn't exist in SA  then HTTP STATUS CODE 404 (Not found)
    • If the role restriction is not met then 403 (Forbidden)

Check Assignment Exists

  • Endpoint : /api/v3/courses/ <course_uuid >/assignments
  • Role restriction: instructor
  • Request: type GET
  • Request params: id=123456
  • Req. Header: Accept=[application/json],  Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response body:

{
  "id": "<original id provided by the caller>",
  "uuid":"<assignment uuid (universally unique identifier)>",
  "title":"<assignment title>",
  "draft":"<draft flag>"
}

  • Response status code:
    • If everything is OK then HTTP STATUS CODE 200 (OK)
    • If id parameter is missing then HTTP STATUS CODE 400 (Bad Request)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If course or assignment doesn't exist in SA  then HTTP STATUS CODE 404 (Not found)
    • If the role restriction is not met then 403 (Forbidden)

Put/Delete Instructor Into/From a Course

  • Endpoint : /api/v3/courses/<course uuid>/members
  • Note: The user id to be put into a course will be given by the user_id parameter contained in the OAUTH_ACCESS_TOKEN i.e. it will be the requesting user. When you try to put/deleted instructor that has already been put/deleted into/from the course nothing happens and HTTP code 200 (OK) is returned.
  • Role restriction: instructor
  • Request: type PUT/DELETE
  • Req. Header: Accept=[application/json],  Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response body: Empty in case everything is OK. Error message in case of 400, 401, 403 or 404.
  • Response status code:
    • If everything is OK and if you try to put/remove instructor already added/removed into/from the course then HTTP STATUS CODE 200 (OK)
    • If course uuid parameter is missing then HTTP STATUS CODE 400 (Bad Request)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If course doesn't exist in SA then HTTP STATUS CODE 404 (Not found)
    • If the role restriction is not met then 403 (Forbidden)

Accept License

  • Endpoint: /api/v3/licenses
  • Note: The user accepts latest license or specified if present in request body, for his registration. License version format used will be *.* where each number is not restricted to only single decimal.
  • Role restriction: instructor
  • Request: type PUT with body:

{
    "acceptorFirstName":"<first name 256 chars>",
    "acceptorLastName":"<last name 256 chars>",
    "acceptorEmail":"<email 1000 chars>",
    "licenseVersionAccepted":"<version 100 chars, optional>" 
}

  • Req. Header: Content-Type=[application/json],  Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response body: Empty in case everything is OK.
  • Response status code:
    • If everything is OK then HTTP STATUS CODE 200 (Ok)
    • If any of mandatory fields are missing or license version is invalid then HTTP STATUS CODE 400 (Bad Request)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If the role restriction is not met then 403 (Forbidden)
    • If a license of this version is already accepted then 409 (Conflict)

Revoke License

  • Endpoint: /api/v3/licenses?license_version=<version optional>
  • Note: The user revokes latest license or specified license if present in query, for his registration.
  • Role restriction: instructor
  • Request: type DELETE
  • Req. Header: Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response body: Empty in case everything is OK.
  • Response status code:
    • If everything is OK then HTTP STATUS CODE 200 (Ok)
    • If specified license cannot be revoked then HTTP STATUS CODE 404 (Not Found)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If the role restriction is not met then 403 (Forbidden)

Get Accepted Licenses

  • Endpoint: /api/v3/licenses/accepted
  • Note: 
    • The user retrieves all accepted license for his registration.
    • The licenseAccepted Timestamp precision: seconds

  • Role restriction: instructor
  • Request: type GET
  • Req. Header: Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response body: 

[
    {
        "licenseVersion": "<version 100 chars>",
        "licenseAccepted": "<date of acceptance>",
        "licenseText": "<license content>"
    }
]

  • Response status code:
    • If everything is OK then HTTP STATUS CODE 200 (Ok)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If the role restriction is not met then 403 (Forbidden)

Get Licenses

  • Endpoint: /api/v3/licenses/all
  • Note: 
    • The user retrieves all available licenses, consist of already accepted and unaccepted licenses.
    • The licenseCreated Timestamp precision: seconds
  • Role restriction: instructor
  • Request: type GET
  • Req. Header: Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response body: 

[
    {
        "licenseVersion": "<version 100 chars>",
        "licenseCreated": "<date of creation>",      
        "licenseText": "<license content>"
    }
]

  • Response status code:
    • If everything is OK then HTTP STATUS CODE 200 (Ok)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If the role restriction is not met then 403 (Forbidden)

Resubmit Files

  • Endpoint: /api/v3/submissions/<submission_uuid>/group
  • Role restriction: instructor
  • Req. Header: Content-Type=[application/x-www-form-urlencoded], Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Request: type POST

<input type="text" name="file_uuid[]" value="<safe_assign_generated_UUID>" />
<input type="text" name="skipped_urls.<file_uuid>" value="<url_1>" />
<input type="text" name="skipped_engine_names.<file_uuid>" value="<engine_name_1>" />
<input type="text" name="skipped_urls.<file_uuid>" value="<url_2>" />
<input type="text" name="skipped_engine_names.<file_uuid>" value="<engine_name_2>" />

Response:

[
    {
        "status": "SUCCESS",
        "file_uuid": <file_uuid>
    },
    {
        "status": "SUCCESS",
        "file_uuid": <file_uuid>
    }
]

  • Response status code:
    • If everything is OK then HTTP STATUS CODE 202 (ACCEPTED)
    • If some of the request parameters don't match then HTTP STATUS CODE 400 (BAD REQUEST)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If the role restriction is not met then 403 (Forbidden)
    • If submission or submission attachment don't exist in SA then HTTP STATUS CODE 404 (Not found)

Suggest URL

  • Endpoint: /api/v3/suggestUrl
  • Note: The users are able to suggest URLs they believe to be missing for inclusion in the SA search corpus. SA will/might then crawl these URLs/domains and add them to the search corpus.
  • Role restriction: instructor
  • Request: type POST with body:

{
  "url":"<suggested URL up to 2000 chars>",
  "add_web_root":"<true/false>" # Optional, default is true. Whether to also add root of the suggested URL (e.g. also add "https://www.1234.com" if the suggested URL is "https://www.1234.com/ab/cdef?foo=bar").
}

  • Req. Header: Content-Type=[application/json], Accept=[application/json],  Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response body: Empty in case everything is OK.
  • Response status code:
    • If everything is OK then HTTP STATUS CODE 201 (Created)
    • If any of mandatory fields are missing or malformed then HTTP STATUS CODE 400 (Bad Request)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If the role restriction is not met then 403 (Forbidden)

Check a Shared Root Folder Exists

  • Endpoint: /api/v3/shared/root
  • Note: The folder is shared among all course instructors.
  • Role restriction: instructor
  • Request: type GET
  • Request params: course_uuid=<course_uuid> to specify the course
  • Req. Header: Accept=[application/json],  Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response body:

{
  "uuid":"<folder_uuid>"
}

  • Response status codes:
    • If everything is OK then HTTP STATUS CODE 200 (OK)
    • If course_uuid parameter is missing then HTTP STATUS CODE 400 (Bad Request)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If the role restriction is not met then 403 (Forbidden)
    • If the course or the shared root folder doesn't exist in SA then HTTP STATUS CODE 404 (Not found)

Check a Private Root Folder Exists

  • Endpoint: /api/v3/private/root
  • Note: The folder is only accessible by its owner (by the user who created it).
  • Role restriction: instructor
  • Request: type GET
  • Req. Header: Accept=[application/json],  Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response body:

{
  "uuid":"<folder_uuid>"
}

  • Response status codes:
    • If everything is OK then HTTP STATUS CODE 200 (OK)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If the role restriction is not met then 403 (Forbidden)
    • If the private root folder doesn't exist in SA then HTTP STATUS CODE 404 (Not found)

Create a Shared Root Folder

  • Endpoint: /api/v3/shared/root
  • Note: The folder is shared among all course instructors.
  • Role restriction: instructor
  • Request: type POST
  • Request params: course_uuid=<course_uuid> to specify the course
  • Req. Header: Accept=[application/json],  Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response body:

{
  "uuid":"<folder_uuid>"
}

  • Response status codes:
    • If everything is OK then HTTP STATUS CODE 201 (Created)
    • If course_uuid parameter is missing then HTTP STATUS CODE 400 (Bad Request)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If the role restriction is not met then 403 (Forbidden)
    • If the course doesn't exist in SA then HTTP STATUS CODE 404 (Not found)
    • If the shared root folder for the course already exists then 409 (Conflict)

Create a Private Root Folder

  • Endpoint: /api/v3/private/root
  • Note: The folder is only accessible by its owner (by the user who created it).
  • Role restriction: instructor
  • Request: type POST
  • Req. Header: Accept=[application/json],  Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response body:

{
  "uuid":"<folder_uuid>"
}

  • Response status codes:
    • If everything is OK then HTTP STATUS CODE 201 (Created)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If the role restriction is not met then 403 (Forbidden)
    • If the private root folder for the user already exists then 409 (Conflict)

Create a (Sub)Folder

  • Endpoint: /api/v3/folders/<parent_folder_uuid>
  • Note: The endpoint doesn't create root folders. They have their own endpoints. The <parent_folder_uuid> parameter specifies the parent folder of the new folder.
  • Role restriction: instructor
  • Request: type POST
  • Request params: name=<new_folder_name> a name of the new folder
  • Req. Header: Accept=[application/json],  Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response body:

{
  "uuid":"<folder_uuid>",
  "parent_folder_uuid":"<parent_folder_uuid (echoing request parameter)>",
  "name":"<new_folder_name (echoing request parameter)>"
}

  • Response status codes:
    • If everything is OK then HTTP STATUS CODE 201 (Created)
    • If name parameter is missing then HTTP STATUS CODE 400 (Bad Request)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If the role restriction is not met then 403 (Forbidden)
    • If the parent folder doesn't exist in SA then HTTP STATUS CODE 404 (Not found)
    • If a folder with this name and parent folder already exists then 409 (Conflict)

Check a (Sub)Folder Exists

  • Endpoint: /api/v3/folders/<folder_uuid>
  • Role restriction: instructor
  • Request: type GET
  • Req. Header: Accept=[application/json],  Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response body:

{
  "uuid":"<folder_uuid (echoing request parameter)>",
  "parent_folder_uuid":"<parent_folder_uuid (null for a root folder)>",
  "name":"<new_folder_name (null for a root folder)>"
}

  • Response status codes:
    • If everything is OK then HTTP STATUS CODE 200 (OK)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If the role restriction is not met then 403 (Forbidden)
    • If the folder doesn't exist in SA then HTTP STATUS CODE 404 (Not found)

Delete a Folder

  • Endpoint: /api/v3/folders/<folder_uuid>
  • Role restriction: instructor
  • Request: type DELETE
  • Req. Header: Accept=[application/json],  Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response body: Empty in case everything is OK. Error message in case of 4xx.
  • Response status codes:
    • If everything is OK then HTTP STATUS CODE 204 (No Content)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If the role restriction is not met then 403 (Forbidden)
    • If the folder doesn't exist in SA then HTTP STATUS CODE 404 (Not found)

View Folder Content

  • Endpoint: /api/v3/folders/<folder_uuid>/content
  • Role restriction: instructor
  • Request: type GET
  • Req. Header: Accept=[application/json],  Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response body:

[
  {
    "content_type":"FOLDER",   
    "uuid":"<folder1_uuid>",
    "name":"<folder1_name>"
  },
  {
    "content_type":"FOLDER",   
    "uuid":"<folder2_uuid>",
    "name":"<folder2_name>"
  },
  {
    "content_type":"PAPER",   
    "uuid":"<paper1_uuid>",
    "name":"<paper1_name>"
  },
  {
    "content_type":"PAPER",   
    "uuid":"<paper2_uuid>",
    "name":"<paper2_name>"
  },
  {
    "content_type":"PAPER",   
    "uuid":"<paper3_uuid>",
    "name":"<paper3_name>"
  }
]

  • Response status codes:
    • If everything is OK then HTTP STATUS CODE 200 (OK)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If the role restriction is not met then 403 (Forbidden)
    • If the folder doesn't exist in SA then HTTP STATUS CODE 404 (Not found)

Create (Submit) a Quick Paper

  • Endpoint: /api/v3/folders/<folder_uuid>/papers
  • Note: Batch submissions (submitting multiple files at once / submitting an archive) aren't supported. In case of submitting multiple files, one of them is picked and processed.
  • Role restriction: instructor
  • Request: type POST with MULTIPART body:

{
  "draft" : "<true/false>", # Optional,  default=false. Whether to add this file to the search index.
  "skip_checking" : "<true/false>" # Optional,  default=false . Whether to do the plagiarism check (generate an originality report).
}

the file you want to submit

  • Example Request:

Content-Type: multipart/form-data; boundary=AaB03x

 --AaB03x
 Content-Disposition: form-data; name="attributes"
 Content-Type: application/json; charset=UTF-8
{
  "draft" : "<true/false>", # Whether to add this file to the search index
  "skip_checking" : "<true/false>" # Whether to check the file for plagiarism (to generate an originality report)
}

 --AaB03x
 Content-Disposition: form-data; name="file"; filename="file.txt"
 Content-Type: text/plain

 ... contents of file.txt ...
 --AaB03x--

  • Req. Header: Content-Type=[multipart/form-data], Accept=[application/json],  Authorization = Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response body:

{
  "uuid":"<paper_uuid>",
  "name":"<paper_name>"
}

  • Response status codes:
    • If everything is OK then HTTP STATUS CODE 200 (OK)
    • If the file is missing or empty or its size exceeds the limit then HTTP STATUS CODE 400 (Bad Request)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If the role restriction is not met then 403 (Forbidden)
    • If folder doesn't exist in SA then HTTP STATUS CODE 404 (Not found)

Resubmit a Quick Paper

  • Endpoint: /api/v3/papers/<paper_uuid>
  • Note: This endpoint is very similar to the Resubmit File endpoint.
  • Role restriction:  instructor
  • Req. Header: Content-Type=[application/x-www-form-urlencoded], Accept=[text/html],  Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Request: type POST

<input type="text" name="skipped_urls[]" value="<url_1>" />
<input type="text" name="skipped_urls[]" value="<url_2>" />
<input type="text" name="skipped_engine_names[]" value="<engine_name_1>" />
<input type="text" name="skipped_engine_names[]" value="<engine_name_2>" />

  • Response status codes:
    • If everything is OK then HTTP STATUS CODE 202 (ACCEPTED)
    • If some of the request parameters don't match then HTTP STATUS CODE 400 (BAD REQUEST)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If the role restriction is not met then 403 (Forbidden)
    • If paper doesn't exist in SA then HTTP STATUS CODE 404 (Not found)

Delete a Quick Paper

  • Endpoint: /api/v3/papers/<paper_uuid>
  • Role restriction: instructor
  • Request: type DELETE
  • Req. Header: Accept=[application/json],  Authorization= Bearer [<OAUTH_ACCESS_TOKEN>]
  • Response body: Empty in case everything is OK. Error message in case of 4xx.
  • Response status codes:
    • If everything is OK then HTTP STATUS CODE 204 (No Content)
    • If wrong <OAUTH_ACCESS_TOKEN> 401 (Unauthorized)
    • If the role restriction is not met then 403 (Forbidden)
    • If the paper doesn't exist in SA then HTTP STATUS CODE 404 (Not found)