---
title: "Custom notifications from flow and Apex"
url: "https://trailassembly.com/salesforce-custom-notifications/"
topic: "Admin and Permissions"
published: "2026-09-19T03:08:29+00:00"
updated: "2026-10-06T13:58:23+00:00"
---

# Custom notifications from flow and Apex

**A custom notification is a bell alert in Lightning and a push message on the Salesforce mobile app, sent from a flow or from Apex.** Define a notification type once, choose its channels, then send it with a title, a body, a target record and recipient Ids. Two things catch people: the flow action wants the type’s Id rather than its name, and a notification leaves no record behind.

## Creating the notification type

Setup, Notification Builder, Notification Types, New. You give it a label and an API name, then tick the channels it supports: Desktop, Mobile, or both.

Desktop means the bell in the Lightning header. The entry sits in the list whether or not the user was looking, though the browser toast appears only if they allowed notifications for the site.

Mobile means a push message through the Salesforce mobile app. It arrives only if the user has the app installed, is logged in, and has not turned notifications off at the operating system level. You control none of those, so mobile delivery is best effort.

Notification Delivery Settings, in the same area of Setup, controls which types deliver on which channel. A custom type that appears to send but never arrives is usually disabled there.

## Sending from a flow

The Send Custom Notification action takes five inputs: the custom notification type Id, recipient Ids, a title, a body, and a target Id.

The type Id is the annoyance. That Id differs in every org, so pasting the sandbox one into the flow breaks the production deployment. Do not hardcode it. Query `CustomNotificationType` by `DeveloperName` and feed the result in, or hold the Id in a custom metadata record per environment.

```apex
SELECT Id, DeveloperName FROM CustomNotificationType
```

Recipient Ids is a collection. Users and public groups work reliably. Roles and queues are also accepted. Build the collection deliberately rather than pointing it at a role containing several hundred people.

The target Id is the record the notification opens. It is required, and the recipient must be able to see it, or tapping produces an insufficient privileges error. A real failure mode when notifying a manager about a record in a private sharing model.

## Sending from Apex

```apex
Messaging.CustomNotification note = new Messaging.CustomNotification();
note.setNotificationTypeId(typeId);
note.setTitle('Order rejected');
note.setBody('Order 10042 was rejected by credit control.');
note.setTargetId(orderId);
note.send(new Set<String>{ userId });
```

Apex gives you two things the flow action does not. `setTargetPageRef()` sends the user somewhere other than a record, such as a [list view](https://trailassembly.com/salesforce-list-views-and-filters/). And you can build the recipient set from logic that would be awkward in a flow.

Wrap the send in a try/catch. A bad recipient Id throws, and an unhandled exception in a trigger rolls back the transaction that was only meant to send a message.

## Write the message properly

Both title and body are short, and a phone will truncate them further. Put the record identifier and the required action in the title, because on a lock screen that is all anyone reads.

“Approval needed” is useless. “Approve discount 42% on Acme renewal” tells the person whether to open it now. Merge in the record name and the number that matters, not a generic sentence with a link.

## What notifications are not

A notification is fire and forget. No delivery receipt, no audit record, no retry, no way to check later whether anyone saw it. If a process depends on someone acting, the notification is a prompt on top of a task, a queue or a list view, never the only trace.

They share the failure mode of every alerting mechanism: volume kills them. A type that fires on every case update trains people to dismiss the bell unread, at which point the genuinely urgent notification is invisible. Reserve them for the unusual and time-critical.

There are daily allocations and a cap on recipients per send, so notifications are not a broadcast channel either. For “tell everyone in support something”, use a [Chatter](https://trailassembly.com/salesforce-chatter-configuration/) post or email.

## Frequently asked

**Can I send a custom notification to an external Experience Cloud user?** Community members can receive them, subject to the usual licence and [sharing rules](https://trailassembly.com/sharing-rules/). The target record still has to be visible to them.

**Do users have to opt in?** Not for the bell. For mobile push, the app and the device both have to permit notifications, and users can turn that off without telling you.

**Can I recall one?** No. Once sent, it is on the device. Check the merge fields before you activate the flow.

**How do I test without spamming people?** Set the recipient to your own user Id in a debug run, then widen the recipient logic once the text and target record are right.

---

Source: https://trailassembly.com/salesforce-custom-notifications/
Trail Assembly — independent Salesforce write-ups.
