Skip to main content
RapidDev - Software Development Agency
bolt-ai-integrationsBolt Chat + API Route

How to Integrate Bolt.new with Podia

To integrate Bolt.new with Podia, use the Podia API (available on Mover plan and above) to fetch customer and subscription data, then build a custom student dashboard or course access portal in Bolt. For free plan users without API access, embed Podia's checkout links or JavaScript widget. Podia webhooks for enrollment events require a deployed URL — the Bolt WebContainer cannot receive incoming connections.

What you'll learn

  • How to access the Podia API and authenticate with your API token in a Bolt.new project
  • How to fetch customer and subscription data from Podia to build a custom student dashboard
  • How to embed Podia checkout links and the JavaScript widget for free plan users without API access
  • How to handle Podia webhooks for enrollment events after deploying to a public URL
  • How to gate content in your Bolt app based on a user's Podia subscription or purchase status
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate19 min read25 minutesE-commerceApril 2026RapidDev Engineering Team
TL;DR

To integrate Bolt.new with Podia, use the Podia API (available on Mover plan and above) to fetch customer and subscription data, then build a custom student dashboard or course access portal in Bolt. For free plan users without API access, embed Podia's checkout links or JavaScript widget. Podia webhooks for enrollment events require a deployed URL — the Bolt WebContainer cannot receive incoming connections.

Build a Custom Student Portal for Your Podia Courses with Bolt.new

Podia is the all-in-one storefront for creators selling courses, digital downloads, and memberships. While Podia's own interface handles payments and content delivery, many creators want a custom-branded portal — a dashboard where students can see their enrolled courses, track progress, access bonus resources, or unlock community features based on their purchase status. Bolt.new lets you build that custom layer on top of Podia by connecting to Podia's REST API.

The Podia API is available on the Mover plan ($33/month) and above. It exposes endpoints for reading customer records, subscriptions, and product purchases. In Bolt, you prompt the AI to generate API routes that proxy requests to Podia using your API token, then build React components that display personalized dashboards for your students. The API token lives in a .env file during development and in your hosting platform's environment variables after deployment — it never touches client-side code.

If you're on Podia's free Starter plan, you don't have API access, but you can still integrate with Bolt using Podia's embed options: checkout buttons with a direct Podia checkout URL, or the JavaScript embed widget that renders a full Podia storefront inside your Bolt app. These approaches require no API token and work immediately in the Bolt preview. Podia webhooks — for triggering actions when someone enrolls or cancels — require a publicly accessible URL, so you'll need to deploy before testing that part of the flow.

Integration method

Bolt Chat + API Route

Bolt.new connects to Podia through its REST API, which is available on the Mover plan and above. You configure your Podia API token in a .env file, prompt Bolt to generate API route handlers that fetch customer and subscription data, and build a custom student portal or course access UI on top of that data. For free plan users, the integration falls back to embedding Podia's hosted checkout links and JavaScript widget directly in the Bolt app. Webhooks for enrollment events require deploying to Netlify or Vercel since Bolt's WebContainer cannot receive incoming HTTP calls.

Prerequisites

  • A Podia account — Mover plan ($33/month) or above for API access; free Starter plan works for embed-only integration
  • Your Podia API token from Podia Dashboard → Settings → Integrations → API (Mover plan and above only)
  • Your Podia store URL (e.g., yourname.podia.com) for embed links and widget configuration
  • A Bolt.new project with a Next.js setup — request Next.js when starting the project for API route support
  • A deployed URL on Netlify or Vercel for testing Podia webhooks in production

Step-by-step guide

1

Set Up Your Podia API Token in the .env File

The Podia API uses token-based authentication. Every request to the Podia REST API must include an Authorization header with your API token. To find your token, go to your Podia Dashboard, click your account avatar in the top-right corner, select Settings, then navigate to the Integrations tab. You'll see an API section with your personal API token — copy this value. In your Bolt.new project, open the .env file in the file tree (or create one in the project root if it doesn't exist). Add the line PODIA_API_TOKEN=your_token_here. For a Next.js project, this is a server-side variable without the NEXT_PUBLIC_ prefix, which means it stays on the server and is never exposed to the browser. The Podia API base URL is https://developers.podia.com/v1 — all endpoints are prefixed with this. Keep in mind that API access is only available on the Mover plan and higher. If you're on the Starter plan, skip ahead to the embed step for the widget-based integration instead. Your .env file should also include NEXT_PUBLIC_PODIA_STORE_URL set to your Podia store URL so client components can link to your store without hardcoding the URL.

.env
1# .env
2# Podia API token available on Mover plan and above
3# Found in: Podia Dashboard Settings Integrations API
4PODIA_API_TOKEN=your_podia_api_token_here
5
6# Your Podia store URL (used for embed links and fallback CTAs)
7NEXT_PUBLIC_PODIA_STORE_URL=https://yourname.podia.com

Pro tip: The PODIA_API_TOKEN must stay server-side only. Never prefix it with NEXT_PUBLIC_ or reference it in client components. All Podia API calls should go through a Next.js API route, not directly from the browser.

Expected result: The .env file contains your Podia API token and store URL. The token is not referenced in any client-side component — only in server-side API routes.

2

Prompt Bolt to Generate a Podia API Route

With the API token configured, prompt Bolt to create an API route that proxies requests to Podia's REST API. The route handles the authentication header and returns Podia data to your React components. Podia's API provides three main endpoints relevant to student portal use cases: GET /customers lists all customers with their email, name, and purchase history; GET /customers/{id} returns a specific customer record; GET /subscriptions lists active subscription records. Because CORS would block direct browser-to-Podia API calls, the API route pattern is essential — your React components call your own Next.js API route, which calls Podia from the server side using the token from process.env. Bolt will generate the route file, the TypeScript types for Podia responses, and a React hook or fetch function that your components can use. Review the generated code to confirm the Authorization header format matches Podia's requirement: Bearer your_token_here. Check the generated Podia response types too — the customer object contains fields like email, full_name, and products, where each product has a name, access_url, and created_at timestamp. The API route should accept an optional email query parameter so you can look up a specific customer without fetching your entire customer list.

Bolt.new Prompt

Create a Next.js API route at app/api/podia/customers/route.ts that fetches customer data from the Podia API. Use GET https://developers.podia.com/v1/customers and include the Authorization: Bearer header using process.env.PODIA_API_TOKEN. The route should accept an optional email query parameter to filter customers by email. Return the customer data as JSON. Also create TypeScript types: PodiaProduct with fields id, name, access_url, created_at — and PodiaCustomer with fields id, email, full_name, products (array of PodiaProduct), and subscriptions. Handle API errors by returning appropriate HTTP status codes with an error message.

Paste this in Bolt.new chat

app/api/podia/customers/route.ts
1// app/api/podia/customers/route.ts
2import { NextRequest, NextResponse } from 'next/server';
3
4export interface PodiaProduct {
5 id: string;
6 name: string;
7 access_url: string;
8 created_at: string;
9}
10
11export interface PodiaSubscription {
12 id: string;
13 status: 'active' | 'cancelled' | 'past_due';
14 product_name: string;
15 created_at: string;
16}
17
18export interface PodiaCustomer {
19 id: string;
20 email: string;
21 full_name: string;
22 products: PodiaProduct[];
23 subscriptions: PodiaSubscription[];
24}
25
26export async function GET(request: NextRequest) {
27 const apiToken = process.env.PODIA_API_TOKEN;
28
29 if (!apiToken) {
30 return NextResponse.json(
31 { error: 'Podia API token not configured' },
32 { status: 500 }
33 );
34 }
35
36 const { searchParams } = new URL(request.url);
37 const email = searchParams.get('email');
38
39 try {
40 const url = email
41 ? `https://developers.podia.com/v1/customers?email=${encodeURIComponent(email)}`
42 : 'https://developers.podia.com/v1/customers';
43
44 const response = await fetch(url, {
45 headers: {
46 Authorization: `Bearer ${apiToken}`,
47 'Content-Type': 'application/json',
48 },
49 });
50
51 if (!response.ok) {
52 const error = await response.text();
53 return NextResponse.json(
54 { error: `Podia API error: ${response.status}`, details: error },
55 { status: response.status }
56 );
57 }
58
59 const data = await response.json();
60 return NextResponse.json(data);
61 } catch (err) {
62 console.error('Podia API fetch failed:', err);
63 return NextResponse.json(
64 { error: 'Failed to reach Podia API' },
65 { status: 500 }
66 );
67 }
68}

Pro tip: The Podia API returns paginated results. If you have many customers, the response includes a next_page_url field. For a student lookup by email, filtering server-side with the email query parameter is faster than fetching all customers and filtering in JavaScript.

Expected result: Visiting /api/podia/customers in the browser returns a JSON array of Podia customers. Visiting /api/podia/customers?email=student@example.com returns the matching customer record or an empty array.

3

Build the Student Dashboard Component

With the API route in place, prompt Bolt to create the student-facing dashboard that fetches and displays a user's Podia courses. The dashboard flow: the student enters their email (or it's pulled from your app's auth system), the app calls /api/podia/customers?email=... to look up their Podia customer record, and the returned products array is rendered as a list of enrolled courses with access links. Each product in the Podia response includes a name, an access_url pointing directly to the Podia course player, and a created_at timestamp. The dashboard component should handle three states clearly: loading (while fetching from the API), empty (customer not found or no products purchased), and populated (showing the enrolled courses). If your Bolt app has authentication via NextAuth or Clerk, you can pre-fill the email from the session so students don't need to type it manually — this creates a seamless single sign-on experience where logging into your Bolt app automatically surfaces their Podia content. For richer course data like thumbnails or descriptions, you'll need to store that metadata in your own database since the Podia API focuses on transactional data and access rights rather than full course content metadata.

Bolt.new Prompt

Build a /dashboard page with a student course portal. Show a form where the user enters their email to look up their Podia purchases. On submit, call /api/podia/customers?email={email} and display the results. For each product in the customer's products array, render a card with the course name, enrollment date formatted as 'Enrolled on Jan 1, 2025', and a green 'Access Course' button linking to the access_url. If the API returns no customer or an empty products array, show: 'No courses found for this email. Purchase a course to get started.' with a link to process.env.NEXT_PUBLIC_PODIA_STORE_URL. Add a loading spinner while the API call is in progress.

Paste this in Bolt.new chat

app/dashboard/page.tsx
1// app/dashboard/page.tsx
2'use client';
3import { useState } from 'react';
4import type { PodiaCustomer } from '@/app/api/podia/customers/route';
5
6export default function DashboardPage() {
7 const [email, setEmail] = useState('');
8 const [customer, setCustomer] = useState<PodiaCustomer | null>(null);
9 const [loading, setLoading] = useState(false);
10 const [notFound, setNotFound] = useState(false);
11
12 async function handleLookup(e: React.FormEvent) {
13 e.preventDefault();
14 setLoading(true);
15 setNotFound(false);
16 setCustomer(null);
17
18 const res = await fetch(`/api/podia/customers?email=${encodeURIComponent(email)}`);
19 const data = await res.json();
20
21 setLoading(false);
22
23 const customers: PodiaCustomer[] = Array.isArray(data) ? data : (data.customers ?? []);
24 const match = customers.find((c) => c.email.toLowerCase() === email.toLowerCase());
25
26 if (match) {
27 setCustomer(match);
28 } else {
29 setNotFound(true);
30 }
31 }
32
33 return (
34 <main className="max-w-2xl mx-auto p-8">
35 <h1 className="text-2xl font-bold mb-6">My Courses</h1>
36 <form onSubmit={handleLookup} className="flex gap-3 mb-8">
37 <input
38 type="email"
39 value={email}
40 onChange={(e) => setEmail(e.target.value)}
41 placeholder="Enter your email"
42 required
43 className="flex-1 border rounded-lg px-4 py-2"
44 />
45 <button
46 type="submit"
47 disabled={loading}
48 className="bg-indigo-600 text-white px-6 py-2 rounded-lg hover:bg-indigo-700 disabled:opacity-50"
49 >
50 {loading ? 'Looking up...' : 'Find My Courses'}
51 </button>
52 </form>
53
54 {notFound && (
55 <div className="text-center py-8">
56 <p className="text-gray-600 mb-4">No courses found for this email. Purchase a course to get started.</p>
57 <a
58 href={process.env.NEXT_PUBLIC_PODIA_STORE_URL}
59 className="text-indigo-600 underline"
60 >
61 Browse courses on Podia
62 </a>
63 </div>
64 )}
65
66 {customer && (
67 <div>
68 <p className="text-gray-500 mb-4">Welcome back, {customer.full_name}!</p>
69 {customer.products.length === 0 ? (
70 <p className="text-gray-600">You have no enrolled courses yet.</p>
71 ) : (
72 <div className="grid gap-4">
73 {customer.products.map((product) => (
74 <div key={product.id} className="border rounded-xl p-5 flex justify-between items-center">
75 <div>
76 <h3 className="font-semibold">{product.name}</h3>
77 <p className="text-sm text-gray-500">
78 Enrolled on{' '}
79 {new Date(product.created_at).toLocaleDateString('en-US', {
80 year: 'numeric',
81 month: 'short',
82 day: 'numeric',
83 })}
84 </p>
85 </div>
86 <a
87 href={product.access_url}
88 target="_blank"
89 rel="noopener noreferrer"
90 className="bg-green-600 text-white px-4 py-2 rounded-lg hover:bg-green-700 text-sm"
91 >
92 Access Course
93 </a>
94 </div>
95 ))}
96 </div>
97 )}
98 </div>
99 )}
100 </main>
101 );
102}

Pro tip: If your Bolt app uses authentication (NextAuth, Clerk), pre-fill the email from the session object so students don't have to type it. Replace the email form with a server-side fetch that automatically uses the signed-in user's email for a seamless experience.

Expected result: The /dashboard page renders a lookup form. Entering a Podia customer's email displays their enrolled courses as cards with access links. Entering an unrecognized email shows the not-found message with a link to your Podia store.

4

Embed the Podia Widget for Free Plan Users

If you're on Podia's free Starter plan, you don't have access to the REST API — but you can still build a Bolt app that showcases and sells your Podia products using Podia's embed widget. Podia provides a JavaScript snippet that renders your entire storefront inline on any web page. The widget loads from Podia's CDN, displays your products, and handles the checkout flow entirely within Podia's hosted experience. To get the embed code, go to your Podia Dashboard → Storefront → Embed. In Bolt, prompt the AI to add a Script tag that loads the Podia embed JavaScript and a container div where the widget renders. Because the embed script comes from an external CDN, use Next.js's built-in Script component with strategy='lazyOnload' to avoid blocking page render. Individual product checkout links (direct URL buttons) don't require any JavaScript at all — you can link directly to yourname.podia.com/your-product-name/buy for a specific product's checkout page. These direct links work immediately in the Bolt preview since they're standard hyperlinks with no API calls required, and they function on the free Starter plan. Use direct links as your primary CTAs alongside the embed widget as a supplementary browsing experience.

Bolt.new Prompt

Add a Podia storefront embed to my /courses page. Use Next.js's Script component with strategy='lazyOnload' to load the Podia embed JavaScript. Render the storefront inside a div with id='podia-embed-container' and minimum height of 600px. Below the embed area, add a fallback paragraph: 'Having trouble viewing? Visit our store directly' with a link to process.env.NEXT_PUBLIC_PODIA_STORE_URL. At the top of the page, add three direct checkout buttons linking to specific Podia product URLs.

Paste this in Bolt.new chat

app/courses/page.tsx
1// app/courses/page.tsx
2import Script from 'next/script';
3
4const PODIA_STORE_URL = process.env.NEXT_PUBLIC_PODIA_STORE_URL ?? 'https://yourname.podia.com';
5
6// Direct checkout links — no API needed, works on all Podia plans including free
7const featuredProducts = [
8 { name: 'Beginner Course', checkoutUrl: `${PODIA_STORE_URL}/beginner-course/buy` },
9 { name: 'Pro Masterclass', checkoutUrl: `${PODIA_STORE_URL}/pro-masterclass/buy` },
10 { name: 'Monthly Membership', checkoutUrl: `${PODIA_STORE_URL}/membership/buy` },
11];
12
13export default function CoursesPage() {
14 return (
15 <main className="max-w-4xl mx-auto p-8">
16 <h1 className="text-3xl font-bold mb-4">Our Courses</h1>
17
18 {/* Direct checkout links — no JavaScript required, works with ad blockers */}
19 <div className="grid grid-cols-3 gap-4 mb-12">
20 {featuredProducts.map((product) => (
21 <a
22 key={product.name}
23 href={product.checkoutUrl}
24 className="block bg-indigo-600 text-white text-center px-4 py-3 rounded-xl font-medium hover:bg-indigo-700 transition"
25 >
26 Buy {product.name}
27 </a>
28 ))}
29 </div>
30
31 {/* Full Podia storefront embed */}
32 <div id="podia-embed-container" style={{ minHeight: '600px' }}>
33 <p className="text-gray-400 text-sm">Loading storefront...</p>
34 </div>
35
36 {/* Fallback for users with JavaScript disabled or ad blockers */}
37 <p className="text-sm text-gray-500 mt-4">
38 Having trouble viewing?{' '}
39 <a href={PODIA_STORE_URL} className="text-indigo-600 underline">
40 Visit our store directly
41 </a>
42 </p>
43
44 {/* Podia embed script — lazyOnload avoids blocking page render */}
45 <Script
46 src="https://podia.com/embed.js"
47 data-store={PODIA_STORE_URL}
48 data-container="podia-embed-container"
49 strategy="lazyOnload"
50 />
51 </main>
52 );
53}

Pro tip: Direct product checkout URLs (yourname.podia.com/product-slug/buy) work for all Podia plans including free and are unaffected by ad blockers. Use them as your primary CTAs alongside the embed widget, not as a fallback — they're more reliable.

Expected result: The /courses page shows direct checkout buttons for your key products and renders the Podia storefront widget below them. Clicking a checkout button opens the Podia checkout page. The embed widget loads the full product catalog after the initial page render.

5

Deploy and Register Podia Webhooks

Podia webhooks notify your Bolt app when enrollment events happen — a new customer purchases a course, a subscription renews, or a member cancels. During development in Bolt's WebContainer, webhooks cannot reach the browser-based runtime because there's no public URL for Podia to POST to. You must deploy first to test the complete webhook flow. Deploy your Bolt app to Netlify or Vercel: export your project from Bolt by connecting it to GitHub via the Git panel, then import the repo in your hosting platform. Add the PODIA_API_TOKEN environment variable in your hosting platform's environment settings (Netlify: Site configuration → Environment variables; Vercel: Project → Settings → Environment Variables) and redeploy. Once deployed, go to your Podia Dashboard → Settings → Integrations → Webhooks and add your endpoint URL in the format https://your-app.netlify.app/api/podia/webhook. Podia sends POST requests to this URL for events like new_customer, new_subscription, and subscription_cancelled. Your webhook handler should return a 200 status quickly to acknowledge receipt. Importantly, Podia does not sign webhook payloads with a cryptographic header (unlike Stripe's Stripe-Signature), so protect your endpoint by embedding a secret token in the URL path itself — register the webhook as /api/podia/webhook/your-secret-token and validate the token in the handler.

Bolt.new Prompt

Create a Podia webhook handler at app/api/podia/webhook/route.ts. It should accept POST requests and handle three Podia event types: new_customer (log the email and full_name), new_subscription (log the customer email and subscription product_name), and subscription_cancelled (log the customer email). Return { received: true } with status 200 for all events. Also add basic security: check for a secret token in the request URL path and return 401 if it's missing or wrong, using PODIA_WEBHOOK_SECRET from process.env.

Paste this in Bolt.new chat

app/api/podia/webhook/[token]/route.ts
1// app/api/podia/webhook/[token]/route.ts
2import { NextRequest, NextResponse } from 'next/server';
3
4interface PodiaWebhookEvent {
5 event: 'new_customer' | 'new_subscription' | 'subscription_cancelled';
6 customer?: {
7 email: string;
8 full_name: string;
9 };
10 subscription?: {
11 id: string;
12 product_name: string;
13 status: string;
14 };
15}
16
17export async function POST(
18 request: NextRequest,
19 { params }: { params: { token: string } }
20) {
21 // Validate secret token in URL path
22 const expectedToken = process.env.PODIA_WEBHOOK_SECRET;
23 if (!expectedToken || params.token !== expectedToken) {
24 return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
25 }
26
27 let event: PodiaWebhookEvent;
28 try {
29 event = await request.json();
30 } catch {
31 return NextResponse.json({ error: 'Invalid JSON payload' }, { status: 400 });
32 }
33
34 console.log('Podia webhook received:', JSON.stringify(event, null, 2));
35
36 switch (event.event) {
37 case 'new_customer': {
38 const { email, full_name } = event.customer ?? {};
39 console.log('New Podia customer:', email, full_name);
40 // TODO: add to email list, create user record, trigger welcome email
41 break;
42 }
43 case 'new_subscription': {
44 const { email } = event.customer ?? {};
45 const planName = event.subscription?.product_name;
46 console.log(`New subscription: ${email} subscribed to ${planName}`);
47 // TODO: update subscription status in your database
48 break;
49 }
50 case 'subscription_cancelled': {
51 const { email } = event.customer ?? {};
52 console.log('Subscription cancelled for:', email);
53 // TODO: revoke premium access in your database
54 break;
55 }
56 default:
57 console.log('Unhandled Podia event type:', (event as { event: string }).event);
58 }
59
60 return NextResponse.json({ received: true });
61}

Pro tip: Register your Podia webhook URL as https://your-app.netlify.app/api/podia/webhook/your-secret-token and set PODIA_WEBHOOK_SECRET=your-secret-token in your .env. This prevents unauthorized actors from triggering your webhook handler since Podia does not provide payload signature verification.

Expected result: After deploying and registering the webhook in Podia Dashboard, purchasing a test product sends a POST to your deployed endpoint. Your server logs show the event payload and the corresponding handler branch executes. Requests with an incorrect token return 401.

Common use cases

Custom Student Dashboard Showing Enrolled Courses

Build a personalized dashboard where logged-in students can see all the Podia courses they've purchased, along with links to access each course. The dashboard fetches the customer record from Podia's API using the student's email, then displays their active enrollments with course names and direct access links.

Bolt.new Prompt

Build a student dashboard page at /dashboard. It should fetch the current user's Podia customer record by email using the Podia API (token stored in PODIA_API_TOKEN). Display all their active course enrollments with course name, enrollment date, and a 'Go to Course' button linking to the Podia course URL. If the API returns no customer record, show a 'No purchases found' message with a link to the Podia store.

Copy this prompt to try it in Bolt.new

Subscription-Gated Bonus Content

Create a members-only section in your Bolt app that becomes accessible only when a visitor has an active Podia membership subscription. When someone visits the gated page, the app checks their email against the Podia API to verify they have an active subscription before rendering the content.

Bolt.new Prompt

Create a /members page that shows exclusive bonus content only to active Podia subscribers. When a user enters their email and clicks 'Access Members Area', call the Podia API to check if they have an active subscription. If they do, render the members content. If not, show a CTA button linking to the Podia membership checkout page. Store PODIA_API_TOKEN in the .env file.

Copy this prompt to try it in Bolt.new

Embedded Podia Storefront for Free Plan Users

For creators on Podia's free Starter plan without API access, embed the Podia JavaScript checkout widget directly in a Bolt app landing page. Visitors can browse and purchase courses without leaving your custom-branded site, and no API token is required.

Bolt.new Prompt

Add a Podia storefront embed to my /courses page. Use Next.js's Script component with strategy='lazyOnload' to load the Podia embed JavaScript from Podia's CDN and render it inside a div with id='podia-embed-container'. Below the embed, add a fallback link to my Podia store URL for users with JavaScript disabled. Also add direct checkout buttons at the top linking to specific Podia product URLs.

Copy this prompt to try it in Bolt.new

Troubleshooting

Every request to the Podia API returns 401 Unauthorized

Cause: The PODIA_API_TOKEN environment variable is missing, the Authorization header format is incorrect (Bearer prefix required), or your Podia plan does not include API access — the API is only available on Mover plan and above.

Solution: Check the .env file contains PODIA_API_TOKEN without quotes around the token value. Verify the API route sends the header as 'Authorization: Bearer your_token_here' — the word Bearer followed by a space is required. Confirm your Podia plan: if you're on the free Starter plan, the API token section will not appear in Podia Dashboard → Settings → Integrations. Upgrade to Mover plan or use the embed widget approach instead.

typescript
1// Correct Authorization header format
2headers: {
3 Authorization: `Bearer ${process.env.PODIA_API_TOKEN}`,
4 'Content-Type': 'application/json',
5}

The student email lookup returns no results even for a customer who definitely made a purchase

Cause: The email comparison is case-sensitive and the Podia customer record may be stored with different letter casing, or Podia is returning paginated results and the matching customer is on a subsequent page beyond the first.

Solution: Normalize both the input email and the Podia customer email to lowercase before comparing. For stores with more than a page of customers, check if the response includes a next_page_url field and fetch subsequent pages until either a match is found or all pages are exhausted. Consider syncing customer records to your own database on a schedule rather than querying Podia live on every lookup.

typescript
1// Case-insensitive email matching
2const match = customers.find(
3 (c) => c.email.toLowerCase() === inputEmail.toLowerCase()
4);

Podia webhook POST requests never arrive at the deployed endpoint

Cause: The webhook URL registered in Podia Dashboard points to the Bolt WebContainer preview URL instead of the deployed Netlify or Vercel URL, or the endpoint was registered before the app was deployed.

Solution: Go to Podia Dashboard → Settings → Integrations → Webhooks and verify the endpoint URL is your deployed domain (e.g., https://your-app.netlify.app/api/podia/webhook/your-secret-token), not a bolt.new or localhost URL. Use the 'Send test event' button in Podia's webhook settings to manually trigger a test delivery and check the response status. Ensure the app was redeployed after adding PODIA_WEBHOOK_SECRET to the hosting platform's environment variables.

The Podia embed widget shows a blank area that never loads the storefront

Cause: The Script component's data-store attribute contains an incorrect Podia store URL, or an ad blocker in the browser is preventing the Podia embed script from loading.

Solution: Verify NEXT_PUBLIC_PODIA_STORE_URL in .env is set to the exact Podia store URL in the format https://yourname.podia.com with no trailing slash. Open the browser console and look for script load errors or 404 responses on the Podia CDN URL. As a reliable fallback, replace or supplement the embed widget with direct product checkout links (yourname.podia.com/product-slug/buy) which work regardless of ad blockers.

Best practices

  • Keep PODIA_API_TOKEN server-side only — never use the NEXT_PUBLIC_ prefix or reference it in any client component or browser-accessible code
  • Cache Podia API customer data in your own database rather than querying Podia on every page load — the API has rate limits and a local database lookup is significantly faster for the end user
  • Use direct Podia checkout links (yourname.podia.com/product-slug/buy) as your primary purchase CTAs — they work on all plans including free and are not affected by ad blockers
  • Protect your webhook endpoint by embedding a secret token in the URL path since Podia does not provide cryptographic payload signing like Stripe does
  • Test the full student dashboard and checkout flows on your deployed URL before announcing to your audience — Podia webhooks only work on publicly accessible URLs, not in Bolt's WebContainer preview
  • Normalize customer emails to lowercase before comparison — Podia may store emails with capitalization that differs from how users type their email in your dashboard form
  • Always show a clear fallback CTA linking to your Podia store when a customer is not found — never show a generic error message to users who may have purchased under a different email

Alternatives

Frequently asked questions

Does Bolt.new work with Podia?

Yes. You can connect Bolt.new to Podia through the Podia REST API (available on Mover plan and above) to fetch customer and subscription data and build custom student dashboards. For free Starter plan users, you can embed the Podia storefront JavaScript widget or link directly to Podia checkout URLs — both approaches require no API token and work immediately in the Bolt preview.

Can I use the Podia API on the free Starter plan?

No. Podia's REST API is only available on the Mover plan ($33/month) and above. On the free Starter plan, use the embed widget integration instead — load Podia's JavaScript embed script in your Bolt app to display your full storefront inline, or link directly to specific product checkout URLs at yourname.podia.com/product-slug/buy without any API calls required.

Can I test Podia webhook events in Bolt's WebContainer preview?

No. Podia webhooks require a publicly accessible URL to send POST requests to, and Bolt's WebContainer development environment runs in the browser without a public URL. You must deploy your Bolt app to Netlify or Vercel first, then register the deployed URL as a webhook endpoint in Podia Dashboard → Settings → Integrations → Webhooks. You can write and review the webhook handler code in Bolt, but real webhook delivery only works after deployment.

How do I gate content in my Bolt app based on a Podia course purchase?

Build a lookup flow that checks the visitor's email against the Podia /customers API endpoint. If the API response includes the specific course in their products array, render the gated content. If not, show a CTA linking to the Podia checkout page for that course. For a smoother repeat-visit experience, store verified customer emails and their purchased product IDs in your own database after the first successful Podia API lookup.

How do I deploy my Bolt app with Podia integration to Netlify?

Connect your Bolt project to GitHub via Bolt's Git panel, then import that repo in Netlify. Set the build command to npm run build and publish directory to .next for a Next.js project. Before deploying, add PODIA_API_TOKEN and NEXT_PUBLIC_PODIA_STORE_URL in Netlify's Site configuration → Environment variables and trigger a new deploy. After the first successful deployment, register your Netlify URL as a Podia webhook endpoint if you're using webhook-driven enrollment features.

How is Podia different from Teachable for building a custom Bolt.new integration?

Podia is an all-in-one platform covering courses, digital downloads, and memberships in a single product, while Teachable focuses specifically on courses with richer student analytics and a more permissive API. Teachable's API is accessible on lower-tier plans, whereas Podia's API requires the Mover plan. If detailed per-student progress tracking via API is important to your Bolt app, Teachable offers more data points to work with.

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.