How to Integrate Freshdesk with Your Headless CMS
Connect Freshdesk to your headless CMS so support articles, product updates, and agent-facing answers stay current across your help center, website, and support workflows.
What is Freshdesk?
Freshdesk is Freshworks' cloud-based customer support platform for ticketing, self-service knowledge bases, team inboxes, automations, and customer communication across channels like email, chat, phone, and social. Support teams use it to route tickets, publish help articles, track service-level agreements, and give agents a shared place to resolve customer issues. It’s commonly used by small, midsize, and enterprise service teams that need a support desk with built-in collaboration tools.
Why integrate Freshdesk with a headless CMS?
Support teams move fast when product content changes. A pricing page gets updated, a troubleshooting step changes, or a new feature ships, and suddenly agents need the same answer in Freshdesk that customers see on your website. If Freshdesk and your content system don’t talk to each other, someone has to copy the update into a solution article, paste the right links into canned replies, and remember to repeat that work for every locale.
A headless CMS setup helps because the content is already separated from the presentation layer. The useful part for Freshdesk is the structure: article title, body, product, audience, locale, troubleshooting steps, related links, and publish status can all be sent as clean fields instead of scraped from rendered HTML. With Sanity’s Content Lake, GROQ queries, webhooks, and Functions, you can publish a support article once and push exactly the fields Freshdesk needs into its Solutions API within seconds.
The trade-off is that you’ll write some integration code. That’s usually better than relying on a one-size-fits-all plugin, especially if your Freshdesk setup has separate folders for products, regions, or internal agent articles. You decide which content syncs, which content stays web-only, and how Freshdesk article IDs map back to your structured content.
Architecture overview
A typical Freshdesk integration starts when an editor publishes or updates a support article in Sanity Studio. The document is structured in the Content Lake as typed JSON, for example title, slug, Portable Text body, product reference, locale, Freshdesk folder ID, Freshdesk article ID, and a publishToFreshdesk flag. A Sanity webhook fires on the publish event, filtered to the supportArticle schema and only when publishToFreshdesk is true. The webhook can call a Sanity Function, a Next.js API route, or another server-side endpoint. That handler uses @sanity/client and a GROQ query to fetch the current document, including joined fields such as product->name or category->freshdeskFolderId. The handler then calls Freshdesk’s REST API with basic authentication, using the Freshdesk API key as the username and X as the password. For a new article, it sends a POST request to /api/v2/solutions/folders/{folder_id}/articles. For an existing article, it sends a PUT request to /api/v2/solutions/articles/{article_id}. Freshdesk indexes the solution article in the support portal, agents can link to it from tickets, and customers can find the answer in self-service search.
Common use cases
Help center article sync
Publish troubleshooting guides in Sanity Studio and send approved versions to Freshdesk Solutions folders for customer self-service.
Ticket deflection with current answers
Keep Freshdesk knowledge base articles aligned with product docs so customers see the latest answer before opening a ticket.
Localized support content
Sync locale-specific articles from Sanity to the right Freshdesk folders, such as en-us, fr-fr, or ja-jp support collections.
Agent-ready release notes
Turn structured release notes into Freshdesk internal solution articles so agents can answer launch-day tickets with the same source material.
Step-by-step integration
- 1
Set up Freshdesk access
Create or use a Freshdesk account, note your domain, such as acme.freshdesk.com, and copy your API key from Profile settings. In Freshdesk, create the Solutions categories and folders you want to sync into, then get folder IDs from the API or the Freshdesk admin UI.
- 2
Install the integration packages
In your integration project, install the Sanity client and any content serializers you need. For a TypeScript webhook handler, start with npm install @sanity/client @portabletext/to-html. Freshdesk can be called directly through its REST API using fetch.
- 3
Model support content in Sanity Studio
Create a supportArticle schema with fields like title, slug, body, product reference, locale, publishToFreshdesk, freshdeskFolderId, and freshdeskArticleId. Add validation so an article can’t sync unless it has a Freshdesk folder ID and a publish-ready body.
- 4
Create the sync trigger
Add a Sanity webhook filtered to supportArticle publish and update events, or run the same logic in a Sanity Function. In production, verify the webhook signature, store Freshdesk credentials as secrets, and ignore draft document IDs that start with drafts.
- 5
Call the Freshdesk Solutions API
Use POST /api/v2/solutions/folders/{folder_id}/articles for new articles and PUT /api/v2/solutions/articles/{article_id} for updates. Freshdesk article status 1 is draft and status 2 is published, so map your Sanity publish state intentionally.
- 6
Test the customer and agent experience
Publish one test article, confirm it appears in the expected Freshdesk folder, search for it in the support portal, and link it from a test ticket. Then test updates, deletes, localization, and error handling before connecting high-traffic help content.
Code example
import {createClient} from '@sanity/client';
import {toHTML} from '@portabletext/to-html';
const sanity = createClient({
projectId: process.env.SANITY_PROJECT_ID!,
dataset: process.env.SANITY_DATASET!,
apiVersion: '2025-01-01',
token: process.env.SANITY_READ_TOKEN,
useCdn: false
});
export async function POST(req: Request) {
const payload = await req.json();
const id = payload._id;
const doc = await sanity.fetch(`*[_id == $id][0]{
title, body, publishToFreshdesk, freshdeskFolderId, freshdeskArticleId,
"product": product->name
}`, {id});
if (!doc?.publishToFreshdesk) {
return Response.json({ok: true, skipped: true});
}
const base = `https://${process.env.FRESHDESK_DOMAIN}/api/v2`;
const auth = Buffer.from(`${process.env.FRESHDESK_API_KEY}:X`).toString('base64');
const url = doc.freshdeskArticleId
? `${base}/solutions/articles/${doc.freshdeskArticleId}`
: `${base}/solutions/folders/${doc.freshdeskFolderId}/articles`;
const res = await fetch(url, {
method: doc.freshdeskArticleId ? 'PUT' : 'POST',
headers: {
Authorization: `Basic ${auth}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: doc.product ? `${doc.product}: ${doc.title}` : doc.title,
description: toHTML(doc.body || []),
status: 2
})
});
if (!res.ok) throw new Error(await res.text());
return Response.json({ok: true});
}How Sanity + Freshdesk works
Build your Freshdesk integration on Sanity
Sanity gives you the structured content foundation, real-time event system, and flexible APIs to connect Freshdesk with the rest of your support and product experience.
Start building free →CMS approaches to Freshdesk
| Capability | Traditional CMS | Sanity |
|---|---|---|
| Support article data shape | Articles often live as rendered pages or HTML-heavy fields, so Freshdesk sync code has to clean and reshape content before sending it. | The Content Lake stores typed JSON with references, so a Freshdesk article can be assembled from exact fields and related documents. |
| Sync timing after publish | Plugins or exports can work for simple flows, but many teams still rely on scheduled jobs or manual copying. | Webhooks and Functions can trigger Freshdesk API calls on publish events without a separate polling service. |
| Field-level control | The integration may receive full page content, navigation data, and presentation markup it doesn’t need. | GROQ projections return only the fields Freshdesk needs, including joined values like product name or Freshdesk folder ID. |
| Agent and customer consistency | Website copy and Freshdesk answers can drift when teams edit them in separate tools. | Sanity Studio can model support workflows directly, including review status, internal-only notes, locale rules, and Freshdesk sync flags. |
| Setup trade-off | A prebuilt plugin may be faster for a single blog-to-help-center sync, but custom support rules can get awkward. | You’ll define schemas and mapping code, but you get precise control when Freshdesk is one of several destinations for the same content. |
Keep building
Explore related integrations to complete your content stack.
Sanity + Slack
Send support article publish events, review requests, and Freshdesk sync failures to the Slack channels where your support team already works.
Sanity + Microsoft Teams
Notify product, documentation, and support teams in Microsoft Teams when customer-facing help content changes.
Sanity + Intercom
Reuse structured support content for Intercom help articles, in-app messages, and customer conversations alongside your Freshdesk workflow.