---
meta:
  title: "Email notifications"
  parentTitle: "Notifications"
  description: "Send notifications with webhooks"
---

Using Liveblocks webhooks, it’s possible to trigger your API endpoints when
certain events occur, such as users joining or leaving rooms. One of these
events was created specifically for sending notifications from your back end,
the "`notification"` event. Certain notifications can be enabled or disabled on
different channels for this event, for example you could enable notifications on
`email` and `slack`, but not on `teams`.

<Figure>
  <Image
    src="/assets/comments/email-notification.png"
    alt="An email titled 'New notifications' showing two comments and a link to the thread"
    width={1500}
    height={1000}
  />
</Figure>

## Step-by-step guides

This page is an overview—if you’re looking to send email notifications after
Comments or Text Editor updates, makes sure to read our specific guides:

- [How to send email notifications of unread comments](/docs/guides/how-to-send-email-notifications-of-unread-comments).
- [How to send email notifications for unread text editor mentions](/docs/guides/how-to-send-email-notifications-for-unread-text-editor-mentions).

## Inbox notifications

Email notifications are built around the concept of inbox notifications, which
are different from “normal” notifications in the sense that they can group
multiple activities together and evolve over time. This makes more sense when
sending email notifications because it helps to avoid flooding your users with
too many emails.

## Sending email notifications with webhooks

Using [Liveblocks webhooks](/docs/platform/webhooks#Liveblocks-events) you can
listen to a range of events such as user joining rooms, or threads being
created. On [your dashboard](https://liveblocks.io/dashboard) you can create a
webhook for a project, and select which events you’d like to listen to.

<Figure>
  <video width={1512} height={982} autoPlay loop muted playsInline>
    <source src="/assets/webhooks/edit-events.mp4" type="video/mp4" />
  </video>
</Figure>

The endpoint URL you pass will receive request with relevant data when the event
occurs. The webhook event built for creating these unread notification emails is
called `"notification"`, and by default is sent up to every 30 minutes to each
user, though this can be customized in the webhooks dashboard.

### Notification channels

`"notification"` webhooks can be enabled and disabled on certain channels in the
notifications dashboard page. Channels are used to represent different places
your users may receive notifications, such as on `email`, `slack`, `teams`, and
`webPush`.

<Figure>
  <video width={1512} height={982} autoPlay loop muted playsInline>
    <source src="/assets/webhooks/notification-settings.mp4" type="video/mp4" />
  </video>
</Figure>

### Event object

Here’s an example of an event object that’s sent when a user receives a new (or
updated) inbox notification. Note that this is custom notification sent on the
`email` channel.

```ts
const event = {
  type: "notification",
  data: {
    channel: "email",
    kind: "$myCustomNotification",
    projectId: "my-project-id",
    roomId: "my-room-id",
    userId: "my-user-id",
    inboxNotificationId: "in_xt3p7ak...",
    createdAt: "2021-10-06T01:45:56.558Z",
  },
};
```

### Your endpoint

In your endpoint, you can use this `event` object with
[`liveblocks.getInboxNotification`](/docs/api-reference/liveblocks-node#get-users-userId-inboxNotifications-inboxNotificationId),
which will return the inbox notification for the event.

```ts
// Data from the `notification` event
const { inboxNotificationId, userId } = event.data;

// Get the inbox notification, which details when the user last read the thread
const inboxNotification = await liveblocks.getInboxNotification({
  inboxNotificationId,
  userId,
});

// { kind: "$myCustomNotification", readAt: Date<2024-07-13T14:32:50.697Z>, ... }
console.log(inboxNotification);
```

Once you have the inbox notification you can then send an email to the `userId`
containing information from the notification.

```ts
const emailAddress = __getUserEmail__(userId);

// Send email to the user that received the inbox notification
__sendEmail__({
  from: "hello@my-company.com",
  to: emailAddress,
  title: "New notification",
  html: `
    <h1>New notification</h1>
    <a href="...">Learn more</a>
  `,
});
```

Here’s an example with every step linked together, along with the code necessary
to verify a webhook request is valid.

```ts title="Full example" isCollapsable isCollapsed
import {
  Liveblocks,
  WebhookHandler,
  stringifyCommentBody,
} from "@liveblocks/node";

// Add your webhook secret key from a project's webhooks dashboard
const WEBHOOK_SECRET = "YOUR_WEBHOOK_SECRET";
const webhookHandler = new WebhookHandler(WEBHOOK_SECRET);

// Add your secret key from a project's API keys dashboard
const API_SECRET = "{{SECRET_KEY}}";
const liveblocks = new Liveblocks({ secret: API_SECRET });

export async function POST(request: Request) {
  const body = await request.json();
  const headers = request.headers;

  // Verify if this is a real webhook request
  let event;
  try {
    event = webhookHandler.verifyRequest({
      headers: headers,
      rawBody: JSON.stringify(body),
    });
  } catch (err) {
    console.error(err);
    return new Response("Could not verify webhook call", { status: 400 });
  }

  // When a notification webhook event has triggered
  if (event.type === "notification") {
    const { inboxNotificationId, userId } = event.data;

    // Get the inbox notification, which details when the user last read the thread
    const inboxNotification = await liveblocks.getInboxNotification({
      inboxNotificationId,
      userId,
    });

    // Send email to the user that received the inbox notification
    const emailAddress = __getUserEmail__(userId);
    __sendEmail__({
      from: "hello@my-company.com",
      to: emailAddress,
      title: "New comment",
      html: `
        <h1>New notification</h1>
        <a href="...">Learn more</a>
      `,
    });
  }

  return new Response(null, { status: 200 });
}
```

<Banner title="Sending Comments emails">

This page is an overview of creating email notifications with Notifications. If
you’d like to send emails about new comments, make sure to read
[how to send email notifications of unread comments](/docs/guides/how-to-send-email-notifications-of-unread-comments).

</Banner>

### Permissions

When you receive a `notification` webhook event, it's essential to verify if the
user has access to the room before sending an email. Liveblocks lacks the
necessary information to determine if a user has access to a room. For instance,
we create an inbox notification when a user is mentioned in a comment. In this
user's client context, we can determine if they have access to the notification
thanks to the token generated for that user. However, when we send a
`notification` webhook event, we lack this information.

#### Access token authentication

If you are using access tokens, this will always be true, Liveblocks will never
have the information.

#### ID token authentication

If you are using ID tokens, Liveblocks already possesses certain information
about the permissions you have configured for each room, specifying which users
and groups have access. However, what we currently lack is the relationship
between a user and a group. At present, you need to verify user access before
sending an email. We do, however, plan to include full permissions info in
Liveblocks in our future updates. If you're interested in learning more about
this feature, please feel free to reach out to us.

## Notification settings

It’s possible to allow users to choose their own notification settings for each
channel in your application.

<Figure>
  <Image
    src="/assets/notifications/notification-settings.jpg"
    alt="Notification settings"
    width={1344}
    height={896}
  />
</Figure>

To implement this, import
[`useNotificationSettings`](/docs/api-reference/liveblocks-react#useNotificationSettings)
into your component, and create a list of toggles. Here’s an example of a
checkbox that toggles thread notification emails.

```tsx highlight="4,8-17"
import { useNotificationSettings } from "@liveblocks/react/suspense";

function NotificationSettings() {
  const [{ settings }, updateSettings] = useNotificationSettings();

  return (
    <>
      <label>
        Receive thread notifications by email:
        <input
          type="checkbox"
          checked={settings.email?.thread}
          onChange={(e) =>
            updateSettings({ email: { thread: e.target.checked } })
          }
        />
      </label>
      {/* Other checkboxes */}
    </>
  );
}
```

## Retrieving and modifying Comments data

Here’s every Notifications-related
[`@liveblocks/node`](/docs/api-reference/liveblocks-node) function. Each also
has a corresponding REST API, you can find more info by following the links.

- [`getInboxNotification`](/docs/api-reference/liveblocks-node#get-users-userId-inboxNotifications-inboxNotificationId)
- [`triggerInboxNotification`](/docs/api-reference/liveblocks-node#post-inbox-notifications-trigger)

---

For an overview of all available documentation, see [/llms.txt](/llms.txt).
