How to Integrate OpenAI with Your Headless CMS
Connect OpenAI to a headless CMS so every publish can generate summaries, tags, translations, embeddings, or chat answers from structured content instead of copied text.
What is OpenAI?
OpenAI provides APIs for text generation, embeddings, speech, images, moderation, and tool-using AI applications. Teams use OpenAI models such as GPT-4.1, GPT-4o, and embedding models to build editorial automation, chat interfaces, semantic search, content analysis, and internal workflows. It’s one of the most widely adopted commercial AI platforms for developers building AI into production software.
Why integrate OpenAI with a headless CMS?
AI content workflows break down fast when your source material is scattered across pages, HTML fields, PDFs, and one-off spreadsheets. OpenAI works best when you can send it clean inputs, such as title, summary, body text, product attributes, locale, author, category, and publish state. A headless CMS with structured content gives you those fields directly, which means fewer prompt hacks and less cleanup before every API call.,The practical value is simple. A product team can publish a new feature article and have OpenAI generate a 155-character meta description, five internal search keywords, and a Slack-ready summary in seconds. A support team can turn approved help articles into embeddings for retrieval-augmented generation. A localization team can draft translations while keeping brand terms, product names, and legal disclaimers tied to the original fields.,Without an event-based integration, teams usually copy content into ChatGPT, paste the answer back, and hope nobody edits the source later. With Sanity, content changes in the Content Lake can trigger webhooks or Functions on publish, update, or delete. GROQ selects only the fields OpenAI needs, and server-side code calls OpenAI without exposing API keys in the browser. The trade-off is that you still need to design review rules, error handling, and rate-limit behavior. AI output shouldn’t go straight to production without the checks your team needs.
Architecture overview
A typical OpenAI integration starts when an editor publishes or updates a document in Sanity Studio. A Sanity webhook fires on that mutation, or a Sanity Function runs server-side without separate infrastructure. The handler receives the document ID, uses @sanity/client to query the Content Lake with GROQ, and fetches a precise projection such as title, body text, category, locale, related product data, and author name. That payload is sent to OpenAI using the official SDK, commonly through the Responses API for generation or the Embeddings API for semantic retrieval. The OpenAI result can be written back to Sanity as fields such as aiSummary, aiKeywords, moderationStatus, translatedDraft, or embeddingSyncStatus. Your frontend, app, search index, or AI agent then reads the approved structured content from Sanity. For production, verify the Sanity webhook signature, retry failed OpenAI calls, and keep generated fields separate from human-approved fields so editors can review before publishing.
Common use cases
Editorial summaries on publish
Generate short summaries, meta descriptions, social captions, and internal briefs with OpenAI when an article moves to a published state.
Semantic content search
Create embeddings from approved Sanity documents with OpenAI and sync them to a vector index for meaning-based search across help, product, and marketing content.
Translation drafts with field context
Send structured fields, locale, brand terms, and reference data to OpenAI so translators start from a draft that preserves product names and required copy.
Policy and tone checks
Use OpenAI to flag missing disclaimers, unsupported claims, tone mismatches, or duplicate content before an editor approves a release.
Step-by-step integration
- 1
Set up OpenAI access
Create an OpenAI account, add billing, generate an API key from the OpenAI dashboard, and save it as OPENAI_API_KEY in your server environment. Install the SDK with npm install openai.
- 2
Model the fields OpenAI should read and write
In Sanity Studio, add structured fields such as title, slug, body, excerpt, locale, category, aiSummary, aiKeywords, aiReviewStatus, and aiGeneratedAt. Keep generated fields separate from editor-owned fields so reviews are clear.
- 3
Create a publish trigger
Use a Sanity webhook with a GROQ filter such as _type == "post" && defined(slug.current), or create a Sanity Function that runs on content mutations. Configure the webhook projection to send the document ID, not the full document.
- 4
Fetch exact content with GROQ
In your handler, use @sanity/client to fetch only the fields OpenAI needs. Include referenced data, such as author, category, product, or locale rules, in the same GROQ query when the model needs that context.
- 5
Call OpenAI from server-side code
Use the OpenAI SDK to call the Responses API for generation, the Embeddings API for semantic search, or moderation endpoints for policy checks. Never call OpenAI directly from the browser with a secret key.
- 6
Test review, retries, and the frontend result
Publish a test document, confirm the generated fields are patched back to Sanity, show them in Sanity Studio for review, and render approved output in your frontend. Add retry logic for 429 and 5xx responses before sending real editorial traffic.
Code example
A minimal Next.js webhook handler that receives a Sanity webhook, fetches the full document with GROQ, sends it to OpenAI, and patches generated fields back to Sanity.
import {NextRequest, NextResponse} from "next/server";
import {createClient} from "@sanity/client";
import OpenAI from "openai";
const sanity = createClient({
projectId: process.env.SANITY_PROJECT_ID!,
dataset: process.env.SANITY_DATASET!,
apiVersion: "2025-02-19",
token: process.env.SANITY_WRITE_TOKEN!,
useCdn: false,
});
const openai = new OpenAI({apiKey: process.env.OPENAI_API_KEY!});
export async function POST(req: NextRequest) {
const {_id} = await req.json();
const article = await sanity.fetch(
`*[_id == $id][0]{_id,title,excerpt,body,"author": author->name}`,
{id: _id}
);
if (!article?._id) {
return NextResponse.json({ok: false}, {status: 404});
}
const input = `Write JSON with summary and keywords for this article:
${JSON.stringify(article).slice(0, 6000)}`;
const result = await openai.responses.create({
model: "gpt-4.1-mini",
input,
text: {format: {type: "json_object"}},
});
const parsed = JSON.parse(result.output_text);
await sanity.patch(article._id).set({
aiSummary: parsed.summary,
aiKeywords: parsed.keywords,
aiGeneratedAt: new Date().toISOString(),
}).commit();
return NextResponse.json({ok: true});
}How Sanity + OpenAI works
Build your OpenAI integration on Sanity
Sanity’s AI Content Operating System gives you the structured content foundation, real-time event system, and flexible APIs to connect editorial workflows with OpenAI.
Start building free →CMS approaches to OpenAI
| Capability | Traditional CMS | Sanity |
|---|---|---|
| Structured inputs for OpenAI | Content often lives as rendered pages or large rich-text fields, so prompts need cleanup before model calls. | Content Lake gives OpenAI typed JSON, references, and field-level context from one GROQ query. |
| Real-time AI processing | Teams often rely on plugins, scheduled jobs, or manual copy-paste after publishing. | Webhooks and Functions can trigger OpenAI calls on content events, with server-side execution and no polling. |
| Field-level control | AI workflows may receive too much page content, including navigation, layout text, or unrelated modules. | GROQ can select only the fields OpenAI needs and join referenced documents in the same query. |
| Editorial review of AI output | Generated copy is often pasted into live fields, which makes review history harder to track. | Sanity Studio can show generated fields beside editor-owned fields, with Comments, Tasks, and Content Releases for review. |
| Multi-channel reuse | AI-generated output is usually tied to a web page template. | The same structured content can serve web, mobile, OpenAI workflows, Agent Context, and production AI agents. |
Keep building
Explore related integrations to complete your content stack.
Sanity + Anthropic (Claude)
Use Claude with structured Sanity content for long-form drafting, editorial review, and policy-aware content analysis.
Sanity + AirOps
Connect Sanity content to AirOps workflows for AI-assisted briefs, SEO checks, content refreshes, and approval steps.
Sanity + Writer
Apply Writer’s brand governance and language rules to structured Sanity content before teams publish across channels.