If  the user asks for password reset then console log the token.
Events reference:
user.password_reset
	

Triggered when a user requests to reset their password.

Object of the following format:

{
  email, // string email of user requesting to reset their password
  token // token create to reset the password
}
Events and Subscribers Overview:
Events

In this document, you’ll learn what events are and why they’re useful in Medusa.
Overview

Events are used in Medusa to inform different parts of the commerce ecosystem that this event occurred. For example, when an order is placed, the order.placed event is triggered, which informs notification services like SendGrid to send a confirmation email to the customer.
Tip

If you want to implement order confirmation emails, you can check this step-by-step guide.

The events system in Medusa is built on a publish/subscribe architecture. The Medusa core publish an event when an action takes place, and modules, plugins, or other forms of customizations can subscribe to that event. Subscribers can then perform a task asynchronously when the event is triggered.

Although the core implements the main logic behind the events system, you’ll need to use an event module that takes care of the publish/subscribe functionality such as subscribing and emitting events. Medusa provides modules that you can use both for development and production, including Redis and Local modules.
Database Transactions

Transactions in Medusa ensure Atomicity, Consistency, Isolation, and Durability (ACID) guarantees for operations in the Medusa core.

In many cases, services typically update resources in the database and emit an event within a transactional operation. To ensure that these events don't cause data inconsistencies (for example, a plugin subscribes to an event to contact a third-party service, but the transaction fails) the concept of a staged job is introduced.

Instead of events being processed immediately, they're stored in the database as a staged job until they're ready. In other words, until the transaction has succeeded.

This rather complex logic is abstracted away from the consumers of the EventBusService, but here's an example of the flow when an API request is made:

    API request starts.
    Transaction is initiated.
    Service layer performs some logic.
    Events are emitted and stored in the database for eventual processing.
    Transaction is committed.
    API request ends.
    Events in the database become visible.

To pull staged jobs from the database, a separate enqueuer polls the database every three seconds to discover new visible jobs. These jobs are then added to the queue and processed as described in the Processing section earlier.
Emitting Events

You can emit events in Medusa using the EventBusService. For example:

this.eventBusService.emit("custom-event", {
  // attach any data to the event
})

You can also emit more than one event:

this.eventBusService.emit([
  {
    eventName: "custom-event-1",
    data: {
      // attach any data to the event
    },
  },
  {
    eventName: "custom-event-2",
    data: {
      // attach any data to the event
    },
  },
])

Available Modules
Medusa’s default starter project comes with the local event module (@medusajs/event-bus-local). For production environments, it’s recommended to use the Redis event module package (@medusajs/event-bus-redis) that you can install.
Subscribers

In this document, you'll learn what Subscribers are in Medusa.
What are Subscribers

Subscribers register handlers for an events and allows you to perform an action when that event occurs. For example, if you want to send your customer an email when they place an order, then you can listen to the order.placed event and send the email when the event is emitted.

Natively in Medusa there are subscribers to handle different events. However, you can also create your own custom subscribers.

Custom subscribers are TypeScript or JavaScript files in your project's src/subscribers directory. Subscriber files must default export a handler function and export a configuration object.

Whenever an event is emitted, the subscriber’s handler function is executed. The handler function receives as a parameter an object that includes the data payload, among other parameters. For example, if an order is placed, the order.placed event is emitted and all the handlers receive the order ID in the data object.
Example Use Cases

Subscribers are useful in many use cases, including:

    Send a confirmation email to the customer when they place an order by subscribing to the order.placed event.
    Automatically assign new customers to a customer group by subscribing to the customer.created.
 Handle custom events that you emit

Create Events Module

In this document, you’ll learn how to create an events module.
Overview

Medusa provides ready-made modules for events, including the local and Redis modules. If you prefer another technology used for managing events, you can build a module locally and use it in your Medusa backend. You can also publish to NPM and reuse it across multiple Medusa backend instances.

In this document, you’ll learn how to build your own Medusa events module, mainly focusing on creating the event bus service and the available methods you need to implement within your module.
(Optional) Step 0: Prepare Module Directory

Before you start implementing your module, it's recommended to prepare the directory or project holding your custom implementation.

You can refer to the Project Preparation step in the Create Module documentation to learn how to do that.
Step 1: Create the Service

Create the file services/event-bus-custom.ts which will hold your event bus service. Note that the name of the file is recommended to be in the format event-bus-<service_name> where <service_name> is the name of the service you’re integrating. For example, event-bus-redis.

Add the following content to the file:
services/event-bus-custom.ts

import { EmitData, EventBusTypes } from "@medusajs/types"
import { AbstractEventBusModuleService } from "@medusajs/utils"

class CustomEventBus extends AbstractEventBusModuleService {
  async emit<T>(
    eventName: string, 
    data: T, 
    options: Record<string, unknown>
  ): Promise<void>;
  async emit<T>(data: EmitData<T>[]): Promise<void>;
  async emit(
    eventName: unknown, 
    data?: unknown, 
    options?: unknown
  ): Promise<void> {
    throw new Error("Method not implemented.")
  }
}

export default CustomEventBus

This creates the class CustomEventBus that implements the AbstractEventBusModuleService class imported from @medusajs/utils. Feel free to rename the class to what’s relevant for your event bus service.

In the class you must implement the emit method. You can optionally implement the subscribe and unsubscribe methods.
Step 2: Implement Methods
Note About the eventToSubscribersMap Property

The AbstractEventBusModuleService implements two methods for handling subscription: subscribe and unsubscribe. In these methods, the subscribed handler functions are managed within a class property eventToSubscribersMap, which is a JavaScript Map. The map's keys are the event names, whereas the value of each key is an array of subscribed handler functions.

In your custom implementation, you can use this property to manage the subscribed handler functions. For example, you can get the subscribers of a method using the get method of the map:

const eventSubscribers = 
  this.eventToSubscribersMap.get(eventName) || []

Alternatively, you can implement custom logic for the subscribe and unsubscribe events, which is explained later in this guide.
constructor

The constructor method of a service allows you to prepare any third-party client or service necessary to be used in other methods. It also allows you to get access to the module’s options which are typically defined in medusa-config.js, and to other services and resources in the Medusa backend using dependency injection.

Here’s an example of how you can use the constructor to store the options of your module:
services/event-bus-custom.ts

class CustomEventBus extends AbstractEventBusModuleService {
  protected readonly moduleOptions: Record<string, any>

  constructor({
    // inject resources from the Medusa backend
    // for example, you can inject the logger
    logger,
  }, options) {
    super(...arguments)
    this.moduleOptions = options
  }

  // ...
}

emit

The emit method is used to push an event from Medusa into your messaging system. Typically, the subscribers to that event would then pick up the message and execute their asynchronous tasks.

The emit method has two different signatures:

    The first signature accepts three parameters. The first parameter is eventName being a required string indicating the name of the event to trigger. The second parameter is data being the optional data to send to subscribers of that event. The third optional parameter options which can be used to pass options specific to the event bus.
    The second signature accepts one parameter, which is an array of objects having three properties: eventName, data, and options. These are the same as the parameters that can be passed in the first signature. This signature allows emitting more than one event.

The options parameter depends on the event bus integration. For example, the Redis event bus accepts the following options:
services/event-bus-custom.ts

type JobData<T> = {
  eventName: string
  data: T
  completedSubscriberIds?: string[] | undefined
}

You can implement your method in a way that supports both signatures by checking the type of the first input. For example:
services/event-bus-custom.ts

class CustomEventBus extends AbstractEventBusModuleService {
  // ...
  async emit<T>(
    eventName: string, 
    data: T, 
    options: Record<string, unknown>
  ): Promise<void>;
  async emit<T>(data: EmitData<T>[]): Promise<void>;
  async emit<T>(
    eventOrData: string | EmitData<T>[], 
    data?: T, 
    options: Record<string, unknown> = {}
  ): Promise<void> {
    const isBulkEmit = Array.isArray(eventOrData)
    
    // emit event
  }
}

(optional) subscribe

As mentioned earlier, this method is already implemented in the AbstractEventBusModuleService class. This section explains how you can implement your custom subscribe logic if necessary.

The subscribe method attaches a handler function to the specified event, which is run when the event is triggered. It is typically used inside a subscriber class.

The subscribe method accepts three parameters:

    The first parameter eventName is a required string. It indicates which event the handler function is subscribing to.
    The second parameter subscriber is a required function that performs an action when the event is triggered.
    The third parameter context is an optional object that has the property subscriberId. Subscriber IDs are useful to differentiate between handler functions when retrying a failed method. It’s also useful for unsubscribing an event handler. Note that if you must implement the mechanism around assigning IDs to subscribers when you override the subscribe method.

The implementation of this method depends on the service you’re using for the event bus:
services/event-bus-custom.ts

class CustomEventBus extends AbstractEventBusModuleService {
  // ...
  subscribe(
    eventName: string | symbol, 
    subscriber: EventBusTypes.Subscriber, 
    context?: EventBusTypes.SubscriberContext): this {
    // TODO implement subscription
  }
}

(optional) unsubscribe

As mentioned earlier, this method is already implemented in the AbstractEventBusModuleService class. This section explains how you can implement your custom unsubscribe logic if necessary.

The unsubscribe method is used to unsubscribe a handler function from an event.

The unsubscribe method accepts three parameters:

    The first parameter eventName is a required string. It indicates which event the handler function is unsubscribing from.
    The second parameter subscriber is a required function that was initially subscribed to the event.
    The third parameter context is an optional object that has the property subscriberId. It can be used to specify the ID of the subscriber to unsubscribe.

The implementation of this method depends on the service you’re using for the event bus:
services/event-bus-custom.ts

class CustomEventBus extends AbstractEventBusModuleService {
  // ...
  unsubscribe(
    eventName: string | symbol, 
    subscriber: EventBusTypes.Subscriber, 
    context?: EventBusTypes.SubscriberContext): this {
    // TODO implement subscription
  }
}

Step 3: Export the Service

After implementing the event bus service, you must export it so that the Medusa backend can use it.

Create the file index.ts with the following content:
services/event-bus-custom.ts

import { ModuleExports } from "@medusajs/modules-sdk"

import { CustomEventBus } from "./services"

const service = CustomEventBus

const moduleDefinition: ModuleExports = {
  service,
}

export default moduleDefinition

This exports a module definition, which requires at least a service. If you named your service something other than CustomEventBus, make sure to replace it with that.

You can learn more about what other properties you can export in your module definition in the Create a Module documentation.
Step 4: Test your Module

You can test your module in the Medusa backend by referencing it in the configurations.

To do that, add the module to the exported configuration in medusa-config.js as follows:
medusa-config.js

module.exports = {
  // ...
  modules: { 
    // ...
    eventBus: {
        resolve: "path/to/custom-module", 
        options: { 
          // any necessary options
        },
      },
    },
}

Make sure to replace the path/to/custom-module with a relative path from your Medusa backend to your module. You can learn more about module reference in the Create Module documentation.

You can also add any necessary options to the module.


How to Create a Subscriber

In this document, you’ll learn how to create a Subscriber in Medusa that listens to events to perform an action.
Tip

v1.18 of @medusajs/medusa introduced a new approach to create a subscriber. If you're looking for the old guide, you can find it here. However, it's highly recommended you follow this new approach, as the old one is deprecated.
Implementation

A subscriber is a TypeScript or JavaScript file that is created under src/subscribers. It can be created under subdirectories of src/subscribers as well. For example, you can place all subscribers to product events under the src/subscribers/products directory.

The subscriber file exports a default handler function, and the subscriber's configurations.

For example:
src/subscribers/product-update-handler.ts

import { 
  ProductService,
  type SubscriberConfig, 
  type SubscriberArgs, 
} from "@medusajs/medusa"

export default async function productUpdateHandler({ 
  data, eventName, container, pluginOptions, 
}: SubscriberArgs<Record<string, any>>) {
  const productService: ProductService = container.resolve(
    "productService"
  )

  const { id } = data

  const product = await productService.retrieve(id)

  // do something with the product...
}

export const config: SubscriberConfig = {
  event: ProductService.Events.UPDATED,
  context: {
    subscriberId: "product-update-handler",
  },
}

Subscriber Configuration

The exported configuration object of type SubscriberConfig must include the following properties:

    event: A string or an array of strings, each being the name of the event that the subscriber handler function listens to.
    context: An object that defines the context of the subscriber. It can accept any properties along with the subscriberId property. Learn more about the subscriber ID and the context object in this section.

Subscriber Handler Function

The default-export of the subscriber file is a handler function that is executed when the events specified in the exported configuration is triggered.

The function accepts a parameter of type SubscriberArgs, which has the following properties:

    data: The data payload of the emitted event. Its type is different for each event. So, make sure to check the events reference for the expected payload of the events your subscriber listens to. You can then pass the expected payload type as a type parameter to SubscriberArgs, for example, Record<string, string>.
    eventName: A string indicating the name of the event. This is useful if your subscriber listens to more than one event and you want to differentiate between them.
    container: The dependency container that allows you to resolve Medusa resources, such as services.
    pluginOptions: When the subscriber is created within a plugin, this object holds the plugin's options defined in the Medusa configurations.

Context with Subscriber ID

The context property of the subscriber configuration object is passed to the eventBusService. You can pass the subscriberId and any custom data in it.
Note

The subscriber ID is useful when there is more than one handler function attached to a single event or if you have multiple Medusa backends running. This allows the events bus service to differentiate between handler functions when retrying a failed one, avoiding retrying all subscribers which can lead to data inconsistencies or general unwanted behavior in your system.
Inferred Subscriber ID

If you don't pass a subscriber ID to the subscriber configurations, the name of the subscriber function is used as the subscriber ID. If the subscriber function is an anonymous function, the name of the subscriber file is used instead.
Caveats for Local Event Bus

If you use the event-bus-local as your event bus service, note the following:

    The subscriberId passed in the context is overwritten to a random ID when using event-bus-local. So, setting the subscriber ID in the context won't have any effect in this case.
    The eventName passed to the handler function will be undefined when using event-bus-local as it doesn't pass the event name properly.

Note

While the local event bus is a good option for development, it's highly recommended to use the Redis Event Module in production.
Retrieve Medusa Configurations

Within your subscriber, you may need to access the Medusa configuration exported from medusa-config.js. To do that, you can access configModule using dependency injection.

For example:
src/subscribers/product-update-handler.ts

import { 
  ProductService,
  type SubscriberConfig, 
  type SubscriberArgs,
  type ConfigModule, 
} from "@medusajs/medusa"

export default async function productUpdateHandler({ 
  data, eventName, container, pluginOptions, 
}: SubscriberArgs) {
  const configModule: ConfigModule = container.resolve(
    "configModule"
  )
  
  // ...
}

export const config: SubscriberConfig = {
  event: ProductService.Events.UPDATED,
  context: {
    subscriberId: "product-update-handler",
  },
}
Loaders

In this document, you’ll learn what loaders are in Medusa.
Overview

A loader is a script that runs when the Medusa backend starts. The Medusa backend uses loaders to initialize the database connection, load plugins, register resources in the dependency container, and more.

Loaders can be created within the Medusa backend codebase, in a plugin, or in a module to perform custom actions when the backend starts. The loader is created in a TypeScript or JavaScript file located in the src/loaders directory, then transpiled using the build command into the dist/loaders directory.
Loader Examples

For example, the Redis Event Bus module uses a loader to establish a connection with Redis and log a message in the console.

Another example is the Algolia plugin, which uses a loader to update the index settings when the Medusa backend starts based on the plugin’s options.

Loaders can be used to access the dependency container and register custom resources in it.

Loaders can also be used to create scheduled jobs that run at a specified interval of time.
How to Create a Loader

In this document, you’ll learn how to create a loader in Medusa. A loader can be created in the Medusa backend codebase, in a plugin, or in a module.
Step 1: Create Loader File

Create a TypeScript or JavaScript file in the src/loaders directory that will hold your custom script. There are no restrictions on the name of the file.

For example, create the file src/loaders/my-loader.ts that will hold the loader.
Step 2: Define the Loader

The loader file must export a function.
Parameters of Loaders in Medusa Backend and Plugins

When the loader is defined in the Medusa backend or a plugin, the function receives the following parameters:

    container: the first parameter, which is a MedusaContainer object. You can use the container to register custom resources into the dependency container or resolve resources from the dependency container.
    config: the second parameter, which is an object that holds the loader’s plugin options. If the loader is not created inside a plugin, the config object will be empty.

Parameters of Loaders in Modules

When the loader is defined in a module, it receives the following parameters:

    container: the first parameter, which is a MedusaContainer object. You can use the container to register custom resources into the dependency container or resolve resources from the dependency container.
    logger: the second parameter, which is a Logger object. The logger can be used to log messages in the console.
    config: the third parameter, which is an object that holds the loader’s module options.

Example Implementation

For example, this loader function resolves the ProductService and logs in the console the count of products in the Medusa backend:
src/loaders/my-loader.ts

import { 
  ProductService, 
  ConfigModule,
  MedusaContainer,
} from "@medusajs/medusa"

export default async (
  container: MedusaContainer,
  config: ConfigModule
): Promise<void> => {
  console.info("Starting loader...")
  const productService = container.resolve<ProductService>(
    "productService"
  )
  console.info(`Products count: ${
    await productService.count()
  }`)
  console.info("Ending loader...")
}
Notification Architecture Overview

This document gives an overview of the notification architecture and how it works.
Introduction

Medusa provides a Notification API to mainly handle sending and resending notifications when an event occurs. For example, sending an email to the customer when they place an order.

The Notification architecture is made up of two main components: the Notification Provider and the Notification. Simply put, the Notification Provider handles the sending and resending of a Notification.
Notification Provider

A Notification Provider is a provider that handles sending and resending of notifications. You can either create and integrate your own provider or install a Notification Provider through a third-party plugin.

An example of a notification provider is SendGrid. When an order is placed, the SendGrid plugin sends an email to the customer.
How Notification Provider is Created

A Notification Provider is essentially a Medusa Service with a unique identifier, and it extends the NotificationService provided by the medusa-interfaces package. It can be created as part of a Plugin, or it can be created just as a Service file in your Medusa backend.

As a developer, you mainly work with the Notification Provider when integrating a third-party service that handles notifications in Medusa.

When you run your Medusa backend, the Notification Provider is registered in your backend. If it's a new Notification Provider, it will be inserted into the notification_provider table in your database.
NotificationProvider Entity Overview

The NotificationProvider entity only has 2 attributes: id and is_installed.

id is the value of the static property identifier defined inside the notification Service class.

is_installed indicates whether the Notification Provider is installed or not. When you install a Notification Provider, the value of this attribute is true.

If you installed a Notification provider and then removed the Service files or plugin that registered the Notification Provider, the Notification Provider remains in your database, but the value of the is_installed field changes to false.
Notification

A notification is a form of an alert sent to the customers or users to inform them of an action that has occurred. For example, if an order is placed, the notification, in this case, can be an email that confirms their order and lists the order details.

Notifications can take on other forms such as an SMS or a Slack message.
How Notification is Created

Notifications are created in the NotificationService class in Medusa’s core after the Notification has been handled by the Notification Provider.

The data and additional details that the Notification Provider returns to the NotificationService is used to fill some of the attributes of the Notification in the database.

A Notification also represents a resent notification. So, when a notification is resent, a new one is created that references the original Notification as a parent. This Notification is also created by the NotificationService class.
Notification Entity Overview

The two most important properties in the Notification entity are the to and data properties.

The to property is a string that represents the receiver of the Notification. For example, if the Notification was sent to an email address, the to property holds the email address the Notification was sent to.

The to property can alternatively be a phone number or a chat username. It depends on the Notification Provider and how it sends the Notification.

The data property is an object that holds all the data necessary to send the Notification. For example, in the case of an order confirmation Notification, it can hold data related to the order.

The data property is useful when a notification is resent later. The same data can be used to resend the notification.

In the case of resent notifications, the resent notification has a parent_id set to the ID of the original Notification. The value of the parent_id property in the original Notification is null.

The Notification entity has some properties that determine the context of this Notification. This includes the event_name property which is the event that triggered the sending of this notification.

Additionally, the resource_type property is used to determine what resource this event is associated with. For example, if the event_name is order.placed, the resource_type is order.

You can also access the specific resource using the resource_id property, which is the ID of the resource. So, in case of the order.placed event, the resource_id is the ID of the order that was created.

The Notification entity also includes properties related to the receiver of the Notification. In case the receiver is a customer, the customer_id property is used to identify which customer.
Automating Flows with Notifications

With Medusa you can create notifications as a reaction to a wide spectrum of events, allowing you to automate communication and processes.

An example of a flow that can be implemented using Medusa's Notification API is automated return flows:

    A customer requests a return by sending a POST request to the /store/returns API Route.
    The Notification Provider listens to the order.return_requested event and sends an email to the customer with a return invoice and return label generated by the Fulfillment Provider.
    The customer returns the items triggering the return.received event.
    The Notification Provider listens to the return.received event and sends an email to the customer with confirmation that their items have been received and that a refund has been issued.


How to Create a Notification Provider

In this document, you’ll learn how to create a notification provider in the Medusa backend and the methods you must implement in it. Learn more about the notification architecture in this documentation
Overview
Prerequisites

Before creating a Notification Provider, install an event bus module.

A Notification Provider is a provider that handles sending and resending of notifications.

To create a Notification Provider, create a TypeScript or JavaScript file in src/services. The name of the file is the name of the provider (for example, sendgrid.ts). The file must export a class that extends the AbstractNotificationService class imported from @medusajs/medusa.

For example, create the file src/services/email-sender.ts 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

Identifier Property

The NotificationProvider entity has 2 properties: identifier and is_installed. The value of the identifier property in the notification provider 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 Loader.

For example:

class EmailSenderService extends AbstractNotificationService {
  static identifier = "email-sender"
  // ...
}

constructor

You can use the constructor of your notification provider to access the 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 backend and you want to access the options added for the plugin, you can access it in the constructor.
Example

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

class EmailSenderService extends AbstractNotificationService {
  // ...
  protected orderService: OrderService

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

    this.orderService = container.orderService

    // you can also initialize a client that
    // communicates with a third-party service.
    this.client = new Client(options)
  }

  // ...
}

export default EmailSenderService

Parameters
containerRecord<string, unknown>Required
An instance of MedusaContainer that allows you to access other resources, such as services, in your Medusa backend.
configRecord<string, unknown>
If this notification provider is created in a plugin, the plugin's options are passed in this parameter.
Methods
sendNotification

When an event is triggered that your Notification Provider is registered as a handler for, the NotificationService in the Medusa backend executes this method of your Notification Provider.

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

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,
        },
      }
    }
  }
  // ...
}

Parameters
eventstringRequired
The name of the event that was triggered. For example, order.placed.
dataunknownRequired
The data payload of the event that was triggered. For example, if the order.placed event is triggered, the eventData object contains the property id which is the ID of the order that was placed. You can refer to the Events reference for information on all events and their payloads.
attachmentGeneratorunknownRequired
If you’ve previously register an attachment generator to the NotificationService using the registerAttachmentGenerator method, you have access to it here. You can use the attachmentGenerator to generate on-demand invoices or other documents. The default value of this parameter is null.
Returns
PromisePromise<ReturnedData>Required
The sending details.
ReturnedDataReturnedDataRequired
The details of a sent or resent notification.
tostringRequired
The receiver of the Notification. For example, if you sent an email to the customer then to is the email address of the customer. In other cases, it might be a phone number or a username.
statusstringRequired
The status of the sent notification. There are no restriction on the returned status.
dataRecord<string, unknown>Required
The data used to send the Notification. For example, if you sent an order confirmation email to the customer, then the data object might include the order items or the subject of the email. This data is necessary if the notification is resent later as you can use the same data.
resendNotification

This method is used to resend notifications, which is typically triggered by the Resend Notification API Route.
Example

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 should be changed
    const to: string = 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, // make changes to the data
    }
  }
}

Parameters
notificationunknownRequired
The original Notification record that was created after you sent the notification with sendNotification. It includes the to and data attributes which are populated originally using the to and data properties of the object you return in sendNotification.
configunknownRequired
The new configuration used to resend the notification. The Resend Notification API Route, allows you to pass a new to field. If specified, it will be available in this config object.
attachmentGeneratorunknownRequired
f you’ve previously register an attachment generator to the NotificationService using the registerAttachmentGenerator method, you have access to it here. You can use the attachmentGenerator to generate on-demand invoices or other documents. The default value of this parameter is null.
Returns
PromisePromise<ReturnedData>Required
The resend details.
ReturnedDataReturnedDataRequired
The details of a sent or resent notification.
tostringRequired
The receiver of the Notification. For example, if you sent an email to the customer then to is the email address of the customer. In other cases, it might be a phone number or a username.
statusstringRequired
The status of the sent notification. There are no restriction on the returned status.
dataRecord<string, unknown>Required
The data used to send the Notification. For example, if you sent an order confirmation email to the customer, then the data object might include the order items or the subject of the email. This data is necessary if the notification is resent later as you can use the same data.
Subscribe with Loaders

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

For example, to register the email-sender Notification Provider as a handler for the order.placed event, create the file src/loaders/notification.ts with the following content:
src/loaders/notification.ts

import { 
  MedusaContainer, 
  NotificationService,
} from "@medusajs/medusa"

export default async (
  container: MedusaContainer
): Promise<void> => {
  const notificationService = container.resolve<
    NotificationService
  >("notificationService")

  notificationService.subscribe(
    "order.placed", 
    "email-sender"
  )
}

This loader accesses the notificationService through the MedusaContainer. The notificationService has a subscribe 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's subscribing to that event.
Test Sending a Notification

Make sure you have an event bus module configured in your Medusa backend. You can learn more on how to do that in the Configurations guide.

Then:

1. Run the build command in the root directory of your Medusa backend.

2. Start your Medusa backend.
3. Place an order either using the REST APIs or using the storefront.

4. 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 a Notification

To test resending a notification:

    Retrieve the ID of the notification you just sent using the List Notifications API Route. You can pass as a body parameter the to or event_name parameters to filter out the notification you just sent.

    Send a request to the Resend Notification API Route using the ID retrieved from the previous request. You can pass the to parameter in the body to change the receiver of the notification.

    You should see the message “Notification Resent” in your console.

AdminResetPasswordRequest

The details of the password reset request.
Properties
tokenstringRequired
The password-reset token generated when the password reset was requested.
passwordstringRequired
The User's new password.
emailstring
The User's email.