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

How to Integrate UserTesting with V0

To use UserTesting with V0, generate a UX research dashboard UI in V0, then create a Next.js API route at app/api/usertesting/route.ts that fetches study results and video session data from the UserTesting API. Store your UserTesting API credentials in Vercel Dashboard → Settings → Environment Variables. UserTesting's API is read-only for most plan types — use it to surface insights and session metrics directly in your V0 app.

What you'll learn

  • How to generate a UX research insights dashboard with V0
  • How to create a Next.js API route that fetches UserTesting study and session data
  • How to store UserTesting API credentials securely in Vercel environment variables
  • How to display video session metrics and participant feedback in a V0-generated UI
  • How to handle UserTesting's paginated API responses in Next.js
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate16 min read25 minutesAnalyticsApril 2026RapidDev Engineering Team
TL;DR

To use UserTesting with V0, generate a UX research dashboard UI in V0, then create a Next.js API route at app/api/usertesting/route.ts that fetches study results and video session data from the UserTesting API. Store your UserTesting API credentials in Vercel Dashboard → Settings → Environment Variables. UserTesting's API is read-only for most plan types — use it to surface insights and session metrics directly in your V0 app.

Building a UX Research Insights Dashboard with UserTesting and V0

UserTesting gives product teams a window into how real users interact with their products — capturing video sessions, think-aloud commentary, and task completion data. For founders and product managers who want to surface these insights inside their own tools rather than logging into UserTesting's platform separately, the UserTesting API enables you to pull study results, session recordings metadata, and participant feedback into any application you build.

With V0, you can rapidly generate a polished UX research dashboard that aggregates your UserTesting data in one place. The integration pattern is straightforward: V0 builds the visualization components and data tables, while a Next.js API route fetches from UserTesting's REST API using your credentials stored in Vercel. Because UserTesting's API is primarily read-oriented — retrieving studies, sessions, and results rather than creating new tests — the integration focuses on data fetching, filtering, and presentation.

One important context for V0 users: UserTesting's API availability varies by plan. Enterprise and Professional plans have full API access including session video links and detailed participant data. Starter and lower-tier plans may have limited or no API access. Confirm your plan's API entitlements before building the integration. The API uses OAuth2 client credentials for authentication, which means you exchange a client ID and client secret for an access token that expires after a set period — your API route needs to handle token refresh or request a new token on each API call.

Integration method

Next.js API Route

V0 generates the UX research dashboard components for displaying study results, session metrics, and participant feedback, while a Next.js API route handles all authenticated requests to the UserTesting API. The API route keeps your UserTesting credentials server-side and returns structured study and session data that your V0-generated dashboard renders. This proxy pattern prevents your API token from being exposed in the browser's network tab.

Prerequisites

  • A V0 account with a Next.js project at v0.dev
  • A UserTesting account with API access (typically Professional or Enterprise plan)
  • Your UserTesting API client ID and client secret from UserTesting Dashboard → Settings → API
  • A Vercel account with your V0 project deployed via GitHub
  • Basic understanding of REST API concepts and OAuth2 token-based authentication

Step-by-step guide

1

Generate the UX Research Dashboard UI in V0

Begin by prompting V0 to generate the front-end components for your UX research dashboard. The key UI elements are: a studies list or grid showing high-level study metadata, a sessions view showing individual participant sessions within a study, and optionally a metrics summary section with charts. V0 excels at data-dense dashboard layouts with Tailwind CSS. When prompting, be explicit about the data structure you expect from the API — tell V0 the field names like study_name, participant_count, completion_rate, status, and start_date so it generates components that reference these fields correctly in the JSX. This reduces the amount of code editing you need to do after generation. For displaying session video links, V0 can generate a list component where each session item has a thumbnail area, participant information, key metrics, and an external link button that opens the session recording URL in a new tab. UserTesting's API returns direct links to session recordings for users with appropriate permissions — these open in the UserTesting player. Ask V0 to include loading skeleton states for the dashboard components. Because the API route needs to fetch data from UserTesting on each request, there will be a noticeable loading delay. Skeleton screens (animated gray placeholder rectangles that mimic the final layout) provide a much better user experience than a spinning loader or blank white screen. V0 can generate these using Tailwind's animate-pulse class on placeholder divs. For charts showing metrics like rating distributions or task completion rates over time, prompt V0 to use Recharts — it is already in the V0 default stack and generates clean, responsive bar and line charts with minimal configuration.

V0 Prompt

Create a UX research dashboard with two tabs: Studies and Sessions. The Studies tab shows a responsive grid of cards, each with study name, status badge (colored Active=green/Completed=gray), participant count, overall rating with star icon, and a View Sessions button. The Sessions tab shows a table with columns: Participant ID, Task, Completion (checkmark/X), Rating (1-5 stars), Date, and a Watch Recording link. Include loading skeleton states. Fetch studies from /api/usertesting/studies and sessions from /api/usertesting/sessions.

Paste this in V0 chat

Pro tip: Ask V0 to add error boundary handling in the dashboard components — if the API route returns an error (e.g., expired API credentials), show a friendly 'Could not load research data. Check your API connection.' message instead of a JavaScript runtime error.

Expected result: V0 generates a two-tab research dashboard with study cards and a sessions table, complete with loading skeleton states and data fetching calls to your API routes.

2

Create the UserTesting API Authentication Helper

UserTesting's API uses OAuth2 client credentials flow for authentication. Unlike a simple API key, you need to exchange your client ID and secret for a bearer token, which then expires and needs to be refreshed. Create a helper module at lib/usertesting-auth.ts that handles token acquisition so your API routes can call it without duplicating the authentication logic. The token endpoint for UserTesting is POST https://app.usertesting.com/oauth/token with a Basic Authorization header (base64-encoded clientId:clientSecret) and a body of grant_type=client_credentials. The response includes an access_token string and expires_in value (typically 3600 seconds). For a production-grade implementation, cache the token in memory or in Vercel's KV store and reuse it until it is close to expiration. For a simpler initial implementation, request a new token on every API route invocation — this adds a small latency overhead but eliminates token management complexity. Given that UserTesting API calls are for a dashboard (not a high-throughput path), the simpler approach works fine in most cases. Store your client credentials as USERTESTING_CLIENT_ID and USERTESTING_CLIENT_SECRET in Vercel environment variables. Neither value should have the NEXT_PUBLIC_ prefix — both are server-only secrets. The client secret especially must never appear in browser-side code, as it would allow anyone who sees it to call the UserTesting API on your behalf. Also note a V0-specific limitation here: V0 generates client-side React components that cannot directly call the UserTesting API because the API requires server-side credentials. If you prompt V0 to 'add UserTesting integration,' it may attempt to call the API directly from a client component using environment variables. Always redirect this to the API route pattern described in this guide.

V0 Prompt

Create a TypeScript helper module at lib/usertesting-auth.ts that exports an async function getAccessToken() which exchanges USERTESTING_CLIENT_ID and USERTESTING_CLIENT_SECRET environment variables for a bearer token by calling the UserTesting OAuth token endpoint at https://app.usertesting.com/oauth/token with client_credentials grant type. Return the access_token string.

Paste this in V0 chat

lib/usertesting-auth.ts
1// lib/usertesting-auth.ts
2export async function getAccessToken(): Promise<string> {
3 const clientId = process.env.USERTESTING_CLIENT_ID;
4 const clientSecret = process.env.USERTESTING_CLIENT_SECRET;
5
6 if (!clientId || !clientSecret) {
7 throw new Error('UserTesting credentials not configured');
8 }
9
10 const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
11
12 const response = await fetch('https://app.usertesting.com/oauth/token', {
13 method: 'POST',
14 headers: {
15 Authorization: `Basic ${credentials}`,
16 'Content-Type': 'application/x-www-form-urlencoded',
17 },
18 body: 'grant_type=client_credentials',
19 });
20
21 if (!response.ok) {
22 throw new Error(`UserTesting auth failed: ${response.status}`);
23 }
24
25 const data = await response.json();
26 return data.access_token;
27}

Pro tip: For high-traffic dashboards, cache the access token using a module-level variable with an expiry timestamp. Check if the cached token is still valid (current time < expiry - 60 seconds) before requesting a new one. This avoids an extra HTTP round-trip on every page load.

Expected result: The helper module successfully exchanges your client credentials for a bearer token. Calling getAccessToken() in an API route returns a string like 'eyJhbGciOiJSUzI1NiJ9...' that can be used in Authorization headers for UserTesting API calls.

3

Create the Studies and Sessions API Routes

Create the Next.js API routes that your dashboard components call to fetch UserTesting data. You need at minimum two routes: one for listing studies and one for listing sessions within a study (or across all studies). Create app/api/usertesting/studies/route.ts for fetching the list of studies. This calls GET https://api.usertesting.com/v1/studies using the bearer token from your auth helper. The UserTesting API returns paginated results — handle the page and per_page query parameters by forwarding them from your route's search params to the UserTesting API call. Create app/api/usertesting/sessions/route.ts for fetching session data. This can fetch all sessions across studies, or accept a study_id query parameter to scope results to a specific study. Sessions include participant data, task results, ratings, video URLs (for plans with recording access), and timestamps. For the individual study detail route, create app/api/usertesting/studies/[id]/route.ts using dynamic route segments. Extract the study ID from the params object and fetch from https://api.usertesting.com/v1/studies/{id} to get detailed metrics for a single study. In all routes, use the getAccessToken() helper from your lib module, add the returned token as an Authorization: Bearer {token} header on every UserTesting API call, and handle potential 401 errors (token expired or invalid credentials) with a clear error response. Also handle 403 errors which indicate your plan does not have access to the requested resource — this is common if you try to access session recordings on a plan that does not include them.

V0 Prompt

Create two Next.js API routes: app/api/usertesting/studies/route.ts that calls GET https://api.usertesting.com/v1/studies using getAccessToken() from lib/usertesting-auth, accepts page and per_page query params, and returns the studies array and pagination metadata. Also create app/api/usertesting/sessions/route.ts that accepts an optional study_id query param and fetches sessions from https://api.usertesting.com/v1/sessions (or /v1/studies/{study_id}/sessions when study_id is provided). Both routes return JSON.

Paste this in V0 chat

app/api/usertesting/studies/route.ts
1import { NextRequest, NextResponse } from 'next/server';
2import { getAccessToken } from '@/lib/usertesting-auth';
3
4export async function GET(request: NextRequest) {
5 try {
6 const { searchParams } = new URL(request.url);
7 const page = searchParams.get('page') || '1';
8 const perPage = searchParams.get('per_page') || '20';
9
10 const token = await getAccessToken();
11
12 const response = await fetch(
13 `https://api.usertesting.com/v1/studies?page=${page}&per_page=${perPage}`,
14 {
15 headers: {
16 Authorization: `Bearer ${token}`,
17 Accept: 'application/json',
18 },
19 }
20 );
21
22 if (response.status === 401) {
23 return NextResponse.json(
24 { error: 'UserTesting authentication failed. Check your API credentials.' },
25 { status: 401 }
26 );
27 }
28
29 if (response.status === 403) {
30 return NextResponse.json(
31 { error: 'Your UserTesting plan does not have API access to this resource.' },
32 { status: 403 }
33 );
34 }
35
36 if (!response.ok) {
37 return NextResponse.json(
38 { error: `UserTesting API error: ${response.status}` },
39 { status: response.status }
40 );
41 }
42
43 const data = await response.json();
44 return NextResponse.json({
45 studies: data.studies || data,
46 total: data.total,
47 page: parseInt(page),
48 });
49 } catch (error) {
50 console.error('UserTesting studies fetch error:', error);
51 return NextResponse.json(
52 { error: 'Failed to fetch studies' },
53 { status: 500 }
54 );
55 }
56}

Pro tip: Add Next.js fetch caching with revalidate: 60 to the studies fetch to reduce UserTesting API calls. Study lists do not change frequently, so a 60-second cache provides a good balance between freshness and API rate limit conservation.

Expected result: Calling GET /api/usertesting/studies from the browser (or from your dashboard component) returns a JSON array of study objects with names, statuses, participant counts, and metadata. The sessions route returns similar data scoped to sessions.

4

Add Environment Variables in Vercel and Test

Add your UserTesting API credentials to Vercel's environment variables and test the complete data flow from the dashboard to the API routes to UserTesting's API. Go to Vercel Dashboard → your project → Settings → Environment Variables. Add two variables: USERTESTING_CLIENT_ID with your UserTesting OAuth client ID, and USERTESTING_CLIENT_SECRET with your client secret. Both should be available on the Production, Preview, and Development environments. Neither should have the NEXT_PUBLIC_ prefix. You can find your client ID and secret in UserTesting Dashboard → Settings → Developer → API Credentials (the exact path may vary by UserTesting plan and version). If you do not see an API credentials section in your UserTesting settings, your plan may not include API access — contact UserTesting support to confirm your plan's API entitlements. For local development, create a .env.local file with the same two variables. Then run npm run dev and navigate to your dashboard. Check the browser's network tab to confirm the fetch calls to /api/usertesting/studies are returning 200 responses with study data. If you receive a 401 on the first call, it usually means the credentials are wrong or the OAuth token endpoint URL has changed — check UserTesting's API documentation for the current token endpoint. If you receive a 403, your plan likely does not include API access. A 404 response often means the API endpoint path has changed — UserTesting's API versioning (v1, v2) can shift with platform updates, so verify the current endpoint paths in their developer documentation. After confirming local testing works, push to GitHub to trigger a Vercel deployment and test the production environment as well.

.env.local
1# .env.local (local development only never commit)
2USERTESTING_CLIENT_ID=your_client_id_here
3USERTESTING_CLIENT_SECRET=your_client_secret_here

Pro tip: UserTesting's API documentation is accessible at docs.usertesting.com. If the API endpoint paths in this guide differ from what you see in the documentation, always defer to the official docs — UserTesting occasionally updates their API version and endpoint structure.

Expected result: The Vercel Dashboard shows both environment variables saved. After redeployment, the dashboard successfully loads study and session data from UserTesting, displaying research insights in the V0-generated interface.

Common use cases

UX Research Command Center Dashboard

A product team builds an internal dashboard that surfaces all active and completed UserTesting studies in one view. The V0-generated interface shows study names, participant counts, completion rates, and average task completion times. Team members can click into any study to see session-level metrics without leaving the internal tool.

V0 Prompt

Create a UX research dashboard with a header showing total studies count and average completion rate. Display studies as cards with study name, status badge (Active/Completed), participant count, start date, and a View Sessions button. Fetch data from /api/usertesting/studies. Add a filter bar for status and date range at the top.

Copy this prompt to try it in V0

Session Insights Feed for Product Reviews

A design team creates a weekly review screen that displays the most recent UserTesting session highlights — key quotes, task success rates, and links to session recordings. The V0-generated feed automatically populates with the latest session data from the API route, eliminating the need to export reports manually from UserTesting.

V0 Prompt

Build a session insights feed showing the 10 most recent UserTesting sessions as list items. Each item shows the participant ID, task name, completion status (Success/Fail), rating out of 5, and a top quote extracted from the session. Include a link to the video recording. Fetch from /api/usertesting/sessions?limit=10.

Copy this prompt to try it in V0

Multi-Study Comparison View

A UX researcher needs to compare results across multiple studies testing different versions of a checkout flow. The V0 app generates a side-by-side comparison table showing task completion rates, average ratings, and key metrics for each study. The API route fetches metrics for the selected study IDs and returns normalized data for comparison.

V0 Prompt

Create a study comparison page with a multi-select dropdown to choose 2-4 studies from /api/usertesting/studies. Display the selected studies side-by-side in columns showing: overall rating, task success rate, average time on task, and participant count. Add a bar chart comparing overall ratings across the selected studies.

Copy this prompt to try it in V0

Troubleshooting

API route returns 401 Unauthorized from UserTesting

Cause: The client credentials are incorrect, missing from environment variables, or the OAuth token endpoint URL has changed in a recent UserTesting API update.

Solution: Verify USERTESTING_CLIENT_ID and USERTESTING_CLIENT_SECRET are correctly set in Vercel Dashboard → Settings → Environment Variables. Confirm the token endpoint URL at UserTesting's developer documentation (docs.usertesting.com) — the URL may differ from what is hardcoded. Trigger a Vercel redeployment after updating variables.

API returns 403 Forbidden when fetching studies or sessions

Cause: Your UserTesting plan does not include API access, or the specific resource (e.g., session recordings) requires a higher-tier plan than your current subscription.

Solution: Log in to UserTesting and check your plan tier under Account Settings. API access typically requires a Professional or Enterprise plan. Contact UserTesting sales or support to confirm which API endpoints are available on your plan. Session video links may require a separate recording entitlement even on plans with API access.

Dashboard loads but shows 0 studies even though studies exist in UserTesting

Cause: The API response structure may differ from what your code expects. UserTesting's API may return studies under a different key (e.g., data, results, or items instead of studies), or the pagination is returning an empty page.

Solution: Add console.log(data) in your API route immediately after the successful fetch to inspect the actual response structure. Update your route to reference the correct array key from the response. Also verify the page parameter is starting at 1, not 0 — some APIs are zero-indexed but UserTesting uses 1-based pagination.

typescript
1// Add this temporarily to inspect the response structure
2const data = await response.json();
3console.log('UserTesting response structure:', JSON.stringify(data, null, 2));
4// Then update the return statement based on what you see

Session video links appear in the API response but clicking them shows 'Access Denied' in UserTesting

Cause: Session recording links from the API are typically scoped to the authenticated UserTesting account. Opening them in a new browser window requires the viewer to be logged in to UserTesting with an account that has access to those recordings.

Solution: Ensure the people accessing your dashboard are logged into UserTesting in another browser tab, or add a note in your UI that users must be logged into UserTesting to view recordings. For fully embedded playback, UserTesting offers an embed API on Enterprise plans.

Best practices

  • Store USERTESTING_CLIENT_ID and USERTESTING_CLIENT_SECRET without the NEXT_PUBLIC_ prefix — these are server-only secrets that must never be included in browser-visible JavaScript.
  • Cache OAuth access tokens server-side with their expiry time to avoid requesting a new token on every API call and reduce authentication latency.
  • Handle UserTesting's 403 responses explicitly in your UI — display a helpful message like 'Session recordings require a higher-tier UserTesting plan' rather than a generic error.
  • Use Next.js fetch caching with revalidate for study and session lists since research data does not change in real time — a 60-second cache significantly reduces API call volume.
  • Always check the status field in session and study objects before rendering data — incomplete or processing studies may return null values for metrics.
  • Add pagination controls to your dashboard if you have more than 20 studies — UserTesting's API is paginated and fetching all studies at once may be slow or hit rate limits.
  • Log the UserTesting API response shape in your API route during development — UserTesting's API versioning can change field names between versions.
  • Scope session data access to only what your dashboard needs — fetching video URLs for all sessions when you only need metrics wastes API quota and slows down your dashboard.

Alternatives

Frequently asked questions

Does UserTesting have a public REST API I can use in my V0 app?

Yes, UserTesting provides a REST API for reading study results, session data, and participant feedback. API access requires a Professional or Enterprise plan — it is not available on Starter or free plans. You authenticate using OAuth2 client credentials, exchanging a client ID and secret for a bearer token. The API is primarily read-oriented for retrieving data rather than creating new tests programmatically.

Can V0 generate the UserTesting integration code automatically?

V0 can generate the dashboard UI components and the basic structure of the API routes if you describe the data shape you want to display. However, V0 does not have built-in knowledge of UserTesting's specific API endpoints, OAuth flow, or response schemas. You will need to provide these details in your prompts or refer to UserTesting's developer documentation to wire up the correct endpoint URLs and authentication pattern.

What is the difference between UserTesting and FullStory for V0 integrations?

UserTesting is a moderated research platform where you recruit participants and ask them to perform specific tasks — you get video sessions of real users narrating their experience. FullStory is an automated session replay tool that passively records all user sessions on your live site. For a V0 app, UserTesting integration means fetching structured research results, while FullStory integration involves injecting a tracking script. The two tools answer different questions: UserTesting tells you why users struggle, FullStory shows you what they actually do.

How do I display UserTesting session recordings inside my V0 app?

UserTesting session recordings are hosted on UserTesting's platform. The API returns direct links to recordings that open in the UserTesting player — your dashboard can display these as external links. For embedded playback within your app, UserTesting offers an embed API on Enterprise plans that generates iframe-compatible embed codes. Implement this in your Next.js API route by requesting an embed token for the session ID.

Why does my local development work but the Vercel deployment fails to fetch UserTesting data?

The most likely cause is that your .env.local file was not replicated to Vercel's Environment Variables. Vercel does not read .env.local during deployment — you must manually add USERTESTING_CLIENT_ID and USERTESTING_CLIENT_SECRET in Vercel Dashboard → Settings → Environment Variables and trigger a redeployment. Also verify the variables are enabled for the Production environment specifically.

Can I trigger a new UserTesting study from my V0 app via the API?

UserTesting's API is primarily designed for reading research data rather than creating and launching new studies programmatically. Study creation typically requires the UserTesting dashboard interface. If your use case requires programmatic study creation, check UserTesting's latest API documentation for their study creation endpoints — availability varies by plan and the API's write capabilities have expanded over time.

How do I handle UserTesting API rate limits in my dashboard?

UserTesting imposes API rate limits that vary by plan. To stay within limits, use Next.js fetch caching with revalidate on your API routes so the same data is not re-fetched on every page load. Set a revalidate value of 60-300 seconds for study and session lists. If you hit rate limits (typically a 429 response), implement exponential backoff retry logic in your API route and add caching at a higher TTL.

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.