> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/medusajs/medusa/llms.txt
> Use this file to discover all available pages before exploring further.

# Notification Providers

> Learn how to configure and use notification providers in Medusa for sending emails, SMS, and other notifications.

# 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:

```bash theme={null}
npm install @medusajs/medusa
```

For SendGrid, also install the SendGrid SDK:

```bash theme={null}
npm install @sendgrid/mail
```

## Configuration

<Tabs>
  <Tab title="Local Provider">
    Configure the local notification provider:

    ```typescript medusa-config.ts theme={null}
    import { defineConfig } from "@medusajs/framework/utils"

    export default defineConfig({
    modules: [
    {
      resolve: "@medusajs/medusa/notification",
      options: {
        providers: [
          {
            resolve: "@medusajs/medusa/notification-local",
            id: "local",
            options: {},
          },
        ],
      },
    },
    ],
    })
    ```
  </Tab>

  <Tab title="SendGrid Provider">
    Configure the SendGrid notification provider:

    ```typescript medusa-config.ts theme={null}
    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:

    ```bash .env theme={null}
    SENDGRID_API_KEY=SG.xxx
    SENDGRID_FROM=noreply@yourstore.com
    ```

    <Note>
      Get your SendGrid API key from the [SendGrid Dashboard](https://app.sendgrid.com/settings/api_keys).
      Verify your sender email address in SendGrid before sending emails.
    </Note>
  </Tab>

  <Tab title="Multiple Providers">
    Configure multiple notification providers:

    ```typescript medusa-config.ts theme={null}
    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: {},
          },
        ],
      },
    },
    ],
    })
    ```
  </Tab>
</Tabs>

## Notification Provider Interface

All notification providers extend `AbstractNotificationProviderService` and implement the following method:

### `send(notification: ProviderSendNotificationDTO): Promise<ProviderSendNotificationResultsDTO>`

Sends a notification.

**With HTML Content:**

```typescript theme={null}
const result = await notificationProvider.send({
  to: "customer@example.com",
  channel: "email",
  template: null,
  from: "store@example.com", // 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:**

```typescript theme={null}
const result = await notificationProvider.send({
  to: "customer@example.com",
  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

<Warning>
  SendGrid does not support mixing HTML content and templates. Use either `content.html`
  or `template`, not both.
</Warning>

## Using the Notification Module

Access notification providers through the Notification Module:

```typescript theme={null}
import { Modules } from "@medusajs/framework/utils"

const notificationModule = container.resolve(Modules.NOTIFICATION)

// Send a notification
const notification = await notificationModule.createNotifications({
  to: "customer@example.com",
  channel: "email",
  template: "order-confirmation",
  data: {
    order: orderData,
  },
  provider_id: "sendgrid",
})
```

## Notification Workflows

Notifications are typically sent through workflows that handle specific events:

```typescript theme={null}
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

```typescript theme={null}
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

```typescript theme={null}
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

```typescript theme={null}
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`:

```typescript packages/modules/providers/notification-custom/src/services/custom-notification.ts theme={null}
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

```typescript packages/modules/providers/notification-sms/src/services/sms-notification.ts theme={null}
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:

```typescript packages/modules/providers/notification-custom/src/index.ts theme={null}
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

<CardGroup cols={2}>
  <Card title="Payment Providers" href="/providers/payment" icon="credit-card">
    Send payment confirmation emails
  </Card>

  <Card title="Fulfillment Providers" href="/providers/fulfillment" icon="truck">
    Send shipment notifications
  </Card>
</CardGroup>
