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

How to Integrate Freshdesk with V0

To integrate Freshdesk with V0 by Vercel, create a Next.js API route that uses Freshdesk's REST API with your API key to create, update, and list support tickets. Store your FRESHDESK_API_KEY and FRESHDESK_DOMAIN in Vercel environment variables, and use V0 to generate a customer support portal or ticket management dashboard.

What you'll learn

  • How to get your Freshdesk API key and configure your domain endpoint
  • How to create a Next.js API route that submits tickets to Freshdesk
  • How to build a customer-facing support form with V0 that creates real Freshdesk tickets
  • How to display and filter ticket lists in a V0-generated support dashboard
  • How to handle Freshdesk webhook events for ticket status updates
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate15 min read30 minutesCommunicationApril 2026RapidDev Engineering Team
TL;DR

To integrate Freshdesk with V0 by Vercel, create a Next.js API route that uses Freshdesk's REST API with your API key to create, update, and list support tickets. Store your FRESHDESK_API_KEY and FRESHDESK_DOMAIN in Vercel environment variables, and use V0 to generate a customer support portal or ticket management dashboard.

Building a Customer Support Portal with Freshdesk and V0

Freshdesk is one of the most widely adopted helpdesk platforms for growing businesses, offering a straightforward REST API that makes it easy to integrate ticket creation and management into custom web apps. For V0 users, the most common integration pattern is a branded customer support portal: your V0-generated front-end collects customer issues through a form, and a Next.js API route creates the corresponding Freshdesk ticket behind the scenes. Customers interact with your app's UI, while your support team handles everything inside Freshdesk.

Freshdesk's API uses basic HTTP authentication with your API key as the username and an 'X' as the password. Every request goes to a subdomain-specific endpoint at https://{your-domain}.freshdesk.com/api/v2/. The API key is available in your Freshdesk account under your profile settings and should be stored as a server-side environment variable — never exposed to the browser, as it grants full access to your helpdesk data.

Beyond basic ticket creation, you can build richer integrations: a customer-facing ticket status tracker where users check the progress of their open tickets, an internal agent dashboard showing all open tickets with priority filtering, or a support form that automatically assigns tickets to specific agents or groups based on the issue type. V0 can generate all of these UIs quickly — the integration layer is your Next.js API routes calling Freshdesk's API.

Integration method

Next.js API Route

V0 generates the customer-facing support forms and internal ticket management UI, while Next.js API routes handle all communication with Freshdesk's REST API using API key authentication. When a customer submits a support request through your V0-generated form, the API route creates a Freshdesk ticket and returns the ticket ID to confirm the submission. Support agents can also view and update tickets through a V0-built internal dashboard.

Prerequisites

  • A V0 account with a Next.js project at v0.dev
  • A Vercel account with the project deployed via GitHub
  • A Freshdesk account at freshdesk.com (free Sprout plan works for development)
  • Your Freshdesk API key from Freshdesk → Profile icon → Profile Settings → API Key
  • Your Freshdesk domain subdomain (the part before .freshdesk.com in your account URL)

Step-by-step guide

1

Generate the Support UI with V0

Start by prompting V0 to generate the customer-facing or internal support interface. The most common starting point is a support contact form that customers can fill out to submit issues. Think carefully about what fields you need — Freshdesk tickets require at minimum a subject, description, email, and priority. Additional fields like ticket type, product category, or custom fields can also be created if you have configured custom ticket fields in your Freshdesk account. V0 generates excellent form UIs with validation, loading states, and success messages. Be specific about the form fields and their types: text inputs, dropdowns for enumerations like priority and type, and a multi-line textarea for the issue description. Also specify the desired behavior on submit — show a spinner during the request, display the returned ticket ID in a success banner, and handle error states gracefully. For an internal agent dashboard, describe the table layout V0 should generate: ticket ID, customer name, subject, status with colored badges, priority, and assigned agent. Include pagination if you expect many tickets, or a scroll container for the table. Ask V0 to add filter controls for status and priority so agents can narrow down their queue. V0 will likely generate fetch calls to your API routes using useEffect or React Query patterns. Check that the API endpoint paths in the generated code match what you plan to create in the next step.

V0 Prompt

Create a support ticket submission form with a card layout. Include fields: customer name (text), email (email input), subject (text), issue type (select: Bug Report, Billing Question, Technical Help, Feature Request, Other), priority (select: Low, Normal, High, Urgent), and message (textarea with min 50 chars). Submit button says 'Submit Ticket' and POSTs to /api/freshdesk/tickets. On success, show a green banner with 'Ticket #[id] submitted successfully'. On error, show a red error message.

Paste this in V0 chat

Pro tip: Ask V0 to disable the submit button and show a spinner after the first click to prevent duplicate ticket submissions.

Expected result: V0 generates a support form or dashboard UI with fetch calls wired to /api/freshdesk/tickets or /api/freshdesk/list. The component handles loading and error states.

2

Create the Freshdesk API Routes

Create your Next.js API routes to handle Freshdesk operations. Freshdesk uses basic HTTP authentication — you pass your API key as the username and the string 'X' as the password, encoded in Base64. The base URL for all requests is https://{YOUR_DOMAIN}.freshdesk.com/api/v2/. The ticket creation route at app/api/freshdesk/tickets/route.ts handles POST requests. It reads the form data from the request body, constructs a Freshdesk ticket payload, and sends a POST request to Freshdesk's tickets endpoint. The payload requires at minimum: email (requester's email), subject, description, and status (2 = Open). Priority is optional but recommended: 1 = Low, 2 = Medium, 3 = High, 4 = Urgent. For listing tickets, create a GET handler at app/api/freshdesk/list/route.ts that calls Freshdesk's GET /api/v2/tickets endpoint with filtering parameters. You can filter by requester_id, email, or custom fields. The API returns paginated results — include the page query parameter to support pagination. For an internal dashboard, add a route that fetches tickets with filter=open and sorts by created_at. Map the response to the fields your V0 UI expects. Important: Freshdesk rate limits the free Sprout plan to 1000 API calls per hour. For high-traffic forms, consider caching list results with a short TTL using Vercel's fetch caching or Upstash Redis, and only bypass cache for write operations.

V0 Prompt

Add a Next.js API route at app/api/freshdesk/tickets/route.ts that handles POST requests. Read name, email, subject, type, priority, message from the request body. Create a Freshdesk ticket by posting to https://${process.env.FRESHDESK_DOMAIN}.freshdesk.com/api/v2/tickets using basic auth with FRESHDESK_API_KEY as username and X as password. Map the priority field to Freshdesk priority numbers (low=1, normal=2, high=3, urgent=4). Return the created ticket id and display_id.

Paste this in V0 chat

app/api/freshdesk/tickets/route.ts
1// app/api/freshdesk/tickets/route.ts
2import { NextRequest, NextResponse } from 'next/server';
3
4const FRESHDESK_BASE_URL = `https://${process.env.FRESHDESK_DOMAIN}.freshdesk.com/api/v2`;
5
6function getAuthHeader() {
7 const credentials = Buffer.from(`${process.env.FRESHDESK_API_KEY}:X`).toString('base64');
8 return `Basic ${credentials}`;
9}
10
11const PRIORITY_MAP: Record<string, number> = {
12 low: 1,
13 normal: 2,
14 medium: 2,
15 high: 3,
16 urgent: 4,
17};
18
19export async function POST(request: NextRequest) {
20 try {
21 const { name, email, subject, type, priority, message } = await request.json();
22
23 if (!email || !subject || !message) {
24 return NextResponse.json(
25 { error: 'email, subject, and message are required' },
26 { status: 400 }
27 );
28 }
29
30 const ticketPayload = {
31 name,
32 email,
33 subject,
34 description: message,
35 status: 2, // Open
36 priority: PRIORITY_MAP[priority?.toLowerCase()] ?? 2,
37 type: type || 'Question',
38 };
39
40 const response = await fetch(`${FRESHDESK_BASE_URL}/tickets`, {
41 method: 'POST',
42 headers: {
43 'Content-Type': 'application/json',
44 Authorization: getAuthHeader(),
45 },
46 body: JSON.stringify(ticketPayload),
47 });
48
49 if (!response.ok) {
50 const error = await response.json();
51 return NextResponse.json(
52 { error: 'Failed to create ticket', details: error },
53 { status: response.status }
54 );
55 }
56
57 const ticket = await response.json();
58 return NextResponse.json({ id: ticket.id, displayId: ticket.display_id });
59 } catch (error) {
60 return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
61 }
62}

Pro tip: Freshdesk automatically sends a ticket confirmation email to the requester's email address when a ticket is created via API — you do not need to send a separate email.

Expected result: POST /api/freshdesk/tickets creates a real ticket in Freshdesk and returns the ticket ID. The ticket appears in your Freshdesk agent dashboard immediately.

3

Add Environment Variables to Vercel

Go to your Vercel Dashboard, open the project, click Settings in the top nav, and then click Environment Variables. You need to add two server-side variables for Freshdesk authentication. First, add FRESHDESK_API_KEY with your Freshdesk API key. To find this, log into Freshdesk, click on your profile picture in the top right corner, and select Profile Settings. Scroll to the bottom of the page to find the API Key section. Copy the key and paste it as the value. This variable must NOT have a NEXT_PUBLIC_ prefix — it is a server-only secret that grants full API access to your Freshdesk account. Second, add FRESHDESK_DOMAIN with just the subdomain part of your Freshdesk URL. If your Freshdesk URL is https://mycompany.freshdesk.com, add mycompany as the value. Do not include the protocol, the full domain, or any slashes. This value is not sensitive — it is part of your public Freshdesk URL — but storing it as an environment variable makes it easy to switch between accounts. For Preview deployments, you can use the same Freshdesk account as production since Freshdesk tickets from testing are easy to identify by subject prefix. Alternatively, create a test Freshdesk account with the free plan specifically for staging. After saving both variables, click Save and trigger a new deployment by pushing a commit. Check your Vercel function logs to confirm the API route executes without authentication errors.

Pro tip: Add a prefix like [TEST] to ticket subjects created from Preview deployments so your support team can easily distinguish test tickets from real ones.

Expected result: Both FRESHDESK_API_KEY and FRESHDESK_DOMAIN are saved in Vercel. After redeployment, the /api/freshdesk/tickets route successfully authenticates with Freshdesk and creates tickets.

4

Handle Freshdesk Webhooks for Status Updates

Freshdesk can send webhook events to your app when ticket statuses change, when agents reply, or when tickets are resolved. This lets your V0 app reflect real-time ticket state changes without polling the API. Create a webhook handler at app/api/freshdesk/webhook/route.ts. This route accepts POST requests from Freshdesk and processes ticket events. Freshdesk webhooks can be configured to send when: ticket is created, ticket status changes, ticket is resolved, agent is assigned, or a note is added. To configure a webhook in Freshdesk, go to Admin → Automations → Ticket creation / Ticket updates → New rule. In the Actions section, choose Trigger webhook and enter your Vercel deployment URL (https://your-app.vercel.app/api/freshdesk/webhook) as the callback URL. Choose POST as the method and JSON as the encoding. Select which ticket fields to include in the payload. Important: Freshdesk does not send a signature header for webhook verification by default (unlike Stripe). To verify that incoming requests are genuinely from Freshdesk, you can use IP allowlisting (Freshdesk's webhook IPs are documented), add a secret token as a query parameter in your webhook URL, or check that the payload structure matches expected Freshdesk format. For production apps, implement at least the query-parameter secret check. In your webhook handler, update your database based on ticket status changes. For example, if a ticket status changes to 4 (Resolved), mark the corresponding record in your database as resolved so the customer-facing ticket tracker reflects the change.

V0 Prompt

Add a Next.js API route at app/api/freshdesk/webhook/route.ts that handles POST requests from Freshdesk. Log the incoming ticket event and check the freshdesk_ticket object in the body. If ticket status is 4 (Resolved), call a database update function to mark the ticket resolved. Check for a FRESHDESK_WEBHOOK_SECRET query param to verify the request. Return 200 OK.

Paste this in V0 chat

app/api/freshdesk/webhook/route.ts
1// app/api/freshdesk/webhook/route.ts
2import { NextRequest, NextResponse } from 'next/server';
3
4export async function POST(request: NextRequest) {
5 try {
6 // Verify webhook secret from query param
7 const { searchParams } = new URL(request.url);
8 const secret = searchParams.get('secret');
9 if (secret !== process.env.FRESHDESK_WEBHOOK_SECRET) {
10 return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
11 }
12
13 const payload = await request.json();
14 const ticket = payload.freshdesk_ticket;
15
16 if (!ticket) {
17 return NextResponse.json({ received: true });
18 }
19
20 console.log('Freshdesk webhook received:', {
21 ticketId: ticket.id,
22 status: ticket.status,
23 subject: ticket.subject,
24 });
25
26 // Handle status changes
27 // Status: 2=Open, 3=Pending, 4=Resolved, 5=Closed
28 if (ticket.status === 4 || ticket.status === 5) {
29 // Update your database here: mark ticket as resolved
30 // await db.tickets.update({ where: { freshdeskId: ticket.id }, data: { status: 'resolved' } });
31 }
32
33 return NextResponse.json({ received: true });
34 } catch (error) {
35 return NextResponse.json({ error: 'Webhook processing failed' }, { status: 500 });
36 }
37}

Pro tip: Add the webhook secret as a query parameter in the Freshdesk webhook URL: https://your-app.vercel.app/api/freshdesk/webhook?secret=your-secret-value. Store this value as FRESHDESK_WEBHOOK_SECRET in Vercel.

Expected result: Freshdesk sends POST requests to your webhook route when tickets are updated. Your app logs the events and can update its own database to reflect ticket status changes.

Common use cases

Customer Support Contact Form

A SaaS company replaces a generic email contact form with a support form that creates Freshdesk tickets directly. Customers fill in their name, email, subject, and description. The form submits to a Next.js API route that creates the ticket in Freshdesk and returns the ticket ID as a confirmation number.

V0 Prompt

Create a customer support form with fields for: full name, email address, subject (dropdown: Billing, Technical Issue, General Question, Feature Request), priority (dropdown: Low, Medium, High), and description textarea. Include a Submit button that POSTs to /api/freshdesk/tickets. Show a success message with the ticket ID after submission, and a loading spinner during the request.

Copy this prompt to try it in V0

Ticket Status Tracker

A customer portal lets users log in and see all their past support tickets with current statuses. The V0 app fetches tickets from Freshdesk filtered by the customer's email address, showing ticket subject, status (Open, Pending, Resolved), priority, and when it was last updated.

V0 Prompt

Build a my-tickets page with a table showing support tickets. Each row has: ticket ID (with a # prefix), subject, status badge (green for Resolved, yellow for Pending, red for Open), priority, created date, and last updated date. Add a filter dropdown for status. Fetch data from /api/freshdesk/my-tickets with the user's email as a query param. Include a Create New Ticket button at the top.

Copy this prompt to try it in V0

Internal Support Dashboard

A support manager builds an internal dashboard showing all open Freshdesk tickets with real-time counts by priority and agent. V0 generates the dashboard with a ticket inbox, priority heatmap, and quick-action buttons to update ticket status. The API route fetches tickets from Freshdesk and returns aggregated data.

V0 Prompt

Create an internal support dashboard with three stat cards at the top: total open tickets, high priority tickets, and average resolution time. Below that, a ticket table with columns for ID, subject, requester email, assignee, priority badge, status, and time open. Include action buttons to mark tickets as resolved or assign to an agent. Fetch from /api/freshdesk/dashboard.

Copy this prompt to try it in V0

Troubleshooting

API returns 401 Unauthorized when creating tickets

Cause: The FRESHDESK_API_KEY environment variable is missing, incorrect, or the domain subdomain in FRESHDESK_DOMAIN is wrong.

Solution: Verify both variables in Vercel Dashboard → Settings → Environment Variables. The API key comes from Freshdesk Profile Settings → API Key section. The domain should be just the subdomain (e.g., mycompany) without any protocol or .freshdesk.com suffix. After updating, trigger a new Vercel deployment.

Ticket is created but the requester email gets a rate-limit bounce

Cause: Freshdesk's free Sprout plan limits outbound notification emails. High ticket creation rates can trigger Freshdesk's anti-spam protections.

Solution: Upgrade to a paid Freshdesk plan for production use, or add rate limiting to your Next.js API route so the form cannot be submitted more than once per session or within a short time window.

Ticket list returns empty array even though tickets exist in Freshdesk

Cause: The Freshdesk API filter parameters may not match any tickets, or you are querying with an email that does not match the requester exactly (case sensitivity).

Solution: Test the Freshdesk API directly using curl or a REST client with your API key to verify the endpoint and filter syntax. Freshdesk email filters are case-insensitive, but custom field filters are exact-match. Check the Freshdesk API docs for the exact filter query format.

Freshdesk webhook events are not arriving at the API route

Cause: The webhook URL in Freshdesk automation rules was not updated after deploying to Vercel, or the automation rule conditions do not match the ticket events.

Solution: Go to Freshdesk → Admin → Automations → Ticket Updates → find your webhook rule. Verify the URL matches your current Vercel deployment URL. Test the rule by manually resolving a test ticket and watching your Vercel function logs for incoming requests.

Best practices

  • Never expose FRESHDESK_API_KEY in client-side code or use it with the NEXT_PUBLIC_ prefix — it grants full API access to your helpdesk.
  • Add input validation in your form and API route to prevent empty or malformed tickets from reaching Freshdesk — check that email, subject, and description are present and non-empty.
  • Implement honeypot fields or rate limiting on your support form to prevent spam tickets from flooding your Freshdesk inbox.
  • Use Freshdesk ticket tags to categorize tickets created from your V0 app — add a tag like 'website-portal' so agents can filter tickets submitted through your custom form vs direct email.
  • Store the Freshdesk ticket ID in your database when creating tickets so you can link customer records to their support history.
  • Use Freshdesk's CC field in ticket creation to send copies of ticket confirmations to team inboxes or Slack channels via Freshdesk's built-in integrations.
  • Test with Freshdesk's Sprout plan during development, but budget for an upgrade to Garden or Estate for production features like SLA policies and custom roles.

Alternatives

Frequently asked questions

Does Freshdesk have a free plan I can use for development?

Yes, Freshdesk's Sprout plan is free for up to 10 agents and includes full API access for development. The free plan has limitations on automation rules and reporting, but for prototyping and low-volume production use it works well. Create a Freshdesk account at freshdesk.com and you will be on the free plan by default.

How do I find my Freshdesk API key?

Log into your Freshdesk account, click on your profile picture in the upper right corner, and select Profile Settings. Scroll to the bottom of the Profile Settings page — your API key is displayed there with a Show/Hide toggle. Copy the key and store it as the FRESHDESK_API_KEY environment variable in Vercel.

Can customers reply to their tickets through my V0 app?

Yes, use Freshdesk's Conversations API to add replies to existing tickets. Create a route at app/api/freshdesk/reply/route.ts that POSTs to /api/v2/tickets/{ticket_id}/reply with the reply body and the agent's or customer's email. Customers can see the conversation thread and respond through your V0 interface, with all messages synced to Freshdesk.

How do I attach files to Freshdesk tickets?

Freshdesk supports file attachments in tickets via multipart form data. Instead of sending JSON, send the ticket creation request as multipart/form-data with the attachment files included. The Freshdesk API will accept attachments up to 20MB per ticket. Handle file uploads in your Next.js API route using request.formData() and append files to the FormData object sent to Freshdesk.

Can I create tickets on behalf of customers without them knowing their ticket was created via API?

Yes, Freshdesk tickets created via API look identical to tickets created through other channels from the agent's perspective. Freshdesk automatically sends a confirmation email to the requester's email address with the ticket ID and a link to track progress. If you do not want Freshdesk to send the automated confirmation email, you can suppress it using email notification settings in Freshdesk Admin, though this is not recommended as it reduces transparency with customers.

What is the difference between Freshdesk and Zendesk for a V0 integration?

Both have similar REST APIs and can be integrated the same way from a Next.js API route. Freshdesk is significantly cheaper (free tier + affordable paid plans) while Zendesk has more advanced AI features and a larger app marketplace. If you are a small team on a budget, Freshdesk's pricing is more accessible. For enterprise requirements or if your team already uses Zendesk, choose Zendesk instead.

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.