How to Integrate Twilio with Your Headless CMS
Connect Twilio to your content back end so published updates, alerts, and campaign messages can be sent by SMS, WhatsApp, or voice without copying text between tools.
What is Twilio?
Twilio is a cloud communications platform with APIs for SMS, MMS, WhatsApp, voice, email through SendGrid, verification, and customer conversations. Product, support, growth, and operations teams use Twilio to send transactional alerts, appointment reminders, one-time passwords, delivery updates, and two-way customer messages. It’s one of the main platforms in the communications API market, with SDKs for Node.js, Python, PHP, Java, C#, Ruby, and Go.
Why integrate Twilio with a headless CMS?
Communication workflows break down fast when content lives in one place and messages get assembled somewhere else. A support team might update an outage notice in the website experience, while operations copies the same text into Twilio for SMS alerts. That creates two problems: stale messages and slow response. If the incident update changes from “30 minutes” to “2 hours,” every copied version has to be found and fixed.,Connecting Twilio to a headless CMS category tool solves the copy-and-paste problem by making message content addressable through APIs. With structured content in Sanity’s Content Lake, your SMS body, locale, audience segment, legal disclaimer, CTA URL, and publish status can be modeled as fields instead of buried in a page blob. GROQ selects the exact fields Twilio needs, and webhooks can trigger the moment an editor publishes an alert.,The trade-off is that you need to design the workflow carefully. SMS has character limits, opt-in rules, country-specific compliance requirements, and delivery costs. A good integration should include editorial previews, approval states, opt-out handling, and test sends before production messages go out. Sanity’s AI Content Operating System gives you the structured content, event triggers, and server-side logic to build that workflow without making editors log in to Twilio for every content change.
Architecture overview
A typical Twilio integration starts in Sanity Studio, where editors create a structured notification document with fields such as title, messageBody, channel, audience, locale, CTA URL, and publish status. When that document is published, a Sanity webhook fires with the document ID, or a Sanity Function runs directly from the content mutation. The server-side handler uses @sanity/client and GROQ to fetch only the fields Twilio needs, including referenced audience data, localized copy, and opt-in subscriber phone numbers. The handler then calls Twilio’s API, usually twilio.messages.create for SMS or WhatsApp, with a verified sender, recipient number, and message body. Twilio queues and delivers the message to the end user, then sends delivery status callbacks back to your app if you configure a statusCallback URL. Those callbacks can be written back to Sanity or another reporting system so teams can see sent, delivered, failed, and undelivered counts.
Common use cases
Incident and outage alerts
Publish a status update in Sanity Studio and send an SMS or WhatsApp alert through Twilio to affected customers within seconds.
Appointment reminders
Use structured appointment content, localized instructions, and Twilio Messaging to send reminders 24 hours and 2 hours before a visit.
Order and delivery updates
Trigger Twilio messages from content-backed templates for shipped, delayed, ready for pickup, and returned order states.
Two-way support messaging
Pair Sanity-authored response snippets with Twilio Conversations so agents can reply with approved, current language.
Step-by-step integration
- 1
Set up Twilio credentials
Create a Twilio account, verify your sender setup, and buy a Twilio phone number or create a Messaging Service. For SMS, save your Account SID, Auth Token, and sender number. For WhatsApp, configure the Twilio WhatsApp sandbox or an approved WhatsApp Business sender. Install the SDK with npm install twilio.
- 2
Model notification content in Sanity Studio
Create a notification schema with fields such as title, messageBody, channel, locale, audience, ctaUrl, status, testRecipients, and sentAt. Keep SMS body text separate from long-form web copy so editors can preview the 160-character segment count before publishing.
- 3
Create opt-in audience data
Model subscribers or customer references with phone, countryCode, optIn, optInSource, and unsubscribedAt fields. Don’t send to numbers unless you have consent. Twilio can deliver the message, but your application is responsible for honoring opt-outs and local messaging rules.
- 4
Add a Sanity webhook or Function
Configure a webhook to fire when notification documents are published, or use a Sanity Function to run server-side logic on the mutation. Include the document ID in the webhook payload so the handler can fetch the current version from the Content Lake.
- 5
Fetch with GROQ and call Twilio
In the handler, use @sanity/client to fetch the notification and recipient list with GROQ. Then call Twilio’s Messages API with client.messages.create, passing from, to, body, and optionally statusCallback for delivery tracking.
- 6
Test previews, delivery, and failures
Start with Twilio test credentials or a small internal recipient list. Test long messages, special characters, opt-out keywords, invalid numbers, and delivery callbacks. On the frontend, show editors the exact message Twilio will receive, not just the rich content version used on the website.
Code example
import {createClient} from '@sanity/client'
import twilio from 'twilio'
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,
})
const sms = twilio(
process.env.TWILIO_ACCOUNT_SID!,
process.env.TWILIO_AUTH_TOKEN!
)
export async function POST(req: Request) {
const {documentId} = await req.json()
const data = await sanity.fetch(
`*[_id == $id][0]{
title,
messageBody,
ctaUrl,
"phones": *[_type == "smsSubscriber" && optIn == true && !defined(unsubscribedAt)].phone
}`,
{id: documentId}
)
if (!data?.messageBody) {
return Response.json({sent: 0, reason: 'No message body'}, {status: 400})
}
const body = [data.messageBody, data.ctaUrl].filter(Boolean).join(' ')
const recipients = data.phones.slice(0, 50)
const results = await Promise.all(
recipients.map((to: string) =>
sms.messages.create({
from: process.env.TWILIO_PHONE_NUMBER!,
to,
body,
statusCallback: process.env.TWILIO_STATUS_CALLBACK_URL,
})
)
)
return Response.json({sent: results.length})
}How Sanity + Twilio works
Build your Twilio integration on Sanity
Sanity’s AI Content Operating System gives you structured content, real-time events, GROQ queries, and server-side Functions for connecting Twilio to the workflows your team already uses.
Start building free →CMS approaches to Twilio
| Capability | Traditional CMS | Sanity |
|---|---|---|
| Message-ready structured data | Content is often tied to pages, templates, or rich text fields, so SMS copy may need manual extraction. | Schemas can model SMS body, channel, locale, CTA URL, audience, and approval state as typed fields in the Content Lake. |
| Send on publish | Teams often copy published text into Twilio or run a separate plugin with limited workflow control. | Webhooks or Functions can run on publish events and call Twilio from server-side logic without separate polling jobs. |
| Field-level selection for Twilio | APIs may return full pages, rendered HTML, or fields that aren’t shaped for communication APIs. | GROQ can fetch message copy, referenced segments, locale fallbacks, and opted-in phone numbers in one targeted query. |
| Editorial safety before sending | Preview often shows the web page, not the final SMS, WhatsApp, or voice message. | Sanity Studio can show channel-specific previews, validation warnings, test recipient fields, Tasks, and release workflows. |
| Multi-channel reuse | Web, SMS, support, and app copy can drift because each team updates a different system. | One structured back end can feed websites, apps, Twilio messages, support tools, and AI agents through APIs and Agent Context. |
Keep building
Explore related integrations to complete your content stack.
Sanity + Slack
Send editorial alerts, publish notifications, and workflow updates from Sanity to the Slack channels your team watches.
Sanity + Intercom
Use structured product content, release notes, and support snippets from Sanity inside customer messaging workflows.
Sanity + Zendesk
Connect approved help content from Sanity to Zendesk so support agents and customers see current answers.