# Getting started
Goal of this page: get a notification into an inbox and read it back with as little ceremony as possible.
You’ll need:
- A Cognito access token for a signed-in user (you already have this in most Inovus apps)
- Network access to the notifications service (
https://notifications.totumcloud.comin production) - Node / browser environment that can call
fetch
If the shared service isn’t deployed for your environment yet, ask your platform team — or follow Setup to stand one up.
# Step 1 — Install the client
npm install @inovus-medical/notifications
# or: pnpm add @inovus-medical/notifications
# Step 2 — Create a client once
Put this near your auth layer (one instance per app is enough):
import { NotificationsClient } from '@inovus-medical/notifications';
export const notificationsClient = new NotificationsClient({
baseUrl: 'https://notifications.totumcloud.com',
// Return the current Cognito access token. Called per request,
// and once more after a 401 so refreshed tokens are picked up.
getAccessToken: () => auth.getValidAccessToken(),
});
Tip: Don’t put the token in localStorage yourself inside this package — just teach the client how to ask your existing auth module.
# Step 3 — Read the inbox
const { items, unreadCount, nextCursor } = await notificationsClient.list({
limit: 20,
});
console.log(`${unreadCount} unread`);
for (const n of items) {
console.log(n.severity, n.title, n.body);
}
Or keep the bell fresh without thinking about timers:
const stop = notificationsClient.subscribe(({ items, unreadCount }) => {
renderBell(items, unreadCount); // your UI
});
// ALWAYS call this on logout / unmount
stop();
Default poll interval is 30 seconds. Unchanged polls return 304 and barely cost anything.
# Step 4 — React shortcut (optional)
import { useNotifications } from '@inovus-medical/notifications/react';
import { notificationsClient } from './notificationsClient';
export function NotificationBell() {
const { notifications, unreadCount, loading, markRead, markAllRead, remove } =
useNotifications(notificationsClient);
if (loading) return <span>…</span>;
return (
<div>
<span aria-label="Unread">{unreadCount}</span>
<ul>
{notifications.map((n) => (
<li key={n.id}>
<strong>{n.title}</strong>
<p>{n.body}</p>
<button type="button" onClick={() => markRead(n.id)}>
Mark read
</button>
<button type="button" onClick={() => remove(n.id)}>
Delete
</button>
</li>
))}
</ul>
<button type="button" onClick={() => markAllRead()}>
Mark all read
</button>
</div>
);
}
The hook owns subscribe/unsubscribe for you. You still own the markup and styling.
# Step 5 — Create a self-notification (browser)
Useful when the current user should get an inbox item from something that happened in the app:
import { createNotificationService } from '@inovus-medical/notifications';
import { notificationsClient } from './notificationsClient';
export const notification = createNotificationService(notificationsClient);
await notification.success(
'Export ready',
'Your CSV download is ready.',
'/exports/latest',
);
This hits POST /v1/notifications/self. The recipient is always the signed-in user — they cannot target someone else.
# Step 6 — Publish from a backend (the common production path)
Background jobs usually notify another user. That needs a publisher token (M2M scope notifications/publish):
await notificationsClient.publish({
userGuid: recipientCognitoSub,
title: 'Review complete',
body: 'Your assessment feedback is ready.',
severity: 'success',
actionUrl: `/video/${videoId}/feedback`,
dedupeKey: `review_case:${caseId}`, // always set one for jobs
});
Full story: Publishing.
# Checklist: “Am I done?”
- [ ] Client installed and constructed with
baseUrl+getAccessToken - [ ]
listorsubscribereturns data for a real user token - [ ] Bell UI renders
title/body/unreadCount(your components) - [ ] Logout calls
stop()(or unmounts the React hook) - [ ] Producers set
dedupeKeyon every job publish
# Common first-day snags
| Symptom | Likely cause | Fix |
|---|---|---|
401 Unauthorized |
Missing/expired token | Check getAccessToken; ensure Cognito refresh works |
403 Forbidden on publish |
User token without publisher scope | Use M2M token for cross-user publish; or use publishSelf / convenience API for self |
| Empty inbox | Publishing to a different userGuid than the reader’s sub |
Recipients must match Cognito sub exactly |
| “Nothing updates live” | Expecting WebSockets | Polling is ~30s by default — see Advanced |
More fixes: Troubleshooting.
Next: Setup if you need to deploy the service, or Everyday usage for the full inbox toolkit.