Skip to main content

How to Create a Notification Provider

In this document, you’ll learn how to add a Notification Provider to your Medusa server.

If you’re unfamiliar with the Notification architecture in Medusa, it is recommended to check out the architecture overview first.

Prerequisites

Before you start creating a Notification Provider, you need to install a Medusa server.

You also need to setup Redis and configure it with the Medusa server.


Create a Notification Provider

Creating a Notification Provider is as simple as creating a TypeScript or JavaScript file in src/servicesCopy to Clipboard. The name of the file is the name of the provider (for example, sendgrid.tsCopy to Clipboard). A Notification Provider is essentially a Service that extends the AbstractNotificationServiceCopy to Clipboard from @medusajs/medusaCopy to Clipboard.

For example, create the file src/services/email-sender.tsCopy to Clipboard with the following content:

src/services/email-sender.ts
import { AbstractNotificationService } from "@medusajs/medusa"
import { EntityManager } from "typeorm"

class EmailSenderService extends AbstractNotificationService {
protected manager_: EntityManager
protected transactionManager_: EntityManager

sendNotification(
event: string,
data: unknown,
attachmentGenerator: unknown
): Promise<{
to: string;
status: string;
data: Record<string, unknown>;
}> {
throw new Error("Method not implemented.")
}
resendNotification(
notification: unknown,
config: unknown,
attachmentGenerator: unknown
): Promise<{
to: string;
status: string;
data: Record<string, unknown>;
}> {
throw new Error("Method not implemented.")
}

}

export default EmailSenderService
Report Incorrect CodeReport Incorrect CodeCopy to ClipboardCopy to Clipboard

Where EmailSenderServiceCopy to Clipboard is the name of your Notification Provider Service.

Notification Providers must extend NotificationServiceCopy to Clipboard from medusa-interfacesCopy to Clipboard.

Following the naming convention of Services, the name of the file should be the slug name of the Notification Provider, and the name of the class should be the camel case name of the Notification Provider suffixed with “Service”. In the example above, the name of the file should be email-sender.jsCopy to Clipboard. You can learn more in the service documentation.

identifier

Notification Provider Services must have a static property identifierCopy to Clipboard.

The NotificationProviderCopy to Clipboard entity has 2 properties: identifierCopy to Clipboard and is_installedCopy to Clipboard. The value of the identifierCopy to Clipboard property in the Service class is used when the Notification Provider is created in the database.

The value of this property is also used later when you want to subscribe the Notification Provider to events in a Subscriber.

For example, in the class you created in the previous code snippet you can add the following property:

class EmailSenderService extends AbstractNotificationService {
static identifier = "email-sender"
// ...
}
Report Incorrect CodeReport Incorrect CodeCopy to ClipboardCopy to Clipboard

constructor

You can use the constructorCopy to Clipboard of your Notification Provider to have access to different Services in Medusa through dependency injection.

You can also use the constructor to initialize your integration with the third-party provider. For example, if you use a client to connect to the third-party provider’s APIs, you can initialize it in the constructor and use it in other methods in the Service.

Additionally, if you’re creating your Notification Provider as an external plugin to be installed on any Medusa server and you want to access the options added for the plugin, you can access it in the constructor. The options are passed as a second parameter.

You can learn more about plugins and how to create them in the Plugins documentation.

Continuing on with the previous example, if you want to use the OrderServiceCopy to Clipboard later when sending notifications, you can inject it into the constructor:

import { 
AbstractNotificationService,
OrderService,
} from "@medusajs/medusa"

class EmailSenderService extends AbstractNotificationService {
protected manager_: EntityManager
protected transactionManager_: EntityManager
static identifier = "email-sender"
protected orderService: OrderService

constructor(container, options) {
super(container)
// you can access options here in case you're
// using a plugin

this.orderService = container.orderService
}

// ...
}
Report Incorrect CodeReport Incorrect CodeCopy to ClipboardCopy to Clipboard

sendNotification

When an event is triggered that your Notification Provider is registered as a handler for, the NotificationServiceCopy to Clipboard in Medusa’s core will execute the sendNotificationCopy to Clipboard method of your Notification Provider.

In this method, you can perform the necessary operation to send the Notification. Following the example above, you can send an email to the customer when they place an order.

This method receives three parameters:

  1. eventNameCopy to Clipboard: This is the name of the event that was triggered. For example, order.placedCopy to Clipboard.
  2. eventDataCopy to Clipboard: This is the data payload of the event that was triggered. For example, if the order.placedCopy to Clipboard event is triggered, the eventDataCopy to Clipboard object contains the property idCopy to Clipboard which is the ID of the order that was placed.
  3. attachmentGeneratorCopy to Clipboard: If you’ve previously attached a generator to the NotificationServiceCopy to Clipboard using the registerAttachmentGeneratorCopy to Clipboard method, you have access to it here. You can use the attachmentGeneratorCopy to Clipboard to generate on-demand invoices or other documents. The default value of this parameter is null.

You can learn more about what events are triggered in Medusa and their data payload in the Events List documentation.

This method must return an object containing two properties:

  1. toCopy to Clipboard: a string that represents the receiver of the Notification. For example, if you sent an email to the customer then toCopy to Clipboard is the email address of the customer. In other cases, it might be a phone number or a username.
  2. dataCopy to Clipboard: an object that contains the data used to send the Notification. For example, if you sent an order confirmation email to the customer, then the dataCopy to Clipboard object might include the order items or the subject of the email. This dataCopy to Clipboard is necessary if the notification is resent later as you can use the same data.

Continuing with the previous example you can have the following implementation of the sendNotificationCopy to Clipboard method:

class EmailSenderService extends AbstractNotificationService {
// ...
async sendNotification(
event: string,
data: any,
attachmentGenerator: unknown
): Promise<{
to: string;
status: string;
data: Record<string, unknown>;
}> {
if (event === "order.placed") {
// retrieve order
const order = await this.orderService.retrieve(data.id)
// TODO send email

console.log("Notification sent")
return {
to: order.email,
status: "done",
data: {
// any data necessary to send the email
// for example:
subject: "You placed a new order!",
items: order.items,
},
}
}
}
}
Report Incorrect CodeReport Incorrect CodeCopy to ClipboardCopy to Clipboard

In this code snippet, you check first if the event is order.placedCopy to Clipboard. This can be helpful if you’re handling multiple events using the same Notification Provider.

You then retrieve the order using the ID and send the email. Here, the logic related to sending the email is not implemented as it is generally specific to your Notification Provider.

Finally, you return an object with the toCopy to Clipboard property set to the customer email and the dataCopy to Clipboard property is an object that contains data necessary to send the email such as a subjectCopy to Clipboard or itemsCopy to Clipboard.

The toCopy to Clipboard and dataCopy to Clipboard properties are used in the NotificationServiceCopy to Clipboard in Medusa’s core to create a new NotificationCopy to Clipboard record in the database. You can learn more about the NotificationCopy to Clipboard entity in the Architecture Overview documentation.

resendNotification

Using the Resend Notification endpoint, an admin user can resend a Notification to the customer. The NotificationServiceCopy to Clipboard in Medusa’s core then executes the resendNotificationCopy to Clipboard method in your Notification Provider.

This method receives three parameters:

  1. notificationCopy to Clipboard: This is the original Notification record that was created after you sent the notification with sendNotificationCopy to Clipboard. You can get an overview of the entity and its attributes in the architecture overview, but most notably it includes the toCopy to Clipboard and dataCopy to Clipboard attributes which are populated originally using the toCopy to Clipboard and dataCopy to Clipboard properties of the object you return in sendNotificationCopy to Clipboard.
  2. configCopy to Clipboard: In the Resend Notification endpoint you may specify an alternative receiver of the notification using the toCopy to Clipboard request body parameter. For example, you may want to resend the order confirmation email to a different email. If that’s the case, you have access to it in the configCopy to Clipboard parameter object. Otherwise, configCopy to Clipboard will be an empty object.
  3. attachmentGeneratorCopy to Clipboard: If you’ve previously attached a generator to the Notification Service using the registerAttachmentGeneratorCopy to Clipboard method, you have access to it here. You can use the attachmentGeneratorCopy to Clipboard to generate on-demand invoices or other documents. The default value of this parameter is null.

Similarly to the sendNotificationCopy to Clipboard method, this method must return an object containing two properties:

  1. toCopy to Clipboard: a string that represents the receiver of the Notification. You can either return the same toCopy to Clipboard available in the notificationCopy to Clipboard parameter or the updated one in the configCopy to Clipboard parameter.
  2. dataCopy to Clipboard: an object that contains the data used to send the Notification. You can either return the same dataCopy to Clipboard in the notificationCopy to Clipboard parameter or make any necessary updates to it.

Continuing with the previous example you can have the following implementation of the resendNotificationCopy to Clipboard method:

class EmailSenderService extends AbstractNotificationService {
// ...
async resendNotification(
notification: any,
config: any,
attachmentGenerator: unknown
): Promise<{
to: string;
status: string;
data: Record<string, unknown>;
}> {
// check if the receiver of the notification should be changed
const to: string = config.to ? config.to : notification.to

// TODO resend the notification using the same data
// that is saved under notification.data

console.log("Notification resent")
return {
to,
status: "done",
data: notification.data, // you can also make changes to the data
}
}
}
Report Incorrect CodeReport Incorrect CodeCopy to ClipboardCopy to Clipboard

In the above snippet, you check if the toCopy to Clipboard should be changed by checking if the configCopy to Clipboard parameter has a toCopy to Clipboard property. Otherwise, you keep the same toCopy to Clipboard address stored in the notificationCopy to Clipboard parameter.

You then resend the email. Here, the logic related to sending the email is not implemented as it is generally specific to your Notification Provider.

Finally, you return an object with the toCopy to Clipboard property set to the email (either new or old) and the dataCopy to Clipboard property is the same data used before to send the original notification. you can alternatively make any changes to the data.

The toCopy to Clipboard and dataCopy to Clipboard properties are used in the NotificationServiceCopy to Clipboard in Medusa’s core to create a new NotificationCopy to Clipboard record in the database. No changes are made to the original NotificationCopy to Clipboard record created after the sendNotificationCopy to Clipboard method. This new record is associated with the original NotificationCopy to Clipboard record using the parent_idCopy to Clipboard attribute in the entity. You can learn more about the NotificationCopy to Clipboard entity in the Architecture Overview documentation.


Create a Subscriber

After creating your Notification Provider Service, you must create a Subscriber that registers this Service as a notification handler of events.

This section will not cover the basics of Subscribers. You can read the Subscribers documentation to learn more about them and how to create them.

Following the previous example, to make sure the email-senderCopy to Clipboard Notification Provider handles the order.placedCopy to Clipboard event, create the file src/subscribers/notification.jsCopy to Clipboard with the following content:

src/subscribers/notification.js
class NotificationSubscriber {
constructor({ notificationService }) {
notificationService.subscribe("order.placed", "email-sender")
}
// ...
}

export default NotificationSubscriber
Report Incorrect CodeReport Incorrect CodeCopy to ClipboardCopy to Clipboard

This subscriber accesses the notificationServiceCopy to Clipboard using dependency injection. The notificationServiceCopy to Clipboard contains a subscribeCopy to Clipboard method that accepts 2 parameters. The first one is the name of the event to subscribe to, and the second is the identifier of the Notification Provider that is subscribing to that event.

Notice that the value of the identifierCopy to Clipboard static property defined in the EmailSenderServiceCopy to Clipboard is used to register the Notification Provider to handle the order.placedCopy to Clipboard event.


Test Sending Notifications with your Notification Provider

Make sure you've configured Redis with your Medusa server as explained in the Prerequisites section and that the Redis service is running.

Then, start by running your Medusa server:

yarn run start
Report Incorrect CodeReport Incorrect CodeCopy to ClipboardCopy to Clipboard

Then, place an order either using the REST APIs or using the storefront.

If you don’t have a storefront installed you can get started with either the Next.js or Gatsby starter storefronts in minutes.

After placing an order, you can see in your console the message “Notification Sent”. If you added your own notification sending logic, you should receive an email or alternatively the type of notification you’ve set up.


Test Resending Notifications with your Notification Provider

To test resending a notification, first, retrieve the ID of the notification you just sent using the List Notifications admin endpoint. You can pass as a body parameter the toCopy to Clipboard or event_nameCopy to Clipboard parameters to filter out the notification you just sent.

You must be authenticated as an admin user before sending this request. You can use the Authenticate a User endpoint to get authenticated.

List Notifications Request

Then, send a request to the Resend Notification endpoint using the ID retrieved from the previous request. You can pass the toCopy to Clipboard parameter in the body to change the receiver of the notification. You should see the message “Notification Resent” in your console and if you implemented your own logic for resending the notification it will be resent.

Resend Notifications Request

This request returns the same notification object as the List Notifications endpoint, but it now has a new object in the resendsCopy to Clipboard array. This is the resent notification. If you supplied a toCopy to Clipboard parameter in the request body, you should see its value in the toCopy to Clipboard property of the resent notification object.


See Also