Bird email, SMS, and WhatsApp notifications for Medusa v2.
Send email, SMS, and WhatsApp notifications from your Medusa v2 application with Bird. This notification provider runs in your Medusa server and uses your workspace's Bird API key. It supports Medusa 2.21.2 and later v2 releases.
Install the Bird notification provider from npm:
Set your Bird credentials in your hosting platform's environment settings. For local development, add them to and keep that file out of version control:
Set to your connected WhatsApp number when sending from it. Omit sender variables for channels you do not use.
Add the provider to the Notification Module in your existing . Keep its other application settings and environment loading:
Keep the local provider for Medusa admin notifications such as product and order exports. Configuring replaces Medusa's default provider list. Medusa routes each channel to one provider: remove a channel from an existing provider before assigning it to Bird. Register this package in the Notification Module; it needs no entry in .
Restart or redeploy Medusa after changing the configuration. On Medusa Cloud, enable the Build flag for the environment variables used here. Credentials and defaults are server configuration; this package adds no admin settings page or OAuth connection form.
Create an API key in your Bird workspace with send permissions for the channels you enable: , , and . Keep it in server environment variables. The provider derives the API region from the key; no workspace ID or region setting is needed. Use a API key. Short-lived OAuth tokens () are not supported.
Use a verified email domain for and a configured SMS sender for . Configure only the channels you use. A notification's overrides its channel's default sender. For WhatsApp, use a connected number as . For built-in SMS and WhatsApp templates, use their slug and omit ; the provider skips the configured default sender. When referring to a built-in template by ID instead, use a provider configuration without that channel's default sender.
Create and publish an email template with the slug in Bird, including an variable. Add :
accepts a Bird email template ID () or SMS template ID (), or a published template slug. For email and SMS, becomes the template's . Pass when the template requires a language.
Send SMS through the same Notification Module:
Create and publish as an SMS template first. Its category comes from the template; do not pass for SMS template sends.
WhatsApp uses and accepts approved template IDs () or slugs. Pass template components in . See WhatsApp templates and text for examples and sender requirements.
When is present, it takes precedence over . Medusa still requires a string; use a descriptive label such as . Email requires and or . SMS and WhatsApp accept only . Inline email and SMS messages default to ; use for marketing content.
Email maps to Bird's inline Liquid parameters. Render SMS and WhatsApp text in your app or use a stored template; their inline text does not interpolate . WhatsApp text requires an open customer service window.
Supported fields:
Medusa email attachments map to Bird attachments without re-encoding their base64 . For an inline image, set and , then reference in the HTML. SMS and WhatsApp notifications do not accept Medusa attachments; WhatsApp template media belongs in .
The returned ID confirms API acceptance. Delivery is asynchronous; use Bird's message APIs or webhooks to track the outcome. Medusa's notification success state does not confirm delivery to an inbox or handset.
The provider makes one request with a 30-second timeout. It does not retry an uncertain send. Medusa's notification idempotency key is separate from Bird's; set too when retrying. Bird retains responses for three hours by default, with the limits described in the API reference.
Run , , and in this package. Lint uses Medusa's module-provider ESLint preset and checks TypeScript types. Tests mock Bird's HTTP responses and send no messages. Run for the real Medusa Notification Module and PostgreSQL checks; see integration test prerequisites and database cleanup. creates an installable package for testing in a Medusa application before publication; integration tests are included in source mirrors and excluded from npm packages.
Source changes live in the Bird monorepo. The release repository is a mirror; versions and releases follow Bird's surface release process. Publishing and Medusa catalog visibility are separate steps. This package includes Medusa's documented notification integration discovery keywords.
npm install @messagebird/bird-plugin-medusa1BIRD_API_KEY=your_bird_access_key2BIRD_EMAIL_FROM=notifications@example.com3BIRD_SMS_FROM=YourShop1import { defineConfig, loadEnv } from "@medusajs/framework/utils";2
3loadEnv(process.env.NODE_ENV || "development", process.cwd());4
5module.exports = defineConfig({6 modules: [7 {8 resolve: "@medusajs/medusa/notification",9 options: {10 providers: [11 {12 resolve: "@medusajs/medusa/notification-local",13 id: "local",14 options: { channels: ["feed"] },15 },16 {17 resolve: "@messagebird/bird-plugin-medusa/providers/bird",18 id: "bird",19 options: {20 channels: ["email", "sms", "whatsapp"],21 api_key: process.env.BIRD_API_KEY,22 email_from: process.env.BIRD_EMAIL_FROM,23 sms_from: process.env.BIRD_SMS_FROM,24 whatsapp_from: process.env.BIRD_WHATSAPP_FROM,25 },26 },27 ],28 },29 },30 ],31});1import type { SubscriberArgs, SubscriberConfig } from "@medusajs/framework";2import { Modules } from "@medusajs/framework/utils";3
4type OrderEvent = SubscriberArgs<{ id: string }>;5
6export default async function orderPlaced(args: OrderEvent) {7 const container = args.container;8 const data = args.event.data;9 const order = await container.resolve(Modules.ORDER).retrieveOrder(data.id);10 if (!order.email) return;11 await container.resolve(Modules.NOTIFICATION).createNotifications({12 to: order.email,13 channel: "email",14 template: "order-confirmation",15 data: { order_id: order.display_id },16 idempotency_key: `order-confirmation/${order.id}`,17 provider_data: { idempotency_key: `order-confirmation/${order.id}` },18 });19}20
21export const config: SubscriberConfig = { event: "order.placed" };1await notificationModuleService.createNotifications({2 to: "+31612345678",3 channel: "sms",4 template: "order-shipped",5 data: { order_id: "123", tracking_url: "https://shop.example/track/123" },6});