Notification Providers
Notification providers handle sending notifications through various channels like email, SMS, push notifications, and more. They support both template-based and content-based notifications with attachments.
Available Notification Providers
Medusa includes two notification providers:
Local Notification Provider
@medusajs/medusa/notification-local - Logs notifications to the console.
Use cases:
Development and testing
Debugging notification flows
Preview notification data
SendGrid Notification Provider
@medusajs/medusa/notification-sendgrid - Sends email notifications via SendGrid.
Use cases:
Production email delivery
Transactional emails
Marketing emails
Template-based emails
Features:
Support for SendGrid templates
HTML email content
Email attachments
Dynamic template data
Installation
Both providers are included in the core Medusa package:
npm install @medusajs/medusa
For SendGrid, also install the SendGrid SDK:
npm install @sendgrid/mail
Configuration
Local Provider
SendGrid Provider
Multiple Providers
Configure the local notification provider: import { defineConfig } from "@medusajs/framework/utils"
export default defineConfig ({
modules: [
{
resolve: "@medusajs/medusa/notification" ,
options: {
providers: [
{
resolve: "@medusajs/medusa/notification-local" ,
id: "local" ,
options: {},
},
],
},
},
] ,
})
Configure the SendGrid notification provider: import { defineConfig } from "@medusajs/framework/utils"
export default defineConfig ({
modules: [
{
resolve: "@medusajs/medusa/notification" ,
options: {
providers: [
{
resolve: "@medusajs/medusa/notification-sendgrid" ,
id: "sendgrid" ,
options: {
api_key: process . env . SENDGRID_API_KEY ,
from: process . env . SENDGRID_FROM ,
},
},
],
},
},
] ,
})
Environment variables: Get your SendGrid API key from the SendGrid Dashboard .
Verify your sender email address in SendGrid before sending emails. Configure multiple notification providers: import { defineConfig } from "@medusajs/framework/utils"
export default defineConfig ({
modules: [
{
resolve: "@medusajs/medusa/notification" ,
options: {
providers: [
{
resolve: "@medusajs/medusa/notification-sendgrid" ,
id: "sendgrid" ,
options: {
api_key: process . env . SENDGRID_API_KEY ,
from: process . env . SENDGRID_FROM ,
},
},
{
resolve: "@medusajs/medusa/notification-local" ,
id: "local" ,
options: {},
},
],
},
},
] ,
})
Notification Provider Interface
All notification providers extend AbstractNotificationProviderService and implement the following method:
send(notification: ProviderSendNotificationDTO): Promise<ProviderSendNotificationResultsDTO>
Sends a notification.
With HTML Content:
const result = await notificationProvider . send ({
to: "[email protected] " ,
channel: "email" ,
template: null ,
from: "[email protected] " , // Optional, uses default from config
content: {
subject: "Order Confirmation" ,
html: "<h1>Thank you for your order!</h1>" ,
},
data: {
order_id: "order_123" ,
},
attachments: [
{
filename: "invoice.pdf" ,
content: base64Content ,
content_type: "application/pdf" ,
},
],
})
With SendGrid Template:
const result = await notificationProvider . send ({
to: "[email protected] " ,
channel: "email" ,
template: "d-1234567890abcdef" , // SendGrid template ID
data: {
customer_name: "John Doe" ,
order_number: "#12345" ,
order_total: "$99.99" ,
},
})
Parameters:
to - Recipient email address
channel - Notification channel (e.g., “email”, “sms”)
template - Template identifier (provider-specific)
from - Sender email (optional, uses default from config)
content - Notification content
subject - Email subject
html - HTML content
text - Plain text content (optional)
data - Dynamic data for templates
attachments - File attachments
filename - Attachment filename
content - Base64-encoded content
content_type - MIME type
disposition - “attachment” or “inline”
id - Content ID for inline images
SendGrid does not support mixing HTML content and templates. Use either content.html
or template, not both.
Using the Notification Module
Access notification providers through the Notification Module:
import { Modules } from "@medusajs/framework/utils"
const notificationModule = container . resolve ( Modules . NOTIFICATION )
// Send a notification
const notification = await notificationModule . createNotifications ({
to: "[email protected] " ,
channel: "email" ,
template: "order-confirmation" ,
data: {
order: orderData ,
},
provider_id: "sendgrid" ,
})
Notification Workflows
Notifications are typically sent through workflows that handle specific events:
import { createWorkflow , WorkflowData } from "@medusajs/framework/workflows-sdk"
import { createNotificationStep } from "@medusajs/core-flows"
const sendOrderConfirmationWorkflow = createWorkflow (
"send-order-confirmation" ,
( input : WorkflowData <{ order_id : string }>) => {
const notification = createNotificationStep ({
to: input . order . customer . email ,
channel: "email" ,
template: "order-confirmation" ,
data: {
order_number: input . order . display_id ,
order_total: input . order . total ,
items: input . order . items ,
},
provider_id: "sendgrid" ,
})
return notification
}
)
Common Notification Types
Order Confirmation
await notificationModule . createNotifications ({
to: order . customer . email ,
channel: "email" ,
template: "order-placed" ,
data: {
customer_name: order . customer . first_name ,
order_number: order . display_id ,
order_date: order . created_at ,
items: order . items ,
total: order . total ,
shipping_address: order . shipping_address ,
},
provider_id: "sendgrid" ,
})
Shipment Notification
await notificationModule . createNotifications ({
to: order . customer . email ,
channel: "email" ,
template: "order-shipped" ,
data: {
order_number: order . display_id ,
tracking_number: fulfillment . tracking_number ,
tracking_url: fulfillment . tracking_url ,
estimated_delivery: fulfillment . estimated_delivery ,
},
provider_id: "sendgrid" ,
})
Password Reset
await notificationModule . createNotifications ({
to: user . email ,
channel: "email" ,
template: "password-reset" ,
data: {
user_name: user . name ,
reset_token: resetToken ,
reset_url: ` ${ process . env . STORE_URL } /reset-password?token= ${ resetToken } ` ,
},
provider_id: "sendgrid" ,
})
Creating Custom Notification Providers
Create a custom notification provider by extending AbstractNotificationProviderService:
packages/modules/providers/notification-custom/src/services/custom-notification.ts
import {
AbstractNotificationProviderService ,
MedusaError ,
} from "@medusajs/framework/utils"
import { Logger , NotificationTypes } from "@medusajs/framework/types"
type InjectedDependencies = {
logger : Logger
}
interface CustomNotificationConfig {
apiKey : string
from : string
}
export class CustomNotificationService extends AbstractNotificationProviderService {
static identifier = "custom-notification"
protected config_ : CustomNotificationConfig
protected logger_ : Logger
protected client_ : any
constructor (
{ logger } : InjectedDependencies ,
options : CustomNotificationConfig
) {
super ()
this . config_ = options
this . logger_ = logger
// Initialize your notification service client
this . client_ = new NotificationServiceClient ( options . apiKey )
}
async send (
notification : NotificationTypes . ProviderSendNotificationDTO
) : Promise < NotificationTypes . ProviderSendNotificationResultsDTO > {
if ( ! notification ) {
throw new MedusaError (
MedusaError . Types . INVALID_DATA ,
"No notification information provided"
)
}
try {
// Send via your notification service
const result = await this . client_ . send ({
to: notification . to ,
from: notification . from || this . config_ . from ,
subject: notification . content ?. subject ,
html: notification . content ?. html ,
template: notification . template ,
data: notification . data ,
attachments: notification . attachments ,
})
return {
id: result . messageId ,
}
} catch ( error ) {
this . logger_ . error (
`Failed to send notification: ${ error . message } `
)
throw new MedusaError (
MedusaError . Types . UNEXPECTED_STATE ,
`Failed to send notification: ${ error . message } `
)
}
}
}
SMS Provider Example
packages/modules/providers/notification-sms/src/services/sms-notification.ts
import { AbstractNotificationProviderService } from "@medusajs/framework/utils"
import { Logger , NotificationTypes } from "@medusajs/framework/types"
import Twilio from "twilio"
export class SmsNotificationService extends AbstractNotificationProviderService {
static identifier = "sms"
protected client_ : Twilio . Twilio
protected from_ : string
constructor ({ logger }, options ) {
super ()
this . client_ = Twilio ( options . accountSid , options . authToken )
this . from_ = options . from
}
async send (
notification : NotificationTypes . ProviderSendNotificationDTO
) : Promise < NotificationTypes . ProviderSendNotificationResultsDTO > {
const message = await this . client_ . messages . create ({
to: notification . to ,
from: this . from_ ,
body: notification . content ?. text || "" ,
})
return {
id: message . sid ,
}
}
}
Register your custom provider:
packages/modules/providers/notification-custom/src/index.ts
import { ModuleProvider , Modules } from "@medusajs/framework/utils"
import { CustomNotificationService } from "./services/custom-notification"
export default ModuleProvider ( Modules . NOTIFICATION , {
services: [ CustomNotificationService ] ,
})
Reference
Local Provider: packages/modules/providers/notification-local/src/services/local.ts
SendGrid Provider: packages/modules/providers/notification-sendgrid/src/services/sendgrid.ts
Base class: packages/core/utils/src/notification/abstract-notification-provider.ts
Types: packages/core/types/src/notification/provider.ts
Next Steps
Payment Providers Send payment confirmation emails
Fulfillment Providers Send shipment notifications