{"id":37425206,"url":"https://github.com/kstateome/canvas-api","last_synced_at":"2026-01-16T06:12:36.582Z","repository":{"id":13467416,"uuid":"41554307","full_name":"kstateome/canvas-api","owner":"kstateome","description":"Java library for interacting with the Canvas LMS API","archived":false,"fork":false,"pushed_at":"2025-03-26T15:50:43.000Z","size":1426,"stargazers_count":75,"open_issues_count":20,"forks_count":55,"subscribers_count":30,"default_branch":"master","last_synced_at":"2025-08-13T21:33:23.304Z","etag":null,"topics":["canvas-lms","canvas-lms-api","java","java-8","java-library"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kstateome.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"License.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-08-28T15:20:30.000Z","updated_at":"2025-08-13T11:13:53.000Z","dependencies_parsed_at":"2024-05-31T05:33:01.639Z","dependency_job_id":"4dc9eb3b-0144-4ce0-b3cb-0b757d7b97cb","html_url":"https://github.com/kstateome/canvas-api","commit_stats":null,"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"purl":"pkg:github/kstateome/canvas-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kstateome%2Fcanvas-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kstateome%2Fcanvas-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kstateome%2Fcanvas-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kstateome%2Fcanvas-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kstateome","download_url":"https://codeload.github.com/kstateome/canvas-api/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kstateome%2Fcanvas-api/sbom","scorecard":{"id":571630,"data":{"date":"2025-08-11","repo":{"name":"github.com/kstateome/canvas-api","commit":"15a94bef0b11b64a04d134b371c96327cebc8d09"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.2,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":2,"reason":"Found 3/13 approved changesets -- score normalized to 2","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/maven.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/maven.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/kstateome/canvas-api/maven.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/maven.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/kstateome/canvas-api/maven.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/maven.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/kstateome/canvas-api/maven.yml/master?enable=pin","Info:   0 out of   3 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: License.txt:0","Info: FSF or OSI recognized license: GNU Lesser General Public License v3.0: License.txt:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'","Warn: branch protection not enabled for branch 'release-2.0'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 22 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":6,"reason":"4 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-4jrv-ppp4-jm57","Warn: Project is vulnerable to: GHSA-5mg8-w23w-74h3","Warn: Project is vulnerable to: GHSA-7g45-4rm6-3mm3","Warn: Project is vulnerable to: GHSA-j288-q9x7-2f5v"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-20T16:29:56.715Z","repository_id":13467416,"created_at":"2025-08-20T16:29:56.715Z","updated_at":"2025-08-20T16:29:56.715Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28477633,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T03:13:13.607Z","status":"ssl_error","status_checked_at":"2026-01-16T03:11:47.863Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["canvas-lms","canvas-lms-api","java","java-8","java-library"],"created_at":"2026-01-16T06:12:35.772Z","updated_at":"2026-01-16T06:12:36.573Z","avatar_url":"https://github.com/kstateome.png","language":"Java","readme":"# Canvas API Library for Java\nThis is a Java library which wraps the [Canvas LMS REST API](https://canvas.instructure.com/doc/api/index.html). It allows you to make requests to the API using Java domain objects while the low level details of the HTTP requests, authentication, etc are taken care of for you.\n\nSome specific features include:\n* Authentication using a supplied [OAuth token](https://canvas.instructure.com/doc/api/file.oauth.html)\n* Handling of [API pagination](https://canvas.instructure.com/doc/api/file.pagination.html) \n  * Ability to specify pagination page size (Canvas default is 10)\n  * Optional callback procedure that gives you data chunks as they come in without having to wait for the entire request to finish\n* Masquerading as other users by Canvas user ID or SIS ID\n* Requesting items by Canvas ID or SIS ID\n\n## Requirements\nTo use this library, you must be using Java 8. We are making extensive use of [Java Streams](https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html) as well as the [Optional](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html) class.\n\nIf you wish to contribute, you will need to be familiar with [Maven](https://maven.apache.org/) to build the project. [The Spring Framework](http://spring.io/) is also used but only for testing.\n\n## Under Construction\nThis code is currently under very active development. We are implementing API calls as we need them for K-State applications so a lot of calls are still missing. However the core functionality of talking to Canvas is well established so adding individual API calls is not a difficult task. Given the [number of API calls](https://canvas.instructure.com/doc/api/all_resources.html) that Canvas provides and the rate at which they add more and change others, we may never achieve 100% parity on all niche features. But basic operations on accounts, users and courses should be stable over time.\n\n## Library structure\nThe top level object needed to execute API calls is the `CanvasApiFactory` class which takes a Canvas instance URL to construct. From there you can request reader and writer objects which provide the functionality to actually execute calls to the Canvas API.\n\nAPI calls are grouped into reader and writer objects by the object type they handle. So any call that returns `User` objects or a list of `User` objects will be found in the `UserReader` class. For example, both the account level \"[List users in account](https://canvas.instructure.com/doc/api/users.html#method.users.index)\" and the course level \"[List users in course](https://canvas.instructure.com/doc/api/courses.html#method.courses.users)\" API calls are accessed through the `UserReader` class.\n\n## Usage\nEvery API call requires an OAuth token for authentication. It is up to you to acquire this token on behalf of the user. For LTI applications, this is typically done during the LTI launch process. Tokens can also be manually issued from a user's account settings page. More details on OAuth can be found in the [Canvas OAuth2 documentation](https://canvas.instructure.com/doc/api/file.oauth.html)\n\n### Basic Query\nOnce you have a token, executing an API call can be as simple as creating a new `CanvasApiFactory`, getting a reader object from it and executing a call. A short example of retrieving an object representing the root Canvas account:\n\n    String canvasBaseUrl = \"https://\u003cinstitution\u003e.instructure.com\";\n    OauthToken oauthToken = new NonRefreshableOauthToken(\"mYSecreTtoKen932781\");\n    CanvasApiFactory apiFactory = new CanvasApiFactory(canvasBaseUrl);\n    AccountReader acctReader = apiFactory.getReader(AccountReader.class, oauthToken);\n    Account rootAccount = acctReader.getSingleAccount(\"1\").get();\n\n### API Options\nMany of the API methods take some form of method-specific *Options* class as a parameter. This is done instead of just accepting multiple (possibly null) parameters because some API calls have a gigantic list of optional parameters. It also insulates the users of this library from compilation breaking changes just because Canvas added a new optional parameter to an API call. Information required to execute the API call is passed into the option class constructor while optional parameters are added to the option class via methods in a pseudo-builder pattern. For example the \"[Get Users in Course](https://canvas.instructure.com/doc/api/courses.html#method.courses.users)\" method has one required piece of information (`course ID`) and 8 optional parameters. To query all students and observers who match the search term \"John\" you would do as follows:\n\n    GetUsersInCourseOptions options =\n        new GetUsersInCourseOptions(\"1234\") //required course ID\n        .searchTerm(\"John\")\n        .enrollmentType(Arrays.asList(EnrollmentType.STUDENT, EnrollmentType.OBSERVER));\n    List\u003cUser\u003e users = userReader.getUsersInCourse(options);\n\n### Masquerading\nCanvas allows you to execute API calls while masquerading as another user. In order to do this, your OAuth token must have sufficient privileges. Details can be found in the [Canvas documentation](https://canvas.instructure.com/doc/api/file.masquerading.html).\n\nTo execute a read API call while masquerading, simply add a call to the `readAsCanvasUser(\"\u003ccanvas user ID\u003e\")` or `readAsSisUser(\"\u003cSIS user ID\u003e\")` method on the reader object. Corresponding methods also exist in writer objects\n\n    acctReader.readAsSisUser(\"1234567\").getSingleAccount(\"1\");\n\n### Using SIS IDs\nMany Canvas objects can be queried either by their numeric Canvas ID or by the SIS ID assigned to that object during the SIS to Canvas import process. Details can be found in the [Canvas documentation](https://canvas.instructure.com/doc/api/file.object_ids.html)\n\nTo request an object by its SIS ID, prepend the ID with the appropriate string, followed by a colon. For an account:\n\n    acctReader.getSingleAccount(\"sis_account_id:12345\");\n\n### Pagination\nAll API calls that return a list of objects have the potential to require pagination to get all of the requested objects. If no `per_page` parameter is specified on a request, Canvas defaults to only returning 10 objects at a time which can cause problems if you are trying to query large lists in a timely fashion. Details on pagination can be found in the [Canvas documentation](https://canvas.instructure.com/doc/api/file.pagination.html)\n\nTo specify the pagination page size to be used on calls, an additional parameter is passed into the `CanvasApiFactory` when requesting a reader object. Note that while you can request any number you like, Canvas can also choose to ignore this number and return however many objects it wants. Currently, hosted instances of Canvas are set to max out at 100 objects per page but this is subject to change without warning. To set the pagination page size to 100:\n\n    UserReader userReader = apiFactory.getReader(UserReader.class, oauthToken, 100);\n\nAll requests made using this `UserReader` object will request 100 objects per page.\n\n### Pagination Callbacks\nCalls that return a large list of objects can take a while even if you set the pagination page size to 100. Querying certain lists in large courses may take 15+ seconds. If you are trying to do this in real time to display to a user, you may want to take chunks of the data as they come in from Canvas and either display the partial list to the user or do some back end processing so that your results will be ready to display more quickly once the full list is done downloading. For this situation, the library provides optional callbacks for reader methods which will call a method you specify every time a page of results comes back from Canvas and pass the partial list in so you can start processing. To use this feature, it looks like this:\n\n    GetUsersInCourseOptions options = new GetUsersInCourseOptions(\"1146\");\n    List\u003cUser\u003e courseUsers = userReader.withCallback(this::processUserPage).getUsersInCourse(options);\n    System.out.println(\"Total users in course: \" + courseUsers.size());\n\n    private void processUserPage(List\u003cUser\u003e users) {\n        System.out.println(\"Got a page of users back: \" + users.size());\n    }\n\nIf this code is run on a course with 325 users it would print the following:\n\n    Got a page of users back: 100\n    Got a page of users back: 100\n    Got a page of users back: 100\n    Got a page of users back: 25\n    Total users in course: 325\n\n## Integration tests\n\nTo run the integration tests copy the file `integration-example.properties` to `integration.properties` and update the values to make sense for the copy of Canvas you are testing again. Be aware this does manipulate the Canvas instance so it's best used against a test/beta instance.\n\nTo run the integration tests use:\n\n    mvn -Pfailsafe verify\n\n## Making a release\n\nThis project is deployed to the central repository, once ready to release you can have the release plugin tag everything:\n\n    mvn -Prelease release:clean release:prepare\n    \nthen if that completes successfully a release bundle can be pushed to the staging area of the Sonatype OSS repository with:\n\n    mvn -Prelease release:perform\n    \nWe don't automatically close the staged artifacts so after checking that the files are ok you can login to the [repository](https://oss.sonatype.org/) and release it.\n\n## Notes\n\nCurrently this library is hand coded, however there is a machine readable API specification at\nhttps://canvas.instructure.com/doc/api/api-docs.json which could be used to generate an API \nautomatically, however it's currently using an outdated version of Swagger which doesn't work\nwell with the existing libraries.\n\nIf you don't supply enough data to the the Canvas API on a creation request (POST) you can \nend up getting a 404 response. That endpoint does exist, you just haven't supplied the correct\ninformation.\n\n## License\nThis software is licensed under the LGPL v3 license. Please see the [License.txt file](License.txt) in this repository for license details.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkstateome%2Fcanvas-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkstateome%2Fcanvas-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkstateome%2Fcanvas-api/lists"}