Push Notifications API

Overview

The Push Notifications API enables Web Push notifications for Cloudillo. It uses the VAPID (Voluntary Application Server Identification) protocol to securely deliver notifications to users’ browsers when they’re offline.

Push notifications are sent when actions are received for the user while they are not connected via WebSocket.

Endpoints

Get VAPID Public Key

GET /api/notification/vapid-public-key

Get the VAPID public key for subscribing to push notifications. The key is automatically generated on first request if it doesn’t exist.

Alternative path: GET /api/auth/vapid (alias)

Authentication: Required

Response:

{
  "vapidPublicKey": "BM5..."
}
Field Type Description
vapidPublicKey string Base64-encoded VAPID public key

Example:

const response = await api.notifications.getVapidPublicKey()
const vapidPublicKey = response.vapidPublicKey

// Use with browser Push API
const subscription = await registration.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey: vapidPublicKey
})

Register Subscription

POST /api/notification/subscription

Register a push notification subscription. The subscription is stored and used to send notifications when the user is offline.

Authentication: Required

Request:

{
  "subscription": {
    "endpoint": "https://fcm.googleapis.com/fcm/send/...",
    "expirationTime": null,
    "keys": {
      "p256dh": "BKgS...",
      "auth": "Qs..."
    }
  }
}
Field Type Required Description
subscription.endpoint string Yes Push service endpoint URL
subscription.expirationTime number No Expiration timestamp (Unix milliseconds)
subscription.keys.p256dh string Yes P-256 public key (base64url)
subscription.keys.auth string Yes Auth secret (base64url)

Response:

{
  "id": 12345
}
Field Type Description
id number Subscription ID for later deletion

Example:

// After getting VAPID public key and subscribing via Push API
const browserSubscription = await registration.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey: vapidPublicKey
})

// Send subscription to server
const result = await api.notifications.subscribe({
  subscription: browserSubscription.toJSON()
})

// Store subscription ID for later unsubscription
localStorage.setItem('pushSubscriptionId', result.id)

Unregister Subscription

DELETE /api/notification/subscription/{id}

Remove a push notification subscription. The subscription will no longer receive notifications.

Authentication: Required

Path Parameters:

Parameter Type Description
id number Subscription ID to delete

Response: 204 No Content

Example:

const subscriptionId = localStorage.getItem('pushSubscriptionId')
if (subscriptionId) {
  await api.notifications.unsubscribe(subscriptionId)
  localStorage.removeItem('pushSubscriptionId')
}

Complete Integration Example

// 1. Check if push is supported
if (!('PushManager' in window)) {
  console.log('Push notifications not supported')
  return
}

// 2. Get service worker registration
const registration = await navigator.serviceWorker.ready

// 3. Get VAPID public key from server
const { vapidPublicKey } = await api.notifications.getVapidPublicKey()

// 4. Subscribe via browser Push API
const subscription = await registration.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey: urlBase64ToUint8Array(vapidPublicKey)
})

// 5. Send subscription to Cloudillo server
const result = await api.notifications.subscribe({
  subscription: subscription.toJSON()
})

console.log('Push subscription registered with ID:', result.id)

// Helper function to convert base64 key
function urlBase64ToUint8Array(base64String: string): Uint8Array {
  const padding = '='.repeat((4 - base64String.length % 4) % 4)
  const base64 = (base64String + padding)
    .replace(/-/g, '+')
    .replace(/_/g, '/')
  const rawData = atob(base64)
  return Uint8Array.from([...rawData].map(char => char.charCodeAt(0)))
}

Notification Settings

Users can control which notification types they receive through the Settings API:

Setting Type Description
notify.push.message boolean Receive notifications for new messages
notify.push.mention boolean Receive notifications when mentioned
notify.push.reaction boolean Receive notifications for reactions
notify.push.connection boolean Receive notifications for connection requests
notify.push.follow boolean Receive notifications for new followers

Example:

// Disable reaction notifications
await api.settings.set('notify.push.reaction', false)

// Get current notification settings
const settings = await api.settings.list()
const pushSettings = Object.entries(settings)
  .filter(([key]) => key.startsWith('notify.push.'))

Web Push Standards

The implementation follows these RFCs:

RFC Title
RFC 8292 VAPID for Web Push
RFC 8188 Encrypted Content-Encoding for HTTP
RFC 8291 Message Encryption for Web Push

See Also