To use ScheduleOnce (now OnceHub) with V0, embed booking pages as iframes in V0-generated React components for zero-backend scheduling, or create a Next.js API route at app/api/scheduleonce/route.ts to fetch booking data via the OnceHub REST API. Store your OnceHub API key in Vercel Dashboard → Settings → Environment Variables as ONCEHUB_API_KEY. ScheduleOnce is designed for enterprise sales team routing; the embed approach works immediately while the API route enables custom booking dashboards.
Enterprise Scheduling and Booking with ScheduleOnce in V0 Apps
ScheduleOnce — now operating under the OnceHub brand — is the enterprise alternative to Calendly, built specifically for sales teams that need intelligent meeting routing. Where Calendly works well for simple 1:1 scheduling, ScheduleOnce handles complex scenarios: round-robin assignment among team members, territory-based routing that assigns prospects to the right regional rep, qualification questions that determine which booking type is appropriate, and multi-step meeting flows with sequential scheduling. For V0 founders building sales tools, CRM dashboards, or client onboarding flows, ScheduleOnce's routing logic can replace an entire scheduling ops workflow.
The integration with V0 follows two distinct paths depending on what you need. The embed approach lets you drop a ScheduleOnce booking page directly into your V0-generated pages using a JavaScript snippet or an iframe — the visitor books directly on the ScheduleOnce-hosted interface, and all routing, assignment, and confirmation happens automatically. This requires no API route, no backend code, and works immediately after you paste the embed code.
The API approach is for reading booking data back into your app — building a dashboard that shows all upcoming meetings across your sales team, checking booking status for a specific prospect, or triggering downstream actions when a meeting is booked. OnceHub's REST API provides access to bookings, scheduled meetings, and booking pages. For real-time notifications on new bookings, cancellations, and reschedules, OnceHub supports webhooks that push events to your Next.js API route as they happen.
Integration method
V0 generates your booking pages and scheduling interfaces as React components, while a Next.js API route fetches scheduled meeting data from the OnceHub REST API using an API key. For embedding booking pages directly, ScheduleOnce provides JavaScript embed snippets and iframe options that work as client-side components in V0-generated React pages.
Prerequisites
- A V0 account with a Next.js project at v0.dev
- A ScheduleOnce (OnceHub) account with at least one booking page configured
- An OnceHub API key from the OnceHub Developer Settings
- A Vercel account with your V0 project deployed via GitHub
- At least one booking page or event type set up in your OnceHub account
Step-by-step guide
Embed the ScheduleOnce Booking Widget
Embed the ScheduleOnce Booking Widget
The fastest way to add ScheduleOnce booking to a V0 app is the direct embed. ScheduleOnce provides several embedding options: an iframe, a JavaScript pop-up button, and an inline page embed. For integration into V0-generated React pages, the iframe approach is the most reliable since it does not depend on third-party script loading timing. In your ScheduleOnce (OnceHub) account, navigate to your booking page and click the Embed / Share button. Copy the embed code. For iframe embedding, the URL follows the pattern https://go.oncehub.com/YourBookingPageName. In your V0 project, create a client component that renders the iframe. The component must have 'use client' at the top because it uses browser-specific rendering. Set the iframe src to your OnceHub booking page URL. Configure the height to at least 600px to ensure the full scheduling interface is visible without scrolling inside the iframe. For the JavaScript-based embed (which renders inline rather than in a separate iframe context), ScheduleOnce provides a script tag and a target div with an id matching your booking page. In a Next.js component, you load this script inside a useEffect hook to ensure it runs only in the browser. This approach gives a more seamless appearance than an iframe but is slightly more complex to implement in a React component. One V0-specific consideration: V0 may generate an iframe component without the 'use client' directive. If you see hydration errors or the iframe fails to render, ensure the component is marked as a client component or wrapped in a Suspense boundary with SSR disabled using Next.js dynamic imports.
Create a booking page component for scheduling a sales demo. Add a section header with the title 'Book Your Demo Call' and three benefit bullets. Below the header, embed the ScheduleOnce booking page using an iframe with src set to the NEXT_PUBLIC_SCHEDULEONCE_URL environment variable, width 100%, height 650px, and no border. This needs to be a client component.
Paste this in V0 chat
1'use client';23interface ScheduleOnceEmbedProps {4 bookingPageUrl?: string;5 height?: number;6 title?: string;7}89export function ScheduleOnceEmbed({10 bookingPageUrl = process.env.NEXT_PUBLIC_SCHEDULEONCE_URL || 'https://go.oncehub.com/your-booking-page',11 height = 650,12 title = 'Schedule a Meeting',13}: ScheduleOnceEmbedProps) {14 return (15 <div className="w-full overflow-hidden rounded-lg border border-gray-200">16 <iframe17 src={bookingPageUrl}18 width="100%"19 height={height}20 frameBorder="0"21 title={title}22 style={{ border: 'none', minWidth: '320px' }}23 allow="camera; microphone"24 loading="lazy"25 />26 </div>27 );28}Pro tip: Add allow="camera; microphone" to the iframe to support video conferencing features that ScheduleOnce may launch from within the booking confirmation flow.
Expected result: The ScheduleOnce booking interface renders inline on your V0-generated page. Visitors can complete the full booking flow — qualification questions, time selection, and confirmation — without leaving your app.
Get Your OnceHub API Key
Get Your OnceHub API Key
To access booking data programmatically, you need an OnceHub API key. Unlike some services that use OAuth for all access, OnceHub supports simple API key authentication for server-to-server use — a static key tied to your account that you include in API request headers. Log into your OnceHub account and navigate to the Account section. Look for Developer settings or API access — the exact menu location varies by account type but is typically under your account profile in the top-right corner → Developer settings → API keys. Click Create API key and give it a descriptive label like 'V0 Dashboard Integration'. Copy the generated key immediately. OnceHub API keys provide full read access to your account's booking data including booking pages, scheduled meetings, and team member information. For production use, note that OnceHub may have different API access tiers depending on your subscription — verify your plan includes API access if this feature is not visible in your settings. The API base URL for OnceHub is https://api.oncehub.com/v2. All requests require an api-key header with your key value. The API follows REST conventions with JSON request and response bodies. Note an important difference from Calendly: ScheduleOnce's API is primarily read-focused. Complex write operations like creating or modifying booking pages are done through the OnceHub dashboard, not the API. The API is well-suited for pulling booking data into your V0 dashboard or triggering actions via webhooks.
Pro tip: OnceHub API keys do not auto-expire but should be rotated if your team membership changes or if there is any risk of exposure. Generate a new key in Developer settings and update the Vercel environment variable.
Expected result: You have an OnceHub API key saved securely, ready to add as a Vercel environment variable.
Create the Bookings API Route
Create the Bookings API Route
Build the server-side Next.js API route that fetches booking data from OnceHub. Create app/api/scheduleonce/route.ts. This serverless function runs on Vercel, authenticates with your OnceHub API key from environment variables, and returns booking data to your V0-generated dashboard components. The OnceHub v2 API uses a consistent pattern: GET requests to /bookings returns a paginated list of bookings across your account. Each booking record includes the booking ID, status (confirmed, canceled, rescheduled), the booking page it came from, the scheduled start and end time, and the booker's details (name and email from the qualification form). For a meeting dashboard, you will want to filter bookings by date range. The OnceHub API supports query parameters for filtering by starting_after and ending_before timestamps. Pass ISO 8601 datetime strings to restrict results to a specific time window — for example, the current week's meetings. OnceHub pagination uses a cursor-based approach. The response includes a next_page_token when there are more results. For typical dashboard use cases (showing one week of meetings), you are unlikely to hit pagination limits, but for historical reporting you should implement cursor-based iteration. One V0-specific limitation to understand: V0 cannot interact with ScheduleOnce's routing configuration or booking page settings through the API. If you need to adjust routing rules, qualification questions, or team assignments, you must do so in the OnceHub dashboard. The API only exposes read access to the resulting booking data.
Add a Next.js API route at app/api/scheduleonce/route.ts that fetches upcoming bookings from the OnceHub API. Use ONCEHUB_API_KEY from environment variables in the api-key request header. Filter for bookings in the next 7 days and return them as a JSON array with id, status, startTime, endTime, bookerName, bookerEmail, and bookingPageName fields.
Paste this in V0 chat
1import { NextRequest, NextResponse } from 'next/server';23const ONCEHUB_BASE_URL = 'https://api.oncehub.com/v2';45interface OnceHubBooking {6 id: string;7 status: string;8 starting_time: string;9 ending_time: string;10 booker: {11 name: string;12 email: string;13 };14 booking_page: {15 label: string;16 id: string;17 };18 owner: {19 name: string;20 email: string;21 };22}2324export async function GET(request: NextRequest) {25 const apiKey = process.env.ONCEHUB_API_KEY;2627 if (!apiKey) {28 return NextResponse.json(29 { error: 'ONCEHUB_API_KEY is not configured' },30 { status: 500 }31 );32 }3334 try {35 const { searchParams } = new URL(request.url);36 const daysAhead = parseInt(searchParams.get('days') || '7');3738 const now = new Date();39 const future = new Date(now);40 future.setDate(future.getDate() + daysAhead);4142 const params = new URLSearchParams({43 starting_after: now.toISOString(),44 ending_before: future.toISOString(),45 status: 'BOOKED',46 limit: '100',47 });4849 const response = await fetch(50 `${ONCEHUB_BASE_URL}/bookings?${params}`,51 {52 headers: {53 'api-key': apiKey,54 'Content-Type': 'application/json',55 },56 }57 );5859 if (!response.ok) {60 const errorBody = await response.text();61 console.error('OnceHub API error:', response.status, errorBody);62 return NextResponse.json(63 { error: `OnceHub API returned ${response.status}` },64 { status: response.status }65 );66 }6768 const data = await response.json();69 const bookings = (data.data || []).map((b: OnceHubBooking) => ({70 id: b.id,71 status: b.status,72 startTime: b.starting_time,73 endTime: b.ending_time,74 bookerName: b.booker?.name || '',75 bookerEmail: b.booker?.email || '',76 bookingPageName: b.booking_page?.label || '',77 assignedTo: b.owner?.name || '',78 }));7980 return NextResponse.json({ bookings, total: bookings.length });81 } catch (error: unknown) {82 console.error('ScheduleOnce API error:', error);83 return NextResponse.json(84 { error: 'Failed to fetch bookings' },85 { status: 500 }86 );87 }88}Pro tip: Add a ?days=30 query parameter to your API route to support viewing the next 30 days of meetings for monthly planning — make the time window configurable from the dashboard UI.
Expected result: The API route returns a JSON array of upcoming bookings. The V0-generated dashboard table displays meeting names, times, booker details, and assigned reps from real OnceHub data.
Add Environment Variables in Vercel
Add Environment Variables in Vercel
Configure the environment variables your app needs in Vercel so they are available to your serverless functions and client components. Open Vercel Dashboard → your project → Settings → Environment Variables. Add two variables: First, ONCEHUB_API_KEY with the API key you generated. Set the scope to Production, Preview, and Development. Do not add the NEXT_PUBLIC_ prefix — API keys must remain server-side only in Next.js API routes. Second, NEXT_PUBLIC_SCHEDULEONCE_URL with your ScheduleOnce booking page URL (e.g., https://go.oncehub.com/your-booking-page-name). This URL is not sensitive and the NEXT_PUBLIC_ prefix is appropriate here because the iframe embed component in the browser needs to read it. After saving both variables, trigger a redeployment. Either push any commit to your GitHub repository or click Redeploy in the Vercel Dashboard. Environment variable changes are frozen into the build at deployment time and require a new deployment to activate. For local development, create or update your .env.local file with both variables. The non-NEXT_PUBLIC_ variable will only be accessible in server-side code locally as well, matching the production behavior.
Pro tip: If you have multiple booking pages (e.g., one for demos, one for support), add each URL as a separate NEXT_PUBLIC_ environment variable with descriptive names like NEXT_PUBLIC_DEMO_BOOKING_URL and NEXT_PUBLIC_SUPPORT_BOOKING_URL.
Expected result: Vercel Dashboard shows ONCEHUB_API_KEY and NEXT_PUBLIC_SCHEDULEONCE_URL saved. After redeployment, the API route returns real booking data and the embed shows your actual booking page.
Set Up Webhooks for Real-Time Booking Notifications
Set Up Webhooks for Real-Time Booking Notifications
For applications that need to react immediately when a meeting is booked — triggering a CRM entry, sending a Slack notification, or creating a follow-up task — OnceHub supports webhooks that POST event data to your API route when bookings are created, canceled, or rescheduled. Create a webhook handler at app/api/scheduleonce/webhook/route.ts. OnceHub webhook payloads contain the booking details including the booker's name and email, the assigned team member, meeting time, and qualification question answers. To register your webhook URL in OnceHub, navigate to Account Settings → Integrations → Webhooks (or API settings depending on your OnceHub version). Add your Vercel deployment URL: https://your-project.vercel.app/api/scheduleonce/webhook. Select the events you want to receive: booking.created, booking.canceled, and booking.rescheduled are the most important ones. OnceHub may require webhook URL verification — it sends a GET request to your URL first to confirm it is reachable and returns a 200 response. Make sure your webhook handler exports both a GET and a POST function, with GET returning a 200 for verification. For security, OnceHub can include a custom header or shared secret in webhook requests that you configure in the webhook settings. Verify this value in your handler before processing the payload. This prevents malicious actors from sending fake booking events to your endpoint. For complex post-booking workflows — like automatically creating HubSpot deals, sending personalized email sequences, or assigning tasks to team members — RapidDev can help design the complete webhook-driven automation architecture.
Add a webhook endpoint at app/api/scheduleonce/webhook/route.ts that handles POST requests from OnceHub. Parse the booking payload, log the event type, booker name, and meeting time. Return a 200 response. Also export a GET handler that returns 200 for webhook URL verification.
Paste this in V0 chat
1import { NextRequest, NextResponse } from 'next/server';23interface OnceHubWebhookEvent {4 event_type: string;5 created_at: string;6 booking: {7 id: string;8 status: string;9 starting_time: string;10 ending_time: string;11 booker: {12 name: string;13 email: string;14 };15 booking_page: {16 label: string;17 };18 owner: {19 name: string;20 email: string;21 };22 };23}2425// Verification GET handler required by some webhook platforms26export async function GET() {27 return NextResponse.json({ status: 'webhook endpoint active' });28}2930export async function POST(request: NextRequest) {31 try {32 const body: OnceHubWebhookEvent = await request.json();3334 console.log('OnceHub webhook received:', body.event_type);3536 switch (body.event_type) {37 case 'booking.created': {38 const { booking } = body;39 console.log(40 `New booking: ${booking.booker.name} (${booking.booker.email})`,41 `for ${booking.booking_page.label} at ${booking.starting_time}`,42 `assigned to ${booking.owner.name}`43 );44 // TODO: Create CRM record, send Slack notification, trigger email sequence45 break;46 }4748 case 'booking.canceled': {49 const { booking } = body;50 console.log(`Canceled: booking ${booking.id} by ${booking.booker.name}`);51 // TODO: Update CRM, notify team, free up resources52 break;53 }5455 case 'booking.rescheduled': {56 const { booking } = body;57 console.log(`Rescheduled: ${booking.booker.name} moved to ${booking.starting_time}`);58 // TODO: Update calendar events and CRM records59 break;60 }6162 default:63 console.log('Unhandled OnceHub event:', body.event_type);64 }6566 return NextResponse.json({ received: true });67 } catch (error: unknown) {68 console.error('OnceHub webhook error:', error);69 return NextResponse.json(70 { error: 'Webhook processing failed' },71 { status: 500 }72 );73 }74}Pro tip: Add your deployed Vercel URL to OnceHub's webhook settings only after deploying — local development URLs like localhost are not reachable by OnceHub's servers.
Expected result: The webhook handler receives OnceHub events and logs booking details. New bookings, cancellations, and reschedules trigger the appropriate code paths.
Common use cases
Sales Demo Booking Page Embed
A SaaS company embeds their ScheduleOnce booking page on a V0-generated demo request page. Prospects fill in qualification questions and book a time; OnceHub's routing rules automatically assign the meeting to the correct account executive based on company size and territory. No backend API route is needed.
Create a 'Book a Demo' page with a professional header saying 'Schedule Your Personalized Demo'. Include a section explaining what the 30-minute demo covers with 3 bullet points, then below it embed the scheduling widget. The booking section should use an iframe or div with id='SOID' for the ScheduleOnce embed script.
Copy this prompt to try it in V0
Sales Team Meeting Dashboard
A sales manager builds an internal dashboard that shows all booked demo calls across the team for the current week. The dashboard fetches booking data from a Next.js API route that queries the OnceHub API, displaying prospect names, booked times, assigned reps, and meeting status in a sortable table.
Build an upcoming meetings dashboard that fetches from /api/scheduleonce/bookings. Show a table with columns for Prospect Name, Email, Meeting Type, Assigned Rep, Start Time, and Status. Color-code rows by status: green for confirmed, yellow for pending, red for canceled. Add a date range filter.
Copy this prompt to try it in V0
Post-Booking CRM Record Creation
When a prospect books a discovery call through ScheduleOnce, a webhook fires to a Next.js API route that automatically creates a CRM lead record with the prospect's details and schedules a follow-up reminder. This eliminates manual CRM entry after every booked meeting.
Create a thank-you page at /booking-confirmed that shows a personalized confirmation message. Include the meeting details, a calendar add button, and a checklist of what to prepare for the call. The page should look professional with the company logo and a warm, conversational tone.
Copy this prompt to try it in V0
Troubleshooting
OnceHub API returns 401 Unauthorized
Cause: The ONCEHUB_API_KEY environment variable is missing from Vercel, the API key was revoked, or the api-key header name is incorrect.
Solution: Verify ONCEHUB_API_KEY is set in Vercel Dashboard → Settings → Environment Variables and that a redeployment happened after adding it. Confirm the header name is exactly api-key (lowercase) not Authorization or x-api-key. If the key was recently regenerated, update the environment variable and redeploy.
1// Correct header format for OnceHub API authentication2const response = await fetch(url, {3 headers: {4 'api-key': process.env.ONCEHUB_API_KEY!,5 'Content-Type': 'application/json',6 },7});ScheduleOnce iframe displays blank or shows an error page
Cause: The OnceHub booking page URL is incorrect, the booking page is unpublished, or a Content Security Policy header is blocking the iframe.
Solution: Verify the NEXT_PUBLIC_SCHEDULEONCE_URL matches an active, published booking page URL in your OnceHub account. Booking page URLs follow the format https://go.oncehub.com/your-page-name. If the URL is correct, check your Next.js middleware or vercel.json for X-Frame-Options or Content-Security-Policy headers that may block the iframe.
API returns empty bookings array even though meetings exist in OnceHub
Cause: The date range filter (starting_after / ending_before) does not overlap with when the bookings are scheduled, or the status filter is excluding the bookings.
Solution: Temporarily remove the date range and status filters to fetch all bookings and confirm the API key has data access. Then adjust the starting_after and ending_before values. OnceHub uses ISO 8601 timestamps — make sure you are not accidentally filtering for the past rather than the future.
1// Debug: fetch all bookings without date filter first2const response = await fetch(`${ONCEHUB_BASE_URL}/bookings?limit=10`, {3 headers: { 'api-key': apiKey },4});5const data = await response.json();6console.log('All bookings:', JSON.stringify(data, null, 2));Best practices
- Use the iframe embed for public-facing booking pages — it requires no backend and is immediately maintainable from the OnceHub dashboard without code changes.
- Never expose ONCEHUB_API_KEY with a NEXT_PUBLIC_ prefix; it grants read access to all your account's booking data and should only be readable in server-side API routes.
- Store the booking page URL as NEXT_PUBLIC_SCHEDULEONCE_URL rather than hardcoding it, so you can update your booking page in OnceHub and redeploy without a code change.
- Add error boundaries around the ScheduleOnce iframe embed — if OnceHub has a service interruption, you want the rest of your page to remain functional.
- Implement idempotent webhook handling by checking the booking ID before processing — OnceHub may retry webhook deliveries if your server does not respond within the timeout.
- Use OnceHub's qualification questions to capture structured data (company size, use case, budget) that you can pass to downstream CRM systems via webhooks.
- For multi-team setups, use separate API routes per booking page type (demos, support, onboarding) to keep handler logic focused and easy to modify.
- Test webhook processing with OnceHub's test booking feature before going live to ensure your handler correctly parses all event types.
Alternatives
Calendly is an alternative if you need simpler 1:1 scheduling without complex team routing rules — it has a more polished embed widget and broader third-party integrations for smaller teams.
Acuity Scheduling is an alternative if your scheduling involves service-based appointments with payment collection, intake forms, and package management rather than sales routing.
Doodle is an alternative if your primary scheduling need is finding group availability across multiple participants rather than automated individual booking.
Frequently asked questions
What is the difference between ScheduleOnce and Calendly?
ScheduleOnce (OnceHub) is designed for enterprise sales teams that need intelligent meeting routing — assigning incoming bookings to the right team member based on territory, workload, or qualification answers. Calendly is simpler and better suited to individual or small team 1:1 scheduling. If your use case involves routing prospects to specific reps or complex booking rules, ScheduleOnce is the better fit. For straightforward personal scheduling, Calendly is easier to set up.
Does V0 have a native ScheduleOnce integration?
No, V0 does not have a one-click ScheduleOnce integration through the Vercel Marketplace. You embed the booking page manually using an iframe component or build a Next.js API route for data access. V0 can generate the surrounding UI and API route when you describe the integration in the V0 chat.
Can I use ScheduleOnce to route meetings to different team members in my V0 app?
Yes, but the routing logic lives entirely in ScheduleOnce's dashboard configuration — not in your V0 code. You configure routing rules in OnceHub (round-robin, territory-based, or qualification-driven), then embed the single booking page URL in your V0 app. OnceHub handles all the assignment logic automatically when someone books through the embedded page.
Are OnceHub webhooks available on the free plan?
OnceHub's webhook functionality is part of their paid plans. The free tier provides basic scheduling but does not include API access or webhook subscriptions. Check the current OnceHub pricing page for the specific plan that includes API and webhook features — this varies by their current pricing structure.
How do I prefill the ScheduleOnce booking form with data from my V0 app?
ScheduleOnce supports query parameter prefilling. Append parameters to your booking page URL like ?name=John+Smith&email=john@example.com to pre-populate the invitee's details. In your V0 iframe component, dynamically construct the src URL from user session data to skip the data entry step for logged-in users.
What is OnceHub and is it the same as ScheduleOnce?
OnceHub is the parent brand and company name. ScheduleOnce was their flagship scheduling product that has been integrated into the OnceHub platform. The scheduling functionality is now accessed at oncehub.com, and their API uses the OnceHub branding and API base URL (api.oncehub.com). When you see 'OnceHub' in API docs, it refers to the same platform as ScheduleOnce.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation