Skip to content

Push notifications

Web push reaches a user whose app is closed. Realtime covers users who are connected, and push covers everyone else. The browser shows the notification through a service worker your app hosts.

  1. Your app hosts a service worker and asks the user to allow notifications.
  2. The browser subscribes the user. Your app sends that subscription to Chat.
  3. When a message arrives for an offline user, Chat sends a push to each of their registered browsers.
  4. The service worker shows the notification, and a click opens your chat view.
App --GET /notifications/vapid-public-key--> Chat (public, not a secret)
App --PushManager.subscribe(key)--> browser
App --POST .../notifications/push/devices { platform: "web", subscription }--> Chat
Chat --web push--> browser --> your service worker --> notification
Route Purpose
GET /api/v1/notifications/vapid-public-key Public. Returns the VAPID public key as { "public_key": "..." }, which you pass to PushManager.subscribe().
POST /api/v1/tenants/{tenant_id}/notifications/push/devices Registers a device. Answers 204.
DELETE /api/v1/tenants/{tenant_id}/notifications/push/devices Unregisters it with { "token": "..." }, which for web is the subscription endpoint. Answers 204.

For web, the body of the register call is { "platform": "web", "subscription": { "endpoint": "...", "keys": { "p256dh": "...", "auth": "..." } } }, which is the browser’s PushSubscription. The API also accepts native device tokens, but the SDKs and this site cover web push only.

Registration is tenant-level and for users only. A device belongs to a person in a tenant, not to the application they registered through, so one registration serves every application of the tenant. A machine token answers 403 principal_not_allowed. A user can register several devices, and a push goes to all of them. Chat removes a subscription once the browser reports it expired.

  • A service worker. The SDK ships a template to copy into your public folder as push-sw.js. Adjust the click target to your chat view.
  • A user gesture. The first permission prompt must happen inside a real click. Browsers silently withhold it otherwise, so register from a button handler, not on page load.

The SDK’s register() handles the service worker, the key and the subscription, and never rejects, so a push problem cannot break the rest of your app. See Web push.

Chat sends push only to recipients who are offline. It checks presence when the message arrives, and it checks again that each recipient is still an active member.

Conversation Candidates
DIRECT and GROUP Every other member
CHANNEL Only the members the message mentions

The sender never gets a push. A channel can have a very large membership, so only mentioned members are notified. Mentions are described in Messages.

Part Content
Title The sender’s display name, or the conversation name when there is no sender
Body The first 200 characters of the message, or “Sent an attachment”
data tenant_id, application_id, conversation_id and message_id

Use data in the click handler to open the right conversation. The full shape is in Push payloads.