Connect Retool to Canvas LMS by creating a REST API Resource using your Canvas access token for Bearer authentication. The base URL is your institution's Canvas domain (e.g., https://yourschool.instructure.com/api/v1). Once configured, build queries to manage courses, view student submissions, track grades, and handle enrollments from a centralized LMS administration dashboard.
| Fact | Value |
|---|---|
| Tool | Canvas LMS |
| Category | Other |
| Method | REST API Resource |
| Difficulty | Intermediate |
| Time required | 20 minutes |
| Last updated | April 2026 |
Build a Canvas LMS Administration Dashboard in Retool
Canvas LMS is the backbone of course delivery at many universities and colleges, but its native interface is optimized for individual instructor and student workflows rather than administrative oversight. Department chairs overseeing multiple courses, instructional designers managing large course catalogs, and LMS administrators tracking institutional engagement all need cross-course views that Canvas's native SpeedGrader and Gradebook don't provide efficiently.
Canvas's REST API is one of the best-documented LMS APIs available, offering comprehensive access to courses, sections, users, enrollments, assignments, submissions, discussions, and grades. Authentication uses a personal access token generated from account settings, making the initial Retool connection straightforward. The base URL is institution-specific — each Canvas deployment uses a unique subdomain (e.g., yourschool.instructure.com), which you configure in the Retool resource.
With Retool, LMS administrators can build dashboards for bulk enrollment management, instructors can get aggregate submission status across all sections of a course, and department chairs can monitor student engagement and grade distributions across their department's courses — all in a flexible Retool interface that Canvas's native tools weren't designed to provide.
Integration method
Canvas LMS connects to Retool via a REST API Resource using Bearer token authentication. You generate a personal access token from your Canvas account settings, then configure a REST API Resource with your institution's Canvas subdomain as the base URL (e.g., https://yourschool.instructure.com/api/v1). All requests are proxied server-side through Retool, keeping credentials secure. Canvas uses Link header-based pagination for large result sets.
Prerequisites
- A Canvas LMS account with instructor or admin-level permissions (student accounts cannot generate API tokens with sufficient access)
- A Canvas personal access token (generated from Account → Settings → Approved Integrations in Canvas)
- Your institution's Canvas subdomain URL (e.g., https://yourschool.instructure.com)
- A Retool account with permission to create Resources
- Basic familiarity with Retool's query editor, Table component, and Select components
Step-by-step guide
Generate a Canvas personal access token
In Canvas, click your account avatar (top-left) → Account → Settings. Scroll down to the Approved Integrations section and click New Access Token. Enter a purpose description like 'Retool Dashboard' and optionally set an expiration date (leaving it blank creates a non-expiring token — use expiration for security in production environments). Copy the token immediately after generation — Canvas only shows it once. The token looks like a long alphanumeric string prefixed with a number (e.g., 1234~xxxxxxxxxxxxxxxxxx). Important permission considerations: The token inherits the permissions of the account that generated it. An instructor token can access their own courses and students. An admin token can access all courses and users in the institution. For a comprehensive LMS admin dashboard, you'll want an admin-level token. Contact your Canvas system administrator if you need elevated permissions. For institution-level deployments, Canvas also supports OAuth 2.0 developer keys — this is the preferred approach for multi-user or multi-institution tools. For a single-team Retool dashboard, a personal access token is sufficient and much simpler to configure.
Pro tip: Set an expiration date on production Canvas tokens and use Retool Configuration Variables to store the token — when the token expires, you only need to update the configuration variable, not the resource configuration.
Expected result: You have a Canvas personal access token and your institution's Canvas base URL (e.g., https://yourschool.instructure.com) ready for resource configuration.
Create the Canvas REST API Resource in Retool
In Retool, navigate to the Resources tab and click Add Resource. Select REST API. Configure the resource: - Name: Canvas LMS API - Base URL: https://yourschool.instructure.com/api/v1 Replace 'yourschool' with your institution's Canvas subdomain. The /api/v1 path is included in the base URL since all Canvas REST API endpoints start with it. For authentication, select Bearer Token from the Authentication dropdown. Enter your Canvas personal access token in the Token field. Alternatively, store the token in Configuration Variables: go to Settings → Configuration Variables, create CANVAS_ACCESS_TOKEN, mark it as secret, and use {{ retoolContext.configVars.CANVAS_ACCESS_TOKEN }} as the token value. Add a Content-Type header: Key: Content-Type, Value: application/json. Click Create Resource. Test the connection by creating a query with method GET and path /courses. Canvas returns an array of course objects the authenticated user can access. If you see a JSON array of courses, the connection is working. A 401 error means the token is invalid; a 403 error means the account doesn't have permission to access that resource.
Pro tip: Canvas's base URL is institution-specific — confirm it matches exactly what you use to log into Canvas. Some institutions use custom domains (e.g., canvas.yourschool.edu) rather than the default instructure.com subdomain.
Expected result: The Canvas LMS API resource is configured and a test GET /courses returns a JSON array of courses accessible to your Canvas account.
Fetch courses and enrollments
Create a query named getCourses with method GET and path /courses. Add query parameters to filter and paginate: - enrollment_type: teacher (or 'student', 'ta', 'observer' — use 'teacher' to see courses where the authenticated user is an instructor) - per_page: 50 (Canvas's default is 10; maximum is 100) - include[]: total_students (add student count to each course object) - state[]: available (filter to currently active courses; options: unpublished, available, completed, deleted) For admin-level accounts, use path /accounts/1/courses to get all courses in the institution (account ID 1 is typically the root account). Add state[]: available and per_page: 100. Canvas uses Link header-based pagination — the response headers contain a Link header with URLs for next, prev, first, and last pages. When results exceed per_page, you must follow the 'next' link to get subsequent pages. In Retool, implement this by checking if the response has a next page link and incrementing the page parameter. Create a getEnrollments query with path /courses/{{ select_course.value }}/enrollments and parameters: - type[]: StudentEnrollment - state[]: active - per_page: 100 Bind getCourses to a Select component for course selection.
1// Transformer for Canvas courses2const courses = data || [];3return courses.map(course => ({4 id: course.id,5 name: course.name,6 code: course.course_code || '',7 term: course.enrollment_term_id || '',8 students: course.total_students || 0,9 start_date: course.start_at10 ? new Date(course.start_at).toLocaleDateString()11 : '',12 end_date: course.end_at13 ? new Date(course.end_at).toLocaleDateString()14 : '',15 workflow_state: course.workflow_state,16 is_public: course.is_public || false17}));Pro tip: Canvas returns dates in ISO 8601 format (e.g., '2024-08-26T00:00:00Z'). JavaScript's new Date() parses these correctly, but be aware that Canvas uses UTC — convert to local time in your transformer if needed.
Expected result: The getCourses query populates a Select component with all active courses, showing course name and code. Selecting a course drives the enrollment and assignment queries.
Fetch assignments and submission data
Create a getAssignments query with method GET and path /courses/{{ select_course.value }}/assignments. Add parameters: - per_page: 50 - include[]: submission (includes the authenticated user's submission data — for admins, this is less useful; skip if building admin tools) - order_by: due_at Each assignment object includes: id, name, due_at, points_possible, submission_types, and grades_published. For submission data across all students, create a getSubmissions query with path /courses/{{ select_course.value }}/assignments/{{ select_assignment.value }}/submissions. Add parameters: - include[]: user (includes submitting user's name and email) - include[]: submission_comments (includes any feedback left by instructor) - per_page: 100 Each submission object includes: id, user_id, user (name and email when included), assignment_id, submitted_at, workflow_state ('submitted', 'unsubmitted', 'pending_review', 'graded'), score, grade, and late (boolean). The workflow_state field tells you grading status: 'submitted' means received but not graded; 'graded' means score has been recorded; 'unsubmitted' means the student hasn't submitted yet. Use this to build a grading status Table that shows instructors exactly where each student stands.
1// Transformer for Canvas submissions2const submissions = data || [];3return submissions.map(sub => ({4 user_id: sub.user_id,5 student_name: sub.user?.name || `User ${sub.user_id}`,6 student_email: sub.user?.email || '',7 submitted_at: sub.submitted_at8 ? new Date(sub.submitted_at).toLocaleString()9 : 'Not submitted',10 status: sub.workflow_state === 'graded' ? 'Graded'11 : sub.workflow_state === 'submitted' ? 'Needs Grading'12 : sub.workflow_state === 'pending_review' ? 'Pending'13 : 'Not Submitted',14 score: sub.score !== null ? sub.score : '--',15 grade: sub.grade || '--',16 late: sub.late ? 'Late' : '',17 missing: sub.missing ? 'Missing' : '',18 comment_count: (sub.submission_comments || []).length19}));Pro tip: Canvas marks late submissions with late: true on the submission object. Highlight these rows in red in the Retool Table using conditional column styling to immediately surface late work.
Expected result: The getSubmissions query populates a Table showing all student submissions for the selected assignment with status, score, and late indicators.
Build enrollment management and grade export tools
Add administrative actions to the dashboard for enrollment management and grade operations. For enrolling a student in a course, create an enrollUser query with method POST and path /courses/{{ select_course.value }}/enrollments. The request body should be JSON: {"enrollment": {"user_id": "{{ textInput_userId.value }}", "type": "StudentEnrollment", "enrollment_state": "active"}} For dropping a student (deactivating enrollment), use DELETE /courses/{courseId}/enrollments/{enrollmentId} — you need the enrollment ID (not the user ID) from the getEnrollments response. For grade export, Canvas does not have a direct single-call grade export endpoint. Build a JavaScript query that fetches all assignments for a course, then fetches submissions for each assignment using Promise.all, and finally combines the data into a flat structure suitable for a Table export. Retool's Table component includes a built-in CSV export button — use this to allow instructors to download grade reports. For submitting grades from Retool, use PUT /courses/{courseId}/assignments/{assignmentId}/submissions/{userId} with body {"submission": {"posted_grade": "{{ numberInput_grade.value }}", "comment": {"text_comment": "{{ textArea_feedback.value }}"}}}. For complex Canvas integrations involving custom reports across multiple terms or institutional-level analytics, RapidDev's team can help architect scalable Retool dashboards with proper Canvas admin token configuration.
1// Grade update request body2{3 "submission": {4 "posted_grade": "{{ numberInput_score.value }}"5 },6 "comment": {7 "text_comment": "{{ textArea_feedback.value }}"8 }9}Pro tip: When posting grades via the Canvas API, use posted_grade rather than score — posted_grade triggers the grade notification to the student and respects any grade posting policies configured in your Canvas course.
Expected result: The admin panel supports enrolling new students, viewing existing enrollments, and submitting grades with feedback — all operations confirmed with success notifications and automatic data refresh.
Common use cases
Build an instructor assignment submission tracker
Create a Retool dashboard showing all student submissions for a selected assignment across all course sections. The instructor can see which students have submitted, who hasn't, what scores have been awarded, and which submissions need grading — all in a single sortable Table that replaces navigating through SpeedGrader one submission at a time.
Build a Retool assignment grading dashboard for Canvas LMS. Show a Select for course selection and a second Select for assignment selection. Display all student submissions in a Table with student name, submission date, current score, grading status (graded/ungraded/missing), and a link to the submission. Add a NumberInput to bulk-set a score for selected students. Sort by submission date ascending.
Copy this prompt to try it in Retool
Build a student enrollment management panel
Build a Retool admin panel for managing course enrollments across multiple Canvas courses. LMS administrators can search for students, view their current course enrollments, add them to additional courses, and drop them from courses — performing bulk enrollment changes that would require multiple individual steps in Canvas's native course management interface.
Build a Retool enrollment management panel for Canvas LMS. Show all active courses in a Table. When a course is selected, show all enrolled students with their role (student/teacher/TA), enrollment date, and current grade. Add a Form to enroll a new student by user ID or email. Include a Withdraw button for removing a student from the selected course. Add a search input to filter students by name.
Copy this prompt to try it in Retool
Build a course activity and engagement report
Create a Retool analytics panel showing student engagement metrics across courses — last login dates, assignment submission rates, discussion post counts, and page view activity. Academic advisors and department chairs can use this to identify at-risk students who aren't engaging with course material before they fall too far behind.
Build a Retool student engagement dashboard for a Canvas course. Show all enrolled students with their last login to Canvas, number of assignments submitted vs. total, current course grade, discussion post count, and page views. Add a Chart showing grade distribution as a histogram. Highlight students with no recent activity (no login in 7+ days) with a red badge. Include a DateRange filter for the activity period.
Copy this prompt to try it in Retool
Troubleshooting
GET /courses returns an empty array even though courses exist in Canvas
Cause: The personal access token was generated by a student account that has no instructor-level course visibility, or the query is filtering to courses where the user is a teacher but the token owner is not an instructor.
Solution: Try the request without the enrollment_type filter first (remove enrollment_type: teacher) to see all courses the token owner is enrolled in. If you need institutional-level course access, you'll need an admin-level token or request Canvas admin permissions from your institution's Canvas administrator.
API responses are truncated and missing students or submissions
Cause: Canvas uses link-header pagination with a default of 10 items per page. Without explicitly setting per_page and handling pagination, only the first page of results is returned.
Solution: Always add per_page: 100 to your query parameters (Canvas's maximum). For datasets larger than 100, implement pagination using Canvas's Link header — check the response header for a 'next' URL and build pagination controls in Retool to load additional pages.
Grade submission returns 401 Unauthorized or 403 Forbidden
Cause: The personal access token doesn't have permission to grade submissions — either because the token owner is a student, or the course's grade posting policy requires admin action.
Solution: Confirm the token was generated by an instructor or admin account, not a student account. Canvas also has assignment-level permissions — some assignments may be locked for editing. Check the course's assignment settings and grade posting policy in Canvas. For institutional admin operations, you may need a Canvas Developer Key (OAuth 2.0) rather than a personal access token.
Student submissions show workflow_state as 'submitted' but score and grade are null
Cause: The submission exists but hasn't been graded yet — workflow_state 'submitted' means the student turned in work, not that it was graded. Graded submissions have workflow_state 'graded' with non-null score.
Solution: This is expected Canvas behavior. Filter your submission Table by workflow_state to separate graded and ungraded submissions. Use the status column (built from workflow_state) to show 'Needs Grading' for submitted-but-ungraded work. Only graded submissions have meaningful score and grade values.
Best practices
- Store Canvas access tokens in Retool Configuration Variables marked as secret, and set an expiration on production tokens — regenerate and update the configuration variable when tokens expire.
- Always add per_page: 100 to Canvas API requests to reduce the number of pagination requests needed — Canvas's default of 10 items per page leads to very slow dashboards for large courses.
- Use Canvas's include[] parameter selectively — include[]: user on submissions adds student data to each record but significantly increases response size for large courses with hundreds of students.
- Filter courses by workflow_state: available to exclude unpublished, completed, and deleted courses from your dashboard dropdowns.
- For institutional admin dashboards, request a Canvas Developer Key from your Canvas administrator — it enables OAuth 2.0 authentication that can act on behalf of any user, not just the token owner.
- When submitting grades via the API, use posted_grade rather than score to ensure Canvas's grade notification and grade posting policy systems are properly triggered.
- Cache the getCourses query for at least 5 minutes — course catalogs change infrequently and fetching them on every page interaction is unnecessary.
- Use Canvas's Assignment Overrides API when building assignment management tools — due date overrides for specific students (accommodations) are stored separately from the main assignment due date.
Alternatives
Moodle uses a function-based Web Services API that differs significantly from Canvas's REST approach, while Canvas offers a more modern, resource-oriented REST API that is easier to integrate with Retool.
Blackboard is a competing enterprise LMS that uses Anthology's OAuth 2.0 developer portal for API access, which requires a more complex setup than Canvas's straightforward personal access tokens.
Coursera is a MOOC marketplace for external learners, while Canvas LMS is an institutional platform for managing enrolled students within a school or university's curriculum.
Frequently asked questions
Does Retool have a native Canvas LMS connector?
No, Retool does not have a dedicated native Canvas LMS connector. You connect via a REST API Resource using a Canvas personal access token as Bearer authentication. The setup takes about 20 minutes and provides access to Canvas's full REST API including courses, enrollments, assignments, submissions, grades, and user management.
Can I use Retool with any Canvas institution or only specific deployments?
You can connect Retool to any Canvas LMS deployment — both Instructure-hosted accounts (yourschool.instructure.com) and self-hosted Canvas deployments on custom domains. The only requirement is that your Canvas instance has API access enabled (it's on by default for most deployments) and that you have an account with appropriate permissions to generate an access token.
What permissions does my Canvas account need for the Retool dashboard?
For instructor dashboards (viewing courses you teach, grading submissions), an instructor-level Canvas account is sufficient. For institutional admin dashboards (all courses, all users, cross-department data), you need Canvas admin permissions. The personal access token inherits the permissions of the account that generated it — a student token cannot access other students' data or grade submissions.
How do I handle Canvas's pagination in Retool?
Canvas paginates results and signals pagination through the Link response header (not in the response body). Set per_page: 100 in all queries to minimize pagination needs. For large datasets, implement pagination by parsing the Link header in a JavaScript query or using Retool's pagination controls connected to your query's page parameter. Canvas's Link header includes rel='next' for the next page URL.
Can I bulk-enroll students in courses from Retool?
Yes. Canvas's enrollment API (POST /courses/{courseId}/enrollments) accepts one enrollment at a time. For bulk enrollment, build a JavaScript query that iterates over a list of user IDs and calls the enrollment endpoint for each, using Promise.all for parallel requests or a sequential loop for rate limit safety. Canvas also supports SIS (Student Information System) imports for very large bulk operations — these are separate from the REST API.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation