
Twilio owns some of the most critical infrastructure in the notification space. Their SMS API reaches phones in 180+ countries. SendGrid processes email at scale. Twilio Segment aggregates customer data across your entire stack. But using these tools together? That's where things get complicated.
You can connect all three Twilio products through Courier and ship this week what would otherwise be months of integration work. For a full list of supported channels and providers, see Courier's integrations page.
Twilio SMS handles programmable messaging across SMS, MMS, WhatsApp, and RCS. They reach 180+ countries and back the API with a 99.95% monthly uptime SLA. For time-sensitive notifications like OTP codes, delivery updates, and appointment reminders, SMS still beats every other channel for reliability.
SendGrid (acquired by Twilio in 2019) is a common pick when you need high deliverability without managing mail servers. It offers dynamic templating, analytics, and one platform for both transactional and marketing email.
Twilio Segment (acquired by Twilio in 2020) is the customer data platform that collects user events and pipes them to your analytics, marketing, and product tools. Instead of building direct integrations with every destination, you instrument once and route everywhere.
The catch: managing these integrations separately means maintaining three different APIs, three sets of credentials, three templating systems, and zero coordination between channels. That's the problem Courier solves.
Twilio knows this better than anyone. When they needed to unify notifications for their own platform serving 10+ million developers, they chose Courier. As Raghav Katyal, Technical Lead at Twilio, put it: "We chose Courier because the depth of the inbox and multi-channel integrations allowed us to choose one notification platform for all products and teams at Twilio." They embedded Courier's Inbox in the Twilio Console, replacing a patchwork of Segment, SendGrid, and hand-coded logic, and now use it for onboarding guides, feature announcements, account alerts, and digests of non-urgent messages.
Start by connecting your Twilio account to Courier. You'll need three things from your Twilio console (see the full Twilio integration docs for detailed setup):
In Courier, navigate to Integrations, find Twilio under SMS providers, and paste in these credentials.
If you don't already have an SMS-enabled number, grab one from the Twilio console:
Next, create a Messaging Service to link your number:
Copy the Service SID and add it to your Courier Twilio configuration. Done.
Once configured, sending an SMS through Courier looks like this (see SDK documentation for all supported languages):
import Courier from "@trycourier/courier";
const courier = new Courier({ apiKey: process.env.COURIER_API_KEY });
await courier.send.message({
message: {
to: {
user_id: "user_123",
phone_number: "+15555555555"
},
content: {
title: "Order shipped",
body: "Your order #{{order_id}} has shipped. Track it here: {{tracking_url}}"
},
data: {
order_id: "ORD-78912",
tracking_url: "https://example.com/track/ORD-78912"
},
routing: {
method: "single",
channels: ["sms"]
}
}
});The phone_number field on the recipient tells Courier where to deliver (see the profile docs for all profile fields). Variables wrapped in double curly braces get filled from data. Inline content takes a title too, which SMS doesn't display.
Need to pass specific parameters directly to the Twilio API? Use overrides. They change the request body Courier sends to Twilio, so you can set any field Twilio's Messages endpoint accepts, using Twilio's own parameter names:
await courier.send.message({
message: {
to: {
user_id: "user_123",
phone_number: "+15555555555"
},
content: {
title: "Verification code",
body: "Your verification code is {{code}}"
},
data: {
code: "482913"
},
routing: {
method: "single",
channels: ["sms"]
},
providers: {
twilio: {
override: {
body: {
StatusCallback: "https://yourapp.com/webhooks/sms-status",
ValidityPeriod: 300
}
}
}
}
}
});This sends Twilio's status callbacks to your webhook and sets a 5-minute validity window for the message. Body overrides like this one leave Courier's delivery tracking alone. Swapping your credentials with a config override is different: Courier polls Twilio for delivery status with the credentials you configured, so overriding them stops delivery status events.
SendGrid integration follows a similar pattern. From your SendGrid console (see full SendGrid integration docs):
In Courier, open the SendGrid configuration and enter:
If you've already built templates in SendGrid, you don't have to recreate them. Courier can import your SendGrid Dynamic Templates directly from the Courier SendGrid configuration page:
This preserves your existing work while giving you Courier's orchestration on top.
await courier.send.message({
message: {
to: {
user_id: "user_123",
email: "customer@example.com"
},
template: "ORDER_CONFIRMATION",
data: {
customer_name: "Alex",
order_id: "ORD-78912",
order_total: "$149.99",
items: [
{ name: "Widget Pro", qty: 2 },
{ name: "Gadget Max", qty: 1 }
]
}
}
});Courier routes this to SendGrid automatically based on your channel configuration. If you want to send through SendGrid specifically (useful if you have multiple email providers configured), name the provider in routing instead of the channel (see Send to a provider):
routing: {
method: "single",
channels: ["sendgrid"]
}To keep SendGrid first while other email providers stay available as backups, set the provider order instead with channel priority.
Until you set up tracking, SendGrid messages stay at SENT in Courier, because Courier has sent the email but heard nothing back. SendGrid's event webhook fixes that (see the delivery tracking setup):
The webhook reports in real time and needs only Mail Send permission. Delivered and bounced statuses then show up in your Courier logs. Polling SendGrid's Email Activity API is the fallback if you can't add a webhook, but it needs SendGrid's paid email-history add-on and doesn't work on EU SendGrid accounts.
Twilio Segment changes how you think about triggering notifications. Instead of calling Courier's Send API from your application code every time something happens, you instrument events in Segment and let those events flow to Courier automatically. See the full Segment integration docs for details.
Once connected, three types of Twilio Segment events flow into Courier:
Identify calls update Courier recipient profiles. Courier uses the traits on each call to keep the user's profile current, so a changed email address in Segment reaches the profile Courier sends to.
analytics.identify('user_123', {
email: 'alex@example.com',
name: 'Alex Chen',
plan: 'pro'
});Track calls record user actions that can start journeys. These appear in Courier with a track/ prefix, and the event's properties become the journey's data.
analytics.track('Order Completed', {
order_id: 'ORD-78912',
total: 149.99,
items: ['Widget Pro', 'Gadget Max']
});Group calls are the third Segment event type Courier accepts, alongside Identify and Track.
In Courier, you can build a journey that starts when a specific Segment event arrives (the Start a journey from Segment guide walks through it):
Order Completed)Now every time that event fires in Segment, Courier runs the journey. No additional code in your app. The event's userId has to match a Courier user, so identify your users to Courier first.
Example journey:
Trigger: Twilio Segment, Order Completed
↓
Delay: 2 hours
↓
Branch: data.total > 100
↓
Send (email): "Thanks for your order" (via SendGrid)
↓
Send (SMS): "Your order confirmation" (via Twilio)This sends a follow-up email 2 hours after high-value orders, with an SMS confirmation. Orders of $100 or less take the branch's default path and get neither. All of it runs from a single Segment event.
The integration works both directions. Courier can send delivery events back to Segment as a Source (see Courier as a Segment Source docs):

Courier sends these message events to Segment:
It also sends audience events (Audience User Matched, Audience User Unmatched) and preference events (User Subscribed, User Unsubscribed).
This closes the loop. Your analytics tools now know not only that you sent a notification, but whether the user engaged with it. You can build cohorts based on notification engagement, trigger follow-ups based on opens, or feed engagement data into your BI stack.
The real value shows up when you combine these integrations. Here's a common pattern using the Courier Send API:
await courier.send.message({
message: {
to: {
user_id: "user_123"
},
template: "APPOINTMENT_REMINDER",
data: {
appointment_date: "March 16",
appointment_time: "2:00 PM",
location: "123 Main St"
},
routing: {
method: "all",
channels: ["email", "sms"]
}
}
});This sends to both email (via SendGrid) and SMS (via Twilio) in parallel. User profile data determines where messages go: the email field routes to SendGrid, phone_number routes to Twilio.
To try channels in order with fallback, use the single method:
routing: {
method: "single",
channels: ["sms", "email"]
}Courier tries SMS first and stops at the first channel that delivers. If the user has no phone_number or the SMS fails, the reminder goes out by email instead. To set the provider order inside a channel (say, SendGrid ahead of a second email provider), see channel priority.
Building direct integrations with Twilio, SendGrid, and Segment yourself isn't impossible. But you end up maintaining three separate codepaths, three sets of error handling, three retry mechanisms, and zero coordination between them.

When you need to add batching (so users don't get 50 separate notifications for 50 events), you build it. When you need scheduling or digest emails, you build it. When you need to honor user preferences across channels, you build that too.
This is exactly why Twilio chose Courier for their own platform. Rather than building custom notification infrastructure on top of their own products, they use Courier to orchestrate it all. See the full Twilio case study for details on how they unified notifications for 10+ million developers.
Courier handles all of this out of the box. You get:
The Twilio ecosystem is powerful. Courier makes it practical to use the whole thing without drowning in integration complexity.
Ready to connect your Twilio stack? Sign up for Courier and send your first notification. The free Developer plan includes 10,000 messages a month.

How to protect your email domain and sending reputation
AI agents have made spoofing cheap, and a DMARC record at p=none won't stop it. Here's how to enforce DMARC without bouncing your own mail, keep password resets apart from newsletters, protect your sending reputation, read Google Postmaster Tools, and audit your domain with six AI prompts.

HIPAA-compliant notifications: where PHI should live
A practical guide to HIPAA-compliant notifications across SMS, push, email, and an in-app inbox. One rule, applied to every channel and every place PHI gets stored, including the systems most teams forget are in scope.

How to get your logo in Gmail and Apple Mail
BIMI puts your logo next to your emails in Gmail and Apple Mail, but there is no upload form. It is earned by locking your domain down. Here is the whole project: what it costs, how long it takes, and the five ways it fails silently.