# How to Integrate Bolt.new with Coursera

- Tool: Bolt.new
- Difficulty: Intermediate
- Time required: 25 minutes
- Last updated: April 2026

## TL;DR

Coursera's Catalog API is available through their affiliate program and lets you fetch course listings, specializations, and degree programs to build a learning portal or course recommendation engine in Bolt.new. Sign up for Coursera's affiliate program at coursera.org/affiliates to get API access, then prompt Bolt to generate an API route that searches and displays Coursera courses with ratings and instructor data. Deploy to Netlify or Bolt Cloud before testing any affiliate link tracking.

## Build a Coursera Course Discovery App in Bolt.new Using the Catalog API

Coursera does not have an open public API accessible to all developers, but it offers a Catalog API to approved affiliates and partners. The affiliate program is free to join at coursera.org/affiliates, and approval typically takes a few business days. Once approved, you receive affiliate credentials (client ID and secret) that allow you to query Coursera's course catalog, fetch course details with ratings and instructor information, search by topic or skill, and generate affiliate links that earn commissions on subscriptions.

For Bolt.new developers, the most common use case is building a custom learning portal or course recommendation engine. Instead of sending users directly to Coursera's search results, you build a branded interface that filters and presents Coursera courses relevant to your audience — for example, a data science learning hub that only shows data-related courses with your affiliate links for course enrollment.

If you do not have or want affiliate access, Coursera course pages are also embeddable through their published widget links, and you can build a course catalog that simply links to Coursera URLs without API access. For teams or organizations, Coursera's enterprise API (available to Coursera for Teams/Enterprise customers) provides richer data including learner progress and completion rates — but this requires a paid enterprise subscription.

## Before you start

- A Coursera affiliate account — apply at coursera.org/affiliates (free, typically approved in 2-5 business days)
- Coursera affiliate API credentials (client ID and secret) from the affiliate dashboard
- A Bolt.new project with Supabase connected for storing user course preferences and history
- A deployed URL on Netlify or Bolt Cloud for testing affiliate link attribution in production
- Basic understanding of OAuth 2.0 client credentials flow for API authentication

## Step-by-step guide

### 1. Apply for Coursera Affiliate Access and Get API Credentials

Access to Coursera's Catalog API requires applying for their affiliate program. Navigate to coursera.org/affiliates and click the affiliate program link. The application asks about your website or app, your audience, and how you plan to promote Coursera courses. Approval is not guaranteed — Coursera evaluates whether your platform aligns with their educational mission and has genuine traffic potential.

Once approved (typically 2-5 business days), log into your Coursera affiliate dashboard. Find the API section, which provides your `client_id` and `client_secret`. These credentials use OAuth 2.0 Client Credentials flow — your API route first exchanges them for an access token, then uses that token to query the catalog.

If you need to prototype before affiliate approval, Coursera's catalog data is also accessible without auth through their legacy public API endpoints (some still work as of 2026), though these are not officially supported. For production apps, use the official affiliate API with proper credentials. Coursera also offers a Content API for deeper catalog access, and an Organization API for enterprise customers — the affiliate API is the most accessible entry point for independent developers.

Add your credentials to the .env file once you have them. Never include `client_secret` in client-side code — it must stay server-side in your API route.

```
# .env file in your Bolt project root
COURSERA_CLIENT_ID=your_coursera_client_id
COURSERA_CLIENT_SECRET=your_coursera_client_secret
# Your affiliate partner ID for link tracking (from affiliate dashboard)
COURSERA_AFFILIATE_ID=your_affiliate_partner_id
```

**Expected result:** You have Coursera affiliate credentials (client_id and client_secret) in your .env file and understand the OAuth 2.0 client credentials flow needed to authenticate.

### 2. Build the Coursera API Authentication and Search Route

Coursera's API uses OAuth 2.0 Client Credentials — your API route first requests an access token by POST-ing your client_id and client_secret to Coursera's token endpoint, then includes the token in subsequent catalog API requests. The access token is valid for a short period (typically 1 hour), so you need to handle token expiry and refresh.

For Bolt.new, the recommended pattern is to cache the access token in memory between requests. If the cached token is still valid (check the `expires_in` value from the token response), reuse it. If expired or absent, request a new token. This avoids unnecessary token requests on every API call, which would add 200-400ms of latency.

The Coursera catalog API returns course objects with rich metadata: name, description, slug, photo URL, workload estimate, certificate type, and the institutions offering the course. The search endpoint allows filtering by query string, topic, language, and difficulty level. For course details including instructor information, rating breakdowns, and syllabus items, a separate API call to the course detail endpoint is needed.

Bolt can generate the complete authentication flow and search endpoint from a single prompt. Specify that you want OAuth 2.0 client credentials, the token caching behavior, and the search parameter handling — Bolt will generate the full TypeScript implementation including proper error handling for expired tokens.

```
// app/api/courses/search/route.ts
import { NextRequest, NextResponse } from 'next/server';

// Cache the access token between requests
let cachedToken: string | null = null;
let tokenExpiry: number = 0;

async function getCourseraToken(): Promise<string> {
  // Return cached token if still valid (with 60s buffer)
  if (cachedToken && Date.now() < tokenExpiry - 60000) {
    return cachedToken;
  }

  const credentials = Buffer.from(
    `${process.env.COURSERA_CLIENT_ID}:${process.env.COURSERA_CLIENT_SECRET}`
  ).toString('base64');

  const response = await fetch('https://api.coursera.org/oauth2/client_credentials/token', {
    method: 'POST',
    headers: {
      'Authorization': `Basic ${credentials}`,
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: 'grant_type=client_credentials',
  });

  if (!response.ok) {
    throw new Error(`Token request failed: ${response.status}`);
  }

  const data = await response.json();
  cachedToken = data.access_token;
  tokenExpiry = Date.now() + (data.expires_in * 1000);
  return cachedToken!;
}

export async function GET(request: NextRequest) {
  const { searchParams } = new URL(request.url);
  const query = searchParams.get('q') || 'programming';
  const limit = Math.min(parseInt(searchParams.get('limit') || '12'), 24);
  const affiliateId = process.env.COURSERA_AFFILIATE_ID;

  try {
    const token = await getCourseraToken();

    const params = new URLSearchParams({
      'q': 'search',
      'query': query,
      'limit': limit.toString(),
      'fields': 'name,description,slug,photoUrl,workload,certificates',
    });

    const response = await fetch(
      `https://api.coursera.org/api/courses.v1?${params.toString()}`,
      { headers: { 'Authorization': `Bearer ${token}` } }
    );

    if (!response.ok) {
      return NextResponse.json({ error: 'Coursera API error' }, { status: response.status });
    }

    const data = await response.json();

    const courses = (data.elements || []).map((course: any) => ({
      id: course.id,
      name: course.name,
      description: course.description,
      slug: course.slug,
      photoUrl: course.photoUrl,
      workload: course.workload,
      enrollmentUrl: affiliateId
        ? `https://www.coursera.org/learn/${course.slug}?ranMID=40328&ranEAID=${affiliateId}`
        : `https://www.coursera.org/learn/${course.slug}`,
    }));

    return NextResponse.json({ courses, total: data.paging?.total });
  } catch (error: any) {
    return NextResponse.json({ error: error.message }, { status: 500 });
  }
}
```

**Expected result:** The /api/courses/search?q=python endpoint returns an array of Coursera courses with names, descriptions, workload estimates, and affiliate enrollment URLs.

### 3. Build the Course Discovery UI

With the API route returning course data, prompt Bolt to generate the course discovery interface. The most effective layout for a course catalog is a grid of course cards — each card showing the course thumbnail, name, provider institution, rating (if available), workload estimate, and an enrollment button.

Coursera's course data includes `photoUrl` for a course thumbnail and `slug` for building the enrollment URL. The `workload` field contains a free-text estimate like '4-6 hours per week for 4 weeks' — display this as-is rather than trying to parse it numerically. Course ratings are not directly available through the basic catalog API — the affiliate API endpoint for ratings is separate and may require additional permissions.

For the search experience, add a text input at the top of the page, topic filter chips (Data Science, Business, Computer Science, Personal Development, etc.), and a difficulty filter (Beginner, Intermediate, Mixed). The search should debounce user input (300ms delay) before calling the API to avoid excessive requests while the user types.

Bolt can also generate a course detail modal that loads additional information when a user clicks a course card. The detail view shows the full course description, partner institution logo, certificate type (Professional Certificate, Specialization, Single Course, Degree), and the full workload breakdown.

```
// components/CourseCard.tsx
interface Course {
  id: string;
  name: string;
  description: string;
  slug: string;
  photoUrl?: string;
  workload?: string;
  enrollmentUrl: string;
  provider?: string;
}

export function CourseCard({ course }: { course: Course }) {
  return (
    <div className="bg-white border border-gray-200 rounded-xl overflow-hidden hover:shadow-lg transition-shadow flex flex-col">
      {course.photoUrl && (
        <img
          src={course.photoUrl}
          alt={course.name}
          className="w-full h-40 object-cover"
        />
      )}
      <div className="p-4 flex flex-col flex-1">
        <h3 className="font-semibold text-sm leading-snug line-clamp-2 mb-1">
          {course.name}
        </h3>
        {course.provider && (
          <p className="text-xs text-gray-500 mb-2">{course.provider}</p>
        )}
        <p className="text-xs text-gray-600 line-clamp-2 flex-1 mb-3">
          {course.description}
        </p>
        {course.workload && (
          <p className="text-xs text-blue-600 mb-3">{course.workload}</p>
        )}
        <a
          href={course.enrollmentUrl}
          target="_blank"
          rel="noopener noreferrer"
          className="block text-center text-sm bg-blue-600 text-white rounded-lg py-2 hover:bg-blue-700 transition-colors"
        >
          Enroll on Coursera
        </a>
      </div>
    </div>
  );
}
```

**Expected result:** The course catalog page shows a searchable grid of Coursera courses with thumbnails, names, workload info, and affiliate enrollment links.

### 4. Add Course Saving and Personalized Recommendations

Transform the basic course directory into a personalized learning tool by tracking which courses users browse, save, or complete. This data enables simple recommendation logic — users who saved Python courses get recommendations for data science and machine learning courses next.

Create a `course_interests` table in Supabase that records user-course interactions: user_id, course_id (Coursera's ID), course_slug, action (saved, clicked, enrolled, completed), and timestamp. Enable RLS so users only see their own activity. Based on this data, build a personalized recommendation section: query the most popular topics in the user's saved courses, then fetch Coursera courses in those topics.

The saved courses feature works well in Bolt's WebContainer preview since it only involves Supabase reads and writes (outbound HTTP calls that the WebContainer supports). Users can browse and save courses in the development environment. Affiliate link clicks require a deployed URL for proper attribution tracking since affiliate cookies are set on the Coursera domain after the redirect.

For a complete learning tracker, add a progress notes feature: users can add personal notes to any course they are taking, mark lessons as complete, and track their learning streaks. This data lives entirely in Supabase — no Coursera API calls needed for note-taking — making it a reliable, API-call-free feature that enhances the app's value beyond what Coursera's own interface offers.

**Expected result:** Users can bookmark courses to their saved list, add notes, and track completion. The /my-learning page shows all saved courses with persistent notes across sessions.

### 5. Deploy and Activate Affiliate Link Tracking

Affiliate link tracking requires your app to be deployed to a real URL — Coursera's affiliate system sets tracking cookies when users are redirected from your affiliate URL to Coursera's site, and this requires a stable, publicly accessible domain. Bolt's WebContainer preview uses dynamic localhost URLs that cannot be registered as affiliate tracking origins.

Deploy to Netlify or Bolt Cloud by clicking Publish in Bolt's navigation. After the deployment completes, add environment variables to your hosting platform: `COURSERA_CLIENT_ID`, `COURSERA_CLIENT_SECRET`, and `COURSERA_AFFILIATE_ID` in Netlify's Site Configuration → Environment Variables or Bolt Cloud's Secrets panel.

Once deployed, test affiliate tracking by clicking an enrollment link and checking whether Coursera's affiliate dashboard registers the click within 24-48 hours. Some affiliate programs require approval of specific domains before tracking begins — log into your Coursera affiliate dashboard and verify your deployed domain is registered as an approved referral source.

For production monitoring, add click tracking to your enrollment buttons using a thin redirect handler: instead of linking directly to Coursera's affiliate URL, route through `/api/courses/track-click?slug=[slug]` which logs the click to Supabase and then redirects to the Coursera affiliate URL. This gives you first-party analytics on which courses generate the most engagement, independent of Coursera's affiliate dashboard.

**Expected result:** Deployed app shows affiliate links correctly attributed in Coursera's dashboard. Click events are tracked in Supabase for first-party analytics on course engagement.

## Best practices

- Cache Coursera API access tokens at the module level to avoid requesting a new token on every API call — tokens are valid for at least 1 hour and the token request adds 200-400ms of unnecessary latency
- Store saved course data (name, thumbnail, workload) as a snapshot at save time rather than relying on the Coursera API — courses can be retired or renamed, and you want saved lists to remain accurate
- Always open Coursera affiliate links with target='_blank' and rel='noopener noreferrer' for security and affiliate program compliance
- Add your own click tracking before redirecting to affiliate URLs — Coursera's affiliate dashboard data can be delayed by 24-48 hours, but your Supabase click log is real-time
- Respect Coursera's terms of service when displaying course data — do not present Coursera course content as your own original content, and attribute courses to their institutions
- Test affiliate attribution on your deployed URL before launching — affiliate cookies require stable production domains and do not work correctly on dynamic preview URLs
- Implement search result caching in Supabase for popular queries — a user searching 'Python' dozens of times per day should not trigger dozens of Coursera API calls

## Use cases

### Niche Learning Hub with Affiliate Links

Build a topic-specific learning portal (data science, digital marketing, project management) that curates the best Coursera courses for that niche. Users browse a clean, branded course catalog. When they click 'Enroll', they are redirected to Coursera with your affiliate tracking link, earning you a commission on any new subscriptions.

Prompt example:

```
Build a data science learning hub using the Coursera Catalog API. Fetch courses related to 'data science' and 'machine learning' using the API route that calls https://api.coursera.org/api/courses.v1?q=search&query=data+science with my affiliate credentials from process.env.COURSERA_CLIENT_ID and COURSERA_CLIENT_SECRET. Display courses as cards with: course name, university/provider, rating, number of enrolled students, difficulty level, and a duration estimate. Add an 'Enroll on Coursera' button with my affiliate tracking parameter appended to the URL.
```

### Employee Learning Recommendation Dashboard

An HR tool that recommends Coursera courses to employees based on their role or selected learning goals. Employees input their job title and desired skills, and the dashboard shows a personalized course list fetched from Coursera's catalog, along with the estimated time to complete each course.

Prompt example:

```
Create an employee learning dashboard. Show a skill-selection screen where employees pick 3 skills they want to develop from a list: Leadership, Data Analysis, Communication, Programming, Marketing, Finance. After selection, call the Coursera API to fetch courses matching those skills and display personalized recommendations with course descriptions, ratings out of 5 stars, the offering university, and a 'Start Learning' link. Store the employee's skill interests in Supabase linked to their user account.
```

### Course Comparison Tool

Users search for a topic and see side-by-side comparisons of the top 3-5 Coursera courses on that subject. Each course card shows the syllabus highlights, instructor credentials, total weeks to complete, weekly time commitment, and past student reviews, helping learners choose the best fit.

Prompt example:

```
Build a Coursera course comparison tool. Create a search input where users type a topic (like 'Python programming'). Fetch the top 5 matching courses from the Coursera API and display them in a comparison table with columns: Course Name, Provider, Rating, Duration, Difficulty, Enrollment Count. Add a details button that expands a card showing the course description and instructor bio. Include affiliate links on the enrollment buttons.
```

## Troubleshooting

### Coursera API returns 401 Unauthorized even with correct credentials

Cause: The OAuth 2.0 client credentials token request is failing, usually because the client_id and client_secret are being passed as query parameters instead of in the Authorization header using HTTP Basic authentication.

Solution: Encode your credentials as Base64 and pass them in the Authorization header: `Authorization: Basic [base64(client_id:client_secret)]`. The request body should contain `grant_type=client_credentials` as form-encoded data, not JSON. Verify the token endpoint URL is exactly `https://api.coursera.org/oauth2/client_credentials/token`.

```
// Correct token request format
const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
const response = await fetch('https://api.coursera.org/oauth2/client_credentials/token', {
  method: 'POST',
  headers: {
    'Authorization': `Basic ${credentials}`,
    'Content-Type': 'application/x-www-form-urlencoded',
  },
  body: 'grant_type=client_credentials',
});
```

### Course search returns empty results for valid topic searches

Cause: The Coursera catalog API requires the `q=search` parameter to activate text search mode. Without it, the API defaults to listing all courses and ignores the query parameter.

Solution: Always include `q=search` as a URL parameter before your search query. The correct URL format is: `https://api.coursera.org/api/courses.v1?q=search&query=[your+search+term]&fields=name,description,slug`. Without `q=search`, the API returns all courses regardless of the `query` parameter.

```
// Correct: include q=search parameter
const params = new URLSearchParams({
  'q': 'search',       // Required for text search mode
  'query': userQuery,  // The actual search term
  'limit': '12',
});
```

### Affiliate clicks not appearing in Coursera's dashboard after deployment

Cause: Your deployed domain is not registered as an approved affiliate referral source in the Coursera affiliate dashboard, or the affiliate link parameter format is incorrect.

Solution: Log into your Coursera affiliate dashboard and verify your deployed domain is listed as an approved website. Ensure the affiliate link URL includes the correct tracking parameters provided by your affiliate account — the exact parameter names (ranMID, ranEAID, etc.) depend on Coursera's current affiliate program structure. Check the affiliate dashboard for the correct link format.

## Frequently asked questions

### Do I need to be an affiliate to use the Coursera API?

Coursera's officially supported Catalog API requires affiliate program membership. You can apply at coursera.org/affiliates for free. For prototyping before approval, Coursera's legacy API endpoints (courses.v1) work without authentication for basic course listing, though they are not officially supported for production use. The full affiliate API also earns you commissions on referred subscriptions.

### Does Coursera API data work in Bolt's WebContainer preview?

Yes. The Coursera API calls are outbound HTTP requests from your API route — Bolt's WebContainer supports outbound calls during development. You can search and display courses in the preview without deploying. Affiliate link attribution requires a deployed URL, but browsing and displaying course data works fully in the preview.

### Can I show course ratings and reviews in my Bolt app?

Basic course ratings are not included in the standard catalog API response. The affiliate API provides access to some rating data through additional field requests in the API query. Check Coursera's affiliate API documentation for the current list of available fields — fields like `avgLearnerRating` and `totalEnrollmentCount` may be available with the right field selectors.

### How do I earn affiliate commissions from Coursera?

After joining Coursera's affiliate program, all enrollment links on your deployed app should include your affiliate tracking parameters (provided in your affiliate dashboard). When a user clicks your link and subscribes to Coursera Plus or enrolls in a paid certificate, Coursera attributes the referral to your affiliate ID and pays commission. Commissions are typically 15-45% of the subscription value and tracked via cookies for 30 days after the click.

### Can I build a Coursera app for my company's employee training?

For enterprise employee training use cases, Coursera for Teams or Coursera for Business is the appropriate product — it comes with an Organization API that provides learner progress tracking, completion certificates, and team management. The standard affiliate API is for public-facing course recommendation apps, not internal enterprise learning portals. Contact Coursera's enterprise sales team for an Organization API access.

---

Source: https://www.rapidevelopers.com/bolt-ai-integrations/coursera
© RapidDev — https://www.rapidevelopers.com/bolt-ai-integrations/coursera
