This is the official node.js module for sending notifications with node.js with the Courier REST API.
Courier docs • 3 Different Ways To Send Emails With Node.js
Installation (via npm)
npm install @trycourier/courier
Requirements
You will need to get a Courier API key to get started. You can sign up and create one for free at courier.com.
Getting Started
import { CourierClient } from "@trycourier/courier";
const courier = CourierClient({ authorizationToken: "<AUTH_TOKEN>" });
const { requestId } = await courier.send({
message: {
to: {
data: {
name: "Marty",
},
email: "marty_mcfly@email.com",
},
content: {
title: "Back to the Future",
body: "Oh my {{name}}, we need 1.21 Gigawatts!",
},
routing: {
method: "single",
channels: ["email"],
},
},
});
const { requestId } = await courier.send({
message: {
to: {
data: {
name: "Jenny",
},
phone_number: "8675309",
},
content: {
title: "Back to the Future",
body: "Oh my {{name}}, we need 1.21 Gigawatts!",
},
routing: {
method: "single",
channels: ["sms"],
},
},
});
const { requestId } = await courier.send({
message: {
to: [
{
user_id: "<USER_ID>",
email: "test@email.com",
data: {
name: "some user's name",
},
},
{
email: "marty@email.com",
data: {
name: "Marty",
},
},
{
email: "doc_brown@email.com",
data: {
name: "Doc",
},
},
{
phone_number: "8675309",
data: {
name: "Jenny",
},
},
],
content: {
title: "Back to the Future",
body: "Oh my {{name}}, we need 1.21 Gigawatts!",
},
routing: {
method: "all",
channels: ["sms", "email"],
},
},
});
const { requestId } = await courier.send({
message: {
template: "<TEMPLATE_OR_EVENT_ID>",
to: {
user_Id: "<USER_ID>",
email: "example@example.com",
phone_number: "555-228-3890",
},
data: {},
},
});
const { requestId } = await courier.send({
message: {
template: "<TEMPLATE_OR_EVENT_ID>",
to: {
list_id: "<LIST_ID>",
},
data: {},
},
});
const { requestId } = await courier.send({
message: {
template: "<TEMPLATE_OR_EVENT_ID>",
to: {
list_pattern: "<PATTERN>",
},
data: {},
},
});
const { requestId } = await courier.send({
message: {
to: [
{
list_pattern: "<PATTERN>",
},
{
list_id: "<LIST_ID>",
},
{
email: "test@email.com"
}
]
},
routing: {
method: "single",
channels: ["email"],
},
},
});
const { requestId } = await courier.send({
message: {
to: {
data: {
name: "Marty",
},
email: "marty_mcfly@email.com",
},
content: {
title: "Back to the Future",
body: "Oh my {{name}}, we need 1.21 Gigawatts!",
},
routing: {
method: "single",
channels: ["email"],
},
timeout: {
message: 3600000
},
},
});
const { requestId } = await courier.send({
message: {
to: {
data: {
name: "Marty",
},
email: "marty_mcfly@email.com",
},
content: {
title: "Back to the Future",
body: "Oh my {{name}}, we need 1.21 Gigawatts!",
},
routing: {
method: "single",
channels: ["email"],
},
metadata: {
trace_id: "ravenclaw-for-the-win"
},
},
});
Environment Variables
courier-node
supports credential storage in environment variables. If no authorizationToken
is provided when instantiating the Courier client (e.g., const courier = CourierClient();
), the value in the COURIER_AUTH_TOKEN
env var will be used.
If you need to use a base url other than the default https://api.courier.com, you can set it using the COURIER_BASE_URL
env var.
Advanced Usage
import { CourierClient } from "@trycourier/courier";
const courier = CourierClient({ authorizationToken: "<AUTH_TOKEN>" });
async function run() {
const { requestId } = await courier.send({
message: {
template: "<TEMPLATE_OR_EVENT_ID>",
to: {
user_id: "<RECIPIENT_ID>",
},
data: {},
brand_id: "<BRAND_ID>",
routing: {},
channels: {},
providers: {},
},
});
console.log(requestId);
const { requestId } = await courier.send({
message: {
template: "<TEMPLATE_OR_EVENT_ID>",
to: {...},
routing: {
method: "single",
channels: ["email"],
},
channels: {
email: {
routing_method: "all",
providers: ["sendgrid", "sns"],
metadata: {
utm: {
medium: "f",
campaign: "g",
},
},
},
},
providers: {
sns: {
metadata: {
utm: {
medium: "h",
},
},
},
},
metadata: {
utm: {
source: "a",
medium: "b",
campaign: "c",
},
},
timeout: {
message: 300000,
channel: {
email: 1000
}
}
},
});
const messageStatus = await courier.getMessage(requestId);
console.log(messageStatus);
const { results } = await courier.getMessageHistory(requestId);
console.log(results);
const { results } = await courier.getMessageOutput(requestId);
console.log(results);
const { paging, results } = await courier.getMessages();
console.log(results);
const { status: replaceStatus } = await courier.replaceProfile({
recipientId: "<RECIPIENT_ID>",
profile: {
email: "example@example.com",
},
});
console.log(replaceStatus);
const { status: mergeStatus } = await courier.mergeProfile({
recipientId: "<RECIPIENT_ID>",
profile: {
sms: "555-555-5555",
},
});
console.log(mergeStatus);
const { profile } = await courier.getProfile({
recipientId: "<RECIPIENT_ID>",
});
console.log(profile);
const { paging, results } = await courier.getBrands({
cursor: "<CURSOR>",
});
console.log(results);
const brand = await courier.getBrand("<BRAND_ID>");
console.log(brand);
const newBrand = await courier.createBrand({
name: "My Brand",
settings: {
colors: {
primary: "#0000FF",
secondary: "#FF0000",
tertiary: "#00FF00",
},
},
});
console.log(newBrand);
const replacedBrand = await courier.replaceBrand({
id: "<BRAND_ID>",
name: "My New Brand",
settings: {
color: {
primary: "#FF0000",
secondary: "#00FF00",
tertiary: "#0000FF",
},
},
});
console.log(replacedBrand);
await courier.deleteBrand("<BRAND_ID>");
const { paging, items } = await courier.lists.list({
cursor: "<CURSOR>",
});
console.log(items);
const list = await courier.lists.get("<LIST_ID>");
console.log(list);
const replacedList = await courier.lists.put("<LIST_ID>", {
name: "My New List",
});
console.log(replacedList);
await courier.lists.delete("<LIST_ID>");
await courier.lists.restore("<LIST_ID>");
const { paging, items } = await courier.lists.getSubscriptions("<LIST_ID>");
console.log(items);
await courier.lists.putSubscriptions("<LIST_ID>", [
{ recipientId: "RECIPIENT_ID_1" },
{ recipientId: "RECIPIENT_ID_2" },
]);
const { recipient } = courier.lists.subscribe("<LIST_ID>", "<RECIPIENT_ID>");
console.log(recipient);
await courier.lists.unsubscribe("<LIST_ID>", "<RECIPIENT_ID>");
const { paging, items } = await courier.lists.findByRecipientId(
"<RECIPIENT_ID>"
);
console.log(items);
await courier.preferences.put(recipientId, {
notifications: {
"<NOTIFICATION_ID>": { status: "<OPT_IN_STATUS>" },
},
});
const prefs = await courier.preferences.list();
console.log(prefs);
const profilePrefs = await courier.preferences.get(recipientId);
console.log(profilePrefs);
const { runId } = await courier.automations.invokeAdHocAutomation({
automation: {
cancelation_token: "I_AM_TOKEN",
steps: [
{
action: "send",
},
],
},
brand: "BRAND_ID",
data: {
example: "EXAMPLE_DATA",
},
profile: {
email: "foo@bar.com",
},
recipient: "RECIPIENT_ID",
template: "TEMPLATE_NAME_OR_ID",
});
console.log(runId);
const { runId } = await courier.automations.invokeAutomationTemplate({
templateId: "AUTOMATION_TEMPLATE_ID",
brand: "BRAND_ID",
data: {
example: "EXAMPLE_DATA",
},
profile: {
email: "foo@bar.com",
},
recipient: "RECIPIENT_ID",
template: "TEMPLATE_NAME_OR_ID",
});
console.log(runId);
const { paging, results } = await courier.notifications.list({});
console.log(results);
const { blocks, channels } = await courier.notifications.getContent(
"notification1"
);
console.log(blocks);
console.log(channels);
const { blocks, channels } = await courier.notifications.getDraftContent(
"notification1"
);
console.log(blocks);
console.log(channels);
await courier.notifications.postVariations("notification1", {
blocks: [
{
id: "block_1d4c32e0-bca8-43f6-b5d5-8c043199bce6",
type: "text",
locales: {
fr_FR: "block fr 1",
},
},
{
id: "block_6d50a6e3-ecc3-4815-bf51-0202c6bf54e2",
type: "text",
locales: {
fr_FR: "block fr 2",
},
},
],
channels: [
{
id: "channel_1ba46024-f156-4ed7-893b-cb1cdcfbd36e",
type: "email",
locales: {
fr_FR: {
subject: "French Subject",
},
},
},
{
id: "channel_2c2aad1c-30f0-4a55-8d8f-d213f32147bc",
type: "push",
locales: {
fr_FR: {
title: "French Title",
},
},
},
],
});
await courier.notifications.postDraftVariations("notification1", {
blocks: [
{
id: "block_1d4c32e0-bca8-43f6-b5d5-8c043199bce6",
type: "text",
locales: {
fr_FR: "block fr 1",
},
},
{
id: "block_6d50a6e3-ecc3-4815-bf51-0202c6bf54e2",
type: "text",
locales: {
fr_FR: "block fr 2",
},
},
],
channels: [
{
id: "channel_1ba46024-f156-4ed7-893b-cb1cdcfbd36e",
type: "email",
locales: {
fr_FR: {
subject: "French Subject",
},
},
},
{
id: "channel_2c2aad1c-30f0-4a55-8d8f-d213f32147bc",
type: "push",
locales: {
fr_FR: {
title: "French Title",
},
},
},
],
});
const { checks } = await courier.notifications.getSubmissionChecks(
"notification1",
"submission1"
);
console.log(checks);
const { checks } = await courier.notifications.putSubmissionChecks(
"notification1",
"submission1",
{
checks: [
{
id: "check1",
status: "RESOLVED",
type: "custom",
},
],
}
);
console.log(checks);
await courier.notifications.cancelSubmission("notification1", "submission1");
const response = await courier.bulk.createJob({
message: {
event: "RR4NDQ7NZ24A8TKPWVBEDGE15E9A",
},
});
console.log(response);
const response = await courier.bulk.createJob({
message: {
message: {
template: "RR4NDQ7NZ24A8TKPWVBEDGE15E9A",
},
},
});
console.log(response);
const response = await courier.bulk.getJob({
jobId: "1-61efe386-6ff57552409e311b7a1f371f",
});
console.log(response);
const response = await courier.bulk.ingestUsers({
jobId: "1-61efe386-6ff57552409e311b7a1f371f",
users: [
{
profile: {
email: "tejas@courier.com",
},
},
],
});
console.log(response);
const response = await courier.bulk.ingestUsers({
jobId: "1-61efe386-6ff57552409e311b7a1f371f",
users: [
{
to: {
email: "tejas@courier.com",
},
},
],
});
console.log(response);
await courier.bulk.runJob({
jobId: "1-61efe386-6ff57552409e311b7a1f371f",
});
const response = await courier.bulk.getJobUsers({
jobId: "1-61efe386-6ff57552409e311b7a1f371f",
});
console.log(response);
}
run();
Idempotency
For POST
methods, you can supply an idempotencyKey
in the config parameter to ensure the idempotency of the API Call. We recommend that you use a V4 UUID
for the key. Keys are eligible to be removed from the system after they're at least 24 hours old, and a new request is generated if a key is reused after the original has been removed. For more info, see Idempotent Requests in the Courier documentation.
import { CourierClient } from "@trycourier/courier";
import uuid4 from "uuid4";
const courier = CourierClient();
const idempotencyKey = uuid4();
async function run() {
const { requestId } = await courier.send(
{
template: "<TEMPLATE_OR_EVENT_ID>",
to: {
user_id: "<USER_ID>",
email: "example@example.com",
phone_number: "555-867-5309",
},
data: {
world: "JavaScript!",
},
},
{
idempotencyKey,
}
);
console.log(requestId);
}
run();
Audiences
Audiences APIs are used to create, get, update, and delete audiences. A Courier Audience is a dynamic group of users (created using Courier's Profile API) that matches a set of criteria. Audience is reactive to changes in the user's profile. As you change user profile using profiles
API, the audience will be updated accordingly. You will not have to maintain a list of users in your audience. Courier takes care of that for you. If you have potentially large set of users, you first create an audience and then use the audience's id to retrieve the list of users. Once you satified with the calculated list of users, you can use the audienceId
to send notification using send
API.
const { audienceId } = await courier.audiences.put({
id: "<AUDIENCE_ID>",
filter: {
operator: "EQ",
path: "title",
value: "Software Engineer",
},
});
const { items: audienceMembers } = await courier.audiences.listMembers(
audienceId
);
const { requestId } = await courier.send({
message: {
template: "<TEMPLATE_OR_EVENT_ID>",
to: {
audience_id: audienceId,
},
data: {},
brand_id: "<BRAND_ID>",
routing: {},
channels: {},
providers: {},
},
});
License
MIT License
Author
Courier (support@courier.com)