Coursera's Partner API requires a formal enterprise agreement — it's not available to individual Coursera users. If you have Partner API access, build a RefreshCourseraToken Backend Workflow that exchanges your Client Credentials for a 1-hour access token, store it in a Bubble Config record, and use it in API Connector calls for course catalog and enrollments. For organizations without Partner API access, a CSV import path offers the same enrollment data without API credentials.
| Fact | Value |
|---|---|
| Tool | Coursera |
| Category | Education |
| Method | Bubble API Connector |
| Difficulty | Advanced |
| Time required | 5–8 hours |
| Last updated | July 2026 |
Coursera in Bubble: the enterprise gate you need to know about first
Before writing a single workflow in Bubble, there is one fact about Coursera's API that will determine whether you can build this integration at all: the Coursera Partner API is not self-service. Unlike most tools covered in this series — where you log in, find an API key section in settings, and start building — Coursera API access requires a formal business arrangement. You need either a Coursera for Business enterprise subscription (typically for companies paying for employee learning at scale) or a formal content partnership agreement with Coursera (for universities or course creators publishing on the platform).
If your organization doesn't have one of these agreements yet, the practical next step is to contact a Coursera account manager at coursera.org/business and request API credentials as part of your enterprise contract. This page explains exactly what to build once you have those credentials.
For organizations that do have Partner API access, Coursera's authentication model is OAuth 2.0 Client Credentials — a cleaner pattern than Authorization Code Grant because it doesn't require user login. Your application directly exchanges a clientId and clientSecret for an access token. In Bubble, this token exchange runs in a Backend Workflow, the token is stored in a Bubble Config Data Type, and all API calls read the token from that Config record. A scheduled recurring Backend Workflow refreshes the token every 50 minutes (the token expires approximately every hour).
For organizations without Partner API access, the practical alternative is Coursera's data export feature: Coursera for Business administrators can download CSV reports of learner progress, enrollments, and completions. A Bubble app can import these CSVs and build the same dashboards using locally stored data — without any API credentials.
This page covers both paths.
Integration method
Call the Coursera Partner API (api.coursera.org) using an OAuth 2.0 Client Credentials Bearer token, generated via a Backend Workflow and stored in a Bubble Config Data Type.
Prerequisites
- A Coursera for Business enterprise agreement OR Coursera content partner status — API credentials are not available without one of these; contact coursera.org/business if your organization does not yet have access
- Coursera Partner API credentials: clientId and clientSecret (provided by your Coursera account manager after agreement is in place)
- Your organization's Coursera Business ID (orgId) — provided in your Coursera admin dashboard or by your account manager
- Bubble Starter plan or higher — Backend Workflows are required for token exchange, refresh scheduling, and secure credential handling
- The API Connector plugin installed in your Bubble app (Plugins tab → Add plugins → search 'API Connector' by Bubble)
Step-by-step guide
Understand your access status and set up a Config Data Type
Before configuring anything in Bubble, confirm your organization has Partner API access. The clearest indicator: your Coursera account manager should have provided a `clientId` and `clientSecret`. If you only have a standard Coursera for Business admin login without API credentials, contact your Coursera account manager specifically to request Partner API access as part of your enterprise agreement. If you do not yet have API credentials, skip to Step 6 (CSV Import Alternative) now — it covers the data import path that works for all Coursera for Business subscribers without API credentials. **Set up the Config Data Type in Bubble:** Go to Data tab → Create a new Data Type: **Config**. Add these fields: - `coursera_client_id` (text) - `coursera_client_secret` (text) — marked sensitive - `coursera_access_token` (text) — will be populated by the refresh workflow - `coursera_token_expiry` (date) — when the current access token expires - `coursera_org_id` (text) — your Coursera Business organization ID **Set Privacy Rules on Config:** Data tab → Config → Privacy. Add a rule: 'This Config is visible when' → set the condition to require admin role (e.g., Current User's role is 'admin'). This restricts all Config records — including the client secret — to admin users only. Never expose Config data to regular users. **Manually create one Config record:** In Bubble's Data tab → App Data → Config → New Entry. Enter your clientId, clientSecret, and orgId values. Leave access_token and token_expiry empty — the refresh workflow will populate them.
Pro tip: Do not store the Coursera clientSecret in Bubble's App Settings or Option Sets — both are visible to developers with editor access. The Config Data Type with admin-only privacy rules is the correct storage pattern: it keeps the secret in the database, protected by Bubble's access control layer.
Expected result: A Config Data Type exists in Bubble with fields for clientId, clientSecret, orgId, access_token, and token_expiry. One Config record exists with your Coursera credentials entered. Privacy rules restrict Config visibility to admin users only.
Build the RefreshCourseraToken Backend Workflow
This Backend Workflow exchanges your clientId and clientSecret for a Coursera access token using the OAuth 2.0 Client Credentials grant. First, add the token endpoint to your API Connector. Go to Plugins tab → API Connector. Add a new API Group: **Coursera OAuth**. Add a call: - Name: Get Access Token - Method: POST - URL: `https://api.coursera.org/oauth2/client_credentials/token` - Body type: application/x-www-form-urlencoded - Body parameters: - `grant_type` = `client_credentials` - Authorization method: **Basic Auth** — with username = `<client_id>` (dynamic) and password = `<client_secret>` (dynamic, mark Private) Initialize this call with real credentials to detect the response: you should see `access_token`, `token_type` (Bearer), and `expires_in` fields. Now go to Settings → API → enable 'This app exposes a Workflow API'. Open Backend Workflows. Create a new Backend Workflow: **RefreshCourseraToken** (no parameters). Workflow actions: 1. **Search for Config** → search for the one Config record (your app has only one) 2. **Call Coursera OAuth - Get Access Token** → set username to Config's coursera_client_id, set password to Config's coursera_client_secret 3. **Make changes to Config record:** - `coursera_access_token` → Result of Step 2's access_token - `coursera_token_expiry` → Current date/time + 3600 seconds (you can use a Calculate: Current date/time + 50 minutes as a safety margin) **Schedule the refresh to run every 50 minutes:** In Backend Workflows, create a **Recurring Event**: schedule RefreshCourseraToken every 50 minutes. This ensures the access token never expires during business hours. The token is valid for approximately 1 hour — the 50-minute interval provides a 10-minute buffer.
1{2 "method": "POST",3 "url": "https://api.coursera.org/oauth2/client_credentials/token",4 "headers": {5 "Authorization": "Basic <base64(clientId:clientSecret)>",6 "Content-Type": "application/x-www-form-urlencoded"7 },8 "body": {9 "grant_type": "client_credentials"10 }11}Pro tip: Bubble's API Connector Basic Auth option handles the base64 encoding of clientId:clientSecret automatically when you select 'Basic Auth' as the authentication type and provide username and password as dynamic parameters. You do not need to manually encode the credentials.
Expected result: The RefreshCourseraToken Backend Workflow runs successfully: it calls the Coursera token endpoint, receives an access_token, and saves it to the Config record along with a token_expiry timestamp. The recurring event is scheduled to run every 50 minutes.
Configure Coursera API Connector calls
Add a second API Group in the API Connector: **Coursera API**. Set the Base URL to `https://api.coursera.org`. At the API Group level, add a shared header: - **Authorization**: `Bearer <access_token>` — this will be set dynamically from the Config record in each call **Call 1 — Get Course Catalog:** Add a call: - Name: Get Courses - Method: GET - URL: `/api/businesses/v1/programUserData.v1` - Parameters: `q` = `getCourseraUserData`, `limit` = `50`, `start` = `0` (pagination offset) - Use as: Data Note: Specific Coursera API endpoint paths depend on your contract type (for Business vs. content partner access). Your Coursera account manager will provide the exact endpoint documentation for your account type. The base URL and authentication pattern remain the same. **Call 2 — Get Enrollments:** Add a call: - Name: Get Enrollments - Method: GET - URL: `/api/businesses/v1/userEnrollments.v1` - Parameters: `limit` = `50`, `start` = `<start>` (dynamic, for pagination) - Use as: Data **Call 3 — Get Completions:** Add a call: - Name: Get Completions - Method: GET - URL: `/api/businesses/v1/completions.v1` - Parameters: `limit` = `50`, `start` = `0` For all calls: set the Authorization header value dynamically by reading from the Config record at the start of each workflow chain: - Before calling any Coursera API, add a Data action: 'Search for Config' → store result in a Custom State `current_config` - Pass `current_config's coursera_access_token` as the Authorization Bearer value
1{2 "method": "GET",3 "url": "https://api.coursera.org/api/businesses/v1/userEnrollments.v1",4 "headers": {5 "Authorization": "Bearer <access_token>"6 },7 "params": {8 "limit": "50",9 "start": "<start_offset>"10 }11}Pro tip: Coursera's Partner API returns pagination data in a 'meta' object within the response: meta.pagination.next contains the offset for the next page. Store this value in a Custom State and increment it on 'Load More' button clicks. For most business dashboards, the first 50 enrollments cover daily reporting needs without pagination.
Expected result: API Connector calls for course data and enrollments are configured and initialized successfully. The Initialize call returns real Coursera data (courses or enrollments) confirming that the access token and API endpoints are working correctly.
Build the enrollment dashboard with userId mapping
Create a page `coursera-dashboard` in your Bubble app. Access to this page should be restricted to admin users only (add a page-load condition that redirects non-admin users). **Token freshness check on page load:** Add a page-load workflow: 'Search for Config' (the single Config record). If Config's coursera_token_expiry is in the past → schedule RefreshCourseraToken Backend Workflow and wait before proceeding. If Config's coursera_access_token is empty → show an error message prompting admins to run the initial token refresh manually. **Enrollment list:** Add a Repeating Group. Data Source: 'Get data from external API → Coursera API - Get Enrollments'. Set the Authorization header to `Bearer [Config's coursera_access_token]` by referencing the Custom State loaded on page load. Each enrollment record from Coursera's API contains a Coursera `userId` (internal identifier) — not an employee name or email. To display employee names, you need a mapping table. **Building the userId-to-employee mapping:** Coursera's admin dashboard allows exporting a learner roster as a CSV. Request this export from your Coursera for Business admin. Create a Bubble Data Type: **CourseraUser** with fields: `coursera_user_id` (text), `full_name` (text), `email` (text), `department` (text). Import the CSV: Bubble's built-in CSV import (Data tab → App Data → CourseraUser → Upload CSV) populates this Data Type with your roster. In the enrollment Repeating Group, for each cell: 'Search for CourseraUsers where coursera_user_id = Current cell's userId' and display the matching full_name and email. For RapidDev's approach to building enterprise Coursera dashboards on Bubble — including multi-department filtering and automated roster sync patterns — see rapidevelopers.com/contact for a free scoping session.
Pro tip: Set privacy rules on the CourseraUser Data Type so only admin users can view the full employee roster. Individual employees should only be able to see their own record — add a rule: 'This CourseraUser is visible when Current User's email = This CourseraUser's email OR Current User's role is admin'.
Expected result: The enrollment dashboard loads and displays enrollment records with employee names resolved via the CourseraUser mapping table. The token freshness check prevents 401 errors from stale access tokens. Admin-only access controls prevent regular users from viewing the dashboard.
Implement pagination and completion tracking
Coursera's API uses numeric offset-based pagination: every response includes a `meta` object with `pagination` data containing the `next` offset and `total` count. **Pagination in Bubble:** Add a Custom State to your dashboard page: `pagination_start` (number, default 0). Set the Enrollments API call's `start` parameter to this Custom State value. Below the Repeating Group, add a 'Load More' button. Its workflow: 1. Check if 'pagination_start + 50 < total enrollment count' (use the `meta.pagination.total` from the last API response, stored in another Custom State `total_enrollments`) 2. If true: set `pagination_start` = `pagination_start + 50` 3. The Repeating Group re-fetches with the new start value For the total count, read `meta's total` from the enrollment API response and store it in a Custom State on the first load. **Completion rate display:** For each enrolled employee, call the Get Completions API to check their completion status for each course. This is WU-intensive — avoid calling it per-enrollment-row in a Repeating Group. Instead: 1. Build a 'Sync Completions' Backend Workflow that fetches all completions and stores them in a Bubble Data Type `CourseraCompletion` with fields: `coursera_user_id`, `course_id`, `completed_at`, `grade` 2. Run this workflow on demand (admin 'Sync Now' button) or on a daily schedule 3. Bind the Repeating Group to the locally cached CourseraCompletion data instead of live API calls This pattern — sync API data to Bubble DB, display from local cache — is essential for any Coursera dashboard with more than 50 learners. It dramatically reduces WU consumption and page load times.
Pro tip: Add a 'Last synced' text element on the dashboard showing Config's last sync timestamp. Update this field in the Config record whenever the sync workflow completes. Admins immediately know how fresh their data is and when to trigger a manual sync.
Expected result: The dashboard supports pagination for large enrollment lists. Completion data is synced to a local Bubble Data Type and displayed without live API calls on every page view. The 'Load More' button correctly advances through the enrollment list using offset pagination.
CSV import alternative for organizations without Partner API access
If your organization does not have Coursera Partner API access (no enterprise agreement or credentials from a Coursera account manager), the CSV import path provides the same enrollment and completion data for dashboard purposes. **How to export from Coursera for Business:** 1. Log into your Coursera for Business admin dashboard at coursera.org/business 2. Go to Analytics → Learner Progress (or similar — exact navigation varies by Coursera dashboard version) 3. Export the learner progress report as CSV 4. The CSV contains: user email, full name, course name, enrollment date, completion status, completion date, grade/score **Importing into Bubble:** Create a Data Type: **CourseraEnrollment** with fields matching the CSV columns: `user_email` (text), `user_name` (text), `course_name` (text), `enrolled_at` (date), `completed` (yes/no), `completed_at` (date), `grade` (text). In Data tab → App Data → CourseraEnrollment, click 'Upload CSV'. Map the CSV columns to Bubble fields. Import. Build the same dashboard Repeating Group but bound to the local CourseraEnrollment Data Type. Add a 'Last import' timestamp field to a Config record and display it prominently — CSV data is a point-in-time snapshot, not live. Add a 'Re-import' button on the admin panel that clears all existing CourseraEnrollment records and re-imports a fresh CSV. A Bubble workflow for deletion: 'Delete a list of Things' where the list is 'Search for CourseraEnrollments' (all records). This approach gives you 90% of the dashboard value without any API credentials. Many Coursera for Business subscribers use this pattern successfully alongside their standard subscription.
Pro tip: Display a prominent 'Data as of: [last import date]' badge on the CSV-based dashboard. Users need to know the data is a snapshot, not live — especially for compliance tracking where recent completions matter. Schedule a calendar reminder to refresh the import weekly or monthly.
Expected result: The CSV import-based enrollment dashboard works independently of API credentials. CourseraEnrollment records are imported from the exported CSV and displayed in the same dashboard layout. The admin panel includes a 'Re-import' button for refreshing data from a new CSV export.
Common use cases
Corporate L&D enrollment dashboard
A company with a Coursera for Business subscription builds a Bubble dashboard for HR administrators to track employee course enrollments and completion rates across departments. The Bubble app fetches live enrollment data from Coursera's API, displays completion percentages per employee and per course, and exports compliance training completion reports — replacing a manual monthly CSV-download-and-pivot-table process.
Build a Bubble dashboard for HR administrators that connects to our Coursera for Business API and shows all employee enrollments, grouped by department. Each employee's completion percentage and certificate status should be visible. Include a filter by course name and date range.
Copy this prompt to try it in Bubble
University course catalog portal
A university that publishes courses on Coursera builds a Bubble portal displaying their course catalog with enrollment statistics. The portal pulls live course data from the Coursera Partner API, shows current enrollment counts, course ratings, and completion metrics, and provides an embed widget for the university's main website — giving prospective students a richer view than Coursera's standard listing.
Create a Bubble app that displays our university's Coursera course catalog using the Partner API. Show each course's title, description, enrollment count, average rating, and a link to enroll on Coursera. Add search and filter by subject area.
Copy this prompt to try it in Bubble
Skills gap analysis for internal training teams
A technology company's learning team uses Bubble to build a skills tracking dashboard that maps Coursera course completions to internal job role competencies. As employees complete Coursera courses (pulled via the enrollment API), the Bubble app updates their skill profile and surfaces recommended next courses based on their role — creating a lightweight learning path manager on top of the Coursera catalog.
Build a Bubble app that pulls our Coursera enrollment and completion data via API and maps each completed course to internal skill tags from a lookup table. Show each employee's skill profile with percentage completion toward each required competency for their role.
Copy this prompt to try it in Bubble
Troubleshooting
Coursera token endpoint returns 401 Unauthorized when calling /oauth2/client_credentials/token
Cause: The clientId and clientSecret are incorrect, or Basic Auth is not being formatted correctly. Coursera expects the credentials as Base64-encoded 'clientId:clientSecret' in the Authorization header.
Solution: In Bubble's API Connector, when using Basic Auth, select 'Basic Auth' as the auth type and enter the clientId as username and clientSecret as password — Bubble handles the Base64 encoding automatically. If you're seeing 401, first verify the credentials in your Coursera admin portal by contacting your Coursera account manager to confirm the clientId and clientSecret values are active. Do not manually encode the credentials — use Bubble's built-in Basic Auth support.
All Coursera API calls fail with 401 after working initially
Cause: The access token has expired (approximately 1 hour validity) and the RefreshCourseraToken scheduled recurring event either failed to run or is not set up.
Solution: First, manually trigger the RefreshCourseraToken Backend Workflow from your Bubble admin panel to verify it still works. Check Bubble's Logs tab → Workflow logs for any errors in the scheduled recurring event. If the workflow itself fails, check whether the Config record still has valid clientId and clientSecret values. Add an error notification workflow in RefreshCourseraToken: if the token endpoint call fails, send an email to your admin address via SendGrid so you're alerted immediately.
Initialize call in API Connector returns 'There was an issue setting up your call'
Cause: The access token stored in the Config record is empty, expired, or the API endpoint path is incorrect. Bubble cannot initialize the call without a valid response.
Solution: First run the RefreshCourseraToken Backend Workflow manually to populate the Config's access_token field. Then retry the Initialize call using the fresh token value. If the endpoint path is uncertain, contact your Coursera account manager for the exact API endpoint documentation relevant to your contract type — endpoint paths differ between Coursera for Business and content partner accounts.
Backend Workflow scheduling option is not available in the workflow editor
Cause: Recurring Backend Workflows require a paid Bubble plan. The Free plan does not support Backend Workflows at all.
Solution: Upgrade to Bubble's Starter plan ($32/month) or higher. After upgrading, go to Settings → API → enable 'This app exposes a Workflow API'. The Backend Workflows tab and recurring event scheduling will become available. This plan is required for any secure Coursera integration since the token refresh must run server-side.
Enrollment records show Coursera userIds but no employee names or emails
Cause: The Coursera Partner API returns Coursera's internal userId identifiers in enrollment records, not email addresses or display names. No additional userId-to-email endpoint is provided within most API responses.
Solution: Export the learner roster CSV from your Coursera for Business admin dashboard (Analytics → Learner Progress → Export). Import it into a Bubble CourseraUser Data Type with coursera_user_id and email fields. In the enrollment Repeating Group, search for a matching CourseraUser by coursera_user_id to display the employee name. Keep the roster CSV up to date by re-importing whenever new employees are added to your Coursera subscription.
Best practices
- Lead with the access gate: always confirm your organization has a Coursera for Business enterprise agreement or content partnership before attempting any API integration. Attempting to build without credentials wastes days of development time.
- Store clientId and clientSecret in a Bubble Config Data Type with admin-only privacy rules — never in App Settings, Option Sets, or user-facing Data Types. Config records with privacy rules keep credentials inside Bubble's database access control layer.
- Refresh the access token on a 50-minute schedule rather than every hour. The token lasts approximately 60 minutes, but a 10-minute buffer prevents edge cases where the scheduled workflow runs slightly late and the token expires mid-request.
- Add an error notification workflow in RefreshCourseraToken: if the token endpoint call fails (network error, credentials changed, Coursera outage), send an email alert to administrators immediately. Silent token refresh failures will silently break all Coursera API calls.
- Cache enrollment and completion data locally in Bubble's database rather than calling the Coursera API on every page load. This minimizes WU consumption, improves page load speed, and ensures the dashboard remains responsive even if Coursera's API is temporarily slow.
- Import the learner roster CSV from Coursera's admin dashboard into a Bubble Data Type for userId-to-email mapping. Without this mapping table, enrollment records display only internal Coursera IDs rather than recognizable employee names.
- Set admin-only privacy rules on the CourseraUser mapping table and all enrollment/completion Data Types. Employee learning records are sensitive HR data — ensure only authorized admin users and the individual employee themselves can access each record.
- For organizations without Partner API access, the CSV import path (Step 6) delivers 90% of the dashboard value using standard Coursera for Business admin exports. Do not block product development waiting for API access if the CSV approach meets your immediate needs.
Alternatives
Canvas LMS offers a self-service API accessible to any Canvas account holder without an enterprise agreement. No business contract required, simpler Bearer token auth, and immediate access — unlike Coursera's gated Partner API.
Thinkific's API is available on any paid plan ($36/month Basic tier) without an enterprise agreement. Simple dual-header authentication, no OAuth flow, and full enrollment management API access — a significantly lower barrier to entry than Coursera's partnership requirement.
LearnWorlds API is accessible on Pro plan or higher without requiring a dedicated enterprise partnership. Static API key authentication with no OAuth token refresh needed — substantially simpler to integrate than Coursera's Client Credentials flow.
Frequently asked questions
Can I use the Coursera API without a Coursera for Business enterprise agreement?
No. The Coursera Partner API is not available to individual Coursera account holders, instructors, or learners. Access requires either a formal Coursera for Business enterprise subscription (typically for companies with 10+ employees and a dedicated contract) or a content partnership agreement for universities and course creators publishing on the platform. Contact coursera.org/business to request API access as part of your enterprise agreement.
What is OAuth 2.0 Client Credentials grant and how is it different from the login-based OAuth flow?
OAuth 2.0 Client Credentials grant is a server-to-server authentication pattern where your application directly exchanges credentials (clientId + clientSecret) for an access token — no user login or consent screen is involved. This is different from the Authorization Code Grant used by Google Classroom, where users must log in and approve access. Client Credentials is simpler to implement in Bubble because it's just a POST request in a Backend Workflow, with no redirect URLs, authorization pages, or user interaction required.
How often do I need to refresh the Coursera access token?
Coursera access tokens are valid for approximately 1 hour. The recommended pattern is to run a scheduled Backend Workflow every 50 minutes that calls the token endpoint and updates the stored access token in your Config record. This 10-minute buffer before the hour mark prevents edge cases where the scheduled workflow runs slightly late. If you need precise control, store the token expiry timestamp in the Config record and check it before every API call.
The Coursera API returns userIds in enrollment records — how do I display employee names?
Coursera's Partner API returns internal Coursera userIds rather than email addresses in most enrollment endpoints. To display employee names, export the learner roster CSV from your Coursera for Business admin dashboard (Analytics → Learner Progress → Export) and import it into a Bubble Data Type called CourseraUser with fields for coursera_user_id, full_name, and email. In your enrollment Repeating Group, search for the matching CourseraUser by coursera_user_id to display the employee's name.
Can I build a Coursera dashboard without Partner API access?
Yes — using the CSV export path. Coursera for Business administrators can export learner progress reports as CSV files from the admin dashboard. Import these CSVs into Bubble's database to build the same enrollment and completion dashboards without any API credentials. The main limitation is that CSV data is a point-in-time snapshot (not live), so the dashboard shows data as of the last import. For most compliance reporting and progress tracking needs, weekly or monthly CSV imports are sufficient.
Does this integration work on Bubble's Free plan?
No. The entire Coursera integration requires Backend Workflows for: (1) the initial token exchange POST — which must send the client_secret server-side, (2) the scheduled 50-minute token refresh, and (3) data sync workflows that cache enrollment data locally. Backend Workflows are only available on Bubble's paid plans (Starter $32/month or higher).
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation