Novu offers a simple API providing an easy interface for triggering notifications to multiple subscribers at once. It is called Topics and allows the users to manage their bulk notifications without having to do complex loop implementations. A topic is identified by a custom key that is provided by the user. This custom key will be the identifier for the topic.

The topic key should be unique and can’t be changed once chosen. Novu also safe guards for key uniqueness behind the scenes.

Users can also assign a name to a topic. This name doesn’t need to be unique and it can be changed using the API. So far, it is for descriptive goals.

A topic would get assigned different subscribers that will receive a notification every time a notification is sent to the topic.

Create A Topic

In order to be able to send a notification to a topic, first the user needs to create one. It can be done like this:

import { Novu } from "@novu/node";

const novu = new Novu("<NOVU_API_KEY>");

const result = await novu.topics.create({
  key: "unique-topic-identifier",
  name: "descriptive-topic-name",
});

If successful this will return the internal Id generated by Novu and the topic key given by the user.

That topic key can be used to retrieve the whole Topic entity:

import { Novu } from "@novu/node";

const novu = new Novu("<NOVU_API_KEY>");

const key = "unique-topic-identifier";

const result = await novu.topics.get(key);

Rename a Topic

Descriptive name given during creation of topic can be changed later. This can be done like this:

import { Novu } from "@novu/node";

const novu = new Novu("<NOVU_API_KEY>");

const topicKey = "posts:comment:12345";
const topicName = "Post Comments";

const result = await novu.topics.rename(topicKey, topicName);

This will return the whole Topic information, including the subscribers if having any.

Topic Key can not be changed

Add subscribers to a Topic

Adding subscribers to the topic is the main usecase of topic. A topic is like a group of subscribers. A notification can be sent to all subscribers of a topic at once

Before adding subscribers to a topic, it’s crucial to ensure that they are correctly identified in the Novu system. This identification is done using the identify method or API. When a subscriber is added to a topic, Novu uses the identification information to pick up the email or phone number associated with the subscriber.

import { Novu } from '@novu/node';

const novu = new Novu("<NOVU_API_KEY>");

const topicKey = 'posts:comment:12345';

const response = await novu.topics.addSubscribers(topicKey, {
  subscribers: ['subscriber-id-1', 'subscriber-id-2', ...],
});

This call will return a response in the shape of:

{
    succeeded: ['subscriber-id-1', 'subscriber-id-2', ...],
    failed: {
      notFound: ['subscriber-id-1', 'subscriber-id-2', ...],
    },
}

The field succeeded will return the array of subscriber ids that have been correctly assigned to the topic. The field failed will show up only if there has been any subscriber that couldn’t been assigned to the topic. This probably will happen if there is any typo in the given subscriberId or if the given subscriberId doesn’t belong to the environment and the organization where the topic has been created.

Create topic on the fly

To facilitate flows we allow to create a topic on the fly when adding subscribers.

If the topic key used does not exist for the selected environment and organization, Novu will create a new topic with name Autogenerated-<TOPIC_KEY> and the subscribers will be assigned to this newly created topic.

After that, that topic created on the fly can be managed in the same ways as the ones created in the normal way.

Verify if subscriberId belongs to a topic

There would be times when it would be needed to verify if a certain subscriber belongs to a topic in order to decide what to do with that subscriber. The API call to achieve that is the following:

import { Novu } from "@novu/node";

const novu = new Novu("<NOVU_API_KEY>");

const externalSubscriberId = "external-subscriber-id-1";
const topicKey = "posts:comment:12345";

const response = await novu.topics.getSubscriber(
  topicKey,
  externalSubscriberId
);

The subscriberId to use in this API call is the one used as subscriber identifier. The choice was made to make easier for the user to use this without making extra calls to Novu.

Remove a subscriber from a Topic

A single or group of subscribers can be removed from an existing topic.

import { Novu } from '@novu/node';

const novu = new Novu("<NOVU_API_KEY>");

const topicKey = 'posts:comment:12345';

const response = await novu.topics.removeSubscribers(topicKey, {
  subscribers: ['subscriber-id-1', 'subscriber-id-2', ...],
});

Where subscribers will be an array of the subscriberIds we want to remove from the topic. If successful an empty response will be returned.

Delete a topic

An existing topic can be deleted using topic-key as topic-key is the unique identifier for a topic.

import { Novu } from "@novu/node";

const novu = new Novu("<NOVU_API_KEY>");

const key = "unique-topic-identifier";

const result = await novu.topics.delete(key);

A topic can only be deleted if it doesn’t have any subscriber added. When trying to delete a topic with subscribers a conflict error will be returned. This is done to prevent accidental topic deletions.

Trigger workflow to a topic

A workflow can be triggered to a single subscriber and an array of subscribers. While doing so, one need to send subscriberIds in to field. In case of trigger, we have already stored subscriberIds in a topic, so a topic key can be used to trigger a workflow. Workflow will be triggered to all subscribers in the topic.

const topicKey = "posts:comment:12345";

await novu.trigger("<WORKFLOW_TRIGGER_IDENTIFIER>", {
  to: [{ type: "Topic", topicKey: topicKey }],
  payload: {},
});

Trigger workflow to multiple topics

Workflow can be triggered to multiple subscribers by using an array of topics.

const topicKey = "<TOPIC-KEY-DEFINED-BY-THE-USER>";

await novu.trigger("<WORKFLOW_TRIGGER_IDENTIFIER>", {
  to: [
    { type: "Topic", topicKey: topicKey },
    { type: "Topic", topicKey: "Another Topic Key" },
  ],
  payload: {},
});

Exclude actor from topic trigger event

To exclude the actor responsible for the action of a triggered topic event, you must add the subscriberId of that actor when triggering that event.

const topicKey = "posts:comment:12345";

await novu.trigger("<WORKFLOW_TRIGGER_IDENTIFIER>", {
  to: [{ type: "Topic", topicKey: topicKey }],
  payload: {},
  actor: { subscriberId: "<SUBSCRIBER_ID_OF_ACTOR>" },
});

Usecase Example

User X makes a comment, other users (A, B) who’ve already commented before should get a notification. So, when triggering the notification on that topic, you would usually want to exclude User X from receiving a notification about their own comment. To do that - you would need to add User X’s subscriberId to the trigger event.

API

Frequently Asked Questions