Communication & Collaboration8 min read

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.

Published April 29, 2026
01 — Overview

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.


02 — The case for integration

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.


03 — Architecture

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.


04 — Use cases

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.


05 — Implementation

Step-by-step integration

  1. 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. 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. 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. 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. 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. 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.


06 — Code

Code example

typescript
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});
}

07 — Why Sanity

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 →

08 — Comparison

CMS approaches to Freshdesk

CapabilityTraditional CMSSanity
Support article data shapeArticles 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 publishPlugins 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 controlThe 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 consistencyWebsite 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-offA 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.

09 — Next steps

Keep building

Explore related integrations to complete your content stack.

Ready to try Sanity?

See how Sanity's Content Operating System powers integrations with Freshdesk and 200+ other tools.