Skip to main content
RapidDev - Software Development Agency
v0-integrationsNext.js API Route

How to Integrate Teachable with V0

To integrate Teachable with V0 by Vercel, create a Next.js API route that fetches course and enrollment data from the Teachable API v1 using your TEACHABLE_API_KEY. V0 generates the course display and enrollment UI, the API route keeps your key server-side, and Teachable webhooks notify your app when students enroll or complete courses.

What you'll learn

  • How to fetch Teachable course listings and details using the Teachable API v1 from a Next.js API route
  • How to display course enrollment status and student progress data in a V0-generated UI
  • How to configure TEACHABLE_API_KEY as a server-only Vercel environment variable
  • How to set up a Teachable webhook endpoint in Next.js to receive enrollment notifications
  • How to build a custom course catalog page using V0 that displays Teachable courses with enrollment links
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate16 min read25 minutesOtherMarch 2026RapidDev Engineering Team
TL;DR

To integrate Teachable with V0 by Vercel, create a Next.js API route that fetches course and enrollment data from the Teachable API v1 using your TEACHABLE_API_KEY. V0 generates the course display and enrollment UI, the API route keeps your key server-side, and Teachable webhooks notify your app when students enroll or complete courses.

Embed Teachable Courses in Your V0-Generated Next.js App

Teachable is where many creators and educators host their courses, but the Teachable-hosted school interface may not match your brand or website design. V0 lets you build a fully custom course catalog, landing pages, and student portal in Next.js that pulls real data from your Teachable account via the API. Your students get a seamless branded experience on your site, and you keep Teachable's reliable course delivery infrastructure behind the scenes.

The Teachable API v1 provides access to your courses, enrollments, users, coupons, and reports. From a Next.js API route, you can fetch your complete course catalog with pricing, descriptions, and cover images, check whether a specific user is enrolled in a course, and retrieve a student's progress data. When someone clicks 'Enroll' on your custom page, you redirect them to the Teachable checkout URL for that course — Teachable handles payment processing securely, and a webhook notifies your app when enrollment is complete.

This approach is particularly valuable if you are building a broader content or community platform where Teachable courses are one component among many — alongside a blog, community forum, or coaching booking system all built with V0. Your students never need to know or visit teachable.com directly.

Integration method

Next.js API Route

V0 generates your course catalog, enrollment UI, and student dashboard components. A Next.js API route running on Vercel calls the Teachable API v1 with your TEACHABLE_API_KEY to fetch course listings, enrollment status, and student progress data. A second API route receives Teachable webhook events for enrollment and course completion notifications.

Prerequisites

  • A Teachable account with at least one course created — you need an existing school to generate an API key
  • Your Teachable API key from the Teachable Admin Dashboard under Settings → Integrations → API
  • A V0 project with Next.js App Router structure
  • A Vercel account for deployment and environment variable storage
  • Familiarity with copying and editing code in your project or IDE

Step-by-step guide

1

Get Your Teachable API Key

Log in to your Teachable school's admin panel at yourschool.teachable.com/admin. Navigate to Settings in the left sidebar, then click on the Integrations section. Scroll down until you find the API section, where you will see your API key. If you do not see an API key, you may need to generate one — look for a 'Generate API key' button. Copy this key and keep it secure. This is your TEACHABLE_API_KEY and it provides full API access to your school's data including courses, enrollments, and student information — treat it like a password. The Teachable API v1 base URL is https://developers.teachable.com/v1 and all requests require the apiKey header set to your API key. Note that the Teachable API is only available on certain Teachable plans — if you are on the basic plan, you may have limited API access. Check your current plan in Teachable Admin → Settings → Plan to confirm API access is available. The API provides endpoints for listing courses (/courses), getting course details (/courses/{id}), listing users (/users), checking enrollments (/courses/{id}/enrollments), and accessing reports. You will use the courses endpoint in your Next.js API route to power your course catalog.

Pro tip: Teachable's API documentation is available at developers.teachable.com. The API uses API key authentication via a request header, not OAuth, which makes it simpler to implement in a Next.js API route.

Expected result: You have copied your Teachable API key from Settings → Integrations → API and have it ready to add as a Vercel environment variable.

2

Generate the Course Catalog UI with V0

Open V0 and describe the course catalog layout you want. Be specific about what data you want to display for each course — cover image, title, description, price, number of students enrolled, number of lessons, and a call-to-action button. V0 is excellent at generating responsive card grids with filtering and sorting UI. Think about the user experience: do you want a grid or a list view? Do you need category filters? Should free courses be visually distinguished from paid ones? Describe your brand colors or overall aesthetic so V0 generates styling that matches your site. The course cards should have an 'Enroll Now' button that you will later wire up to redirect to the Teachable course enrollment URL. Teachable course enrollment URLs follow the pattern https://yourschool.teachable.com/purchase?product_id={course_id} for paid courses, or https://yourschool.teachable.com/enroll/{course_id} for free courses. V0 does not know these patterns, so you will add the link logic after generation. Focus on the visual design in this step and connect it to real Teachable data in the next steps.

V0 Prompt

Create a course catalog page at app/courses/page.tsx with a hero section containing a headline and subtitle. Below that, show a filter row with 'All', 'Free', and 'Paid' toggle buttons. Render courses in a responsive grid — 3 columns on desktop, 2 on tablet, 1 on mobile. Each course card should show a course cover image with aspect-ratio 16:9, course title, a 2-line description, instructor name and avatar, number of lessons, price or 'Free', a filled green progress bar showing percentage enrolled if applicable, and an 'Enroll Now' button. Include skeleton loading cards shown while data is loading. Use Tailwind CSS with a clean modern design.

Paste this in V0 chat

Pro tip: Ask V0 to generate skeleton loading cards that match the exact dimensions of your real course cards. This prevents layout shift when the real data loads and creates a polished loading experience.

Expected result: V0 generates a course catalog page with a hero section, filter buttons, responsive course card grid with skeleton loading states, and Enroll Now buttons on each card.

3

Create the Teachable Courses API Route

Now create the Next.js API route that fetches your Teachable course catalog server-side. This route calls the Teachable API v1 using your API key from the server environment. The key is never sent to the browser — all Teachable API communication happens between your Vercel serverless function and Teachable's servers. The Teachable API v1 uses a simple apiKey request header for authentication. Create an API route at app/api/teachable/courses/route.ts that fetches the list of published courses from https://developers.teachable.com/v1/courses, includes the course details like name, image_url, description, lecture_sections_count, heading, and the is_published flag, and returns the filtered list of published courses. You can also create a separate route for individual course details at app/api/teachable/courses/[id]/route.ts that fetches a single course with its full lecture listing. The course listings endpoint returns paginated data — handle pagination by accepting a page query parameter and passing it to Teachable's API, or fetch multiple pages and concatenate the results depending on how many courses you have. For a school with under 50 courses, a single request is usually sufficient. Return the courses as a clean JSON array from your API route, mapping only the fields your frontend needs.

V0 Prompt

Create a Next.js API route at app/api/teachable/courses/route.ts that fetches the list of published courses from the Teachable API v1. Use https://developers.teachable.com/v1/courses as the endpoint with process.env.TEACHABLE_API_KEY as the apiKey header. Filter to only return published courses. Map and return each course's id, name, heading, description, image_url, lecture_sections (count), is_published, price, and the Teachable course URL. Handle API errors and return appropriate error responses.

Paste this in V0 chat

app/api/teachable/courses/route.ts
1import { NextRequest, NextResponse } from 'next/server';
2
3const TEACHABLE_API_KEY = process.env.TEACHABLE_API_KEY;
4const TEACHABLE_API_BASE = 'https://developers.teachable.com/v1';
5
6export async function GET(request: NextRequest) {
7 if (!TEACHABLE_API_KEY) {
8 return NextResponse.json(
9 { error: 'Teachable API key not configured' },
10 { status: 500 }
11 );
12 }
13
14 try {
15 const { searchParams } = new URL(request.url);
16 const page = searchParams.get('page') || '1';
17
18 const res = await fetch(
19 `${TEACHABLE_API_BASE}/courses?page=${page}&per=30`,
20 {
21 headers: {
22 apiKey: TEACHABLE_API_KEY,
23 Accept: 'application/json',
24 },
25 next: { revalidate: 300 }, // Cache for 5 minutes
26 }
27 );
28
29 if (!res.ok) {
30 const error = await res.json().catch(() => ({}));
31 console.error('Teachable API error:', error);
32 return NextResponse.json(
33 { error: 'Failed to fetch courses from Teachable' },
34 { status: res.status }
35 );
36 }
37
38 const data = await res.json();
39 const courses = (data.courses || []).filter(
40 (course: { is_published: boolean }) => course.is_published
41 );
42
43 return NextResponse.json({
44 courses: courses.map((course: {
45 id: number;
46 name: string;
47 heading: string;
48 description: string;
49 image_url: string;
50 is_published: boolean;
51 lecture_sections: { lectures: unknown[] }[];
52 price?: number;
53 }) => ({
54 id: course.id,
55 name: course.name,
56 heading: course.heading || '',
57 description: course.description || '',
58 imageUrl: course.image_url || null,
59 lectureCount: course.lecture_sections?.reduce(
60 (acc: number, section: { lectures: unknown[] }) => acc + (section.lectures?.length || 0),
61 0
62 ) || 0,
63 price: course.price || 0,
64 isFree: !course.price || course.price === 0,
65 enrollUrl: `https://${process.env.TEACHABLE_SCHOOL_SUBDOMAIN}.teachable.com/p/${course.id}`,
66 })),
67 meta: data.meta || {},
68 });
69 } catch (error) {
70 console.error('Teachable API error:', error);
71 return NextResponse.json(
72 { error: 'Internal server error' },
73 { status: 500 }
74 );
75 }
76}

Pro tip: Add next: { revalidate: 300 } to your Teachable API fetch calls to cache course listings for 5 minutes. Course catalogs rarely change more frequently than that, and caching dramatically reduces Teachable API rate limit consumption.

Expected result: Visiting /api/teachable/courses returns a JSON array of published courses with their names, descriptions, image URLs, lecture counts, and enrollment URLs.

4

Add a Teachable Webhook Endpoint for Enrollment Events

Teachable can notify your Next.js app via webhooks when key events happen — most importantly, when a student enrolls in a course or completes it. This lets you trigger actions like sending a welcome email, adding the student to a CRM, unlocking content in your app, or updating a custom student database. Create a webhook endpoint at app/api/teachable/webhook/route.ts. In your Teachable admin, go to Settings → Integrations → Webhooks and add your endpoint URL (https://your-vercel-app.vercel.app/api/teachable/webhook). Teachable will send POST requests to this URL with event data as JSON. The event data includes an event_type field (like enrollment.created or course_completion.created), the course ID, and the user's email and name. Teachable includes a signature header for webhook verification — check the Teachable API documentation for your specific webhook secret setup. In your webhook handler, verify the event type and process it accordingly. For enrollment notifications, you might store the enrollment in your own database, send a custom welcome email via Mailgun, or add the user to a Slack channel. Return a 200 status quickly and do any heavy processing asynchronously to prevent Teachable from timing out and retrying the webhook.

V0 Prompt

Create a Next.js API route at app/api/teachable/webhook/route.ts that receives Teachable webhook POST requests. Parse the JSON body to get event_type, course name, and user email/name. Handle the enrollment.created event by logging the enrollment details. Handle the course_completion.created event by logging the completion. Return 200 on success. Log unhandled event types but still return 200. Add error handling for malformed requests.

Paste this in V0 chat

app/api/teachable/webhook/route.ts
1import { NextRequest, NextResponse } from 'next/server';
2
3type TeachableWebhookPayload = {
4 event_type: string;
5 object_type: string;
6 id: number;
7 course?: {
8 id: number;
9 name: string;
10 };
11 user?: {
12 id: number;
13 name: string;
14 email: string;
15 };
16};
17
18export async function POST(request: NextRequest) {
19 try {
20 const payload: TeachableWebhookPayload = await request.json();
21 const { event_type, user, course } = payload;
22
23 console.log(`Teachable webhook received: ${event_type}`, {
24 userId: user?.id,
25 userEmail: user?.email,
26 courseId: course?.id,
27 courseName: course?.name,
28 });
29
30 switch (event_type) {
31 case 'enrollment.created':
32 // Handle new enrollment
33 // TODO: Add to database, send welcome email, etc.
34 console.log(`New enrollment: ${user?.email} enrolled in ${course?.name}`);
35 break;
36
37 case 'course_completion.created':
38 // Handle course completion
39 // TODO: Send completion email, issue certificate, etc.
40 console.log(`Course completed: ${user?.email} completed ${course?.name}`);
41 break;
42
43 case 'enrollment.payment_refunded':
44 // Handle refund
45 console.log(`Enrollment refunded: ${user?.email} for ${course?.name}`);
46 break;
47
48 default:
49 console.log(`Unhandled Teachable event: ${event_type}`);
50 }
51
52 return NextResponse.json({ received: true });
53 } catch (error) {
54 console.error('Teachable webhook error:', error);
55 // Still return 200 to prevent Teachable from retrying
56 return NextResponse.json({ received: true });
57 }
58}

Pro tip: Always return 200 from your webhook handler even if you encounter an error processing the event. If you return a non-2xx status, Teachable will retry the webhook, potentially causing duplicate processing. Log errors internally and return 200 to Teachable.

Expected result: When a student enrolls in a course, Teachable sends a POST to your webhook URL and your Next.js app logs the enrollment event. The Teachable webhook delivery log shows successful deliveries.

5

Configure Environment Variables and Deploy

Add your Teachable credentials to Vercel so your deployed app can connect to the Teachable API. Go to your Vercel project dashboard, click Settings in the top navigation, and select Environment Variables in the left sidebar. Add the following server-only environment variables: TEACHABLE_API_KEY set to your API key from Teachable Admin → Settings → Integrations → API (no NEXT_PUBLIC_ prefix — this key must stay server-side), and TEACHABLE_SCHOOL_SUBDOMAIN set to your Teachable school subdomain (the part before .teachable.com in your school URL, for example if your school is myschool.teachable.com, the subdomain is myschool). Set both variables for Production, Preview, and Development environments. After saving, go to the Deployments tab and redeploy your latest deployment to pick up the new variables. Once deployed, test the course catalog by visiting your /courses page — it should load your Teachable courses from the API. If the courses do not appear, check Vercel Function Logs under your project's Functions tab for error messages. After confirming the API route is working, register your webhook endpoint in Teachable Admin → Settings → Integrations → Webhooks by entering your full Vercel deployment URL followed by /api/teachable/webhook. For integrations requiring complex data synchronization between Teachable and additional tools, RapidDev's team can help architect a robust solution.

.env.local
1# .env.local (for local development never commit this file)
2TEACHABLE_API_KEY=your-teachable-api-key-here
3TEACHABLE_SCHOOL_SUBDOMAIN=yourschoolname

Pro tip: After registering your webhook in Teachable, use the 'Test' button next to the webhook URL in the Teachable dashboard to send a test event. Check your Vercel function logs to confirm the test event was received and processed correctly.

Expected result: Your deployed Vercel app displays your Teachable course catalog fetched from the API. The Teachable webhook is registered and test events appear in your Vercel function logs.

Common use cases

Custom Course Catalog Landing Page

A course creator wants a branded landing page that displays all their Teachable courses with custom formatting, testimonials, and a consistent design system. The Next.js app fetches the course list from Teachable and renders it in a custom grid layout, with each card linking to the Teachable course checkout.

V0 Prompt

Create a course catalog page that displays courses in a 3-column responsive grid. Each course card should show the cover image, course title, instructor name, a short description, number of lessons, price (or 'Free' for free courses), star rating, and an 'Enroll Now' button. Add a filter bar at the top to filter by category. Fetch courses from /api/teachable/courses. Use Tailwind CSS with a clean modern design.

Copy this prompt to try it in V0

Student Dashboard with Progress Tracking

An existing student wants to see all their enrolled courses and completion progress in one dashboard on the creator's custom site. The app fetches enrollment data and course progress from Teachable and displays it in a personalized dashboard.

V0 Prompt

Build a student dashboard page that shows a welcome message with the student's name, a grid of enrolled courses with progress percentage bars, completed courses with completion dates, and recently viewed lessons. Each course card should show the next lesson to continue. Fetch enrollment data from /api/teachable/enrollments?email=user@example.com. Style with Tailwind CSS in a clean dashboard layout with a sidebar navigation.

Copy this prompt to try it in V0

Course Launch Announcement with Waitlist

A creator is launching a new Teachable course and wants to build a custom pre-launch page with a waitlist form. When the course goes live, Teachable notifies the app via webhook and the waitlist emails receive an automated notification.

V0 Prompt

Create a course waitlist landing page with a hero section showing the course title, a compelling description, instructor bio with photo, a list of what students will learn, and an email signup form to join the waitlist. Show a countdown timer to the launch date. The form should POST to /api/waitlist/join. Include social proof with testimonials from beta students. Style with Tailwind CSS using a bold, high-contrast design.

Copy this prompt to try it in V0

Troubleshooting

Teachable API returns 401 Unauthorized

Cause: The TEACHABLE_API_KEY environment variable is missing from Vercel, set incorrectly, or the API key has been regenerated in Teachable since you copied it.

Solution: Verify your API key in Teachable Admin → Settings → Integrations → API. Copy it again carefully, ensuring no leading or trailing spaces. Update the TEACHABLE_API_KEY in Vercel and redeploy. After updating environment variables in Vercel, you must trigger a new deployment — changes do not apply to existing deployments automatically.

Teachable API returns courses but image_url is null or images are not loading

Cause: Courses without a cover image set in Teachable return null for image_url. Your frontend component may crash or show broken image elements when the image URL is null.

Solution: Add a fallback image in your course card component. Check for null image_url before rendering the img tag, and show a placeholder course cover image when the URL is missing.

typescript
1<img
2 src={course.imageUrl || '/images/course-placeholder.jpg'}
3 alt={course.name}
4 className="w-full aspect-video object-cover"
5/>

Teachable webhook events are being received but not matching expected event_type strings

Cause: Teachable may use different event type strings than documented, or event types vary by Teachable plan. The payload structure may also differ from what is shown in older documentation.

Solution: Log the full raw request body in your webhook handler and check Vercel function logs to see the actual event_type strings being sent. Update your switch statement to match the actual strings from Teachable.

typescript
1// Temporarily log the full payload to see the actual structure:
2export async function POST(request: NextRequest) {
3 const body = await request.text();
4 console.log('Raw Teachable webhook body:', body);
5 const payload = JSON.parse(body);
6 console.log('Parsed payload:', JSON.stringify(payload, null, 2));
7 return NextResponse.json({ received: true });
8}

Course enrollment URLs redirect to a Teachable error page

Cause: The enrollment URL format is incorrect for your Teachable school, or the course ID in the URL does not match an active published course.

Solution: Check the correct enrollment URL format for your Teachable school in the Teachable Admin under the course settings. The URL pattern may be /courses/{course-name} using a slug rather than /p/{course-id}. Open a course in Teachable Admin and click Preview to see the correct public URL for that course.

Best practices

  • Store TEACHABLE_API_KEY as a server-only environment variable without NEXT_PUBLIC_ prefix — the API key provides full access to your school's data including student personal information
  • Cache Teachable API responses using Next.js fetch caching with revalidate times — course listings rarely change in real time and caching reduces API call volume and improves page load speed
  • Handle null values for all Teachable course fields — not every course has a cover image, heading, or description, and your UI components must render gracefully when data is missing
  • Always return HTTP 200 from your webhook endpoint regardless of processing success — returning non-2xx codes causes Teachable to retry the webhook, which can lead to duplicate event processing
  • Test the full enrollment flow end-to-end with a free course before going live — verify that clicking Enroll Now redirects correctly to Teachable and that the post-enrollment webhook fires
  • Implement pagination in your courses API route so it works correctly as your course catalog grows beyond 30 courses
  • Use the Teachable webhook enrollment.created event to trigger welcome emails or onboarding sequences rather than polling the enrollments endpoint, which is more efficient and real-time

Alternatives

Frequently asked questions

Does Teachable's API let me access student enrollment data from my V0 app?

Yes. The Teachable API v1 includes endpoints for listing enrollments for a specific course and checking whether a specific user is enrolled. You can fetch a user's enrollments by email using the /users endpoint combined with /courses/{id}/enrollments. This data includes enrollment date, completion percentage, and last seen timestamp.

Can I process Teachable course payments in my V0 app instead of on Teachable?

Teachable's checkout is handled on Teachable's platform for security and compliance reasons — you cannot fully replace it with your own payment flow. However, you can create a custom pre-checkout experience on your V0 site that collects user interest, applies coupon codes, and then redirects to Teachable's checkout with those parameters pre-filled.

Is the Teachable API available on all Teachable plans?

Teachable API access is available on the Pro plan and above. The Basic (Free) plan does not include API access. If you upgrade to Pro or Business, the API key will appear in your Settings → Integrations → API section. Check teachable.com/pricing for the current plan comparison.

How do I display a student's course progress in my V0 app?

Use the Teachable API's enrollment progress endpoint to fetch a specific user's progress on a course. You will need the course ID and the user's Teachable user ID, which you can look up by email using the /users endpoint. The progress data includes completed_lecture_ids and a percentage completion value. Display this as a progress bar in your V0-generated student dashboard.

Can I use V0 to create a custom Teachable course landing page that outperforms Teachable's built-in sales pages?

Yes, this is one of the most common use cases. V0 can generate highly optimized course landing pages with video sections, instructor bios, curriculum outlines, testimonials, FAQ accordions, and strong CTAs — all with full control over design and SEO. The Enroll Now button links to Teachable's checkout. Your custom page can be optimized for conversion in ways the Teachable page builder does not allow.

How do I issue course completion certificates through my V0 app?

Teachable generates completion certificates automatically for courses where you have enabled that setting in Teachable Admin → Course Settings. When a student completes a course, they can download their certificate directly from Teachable. If you want custom certificates generated by your V0 app, listen for the course_completion.created webhook event and use a PDF generation service like Puppeteer or a PDF API to generate a branded certificate on your side.

What happens if Teachable changes their API and my V0 integration breaks?

Teachable maintains versioned APIs (v1, v2) and typically provides deprecation notices before removing endpoints. Monitor your Vercel function logs and set up error alerting (Vercel has built-in log monitoring) to detect when API calls start failing. When Teachable announces API changes, update your Next.js API routes to use the new endpoint structure. For business-critical integrations, subscribe to Teachable's developer changelog or community announcements.

RapidDev

Talk to an Expert

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

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

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.