Skip to main content
RapidDev - Software Development Agency
bubble-integrationsBubble API Connector

Canvas LMS

Canvas LMS is the cleanest REST API in the Education category: generate a personal Bearer token in Canvas Account → Settings → New Access Token, add it as a Private header in Bubble's API Connector, add per_page=100 as a shared URL parameter (Canvas returns only 30 items by default), and run the Initialize call against /courses. The key gotcha: Canvas paginates via the HTTP Link response header, not a JSON field — Bubble can't read it, so use per_page=100 to minimize pagination needs for most course rosters.

What you'll learn

  • How to generate a personal Canvas access token in Canvas Account → Settings
  • How to configure the Bubble API Connector with the institution's subdomain as the base URL
  • Why per_page=100 is a critical shared parameter and how it solves Canvas's pagination for most use cases
  • How to run the Initialize call against /courses and detect Canvas's response schema
  • How to build API calls for courses, assignments, student rosters, and grade submissions
  • How Canvas ISO 8601 dates are handled in Bubble
  • How to handle multi-user Bubble apps where each user has their own Canvas token
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner21 min read2–3 hoursEducationLast updated July 2026RapidDev Engineering Team
TL;DR

Canvas LMS is the cleanest REST API in the Education category: generate a personal Bearer token in Canvas Account → Settings → New Access Token, add it as a Private header in Bubble's API Connector, add per_page=100 as a shared URL parameter (Canvas returns only 30 items by default), and run the Initialize call against /courses. The key gotcha: Canvas paginates via the HTTP Link response header, not a JSON field — Bubble can't read it, so use per_page=100 to minimize pagination needs for most course rosters.

Quick facts about this guide
FactValue
ToolCanvas LMS
CategoryEducation
MethodBubble API Connector
DifficultyBeginner
Time required2–3 hours
Last updatedJuly 2026

Canvas LMS in Bubble: the Education API that just works

If you've tried integrating Google Classroom (OAuth 2.0 with token refresh) or Moodle (single-endpoint function-based API with HTTP-200 errors) before finding Canvas, the contrast is striking. Canvas requires no OAuth dance, no enterprise agreement, no Webhook API configuration. A Canvas user goes to Account → Settings → New Access Token, names the token, clicks Generate, copies the string, and the integration is ready to build.

In Bubble's API Connector, this token goes into an Authorization: Bearer header marked Private — meaning it never leaves Bubble's servers and never appears in browser network requests. Add your institution's Canvas subdomain as the base URL (yourschool.instructure.com/api/v1), add per_page=100 as a shared URL parameter, and click Initialize. Bubble reads the response and auto-detects all the course fields: id, name, course_code, start_at, end_at, enrollment_term_id, workflow_state, and more.

The one meaningful technical hurdle: Canvas paginates using the HTTP Link response header rather than a JSON field. Bubble's API Connector cannot read HTTP response headers — so for large data sets requiring more than 100 records, you need to build a Backend Workflow that explicitly fetches pages by constructing the next-page URL with incrementing page number parameters.

For most school and corporate training apps, per_page=100 covers the complete dataset in a single call. Canvas supports institution subdomains independently, which is a genuine advantage for Bubble developers building multi-school platforms — each school's token and subdomain can be stored separately in Bubble's database, enabling the same Bubble app to serve dozens of institutions.

The result is a clean, fast integration that most Bubble developers complete in 2–3 hours — making Canvas the recommended starting point for any new education-focused Bubble project.

Integration method

Bubble API Connector

Call the Canvas LMS REST API (https://YOURSCHOOL.instructure.com/api/v1) using a personal Bearer access token stored as a Private header in Bubble API Connector.

Prerequisites

  • A Canvas LMS account with API access enabled (most Canvas institutions enable API access by default; confirm with your institution's Canvas administrator if uncertain)
  • A Canvas personal access token generated in Canvas Account → Settings → Approved Integrations → New Access Token
  • Your institution's Canvas subdomain (the part before .instructure.com in your Canvas URL, e.g., 'myschool' from myschool.instructure.com)
  • The API Connector plugin installed in your Bubble app (Plugins tab → Add plugins → search 'API Connector' by Bubble)
  • Bubble Starter plan or higher for Backend Workflows (needed for large dataset pagination beyond per_page=100; basic course and roster views work on the Free plan)

Step-by-step guide

1

Generate a Canvas personal access token

Log into your Canvas LMS account at your institution's Canvas URL (e.g., yourschool.instructure.com). In the top-right corner, click your profile avatar or name → **Account** → **Settings**. Scroll down to the **Approved Integrations** section (you may need to scroll past notification settings). Click **New Access Token**. In the dialog: - **Purpose**: Enter a descriptive name like 'Bubble Integration' — this helps you identify the token in the future - **Expires**: Leave blank for a non-expiring token, OR set an expiry date if your institution's policy requires it. For development purposes, no expiry date is convenient; for production, consider a 1-year expiry and build a token rotation reminder into your Bubble app Click **Generate Token**. Canvas displays the token string once — copy it immediately and store it somewhere safe (a password manager or secure notes app). Canvas will not show this token again after you close the dialog. The token looks like a long alphanumeric string (approximately 64 characters). This is your complete authentication credential — you do not need any additional client ID, secret, or OAuth flow. **Verify the token works:** In a new browser tab, visit this URL (replace values with your actual subdomain and token): `https://yourschool.instructure.com/api/v1/courses?access_token=YOUR_TOKEN_HERE&per_page=3` You should see a JSON array of your Canvas courses. If you see a 401 error, the token was copied incorrectly. If you see an empty array [], you have no active course enrollments with this account.

Pro tip: If you're building a multi-user Bubble app (where each user has their own Canvas token), you don't need to generate all tokens upfront. Each user will enter their own Canvas token in your Bubble app's onboarding flow, and the app stores it in their user record. This step only covers generating a single token for initial development and testing.

Expected result: You have a Canvas personal access token string (64+ characters). The verification URL in the browser returns a JSON array of Canvas courses, confirming the token is valid.

2

Configure the API Connector with institution subdomain and Private header

In your Bubble app, go to **Plugins tab → Add plugins**, search for 'API Connector' (by Bubble), and install it. Open the API Connector plugin settings. Click **Add another API** and name it **Canvas LMS**. Set the **Base URL** to: `https://yourschool.instructure.com/api/v1` — replace 'yourschool' with your actual Canvas subdomain. For multi-school apps where different users connect different Canvas instances, use a Bubble App Setting instead: create an App Setting named `canvas_base_url` and set the Base URL to a dynamic value populated from that setting per user session. **Shared Headers (API Group level):** Add one shared header: - **Key:** `Authorization` - **Value:** `Bearer YOUR_TOKEN_HERE` — paste your actual token - **Private:** YES — check this box. This marks the entire Authorization header as server-side only; it will not appear in browser network requests regardless of the calling context **Shared URL Parameters (API Group level):** Add one shared URL parameter: - **Key:** `per_page` - **Value:** `100` - **Private:** NO The per_page=100 parameter is critical — Canvas's default page size is 30 items. Without this parameter, a Repeating Group showing course enrollments will appear to show only 30 students even when a course has 200. Canvas supports a maximum of 100 items per page via per_page. The resulting API Group configuration: ```json { "base_url": "https://yourschool.instructure.com/api/v1", "headers": { "Authorization": "Bearer <private>" }, "shared_params": { "per_page": "100" } } ```

canvas-api-connector-config.json
1{
2 "base_url": "https://yourschool.instructure.com/api/v1",
3 "headers": {
4 "Authorization": "Bearer <private>"
5 },
6 "shared_params": {
7 "per_page": "100"
8 }
9}

Pro tip: For multi-user Bubble apps where each user provides their own Canvas token, store each user's token in a private User field (e.g., User's canvas_token) and pass it dynamically to the API Connector Authorization header. Store the institution's Canvas subdomain in a separate User field (canvas_subdomain) to allow users from different institutions to connect to their respective Canvas instances.

Expected result: The Canvas LMS API Group is created with the institution's subdomain in the base URL, Authorization header set as Private with your token, and per_page=100 as a shared URL parameter.

3

Add API calls and run Initialize

Within the Canvas LMS API Group, add individual API Calls for each Canvas endpoint you need. Each call inherits the shared Authorization header and per_page=100 parameter. **Call 1 — Get Courses:** - Name: Get Courses - Method: GET - URL append: `/courses` - Additional URL parameters: `enrollment_state` = `active` (to exclude concluded/deleted courses) - Use as: Data Click **Initialize call**. Bubble contacts Canvas and auto-detects the response fields from the courses array. You should see fields detected: `id`, `name`, `course_code`, `start_at`, `end_at`, `enrollment_count`, `workflow_state`, `time_zone`, `calendar`, and more. If Initialize fails with 'There was an issue setting up your call', check that your Authorization header value starts with 'Bearer ' (with a space), and that the token is copied correctly without any line breaks. **Call 2 — Get Course Assignments:** - Name: Get Assignments - Method: GET - URL append: `/courses/<course_id>/assignments` - Parameters: `course_id` = dynamic (will be set in workflows) - Use as: Data Initialize with a real course ID from your Canvas account (visible in the URL when you open a course in Canvas). **Call 3 — Get Course Students (roster):** - Name: Get Students - Method: GET - URL append: `/courses/<course_id>/students` - Parameters: `course_id` = dynamic - Use as: Data **Call 4 — Get Student Submissions:** - Name: Get Submissions - Method: GET - URL append: `/courses/<course_id>/students/submissions` - Parameters: `course_id` = dynamic, `student_ids` = `all`, `workflow_state` = `submitted` - Use as: Data Initialize each call with real IDs from your Canvas test account.

canvas-get-courses-call.json
1{
2 "method": "GET",
3 "url": "https://yourschool.instructure.com/api/v1/courses/active",
4 "headers": {
5 "Authorization": "Bearer <private>"
6 },
7 "params": {
8 "per_page": "100",
9 "enrollment_state": "active"
10 }
11}

Pro tip: Run Initialize call before wiring any API call to Bubble workflows or Repeating Groups. Bubble needs the response schema to show you the available data fields in the property editor. If Canvas adds new fields in an API update and they don't appear in Bubble, re-run Initialize to refresh the schema.

Expected result: All four API calls are initialized successfully. Bubble auto-detects response fields for courses (id, name, course_code, start_at, etc.), assignments, students, and submissions. The API Connector shows green checkmarks on all initialized calls.

4

Handle Canvas dates and build the course dashboard

Canvas returns dates as ISO 8601 strings with timezone offsets — for example: `2026-09-01T23:59:00-07:00`. Bubble handles these natively with the `:formatted as date` dynamic operator, but there's a subtle display gotcha: timezone offsets can cause off-by-one-day display bugs for users in different time zones. **Safe date handling in Bubble:** When displaying Canvas dates: - Use `:formatted as date` with a fixed UTC reference or specify the timezone explicitly if your Bubble app's user base is in a known region - For due dates, always display time alongside date (e.g., 'Sep 1, 2026 at 11:59 PM') to avoid ambiguity when the due time is close to midnight **Build the course dashboard page:** Create a page `canvas-dashboard` in Bubble. Add a **Repeating Group** with: - Type: Canvas LMS - Get Courses (auto-detected Data Type) - Data Source: Get data from external API → Canvas LMS - Get Courses - If multiple Canvas users: add the Authorization header as a dynamic value from `Current User's canvas_token` In each cell, display: - `Current cell's name` — course full name - `Current cell's course_code` — the short code (e.g., BIO-101-S26) - `Current cell's start_at formatted as date` — course start date - `Current cell's enrollment_count` — number of enrolled students - A 'View Course' button that navigates to a course detail page with `Current cell's id` as a URL parameter **Course detail page:** Create a page `canvas-course` with URL parameter `course_id` (number). Add a Repeating Group for Students: Data Source = Get Students with course_id = URL parameter. Add a Repeating Group for Assignments: Data Source = Get Assignments with course_id = URL parameter. For each student row, show name, email (if returned by your Canvas instance's privacy settings), and a count of submitted assignments (filtered from the Submissions call where student_id = current student's id).

Pro tip: Canvas's /courses endpoint only returns courses where the authenticated user is enrolled (as student, teacher, or observer). If you need all courses in the institution regardless of enrollment, an admin token with the 'manage_courses' permission can use the /api/v1/accounts/{account_id}/courses endpoint — ask your Canvas administrator for the account ID.

Expected result: The Canvas dashboard page displays the authenticated user's active Canvas courses in a Repeating Group with course names, codes, start dates, and enrollment counts. Clicking a course navigates to the course detail page showing the student roster and assignment list.

5

Handle multi-user Canvas tokens and privacy rules

For Bubble apps where each user provides their own Canvas personal token (such as a platform serving multiple teachers or students from the same school), you need to store tokens per-user and pass them dynamically to API calls. **User Data Type configuration:** Go to Data tab → User. Add two text fields: - `canvas_token` — the user's personal Canvas access token - `canvas_subdomain` — the user's institution subdomain (if your app supports multiple institutions) **Privacy rules on User fields:** Go to Data tab → User → Privacy. Add a rule: - 'This User is visible when' → Current User is the User (or: Current User = [User record]) - Under field-level visibility: ensure `canvas_token` and `canvas_subdomain` are only visible when 'Current User is the User' This prevents any user from seeing another user's Canvas token — critical since the token grants the same permissions as the Canvas account holder. **Canvas token onboarding flow:** Create an onboarding page for new users that walks them through: 1. Finding their Canvas URL (yourschool.instructure.com) 2. Generating a token in Canvas Account → Settings → New Access Token 3. A text input field in your Bubble app where they paste the token 4. A 'Connect Canvas' button that saves the token to `Current User's canvas_token` via a workflow 5. After saving, immediately validate the token by running the Get Courses API call — if it succeeds (returns at least one course or an empty array), show 'Connected ✓'. If it returns 401, show 'Invalid token — please try again'. **Dynamic Authorization in API calls:** For all Canvas API calls in a multi-user app, do NOT use a hardcoded token in the shared header. Instead, set the Authorization header value dynamically in each workflow or Repeating Group data source binding: `Bearer [Current User's canvas_token]`.

Pro tip: RapidDev's team has built multi-school Canvas dashboards on Bubble for ed-tech platforms serving dozens of institutions from a single Bubble app. If your architecture involves multiple institutions, custom role hierarchies, or district-level reporting across schools, book a free scoping call at rapidevelopers.com/contact.

Expected result: Each Bubble user has their own Canvas token stored in a private User field with privacy rules restricting access to themselves only. The API Connector calls dynamically use the current user's token. The onboarding flow validates the token on submission and gives immediate feedback on whether the connection succeeded.

6

Handle pagination for large datasets and launch

For most Canvas deployments (courses with fewer than 100 students, schools with fewer than 100 active courses), the per_page=100 shared parameter handles the complete dataset in a single API call. For large institutions where a single call returns fewer than the actual total, you need explicit pagination. **Understanding Canvas pagination:** Canvas signals 'there are more pages' via an HTTP Link response header that looks like: `<https://yourschool.instructure.com/api/v1/courses?page=2&per_page=100>; rel="next"` Bubble's API Connector cannot read HTTP response headers — only the JSON body. This means you cannot auto-detect when more pages exist. **Workaround for large datasets:** Option 1 (recommended for most cases): Use per_page=100 and build a note in your admin UI: 'Showing up to 100 records. Contact your Canvas administrator if your institution has more.' Most school and corporate Canvas deployments have fewer than 100 active courses. Option 2 (for institutions with 100+ records): Build a Backend Workflow that fetches pages explicitly: - Page 1: call `/courses?per_page=100&page=1`, store results in a Bubble Data Type (CanvasCourse) - If the result count = 100 (suggesting more may exist), run the same call with `&page=2`, merge results - Continue until a page returns fewer than 100 results (indicating the final page) This approach requires Bubble Starter plan for Backend Workflows and is only necessary for large institutional deployments. **Canvas token expiry:** Canvas tokens do not expire by default (unless an expiry date was set at creation). However, tokens can be invalidated by: - The user manually deleting the token in Canvas Settings - The institution's Canvas admin revoking all tokens (after a security incident) - Canvas policy changes at the institution level Build a 'token status' indicator in your Bubble app: run a lightweight Canvas API call (e.g., Get Courses with per_page=1) on login. If it returns 401, clear the stored token and redirect to the onboarding flow to reconnect. Before launch, test the full flow in the published app version, confirm per_page=100 parameter is visible in Bubble's Network tab as a URL parameter (not in the Authorization header — the header should not appear in network requests), and verify privacy rules prevent cross-user token access.

canvas-page2-call.json
1{
2 "method": "GET",
3 "url": "https://yourschool.instructure.com/api/v1/courses",
4 "headers": {
5 "Authorization": "Bearer <private>"
6 },
7 "params": {
8 "per_page": "100",
9 "page": "2",
10 "enrollment_state": "active"
11 }
12}

Pro tip: Add a token rotation reminder to your Bubble app: store `canvas_token_created_at` (date) in the User record when they first connect, and show a banner after 90 days: 'Your Canvas token is 90 days old — consider generating a new one in Canvas Settings for security.' This is especially important if Canvas administrators at your institution require periodic token rotation.

Expected result: The integration handles the per_page=100 limit appropriately for your institution's scale. The token status check on login prevents stale token errors. The full Canvas dashboard is live and accessible to all users who have connected their Canvas account through the onboarding flow.

Common use cases

Course roster and grade dashboard for instructors

A university instructor uses Bubble to build a consolidated view of their Canvas courses, showing student rosters, assignment submission rates, and grade distributions in a single dashboard. The app pulls live data via the Canvas API — including which students have not submitted an assignment yet — saving hours of clicking through Canvas's individual course views to compile the same information.

Bubble Prompt

Build a Bubble dashboard for a Canvas LMS instructor that shows all their active courses, and for each course lists enrolled students with their assignment submission status and current grades. Highlight students who have missing submissions in red.

Copy this prompt to try it in Bubble

Multi-school Canvas reporting platform

An ed-tech company builds a Bubble platform that allows multiple school districts to connect their Canvas LMS instances. Each district administrator registers with their Canvas subdomain and personal token; the Bubble app stores these per-district and fetches Canvas data per institution. A district-level admin sees course enrollment and completion rates across all schools in their district, aggregated in one view.

Bubble Prompt

Build a multi-tenant Bubble app where each school district enters their Canvas subdomain and personal token. The app fetches course data from each school's Canvas instance and displays a consolidated enrollment and course completion report per district.

Copy this prompt to try it in Bubble

Student assignment tracker and deadline reminder

A high school student builds a Bubble app that students use alongside Canvas. Students log in with their own Canvas personal token, and the app displays all upcoming assignments across all their enrolled courses in a unified deadline calendar view. The app highlights overdue assignments, shows submission status for each, and allows setting personal reminders — a unified view that Canvas's default interface doesn't provide across courses.

Bubble Prompt

Create a Bubble app where students enter their Canvas personal token. The app fetches all their enrolled courses and lists every upcoming assignment with due dates, formatted as a single deadline calendar. Mark submitted and missing assignments with different colors.

Copy this prompt to try it in Bubble

Troubleshooting

Initialize call returns 'There was an issue setting up your call' or a 401 Unauthorized response

Cause: Either the Authorization header value is incorrectly formatted (must be 'Bearer ' followed by the token with a space between Bearer and the token), the token was copied with extra whitespace or line breaks, or the Canvas institution's subdomain in the base URL is incorrect.

Solution: Verify the token in a browser: visit https://yourschool.instructure.com/api/v1/courses?access_token=YOUR_TOKEN&per_page=3. If this returns JSON course data, the token is valid. If it returns 401, regenerate the token in Canvas Settings. Then ensure the API Connector header value is exactly 'Bearer YOUR_TOKEN_HERE' with a single space between 'Bearer' and the token, no surrounding quotes, and no line breaks.

Repeating Group shows only 30 courses or students even though more exist in Canvas

Cause: The per_page shared URL parameter is missing or not set to 100. Canvas defaults to returning 30 items per page, and without per_page=100 the Repeating Group shows only the first 30 records.

Solution: Go to the Canvas LMS API Group in the API Connector. Under Shared URL Parameters at the group level (not the individual call level), confirm per_page=100 is present with value 100 and Private unchecked. If it's not there, add it. Re-initialize the affected calls after adding the parameter — Bubble needs to re-detect the response schema with the new parameter in place.

Canvas course dates display as off by one day for some users

Cause: Canvas returns dates as ISO 8601 strings with timezone offsets. A date of '2026-09-01T23:59:00-07:00' represents midnight minus 1 minute in Pacific Time — which is September 2nd in UTC. Users in UTC+ timezones see a different date than users in UTC- timezones.

Solution: When displaying Canvas dates in Bubble, use ':formatted as date' with an explicit time component to avoid ambiguity: show the full date and time rather than date-only. For due dates specifically, always include the time ('Sep 1 at 11:59 PM PDT') so users understand the exact deadline regardless of their timezone.

The Repeating Group seems to show all 100 items but the actual dataset has more than 100 records

Cause: Canvas paginates via the HTTP Link response header, not a JSON field. Bubble cannot read HTTP response headers, so it has no way to know there are additional pages. The Repeating Group shows exactly the records returned in the first API response (up to 100 with per_page=100).

Solution: For datasets larger than 100 items, build a Backend Workflow that explicitly fetches additional pages: call the endpoint with &page=1, store results in a Bubble Data Type, if result count = 100 call again with &page=2, continue until a page returns fewer than 100 items. This requires Bubble Starter plan for Backend Workflows. Alternatively, add a note in the admin UI: 'Showing first 100 records' with instructions to refine the search using Canvas-side filters (enrollment_state, course_code search).

API calls work for one user but return 401 for other users in the same Bubble app

Cause: In a multi-user app, each user's Canvas token must be stored individually and passed dynamically to API calls. If the Authorization header uses a hardcoded token at the API Group level, all users share that single token — which only works for the account that generated it.

Solution: Remove the hardcoded token from the shared Authorization header at the API Group level. Instead, set the Authorization header value dynamically in each Bubble workflow or Repeating Group data source: 'Bearer [Current User's canvas_token]'. Each user's canvas_token is stored in their private User record during the onboarding flow.

Some Canvas institutions block API access even with a valid token

Cause: Some Canvas institutions disable developer/API access as a security policy at the institutional level. The error appears as a generic 401 with no informative message distinguishing it from a bad token.

Solution: Contact the institution's Canvas administrator and ask whether the Developer Keys and API access are enabled for the institution's Canvas instance. If API access is blocked as a policy decision, there is no workaround at the Bubble app level — the institution must enable it in their Canvas admin settings. As an alternative for restricted institutions, request a Canvas data export (CSV) and use the CSV import approach instead.

Best practices

  • Always add per_page=100 as a shared URL parameter at the API Group level — this single setting prevents the most common Canvas API complaint in Bubble (Repeating Groups showing only 30 records). Canvas's default page size of 30 causes silently incomplete data without this parameter.
  • Mark the Authorization header as Private in Bubble's API Connector. Canvas personal tokens carry the full permissions of the generating user's account — a leaked token gives anyone who finds it complete API access to that user's Canvas data.
  • Store the Canvas base URL (institution subdomain) as a Bubble App Setting rather than hardcoding it in the API Connector base URL. This makes it easy to update when deploying the same Bubble app for a different institution, and enables multi-tenant apps to serve users from different Canvas deployments.
  • For multi-user apps, never hardcode a single Canvas token in the shared API Connector header. Each user's token must be stored in their private User record and passed dynamically. Set privacy rules on the canvas_token User field to restrict visibility to each user themselves.
  • Add a token validation check on every page load: run a lightweight Canvas API call (e.g., Get Courses with per_page=1) and if it returns 401, redirect the user to reconnect their Canvas account. Canvas tokens can be invalidated without notice by institutional administrators.
  • Display Canvas dates with time components, not date-only. Canvas's ISO 8601 dates include timezone offsets, and date-only display causes off-by-one-day bugs for users in different timezones — especially for due dates near midnight.
  • Cache assignment and submission data locally in Bubble's database for performance. The /students/submissions endpoint for a course with 100 students and 20 assignments represents a significant data fetch — run it once in a Backend Workflow, store results in a CanvasSubmission Data Type, and bind UI to the local cache rather than fetching live on every page view.
  • Set privacy rules on any locally cached Canvas data in Bubble's database. Student grade data and submission status are personally identifiable information under FERPA — ensure each student can only access their own records, and teacher-visible data is restricted to authorized roles.

Alternatives

Frequently asked questions

Do Canvas personal access tokens expire?

Canvas personal access tokens do not expire unless you set an expiry date when creating them. If you generate a token without setting an expiry, it remains valid indefinitely until you manually delete it in Canvas Settings or until an institution administrator revokes all tokens. For production Bubble apps, consider setting a 1-year expiry and building a token rotation reminder into your app that alerts users when their token is approaching its expiry date.

Why does my Repeating Group only show 30 courses when I have more than 30 in Canvas?

Canvas defaults to returning 30 items per API response page. Without the per_page=100 parameter, every Canvas API call returns only the first 30 results. Add per_page=100 as a shared URL parameter at the Canvas LMS API Group level in Bubble's API Connector — this increases the page size to Canvas's maximum and covers most use cases in a single API call.

Can I build a Canvas integration on Bubble's Free plan?

Yes, for basic read-only integrations. The API Connector with a Private Authorization header works on the Free plan — the Canvas token stays server-side through Bubble's infrastructure. You can build course and student roster Repeating Groups on the Free plan. However, Backend Workflows (for multi-page data fetching, scheduled syncs, and server-side data caching) require Bubble's Starter plan ($32/month) or higher.

My Canvas institution requires all students to keep their accounts' developer tokens disabled — what are my options?

If your institution's Canvas admin has disabled developer/API access as a policy, you have two paths: (1) Request that the admin enable API access for your integration specifically — admins can grant API access to specific users via Developer Keys in Canvas Settings. (2) Use Canvas's data export feature: Canvas administrators can export course, enrollment, and grade data as CSV. Import these CSVs into Bubble's database to build the same dashboards without live API access.

How do I handle a Canvas deployment with more than 100 courses or students?

For datasets larger than 100 items: build a Backend Workflow (requires Bubble Starter plan) that fetches pages explicitly using &page=1, &page=2, etc. Each page uses per_page=100. Continue fetching pages until a response returns fewer than 100 items, indicating the final page. Store all results in a local Bubble Data Type (e.g., CanvasCourse) and bind your Repeating Groups to the cached local data. This is more WU-efficient than live API calls and handles any dataset size.

Does a teacher's Canvas token give access to student grade data?

Yes — a teacher's Canvas token has the same permissions as their Canvas teacher account. In Canvas, teachers can read their students' grades, submission details, and quiz results. A student's token can only read their own data. For multi-role Bubble apps, validate the token's role before showing sensitive grade data: use the /api/v1/courses/{courseId}/enrollments?type=TeacherEnrollment call to check whether the token belongs to a teacher vs. student in a specific course, and show admin UI only to teachers.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Integrations are where projects stall

We wire Bubble integrations like this one every week — auth, webhooks, edge cases included. Fixed-price builds from $13K, delivered in 6–10 weeks.

Talk to an integration engineer

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.