Kyle Seyler
December 10, 2025

Twilio owns some of the most critical infrastructure in the notification space. Their SMS API handles billions of messages. SendGrid processes email at scale. Segment aggregates customer data across your entire stack. But using these tools together? That's where things get complicated.
This guide covers how to integrate all three Twilio products through Courier, turning what would normally be months of integration work into something you can ship this week. For a full list of supported channels and providers, see Courier's integrations page.
Before diving into setup, here's what each piece brings to the table:
Twilio SMS handles programmable messaging across SMS, MMS, WhatsApp, and RCS. They've got phone number inventory across 180+ countries and 99.95% monthly uptime. 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) processes billions of emails monthly and has become the default for teams that need high deliverability without managing mail servers. They offer dynamic templating, analytics, and a unified platform for both transactional and marketing messages.
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 now use Courier to sync SendGrid email with their in-app notification center, managing everything from onboarding flows to marketplace transactions through a single system.
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):
Copied!
The phone_number field in the recipient profile tells Courier where to deliver (see user management docs for all profile options). Variables wrapped in double curly braces get populated from your data payload.
Need to pass specific parameters directly to the Twilio API? Use overrides. Note that using overrides bypasses Courier's status polling, so use them only when necessary:
Copied!
This sends status callbacks to your webhook and sets a 5-minute validity window for the message.
SendGrid integration follows a similar pattern. From your SendGrid console (see full SendGrid integration docs):
In Courier, find SendGrid under Email providers in your Channels 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.
Copied!
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), add explicit routing:
Copied!
To get delivery events back from SendGrid into Courier (see full setup guide):
This lets you see delivered, opened, clicked, and bounced events in your Courier logs.
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 Segment events flow into Courier:
Identify calls update Courier recipient profiles. When a user's email or phone number changes in Segment, it automatically syncs to Courier.
Copied!
Track calls record user actions that can trigger automations. These appear in Courier with a track/ prefix.
Copied!
Group calls associate users with organizations, useful for B2B notification logic and tenant-based routing.
Here's where it gets powerful. In Courier, you can create automations that fire when specific Segment events arrive:
track/Order Completed)Now every time that event fires in Segment, Courier sends the notification. No additional code in your app.
Example automation flow:
Copied!
This sends a follow-up email 2 hours after high-value orders, with an SMS confirmation. All orchestrated 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 events to Segment:
This closes the loop. Your analytics tools now know not just 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:
Copied!
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.
For priority-based delivery with fallback, use the priority routing method:
Copied!
Courier tries each channel in order until one succeeds. If push fails or the user doesn't have a device token, it falls back to email, then SMS. You can also configure channel priority settings globally in your workspace.
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 in under 5 minutes. Free tier includes 10,000 notifications per month.

Expo Push Notifications: The Complete Implementation Guide (SDK 52+)
Expo push notifications are alerts sent from a server to a user's phone, even when the app isn't open. To set them up, install the expo-notifications library, ask the user for permission, and get a unique push token for their device. Your server sends a message to Expo's push service with that token, and Expo delivers it through Apple or Google. Push notifications only work on real phones, not simulators. Local notifications are different — they're scheduled by the app itself for things like reminders. You can also route Expo push through services like Courier to add email, SMS, and Slack fallbacks.
By Kyle Seyler
February 24, 2026

Best Email API Providers for Developers in 2026: SendGrid vs Postmark vs Mailgun vs SES vs Resend
Your email provider sticks with you longer than most technical decisions. Courier handles notification infrastructure for thousands of teams, so we went deep on the six email providers that show up most: SendGrid, Postmark, Mailgun, Amazon SES, Resend, and SMTP. This guide covers real API primitives, actual code from each provider's docs, Courier integration examples with provider overrides, and an honest read on where each developer experience holds up and where it breaks down. We also asked Claude to review every API and tell us which one it would wire up first. The answer surprised us.
By Kyle Seyler
February 23, 2026

A Resilient Notification Strategy for Regulated Industries
Notification compliance isn't a legal checklist—it's an infrastructure problem. In 2026, Reg E deadlines, HIPAA content rules, and TCPA consent requirements dictate your system architecture. This guide breaks down the engineering constraints of regulated notifications for fintech, healthcare, and insurance. Learn why hard-coded deadlines fail, how "alert without disclosing" works in practice, and why the smart escalation pattern (Push → SMS → Email) is the only way to satisfy both user urgency and regulatory documentation. Build systems that absorb complexity, not application code that breaks every time a state law changes.
By Kyle Seyler
February 11, 2026
© 2026 Courier. All rights reserved.
const { CourierClient } = require("@trycourier/courier");const courier = CourierClient({ authorizationToken: "YOUR_AUTH_TOKEN" });await courier.send({message: {to: {user_id: "user_123",phone_number: "+15555555555"},content: {body: "Your order #{{order_id}} has shipped. Track it here: {{tracking_url}}"},routing: {method: "single",channels: ["sms"]}}});
await courier.send({message: {to: {user_id: "user_123",phone_number: "+15555555555"},content: {body: "Your verification code is {{code}}"},routing: {method: "single",channels: ["sms"]},providers: {twilio: {override: {body: {statusCallback: "https://yourapp.com/webhooks/sms-status",validityPeriod: 300}}}}}});
await courier.send({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 }]}}});
routing: {method: "single",channels: ["email"],providers: ["sendgrid"]}
analytics.identify('user_123', {email: 'alex@example.com',phone: '+15555555555',name: 'Alex Chen',plan: 'pro'});
analytics.track('Order Completed', {order_id: 'ORD-78912',total: 149.99,items: ['Widget Pro', 'Gadget Max']});
Trigger: track/Order Completed↓Wait: 2 hours↓Condition: order.total > 100↓Send: "Thanks for your order" (Email via SendGrid)↓Send: "Your order confirmation" (SMS via Twilio)
await courier.send({message: {to: {user_id: "user_123"},template: "APPOINTMENT_REMINDER",data: {appointment_date: "December 15, 2025",appointment_time: "2:00 PM",location: "123 Main St"},routing: {method: "all",channels: ["email", "sms"]}}});
routing: {method: "priority",channels: ["push", "email", "sms"]}