Changelog

Notable changes to the NotificationStream API and SDKs.

The REST API is versioned in the URL (/v1). Within a version, changes are additive only: new endpoints, new optional request fields and new response fields. Make your clients ignore fields they don't know.

Unreleased

2026-10-25: Growth plan features are enforced

  • On the Starter plan, tags and segment audiences, contents in more than one locale, {{…}} templates and a publishAt more than a minute ahead return 403 forbidden, and so do creating and updating segments. Editing other fields of a notification saved on a larger plan keeps working. See Billing and limits.

2026-10-25: Feed counts cover the newest 100 notifications

  • unreadCount and unseenCount count the user's newest 100 notifications, so they are at most 100.
  • A feed page can hold fewer than limit items, even none, while nextCursor is set. Keep paging until nextCursor is null.

2026-10-24: Subscribers are now project users (breaking)

The API and Node SDK called your users "subscribers" while the client SDKs and user tokens called them users. They are now project users everywhere.

  • /v1/subscribers is now /v1/project-users, with the same operations. The Subscriber, UpsertSubscriber and SubscriberList schemas are now ProjectUser, UpsertProjectUser and ProjectUserList.
  • @notificationstream/node: ns.subscribers is now ns.projectUsers, and the Subscriber… types are now ProjectUser… (ProjectUserView, UpsertProjectUserInput, ListProjectUsersOptions, ProjectUserFeedOptions, ProjectUsersResource).

2026-10-24: Realtime, and polling is opt-in (breaking)

  • New GET /v1/client/realtime (Growth plan and up): a WebSocket that says when the user's feed changed. Refused connections close with a 44xx code. After a changed message, fetch the feed with its at as X-Changed-At. See Realtime.
  • The SDKs no longer poll by default. They fetch on start, when the app becomes visible again and on refresh(). client.poll(interval) / usePolling(interval) polls on a timer (10 seconds at the shortest), and client.realtime() / useRealtime() keeps a realtime connection open; polling pauses while it is connected.
  • The project's poll interval setting and config.pollInterval in feed responses are gone.

2026-10-24: Signed user tokens, no sessions (breaking)

This changes the client endpoints and SDK options without a new API version. The SDKs haven't been published yet, so no deployed app is affected.

  • Signing keys replace the identity secret. User tokens are now ES256 JWTs your backend signs with a project signing key (sub = user id, exp at most 7 days ahead, optional kid). Signing keys are created on the API keys page; only the public key is stored. The ids_… identity secret and HMAC-SHA256 user tokens are gone. See Identity verification.
  • Identity verification is always on. The project setting to turn it off is gone.
  • No sessions. POST /v1/client/session and ?token= are removed. Every client request sends X-Publishable-Key: pk_… and Authorization: Bearer <user token>. A user's first request creates the project user; 401 errors carry details.reason.
  • GET /v1/client/feed also returns the project's client config.
  • New POST /v1/client/profile syncs profile fields and attributes. The SDKs call it only when the profile changed.
  • SDK options: user: { id, …profile } replaces userId + user, and token replaces userToken. It is required and can be a function that returns a fresh token (type TokenProvider). identify(user, token) replaces identify(userId, userToken?, user?).
  • @notificationstream/node: createUserToken(signingKey, userId, { keyId?, expiresIn? }) signs a JWT (default lifetime one hour) instead of computing an HMAC.

SDKs: <notification-bell> removed

  • @notificationstream/js no longer ships the <notification-bell> web component: the @notificationstream/js/ui entry (mountNotificationBell, defineNotificationBell) is gone. Use the React or React Native components, or build your own UI on the client and its headless UI core.

SDKs: present new notifications

  • @notificationstream/js: client.onNotification(listener, { filter }) hands each newly arrived notification to one listener, with a queue for notifications no listener takes yet, and the deliverOnStart option ("none", "latest", "unseen") for the ones that already exist on start.
  • React and React Native: usePresentedNotification() and useNotificationArrival(), with filter and enabled to choose the screens. See Presenting new notifications.

2026-10-23: Lapsed subscriptions block the client endpoints

  • Without an active, trialing or past_due subscription, every client endpoint returns 402 payment_required. @notificationstream/js then clears the feed and its cache and stops polling until refresh() or identify().

2026-10-22: Monthly request limits

  • Client requests count towards the organization's monthly request limit. Over it, each user's feed refreshes every 10 minutes; other feed requests get 429 rate_limited with a Retry-After header, which browsers can read. See Billing and limits.

SDKs: headless UI core and shared stylesheet

  • @notificationstream/js exports a headless UI core used by every bundled UI: createItemModel, handleNotificationClick, createFeedController, feedPhase, tab/empty/bell label helpers, badgeText, a shared "now" ticker, getSystemDark / subscribeSystemDark, mergeClientTheme and resolveClientLabels. See Headless UI core.
  • New @notificationstream/js/styles (styles, injectStyles, icons) and @notificationstream/js/styles.css: the stylesheet of @notificationstream/react (whose styles.css is now the same file).
  • New themeConfigToCssVariables(theme, scheme).
  • React: --ns-panel-width and --ns-panel-max-height variables; itemTitle is the stretched row button and itemMain is no longer a button; only URLs passing isSafeUrl are navigated to; renderItem's helpers.onClick runs the full click flow.
  • React Native: built on the same headless core. Linking opens absolute URLs and deep links, never javascript:, data:, vbscript: or file: URLs.

API v1

  • Public REST API: notifications, project users, segments, project and client (SDK) endpoints, with an OpenAPI 3.1 spec at /v1/openapi.json.
  • Audiences: everyone, user ids, tags and segments, evaluated at read time.
  • Localization with exact, language and regional-sibling fallback; per-user templates.
  • Scheduling, expiry, drafts, cancel; idempotent creation.
  • ETag revalidation for feeds.

SDKs

  • @notificationstream/js 0.1.0: client store and <notification-bell> web component.
  • @notificationstream/react, @notificationstream/react-native: providers, hooks and components.
  • @notificationstream/node: server SDK with retries, pagination and createUserToken.