Push Notifications

Send real-time notifications to users via the LoadSites Cloud relay. Handle notifications both as system alerts and in-app events.

License required

Push notifications require a LoadSites license (Basic tier or higher). The notification relay infrastructure is managed by LoadSites Cloud. See Licensing below for tier details.

Two keys, two roles

Each license comes with two keys:

  • license_key (public) — Included in your manifest and used by the LoadSites container app when registering or unregistering devices. Safe to embed in client-side code.
  • secret_key (private) — Used exclusively by your backend server to send notifications via the /send and /send-batch endpoints. Never expose this key in client-side code, your manifest, or source control.

Architecture

Your Server                  LoadSites Cloud              User's Device
┌──────────┐    HTTP POST    ┌──────────────────┐   FCM    ┌──────────────────┐
│           │ ─────────────► │                  │ / APNS  │  LoadSites App   │
│  Backend  │                │  Notification    │ ───────► │  ┌────────────┐  │
│  Server   │   device_key   │  Relay Service   │          │  │ Your CWA   │  │
│           │  + secret_key  │                  │          │  │ App        │  │
└──────────┘                 └──────────────────┘          │  └────────────┘  │
                                                           └──────────────────┘

Container App                LoadSites Cloud
┌──────────────────┐  POST   ┌──────────────────┐
│  LoadSites App   │ ──────► │  Register /      │   Stores FCM token +
│  (on device)     │         │  Unregister      │   device_key mapping
│                  │         │                  │
│  uses            │         └──────────────────┘
│  license_key     │
└──────────────────┘
  1. Your app requests a device key via the bridge.
  2. You send the device key to your backend server.
  3. Your server sends notifications to the LoadSites Cloud API using the device key + your secret key.
  4. LoadSites Cloud delivers via APNS (iOS) or FCM (Android) — the standard platform push channels.
  5. The LoadSites container shows a system notification or forwards it to the open app.
Standard platform channels

All push notifications flow through Apple's APNS and Google's FCM — the same infrastructure used by all native apps. The LoadSites container does not implement custom background networking, persistent sockets, or polling. This ensures compliance with platform battery and background execution policies.

Client-Side Setup

Three steps to enable notifications in your CWA app:

Step 1: Declare the Permission

Add "notifications" to your manifest's permissions array:

{
  "permissions": ["notifications", "haptics", "storage"]
}

Step 2: Request Permission & Get Device Key

async function setupNotifications() {
  // Request OS-level notification permission
  const perm = await LoadSites.notifications.requestPermission();
  if (!perm.granted) {
    console.log('User declined notifications');
    return;
  }

  // Get the unique device key for this installation
  const result = await LoadSites.notifications.getDeviceKey();
  const deviceKey = result.deviceKey;

  // Send the device key to your server
  await fetch('https://your-api.com/register-device', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ deviceKey: deviceKey })
  });

  console.log('Notifications registered with key:', deviceKey);
}

Step 3: Handle In-App Notifications

When a notification arrives while the app is open, the container forwards it to your app instead of showing a system notification. Register a handler:

// Listen for notifications received while app is in foreground
LoadSites.notifications.onNotification(function(notification) {
  // notification = {
  //   title: 'New Message',
  //   body: 'You have a message from Alice',
  //   data: { messageId: '123', sender: 'alice' }
  // }

  // Option A: Show an in-app toast
  showToast(notification.title, notification.body);

  // Option B: Update a badge count
  updateBadgeCount(notification.data);

  // Option C: Navigate to the relevant content
  if (notification.data.messageId) {
    navigateToMessage(notification.data.messageId);
  }
});
Foreground vs background

When the app is in the foreground, the notification is delivered to your onNotification callback and no system notification is shown. When the app is in the background or closed, a system notification is shown and tapping it opens the app.

Server-Side Registration

Device registration is handled automatically by the LoadSites container app using the license_key from your manifest. When the user grants notification permission, the container calls the register endpoint with the device's FCM token and a unique device key.

You do not need to call these endpoints from your backend — the container handles registration and unregistration. The endpoints are documented here for reference.

Register a Device

POST https://api.loadsites.app/v1/notifications/register

// Node.js example
const response = await fetch('https://api.loadsites.app/v1/notifications/register', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    fcmToken: 'firebase-cloud-messaging-token',
    deviceKey: 'unique-device-uuid',
    domain: 'yourdomain.com',
    appId: 'default',
    licenseKey: 'LS-XXXX-YYYY-ZZZZ'
  })
});
FieldTypeStatusDescription
fcmToken string Required Firebase Cloud Messaging token for the device.
deviceKey string Required Unique per-domain device key (UUID).
domain string Required The domain of the CWA app.
appId string Required Which app within the domain. Defaults to "default".
licenseKey string Required Your LoadSites license key.

Returns { "success": true } on success, or 403 if your license tier doesn't allow notifications.

Unregister a Device

POST https://api.loadsites.app/v1/notifications/unregister

const response = await fetch('https://api.loadsites.app/v1/notifications/unregister', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    deviceKey: 'unique-device-uuid',
    domain: 'yourdomain.com',
    appId: 'default',
    licenseKey: 'LS-XXXX-YYYY-ZZZZ'
  })
});

Returns { "success": true } on success, or 404 if the registration was not found.

Sending Notifications (Server-Side)

Send notifications from your backend server by POSTing to the LoadSites Cloud API. These endpoints require your secret key (not the license key).

Use your secret key

The /send and /send-batch endpoints authenticate with your secretKey — the private key from your LoadSites dashboard. This is different from the license_key in your manifest. Never expose the secret key in client-side code.

Single Device

POST https://api.loadsites.app/v1/notifications/send

// Node.js example
const response = await fetch('https://api.loadsites.app/v1/notifications/send', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    deviceKey: 'target-device-key-here',
    secretKey: process.env.LOADSITES_SECRET_KEY,
    title: 'Order Shipped',
    body: 'Your order #1234 has shipped!',
    type: 'standard',
    appId: 'default',
    data: {
      orderId: '1234',
      status: 'shipped'
    }
  })
});

Batch Sending

Send to multiple devices in a single request:

POST https://api.loadsites.app/v1/notifications/send-batch

const response = await fetch('https://api.loadsites.app/v1/notifications/send-batch', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    deviceKeys: [
      'device-key-1',
      'device-key-2',
      'device-key-3'
    ],
    secretKey: process.env.LOADSITES_SECRET_KEY,
    title: 'System Update',
    body: 'Version 2.0 is now available',
    type: 'standard',
    appId: 'default',
    data: { version: '2.0.0' }
  })
});

API Responses

Single device response:

{
  "success": true,
  "messageId": "msg-abc123"
}

Batch response:

{
  "success": true,
  "sent": 3,
  "failed": 0
}

Error Responses

The send endpoints return standard HTTP status codes with a JSON error body:

{
  "error": "Device key not registered for notifications",
  "code": "NOT_REGISTERED"
}
HTTP StatusError CodeDescription
400 Missing required fields in the request body.
403 Invalid secretKey, or the license tier doesn't allow notifications.
403 USER_DISABLED The user has disabled notifications for this app on their device.
404 NOT_REGISTERED The device key was never registered for notifications.
Handling USER_DISABLED

When you receive a 403 with "code": "USER_DISABLED", the user has toggled off notifications for this app from their LoadSites home screen. Do not retry — respect the user's preference and stop sending until they re-enable.

Send Notification Fields

FieldTypeStatusDescription
deviceKey string Required Target device key. Use deviceKeys (array) for batch sends.
secretKey string Required Your LoadSites secret key (private, server-only). Not the license_key from your manifest.
title string Required Notification title displayed to the user.
body string Required Notification body text.
type string Optional Notification type: "standard" (default) or "call". The "call" type shows a high-priority notification with Answer/Decline buttons and a ringtone.
appId string Optional Which app within the domain this notification is for. Defaults to "default".
actionData object Optional Custom data passed to the CWA when the user acts on the notification (taps, answers, declines).
data object Optional Additional custom data payload. Delivered to onNotification callback and available when the user taps the notification.

Handling Notifications in Your App

In-App (Foreground)

Use onNotification to handle notifications when the user is actively using your app. Common patterns include:

// Complete example: in-app notification handling
LoadSites.notifications.onNotification(function(notification) {
  // Play haptic feedback
  LoadSites.haptics.notification('success');

  // Show a toast
  const toast = document.createElement('div');
  toast.className = 'in-app-toast';
  toast.innerHTML = '<strong>' + notification.title + '</strong><p>' + notification.body + '</p>';
  document.body.appendChild(toast);

  // Auto-dismiss after 4 seconds
  setTimeout(function() { toast.remove(); }, 4000);

  // Handle the data payload
  if (notification.data && notification.data.type === 'message') {
    updateMessageBadge();
  }
});

Background & Tap-to-Open

When the user taps a system notification to open the app, the notification data is available through the normal app launch flow. The container stores the most recent notification and delivers it via onNotification when the app initializes.

Unsubscribing

// Remove a specific callback
function myHandler(notification) { /* ... */ }
LoadSites.notifications.onNotification(myHandler);

// Later...
LoadSites.notifications.offNotification(myHandler);

Security Model

Push notifications are delivered through the platform's standard push infrastructure — Apple Push Notification Service (APNS) on iOS and Firebase Cloud Messaging (FCM) on Android. The LoadSites Cloud relay forwards notifications through these official channels; no custom background networking or persistent connections are used. This architecture complies with Apple and Google platform policies for push notification delivery.

Key Separation

LoadSites uses a two-key model to separate client-side and server-side concerns:

KeyVisibilityUsed ForEndpoints
license_key Public Manifest, device registration /register, /unregister, /license/*
secret_key Private Sending notifications from your server /send, /send-batch

The license_key is safe to include in your manifest because it can only register or unregister devices — it cannot send notifications. Only the secret_key can trigger notification delivery, and it should never leave your server environment.

Additional Protections

Best Practices

Licensing

Push notifications are the only CWA feature that requires a paid license. Each license includes two keys:

Both keys are available in your LoadSites dashboard after purchasing a license.

TierMonthly PriceNotifications / MonthFeatures
Free $0 0 All bridge APIs except notifications
Basic $9 10,000 Push notifications, email support
Pro $29 100,000 Push notifications, priority support, analytics dashboard
Enterprise Custom Unlimited Custom SLA, dedicated infrastructure, white-label option
All other features are free

Camera, haptics, biometrics, geolocation, storage, share, clipboard, network, device info, and navigation — all available at no cost, no license needed.

Troubleshooting

Notifications not arriving

onNotification not firing