Subscribers
In Novu, we call the entities designed to receive notifications as Subscribers
. Each subscriber is unique and identified by a unique subscriber ID.
subscriberId
is a unique identifier used by Novu to keep track of a specific subscriber.
We recommend using the internal unique id your application uses for a specific user.
Each subscriber has the following data points:
- User Data - Data stored in the subscriber object that you can easily access in your notification templates. This contains basic info such as first name, last name, avatar, locale, email, and phone. This data is fixed and structured.
- Custom Data - Apart from the above fixed structured user data, any unstructured custom data such as user’s address, nationality, height, etc can also be stored in the
data
field using key-value pairs. - Channel Specific Credentials -
deviceTokens
required to send push notifications andwebhookUrl
for chat channel providers can also be stored.
Subscriber attributes
Field | Type | Required | Example |
---|---|---|---|
subscriberId | string | true | b0bea066-f5fe-11ed-b67e-0242ac120002 |
firstName | string | false | John |
lastName | string | false | Doe |
string | false | john.doe@domain.org. | |
phone | string | false | +13603963366 |
locale | string | false | en |
avatar | string | false | https://example.com/images/avatar.jpg |
data | object | false | {"key": "value"} |
Subscriber response schema
Novu subscriber object
{
"_id": "NOVU_GENERATED_SUBSCRIBER_ID",
"_organizationId": "NOVU_GENERATED_ORG_ID",
"_environmentId": "NOVU_GENERATED_ENV_ID",
"firstName": "John",
"lastName": "Doe",
"subscriberId": "subscriberId",
"email": "[john.doe@org.com](mailto:john.doe@org.com)",
"phone": "+98712345670"
"data": {
"custome_key_1" : "custom_value_1",
"custome_key_2" : "custom_value_2"
}
"channels": [
{
"credentials": {
"deviceTokens": [
"token1",
"token2"
]
},
"_integrationId": "NOVU_GENERATED_INTEGRATION_ID",
"providerId": "fcm"
},
{
"credentials": {
"webhookUrl": "URL"
},
"_integrationId": "NOVU_GENERATED_INTEGRATION_ID",
"providerId": "discord"
}
],
"deleted": false,
"createdAt": "2022-10-13T17:40:53.231Z",
"updatedAt": "2022-10-13T17:41:53.238Z",
"__v": 0,
"isOnline": false,
"lastOnlineAt": "2022-10-13T17:41:53.238Z",
"avatar": "AVATAR_URL",
"id": "NOVU_GENERATED_SUBSCRIBER_ID"
}
Create a subscriber
You can create a subscriber in Novu using the identify
method provided in Novu’s SDK.
identify
method serves the purpose of handling existing “subscriberId” providers within the database.
When a provider with the same subscriberId already exists, this method performs an update operation using the data present in the payload.
In cases where there is no pre-existing entry, the method generates a new one, thus exhibiting an upsertA combination of the words “update” and “insert”
behavior.import { Novu } from "@novu/node";
// Insert your Novu API Key here
const novu = new Novu("YOUR_NOVU_API_KEY_HERE");
// Create a subscriber on Novu
await novu.subscribers.identify("132", {
email: "john.doe@domain.com",
firstName: "John",
lastName: "Doe",
phone: "+13603963366",
});
phone
parameter must be parsed as a string.You should now be able to see your new subscriber on the Novu dashboard.
You can also add additional fields such as phone
, avatar
, and data
.
If you face issues with the subscriber creation only taking the user ID and omitting other fields such as firstName, lastName, etc., you could consider updating the subscriber after creation.
Please also be aware that although it’s currently possible to create a subscriber with an empty subscriberId
, this subscriber cannot be deleted later.
We support creating new subscriber using two ways, Ahead of Trigger
means adding subscribers before triggering notification or Inline of Trigger
means sending complete subscriber data in to
field while triggering.
1. Ahead of Trigger
Create the subscriber and then trigger the notification to this subscriber. Here subscriberId
is the required field and other fields are optional.
Node.js
PHP
import { Novu } from '@novu/node';
const novu = new Novu('<NOVU_API_KEY>');
await novu.subscribers.identify('111', {
email: 'john.doe@domain.com',
firstName: 'John',
lastName: 'Doe',
phone: '+13603963366',
avatar: 'https://example.com/images/avatar.jpg',
locale: 'en',
data: { customKey1: 'customVal1', customKey2: 'customVal2' },
});
Novu will create a subscriber if one does not exist and will update the existing subscriber based on the identify
payload. You can call this function during registration or signup to make sure the subscriber data is up-to-date, if you wish to save additional attributes with a subscriber, you can pass additional custom data in the data field as key-value pairs.
2. Inline of Trigger
A non-existing subscriber can be added by sending subscriber data in to
field of the trigger method. If any subscriber with provided subscriberId
does not exists, a new subscriber will be created. In this case, subscriber will be created first and then the trigger will be executed synchronously.
Node.js
PHP
import { Novu } from '@novu/node';
const novu = new Novu('<NOVU_API_KEY>');
await novu.trigger('<TEMPLATE_IDENTIFIER>', {
to: {
subscriberId: '111',
email: 'john.doe@domain.com',
firstName: 'John',
lastName: 'Doe',
phone: '+13603963366',
},
payload: {
customVariable: 'variableValue',
organization: {
logo: 'https://organisation.com/logo.png',
},
},
});
Bulk Subscriber Creation
You can create subscribers in bulk (up to 500 at once) via the SDKs or API.
Node.js
await novu.subscribers.bulkCreate([
{
subscriberId: 'test-subscriber-1',
email: 'test-user@sd.com',
firstName: 'subscriber-1',
lastName: 'test-1',
},
{
subscriberId: 'test-subscriber-2',
email: 'test-user-2@sd.com',
firstName: 'subscriber-2',
lastName: 'test-2',
},
{
subscriberId: 'test-subscriber-3',
},
]);
Import subscribers
Here, mock_data.csv
file is a CSV file having mock data. The below script will read this CSV file and create a new subscriber in Novu. Change example variables values like API_KEY
value with your valid values. Download mock_data.csv
file from here.
mock_data.csv
file should be in the same directory of script Steps:
- Export your user details in CSV format.
- Clean this exported CSV file. Keep only relevant fields.
- Move this CSV file to the script directory.
- Change the file name in the script with your file name.
- Run the script. (Make script.sh executable before using)
Shell
Node.js
#!/bin/bash
# Change these variables with your own values
CSV_FILE="mock_data.csv"
API_ENDPOINT="https://api.novu.co/v1/subscribers"
API_KEY="ApiKey <API_KEY>"
OLDIFS=$IFS
IFS=','
[ ! -f $CSV_FILE ] && { echo "$CSV_FILE file not found"; exit 99; }
SECONDS=0
# Read the CSV file line by line
while read subscriberId firstName lastName email phone locale avatar
do
# Check if subscriberId is empty or not present
if [[ -z "$subscriberId" ]]; then
echo "Skipping row with missing subscriberId"
continue
fi
# Construct the JSON body for the POST request
json_body="{\"subscriberId\": \"$subscriberId\""
# Add optional fields to the JSON body if present
if [[ -n "$firstName" ]]; then
json_body="$json_body, \"firstName\": \"$firstName\""
fi
if [[ -n "$lastName" ]]; then
json_body="$json_body, \"lastName\": \"$lastName\""
fi
if [[ -n "$email" ]]; then
# Validate email using regex
if [[ ! "$email" =~ ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$ ]]; then
echo "Invalid email format for subscriberId: $subscriberId"
continue
fi
json_body="$json_body, \"email\": \"$email\""
fi
if [[ -n "$phone" ]]; then
json_body="$json_body, \"phone\": \"$phone\""
fi
if [[ -n "$locale" ]]; then
# Validate locale using regex
if [[ ! "$locale" =~ ^[a-zA-Z]{2}(-[a-zA-Z]{2})?$ ]]; then
echo "Invalid locale format for subscriberId: $subscriberId"
continue
fi
json_body="$json_body, \"locale\": \"$locale\""
fi
if [[ -n "$avatar" ]]; then
json_body="$json_body, \"avatar\": \"$avatar\""
fi
if [[ -n "$address" || -n "$job" ]]; then
json_body="$json_body, \"data\": {"
if [[ -n "$address" ]]; then
json_body="$json_body \"address\": \"$address\""
else
json_body="$json_body \"address\": \"\""
fi
if [[ -n "$job" ]]; then
json_body="$json_body, \"job\": \"$job\""
else
json_body="$json_body, \"job\": \"\""
fi
json_body="$json_body }"
fi
json_body="$json_body}"
echo $json_body
#Send the cURL POST request with the JSON body and handle exceptions
response=$(curl -s -X POST -H "Content-Type: application/json" -H "Authorization: $API_KEY" -d "$json_body" -w "%{http_code}" "$API_ENDPOINT")
http_code=${response:${#response}-3}
if [[ $http_code -eq 201 ]]; then
echo "cURL request successful for subscriberId: $subscriberId - HTTP Status Code: $http_code"
else
echo "cURL request failed for subscriberId: $subscriberId - HTTP Status Code: $http_code - response : $response"
fi
done < "$CSV_FILE"
ELAPSED="Time Elapsed: $(($SECONDS / 3600))hrs $((($SECONDS / 60) % 60))min $(($SECONDS % 60))sec"
echo $ELAPSED
Delete a subscriber
To stop a subscriber from receiving notifications, you can delete the subscriber. This will hard delete the subscriber and means you will not be able to access this subscriber later. You will have to create this subscriber again.
Node.js
PHP
import { Novu } from '@novu/node';
const novu = new Novu('<NOVU_API_KEY>');
await novu.subscribers.delete('111');
Update a subscriber
In some cases, you want to access a subscriber to update a specific user data field or custom data field. For example, when the users change their email address or personal details.
Node.js
PHP
import { Novu } from '@novu/node';
const novu = new Novu('<NOVU_API_KEY>');
await novu.subscribers.update('111', {
// new email
email: 'john@domain.com',
// new phone
phone: '+19874567832',
});
Find a subscriber
Any subscriber can be retrieved using a unique subscriber identifier subscriberId
. Check the returned subscriber schema here.
Node.js
PHP
import { Novu } from '@novu/node';
const novu = new Novu('<NOVU_API_KEY>');
await novu.subscribers.get('111');