Push notifications reach a user whose app isn't connected: a phone in a pocket, a closed browser tab. Livqeno sends one through APNs (iOS) or FCM (Android and web) for each new message, to each of the user's registered devices.
Where this fits: someone on your team has added your APNs key or FCM service account to the project in the dashboard. That's where the credentials live; they never go in your app. Your app then does two things: register the device's push token, and let the user pick what they want to be notified about.
Register the device
Get the token from the platform (firebase_messaging, Expo, the browser's
Push API…) and hand it to Livqeno. Registering is an upsert keyed on the
token, so it's safe to call on every app start.
await chat.registerDevice({
provider: 'fcm',
token: fcmToken,
platform: 'web',
});
const devices = await chat.listDevices();await livqeno.chat!.registerDevice({
provider: Platform.OS === 'ios' ? 'apns' : 'fcm',
token: deviceToken,
platform: Platform.OS === 'ios' ? 'ios' : 'android',
appBundleId: 'com.example.app', // optional, when you ship more than one app
});await chat.registerDevice(
provider: LivqenoPushProvider.fcm,
token: await FirebaseMessaging.instance.getToken() ?? '',
platform: Platform.isIOS ? LivqenoDevicePlatform.ios : LivqenoDevicePlatform.android,
);On sign-out, unregister the token so the next user on this device doesn't get the previous user's messages:
await chat.unregisterDevice(deviceToken);A token that's registered again by a different user is moved to that user. Tokens APNs or FCM report as invalid are removed by the server.
Who gets a push
When a message is saved, each member other than the sender gets one push per device if they:
- aren't connected to that conversation right now,
- haven't set notifications to
none(ormentions, unless the message mentions them), - aren't banned, and haven't blocked the sender.
Pushes for one conversation collapse into one notification. The payload has
a title, the message (cut to 120 characters, or "Sent an attachment"), and
data: { conversationId, messageId, seq } for opening the right screen.
The badge is the user's total unread count. Live-stream audience chats
don't push by default.
Notification settings per conversation
await chat.setNotificationLevel('conv_…', 'mentions'); // 'all' | 'mentions' | 'none'
await chat.muteConversation('conv_…'); // same as 'none'
await chat.muteConversation('conv_…', false); // unmuteawait livqeno.chat!.setNotificationLevel(conversationId, 'mentions');await chat.setNotificationLevel(conversationId, LivqenoNotificationLevel.mentions);
await chat.muteConversation(conversationId);These settings belong to the user's membership, so they follow them across
devices. The inbox shows them as notifications and muted
on each conversation, and a muted conversation doesn't add to
totalUnread. This is the user muting a conversation for themselves; it's
different from a moderator muting a user.
Audience viewers on a live stream aren't members, so these calls reject
with NOT_A_MEMBER.
Common mistakes
| Mistake | What you'll see | Fix |
|---|---|---|
| Putting the APNs key or FCM JSON in the app | Credentials anyone can extract. | Add them in the dashboard only. |
| Not unregistering on sign-out | The next user on the device gets the old user's pushes. | Call unregisterDevice(token) on sign-out. |
| Expecting a push while the app is open in that conversation | No push. | By design: a connected user already sees the message live. |