New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

magicbell

Package Overview
Dependencies
Maintainers
1
Versions
40
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

magicbell

MagicBell API wrapper

  • 0.2.0
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
5.9K
decreased by-28.66%
Maintainers
1
Weekly downloads
 
Created
Source

MagicBell Node.js Library

This package provides a convenient interface to query the MagicBell API. Note that as some methods depend on your secret key, this SDK is not to be used in browsers.

Note

This package is in early release and is subject to change. TypeScript is supported, but api responses are untyped at the moment. We'll add types before we reach v1.0.0.

Requirements

Node 14 or higher.

Installation

Install the package with npm:

npm install magicbell --save

or yarn:

yarn add magicbell

Usage

The package needs to be configured with your project's secret key & api key, which are available in the MagicBell Dashboard.

import MagicBell from 'magicbell';

const magicbell = new MagicBell({
  apiKey: 'your-api-key',
  apiSecret: 'your-api-secret',
});

try {
  const notification = await magicbell.notifications.create({
    title: 'Sweet!',
    content: 'When you see it, you know it!',
    recipients: [{ email: 'customer@example.com' }],
  });
  console.log(notification.id);
} catch (error) {
  console.error(error);
}

or go old-school with require and promises:

const MagicBell = require('magicbell').default;

const magicbell = new MagicBell({
  apiKey: 'your-api-key',
  apiSecret: 'your-api-secret',
});

magicbell.notifications
  .create({
    title: 'Sweet!',
    content: 'When you see it, you know it!',
    recipients: [{ email: 'customer@example.com' }],
  })
  .then((notification) => console.log(notification.id))
  .catch((error) => console.error(error));

Some endpoints, like notifications.list are user oriented, and require the userEmail option to be set. This can be done via the client options, or on a per-request basis:

const magicbell = new MagicBell({
  apiKey: 'your-api-key',
  apiSecret: 'your-api-secret',
  userEmail: 'you@example.com',
});

const notification = await magicbell.notifications.list();

// alternatively, provide the userEmail via request option instead
const notification = await magicbell.notifications.list({
  userEmail: 'someone@example.com',
});

Note that every resource method accepts an optional options object, which can be used to override client defaults and pass additional options to the request.

This can for example be used to fetch notification preferences for specific users:

const johnsPreferences = await magicbell.notificationPreferences.list({
  userEmail: 'john@example.com',
});

const janesPreferences = await magicbell.notificationPreferences.list({
  userEmail: 'jane@example.com',
});

Using Promises

Every method returns a promise.

const user = await magicbell.users.create({
  email: 'person@example.com',
  first_name: 'Person',
  last_name: 'Doe',
});

List methods return iterable promises and the response can be handled in different ways:

standard promise - this method requires manual iteration to fetch multiple pages.

const firstPage = await magicbell.notifications.list();
// firstPage: { page: 1, total_pages: 5, notifications: [{ id: '…', title: '…', … }, …], … }
const nextPage = await magicbell.notifications.list({ page: firstPage.current_page + 1 });

async iterator - this iterates over all items across multiple pages. Call break when you wish to step out of the iteration / auto fetching.

for await (const notification of magicbell.notifications.list()) {
  console.log(notification.title);
  // break to abort and stop fetching/iterating
  if (shouldStop()) break;
}

forEach - similiar to the iterator, but in a callback style fashion. Return false when you wish to step out of the iteration / auto fetching.

await magicbell.notifications.list().forEach((notification) => {
  console.log(notification.title);
  // return false to abort and stop fetching/iterating
  if (shouldStop()) return false;
});

toArray - all items across multiple pages are fetched and returned in a single array. This method cannot be cancelled half way, and requires a limit to be set to prevent your process from running out of memory. Use the iterators above if you need to fetch lots of data.

const notifications = await magicbell.notifications.list().toArray({ limit: 1000 });

Configuration

Initialize with config object

The package can be initialized with several options:

import MagicBell from 'magicbell';

const magicbell = new MagicBell({
  host: 'https://api.magicbell.com',

  // auth
  apiKey: 'your-api-key', // required
  apiSecret: 'your-secret-key', // required for project oriented endpoints
  userEmail: 'you@example.com', // required for user oriented endpoints

  // network
  timeout: 30_000,
  maxRetries: 3,
  maxRetryDelay: 60,
  telemetry: true,

  // logging
  debug: false,
});
Options
  • host String

    The current refresh token.

  • apiKey String

    Your project api key which can be found on the MagicBell Dashboard. This key is required for all calls.

  • apiSecret String

    Your project api secret which can be found on the MagicBell Dashboard. This key is required for project oriented endpoints.

  • userEmail String

    The email of the user you want to make requests for. This key is required for user oriented endpoints, but can also be provided on a per request basis. You only want to provide it to the client, if you're using the SDK for a single user/inbox.

  • timeout Number

    A network timeout in milliseconds. Defaults to 30 seconds. Network requests will be canceled if they take longer than this.

  • maxRetries Number

    The maximum number of times to retry a request. Defaults to 3. Set to 0 to disable retries.

  • maxRetryDelay Number

    The maximum time in milliseconds to wait between retry requests. Note that subsequent retries can have a longer total duration than this. Defaults to 60 seconds.

  • telemetry Boolean

    Each request - after the first - includes a header with the response time of the previous request. This helps us to improve the performance of the API. You can opt out of this by setting this option to false.

Configuring Timeout

Timeout can be set globally via the config object:

const magicbell = new MagicBell({
  // ...
  timeout: 20_000, // 20 seconds
});

And overridden on a per-request basis:

magicbell.notifications.create(
  { title: 'Hi there!' },
  { timeout: 1_000 }, // 1 second
);

Configuring for users

A per-request userEmail header can be added to any method. Note that we'll automatically add a userKey containing the HMAC, if you've provided the apiSecret option.

// List the notifications for a specific account
magicbell.notifications.list({ page: 1 }, { userEmail: 'person@example.com' });

Network retries

Automatic network retries can be configured with the maxRetries option. This will retry network requests - with an exponential backoff - when it makes sense to retry them. For example, a request that failed due to a network error will be retried, but a request that failed due to an invalid API key or incorrect data will not.

note: automatic retries are meant to handle short network disturbances. They're handled in-process, and don't use a persistent job queue. They won't survive process restarts. You might need to implement your own persistent workers with retry logic if delivery is crucial to your business.

We'll automatically add idempotency keys if you haven't provided on, to prevent duplication.

A request that was retried, will take longer, but looks exactly the same as a direct success to the caller. The caller will not be notified that a request was retried.

const magicbell = new MagicBell({
  maxRetries: 2, // Retry a request twice before giving up
});

Network retries can also be set on a per-request basis:

magicbell.notifications.create(
  { recipients: [{ email: 'person@example.com' }] },
  { maxRetries: 2 }, // Retry this specific request twice before giving up
);

Using in a package

If you're wrapping our SDK, or using it in a specific app, we'd appreciate it if you instantiated your MagicBell client with appInfo, eg;

const magicbell = new MagicBell({
  apiKey: '...',
  appInfo: {
    name: 'MyAwesomePlugin',
    version: '1.2.34', // Optional
    url: 'https://myawesomeplugin.info', // Optional
  },
});

Request latency telemetry

By default, the library sends request latency telemetry to MagicBell. These numbers help us to improve the overall latency of our API for all users.

You can disable this behavior if you prefer:

const magicbell = new MagicBell({
  telemetry: false,
});

Resource methods

Below you'll find the all supported resource methods, with their signatures. The full documentation can be found in our api-reference. When comparing the api-reference with these methods, you'll notice that the SDK removes any wrapping entities for your convenience. Meaning, instead of posting { notification: { title: 'hi' } }, you'll call create({ title: 'hi' }).

Apart from the removal of the wrappers, returned entities and provided parameters are identical between our REST API and this SDK.

Notifications

Create notifications

Send a notification to one or multiple users. You can identify users by their email address or by an external_id.

You don't have to import your users into MagicBell. If a user does not exist we'll create it automatically.

You can send user attributes like first_name, custom_attributes, and more when creating a notification.

The new notification will be shown in the notification inbox of each recipient in real-time. It will also be delivered to each recipient through all channels your have enabled for your MagicBell project.

await magicbell.notifications.create({
  title: "We're processing your order",
  content: "<p>Thank you for your order. We'll notify you when these items are ready.</p>",
  category: 'order_created',
  topic: 'order:33098',
  recipients: [
    {
      email: 'dan@example.com',
    },
    {
      external_id: '83d987a-83fd034',
      first_name: 'Hana',
      last_name: 'Mohan',
      custom_attributes: {
        plan: 'enterprise',
        pricing_version: 'v10',
        preferred_pronoun: 'She',
      },
      phone_numbers: ['+15005550001'],
    },
    {
      matches: 'custom_attributes.order.id = 88492',
    },
  ],
  overrides: {
    email: {
      title: "[MagicBell] We're processing your order",
      content:
        "Thank you for your order. If you need help, or have any questions please don't hesitate to reach out to us directly at hello@magicbell.com",
    },
  },
});
Fetch notifications

Fetch a user's notifications. Notifications are sorted in descendent order by the sent_at timestamp.

await magicbell.notifications.list(
  {
    per_page: 1,
    page: 1,
    read: true,
    seen: true,
    archived: true,
    categories: ['…'],
    topics: ['…'],
  },
  {
    userEmail: 'person@example.com',
  },
);
Fetch a notification

Fetch a user's notification by its ID.

await magicbell.notifications.get('{notification_id}', {
  userEmail: 'person@example.com',
});
Delete a notification

Delete a user's notification by its ID. The notification is deleted immediately and removed from the user's notification inbox in real-time.

await magicbell.notifications.delete('{notification_id}', {
  userEmail: 'person@example.com',
});
Mark a notification as read

Mark a user notification as read. The notification will be automatically marked as seen, too.

The new state will be reflected in the user's notification inbox in real-time.

await magicbell.notifications.markAsRead('{notification_id}', {
  userEmail: 'person@example.com',
});
Mark a notification as unread

Mark a user notification as unread. The new state will be reflected in the user's notification inbox in real-time.

await magicbell.notifications.markAsUnread('{notification_id}', {
  userEmail: 'person@example.com',
});
Archive a notification

Mark a user notification as archived.

await magicbell.notifications.archive('{notification_id}', {
  userEmail: 'person@example.com',
});
Unarchive a notification

Mark a user notification as unarchived.

await magicbell.notifications.unarchive('{notification_id}', {
  userEmail: 'person@example.com',
});
Mark all notifications as read

Mark all notifications of a user as read. When you call this endpoint, the notification inboxes of this user will be updated in real-time.

await magicbell.notifications.markAllRead(
  {
    archived: true,
    read: true,
    seen: true,
    categories: ['…'],
    topics: ['…'],
  },
  {
    userEmail: 'person@example.com',
  },
);
Mark all notifications as seen

Mark all notifications of a user as seen. When you call this endpoint, the notification inboxes of this user will be updated in real-time.

await magicbell.notifications.markAllSeen(
  {
    archived: true,
    read: true,
    seen: true,
    categories: ['…'],
    topics: ['…'],
  },
  {
    userEmail: 'person@example.com',
  },
);

Users

Create a user

Create a user. Please note that you must provide the user's email or the external id so MagicBell can uniquely identify the user.

The external id, if provided, must be unique to the user.

await magicbell.users.create({
  external_id: '56780',
  email: 'hana@supportbee.com',
  first_name: 'Hana',
  last_name: 'Mohan',
  custom_attributes: {
    plan: 'enterprise',
    pricing_version: 'v10',
    preferred_pronoun: 'She',
  },
  phone_numbers: ['+15005550001'],
});
Update a user

Update a user's data. If you identify users by their email addresses, you need to update the MagicBell data, so this user can still access their notifications.

await magicbell.users.update('{user_id}', {
  email: 'hana@magicbell.io',
});
Delete a user

Immediately deletes a user.

await magicbell.users.delete('{user_id}');
Update a user by email

Update a user's data. If you identify users by their email addresses, you need to update the MagicBell data, so this user can still access their notifications.

await magicbell.users.updateByEmail('{user_email}', {
  external_id: '56780',
  email: 'hana@supportbee.com',
  first_name: 'Hana',
  last_name: 'Mohan',
  custom_attributes: {
    plan: 'enterprise',
    pricing_version: 'v10',
    preferred_pronoun: 'She',
  },
  phone_numbers: ['+15005550001'],
});
Delete a user by email

Immediately deletes a user.

await magicbell.users.deleteByEmail('{user_email}');
Update a user by external ID

Update a user's data. If you identify users by their email addresses, you need to update the MagicBell data, so this user can still access their notifications.

await magicbell.users.updateByExternalId('{external_id}', {
  external_id: '56780',
  email: 'hana@supportbee.com',
  first_name: 'Hana',
  last_name: 'Mohan',
  custom_attributes: {
    plan: 'enterprise',
    pricing_version: 'v10',
    preferred_pronoun: 'She',
  },
  phone_numbers: ['+15005550001'],
});
Delete a user by external ID

Immediately deletes a user.

await magicbell.users.deleteByExternalId('{external_id}');

Notification Preferences

Fetch user notification preferences

Fetch a user's notification preferences. If a user does not disable a channel explicitly, we would send notifications through that channel as long as your project is enabled.

await magicbell.notificationPreferences.get({
  userEmail: 'person@example.com',
});
Update user notification preferences

Update a user's notification preferences. These preferences will be applied only to channels you enabled for your project.

await magicbell.notificationPreferences.update(
  {
    categories: [
      {
        slug: 'billing',
        channels: [
          {
            slug: 'email',
            enabled: false,
          },
          {
            slug: 'web_push',
            enabled: false,
          },
        ],
      },
    ],
  },
  {
    userEmail: 'person@example.com',
  },
);

Subscriptions

List subscriptions

List a user's subscriptions status for all topics and categories.

await magicbell.subscriptions.list({
  userEmail: 'person@example.com',
});
Create a topic subscription

Set a user's subscription status to subscribed for a particular topic (and optional categories). If the user previously unsubscribed, the user will be resubscribed.

await magicbell.subscriptions.create(
  {
    categories: [
      {
        slug: 'comments',
        reason: 'watching-the-repo',
      },
    ],
    topic: 'acme-inc.orders.1234',
  },
  {
    userEmail: 'person@example.com',
  },
);
Unsubscribe from a topic

Unusbscribe a user from a particular topic (and optional categories).

await magicbell.subscriptions.unsubscribe(
  '{topic}',
  {
    categories: [
      {
        slug: 'comments',
      },
    ],
  },
  {
    userEmail: 'person@example.com',
  },
);
Show a topic subscription

Show a user's subscription status for a particular topic and categories.

await magicbell.subscriptions.get('{topic}', {
  userEmail: 'person@example.com',
});
Delete topic subscription(s)
await magicbell.subscriptions.delete(
  '{topic}',
  {
    categories: [
      {
        slug: '…',
      },
    ],
  },
  {
    userEmail: 'person@example.com',
  },
);

Support

New features and bug fixes are released on the latest major version of the magicbell package. If you are on an older major version, we recommend that you upgrade to the latest in order to use the new features and bug fixes including those for security vulnerabilities. Older major versions of the package will continue to be available for use, but will not be receiving any updates.

Credits

Credit where credits due, this package is inspired by and based on the Stripe Node.js SDK.

Keywords

FAQs

Package last updated on 23 Sep 2022

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc