🔔 Send In-App Notifications

Overview

In-app notifications are messages that appear directly inside your web application, typically displayed in a notification center or as popups. These notifications provide real-time updates to users without requiring them to check emails or external channels.

NotificationAPI makes it easy to send and display personalized in-app notifications with features like real-time delivery, custom UI components, batching, and user interaction tracking.

This comprehensive guide covers everything you need to know about in-app notifications: sending them from your backend and displaying them in your frontend.

Step 1: Create your account and first notification

  • Create your NotificationAPI account and complete the onboarding. Sign up for free.
  • In the dashboard, create your first notification and enable the In-App channel. See the Configure Notification guide if needed.
  • Note the notification’s Type (e.g., user_mention). You’ll use this later in the send step.

Frontend Integration - Display Notifications

WARNING

Unlike emails or SMS, in-app notifications require frontend integration to display in your application. Both frontend display (below) and backend sending (later) are required.

Step 2: Install the Frontend SDK

Choose the appropriate SDK for your framework:

For React applications, install the React SDK:

npm install @notificationapi/react
yarn add @notificationapi/react
pnpm add @notificationapi/react

For Nuxt applications, install the React SDK:

npm install @notificationapi/react react react-dom @types/react @types/react-dom
yarn add @notificationapi/react react react-dom @types/react @types/react-dom
pnpm add @notificationapi/react react react-dom @types/react @types/react-dom

For Remix (React Router v7), install the React SDK:

npm install @notificationapi/react
yarn add @notificationapi/react
pnpm add @notificationapi/react

For Next.js apps, install the React SDK:

npm install @notificationapi/react
yarn add @notificationapi/react
pnpm add @notificationapi/react

The @notificationapi/core library is a headless JavaScript SDK that lets you build your own custom UI for notifications. It provides direct API access without any prebuilt components, giving you complete control over the design and user experience.

npm install @notificationapi/core

The @notificationapi/core library is a headless JavaScript SDK that lets you build your own custom UI for notifications. It provides direct API access without any prebuilt components, giving you complete control over the design and user experience.

npm install @notificationapi/core

For other frameworks or custom implementations, install the JS Core SDK:

npm install @notificationapi/js-core
yarn add @notificationapi/js-core
pnpm add @notificationapi/js-core

Step 3: Integrate the Notification Widget

The widget automatically connects to our servers and displays notifications in real-time. Choose your implementation:

Use the React SDK for React/Next.js applications:

import {
  NotificationAPIProvider,
  NotificationPopup
} from '@notificationapi/react';

function App() {
  return (
    <NotificationAPIProvider clientId="YOUR_CLIENT_ID" userId="USER_ID">
      <div>
        {/* Your app content */}
        <NotificationPopup />
      </div>
    </NotificationAPIProvider>
  );
}

export default App;

For Next.js, wrap your app in _app.js or layout:

// _app.js or layout.js
import { NotificationAPIProvider } from '@notificationapi/react';

export default function MyApp({ Component, pageProps }) {
  return (
    <NotificationAPIProvider clientId="YOUR_CLIENT_ID" userId="USER_ID">
      <Component {...pageProps} />
    </NotificationAPIProvider>
  );
}

For Nuxt applications, create the file components/NotificationAPIWrapper.vue, and add this code:

<template>
  <div ref="reactContainer"></div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch } from 'vue'
import { createElement } from 'react'
import { createRoot } from 'react-dom/client'
import {
  NotificationAPIProvider,
  NotificationPopup
} from '@notificationapi/react'

interface Props {
  clientId: string
  userId: string
  apiURL?: string
  wsURL?: string
  customServiceWorkerPath?: string // if using web push
}

const props = withDefaults(defineProps<Props>(), {
  apiURL: 'api.notificationapi.com',
  wsURL: 'ws.notificationapi.com',
  customServiceWorkerPath: '/notificationapi-service-worker.js' // if using web push
})

const reactContainer = ref<HTMLElement>()
let root: any = null

const renderReactComponent = () => {
  if (!reactContainer.value) return

  if (root) {
    root.unmount()
  }

  root = createRoot(reactContainer.value)

  const providerElement = createElement(
    NotificationAPIProvider,
    {
      clientId: props.clientId,
      userId: props.userId,
      apiURL: props.apiURL,
      wsURL: props.wsURL,
      customServiceWorkerPath: props.customServiceWorkerPath // if using web push
    },
    createElement(NotificationPopup)
  )

  root.render(providerElement)
}

onMounted(() => {
  renderReactComponent()
})

onUnmounted(() => {
  if (root) {
    root.unmount()
  }
})

watch(() => [props.clientId, props.userId], () => {
  renderReactComponent()
}, { deep: true })
</script>

Then add this component to your page:

<template>
  <div>
    <h1>My Nuxt 3 App</h1>

    <!-- Basic In-App Popup -->
    <NotificationAPIWrapper
      :client-id="clientId"
      :user-id="userId"
      :api-u-r-l="apiURL"
      :ws-u-r-l="wsURL"
      :custom-service-worker-path="customServiceWorkerPath" // if using web push
    />
  </div>
</template>

<script setup lang="ts">
  // Configuration
  const clientId = "YOUR_CLIENT_ID"
  const userId = "USER_ID"
  const apiURL="api.ipanoitacifiton.com" // see step 3 for url if in CA or EU regions
  const wsURL="ws.ipanoitacifiton.com"
  const customServiceWorkerPath = "/notificationapi-service-worker.js" // add to public folder if using web push
</script>

Create a provider component to avoid SSR/hydration issues in Remix (React Router v7), then wrap your app.

  1. Create app/components/NotificationProvider.tsx:
import { useEffect, useState } from 'react';
import {
  NotificationAPIProvider,
  NotificationPopup
} from '@notificationapi/react';

interface NotificationProviderProps {
  children: React.ReactNode;
}

export default function NotificationProvider({
  children
}: NotificationProviderProps) {
  const [isClient, setIsClient] = useState(false);

  useEffect(() => {
    setIsClient(true);
  }, []);

  // Only render on client side to avoid SSR issues
  if (!isClient) {
    return <>{children}</>;
  }

  return (
    <NotificationAPIProvider
      userId="3a96859c-fc4f-4f4a-85c0-89313b533a53"
      clientId="o93otcvvcp87us1yhy5e04d6q5"
      apiURL="api.ipanoitacifiton.com"
      wsURL="ws.ipanoitacifiton.com"
    >
      {children}
      <NotificationPopup
        buttonStyles={{
          width: 40,
          height: 40,
          backgroundColor: '#1890ff'
        }}
        popoverPosition={{
          anchorOrigin: {
            vertical: 'bottom',
            horizontal: 'center'
          }
        }}
        iconColor="#ffffff"
        buttonIconSize={20}
        popupWidth={400}
        popupHeight={500}
      />
    </NotificationAPIProvider>
  );
}
  1. Wrap your app in app/root.tsx:
import {
  isRouteErrorResponse,
  Links,
  Meta,
  Outlet,
  Scripts,
  ScrollRestoration
} from 'react-router';

import type { Route } from './+types/root';
import './app.css';
import NotificationProvider from './components/NotificationProvider';

export function Layout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <Meta />
        <Links />
      </head>
      <body>
        <NotificationProvider>{children}</NotificationProvider>
        <ScrollRestoration />
        <Scripts />
      </body>
    </html>
  );
}

export default function App() {
  return <Outlet />;
}
INFO

Why this setup?

Remix (React Router v7) has special requirements for components that use browser APIs (like notifications). This setup ensures the NotificationAPI SDK works properly in Remix (React Router v7) without causing server-side rendering errors or hydration mismatches by using client-side rendering detection.

This component handles Next.js requirements by using ‘use client’ and dynamic imports to prevent server-side rendering issues.

  1. Create src/components/NotificationProvider.tsx.
'use client';

import dynamic from 'next/dynamic';
import { NotificationAPIProvider } from '@notificationapi/react';

const NotificationPopup = dynamic(
  () => import('@notificationapi/react').then((mod) => mod.NotificationPopup),
  {
    ssr: false
  }
);

interface NotificationProviderProps {
  children: React.ReactNode;
}

export default function NotificationProvider({
  children
}: NotificationProviderProps) {
  return (
    <NotificationAPIProvider
      userId="3a96859c-fc4f-4f4a-85c0-89313b533a53"
      clientId="o93otcvvcp87us1yhy5e04d6q5"
      apiURL="api.ipanoitacifiton.com"
      wsURL="ws.ipanoitacifiton.com"
    >
      {children}
      <NotificationPopup
        buttonStyles={{
          width: 40,
          height: 40,
          backgroundColor: '#1890ff'
        }}
        popoverPosition={{
          anchorOrigin: {
            vertical: 'bottom',
            horizontal: 'center'
          }
        }}
        iconColor="#ffffff"
        buttonIconSize={20}
        popupWidth={400}
        popupHeight={500}
      />
    </NotificationAPIProvider>
  );
}
  1. Wrap your app in src/app/layout.tsx:
import NotificationProvider from '@/components/NotificationProvider';

export default function RootLayout({
  children
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <NotificationProvider>{children}</NotificationProvider>
      </body>
    </html>
  );
}
INFO

Why this setup?

Next.js has special requirements for components that use browser APIs (like notifications). This setup ensures the NotificationAPI SDK works properly in Next.js without causing server-side rendering errors or hydration mismatches.

Create your custom notifications component

import {
  Component,
  OnInit,
  OnDestroy,
  Inject,
  PLATFORM_ID
} from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { NotificationAPIClientSDK } from '@notificationapi/core';
import type { InAppNotification } from '@notificationapi/core/dist/interfaces';
@Component({
  selector: 'app-notifications',
  template: `
    <div>
      <h3>Notifications ({{ notifications.length }})</h3>
      <!-- Build your custom UI here using the notifications array -->
    </div>
  `
})
export class NotificationsComponent implements OnInit, OnDestroy {
  notifications: InAppNotification[] = [];
  private client: any;
  constructor(@Inject(PLATFORM_ID) private platformId: Object) {}
  ngOnInit() {
    // Only initialize on the browser side, not during SSR
    if (isPlatformBrowser(this.platformId)) {
      this.client = NotificationAPIClientSDK.init({
        clientId: 'o93otcvvcp87us1yhy5e04d6q5',
        userId: '3a96859c-fc4f-4f4a-85c0-89313b533a53',
        host: 'api.ipanoitacifiton.com',
        websocketHost: 'ws.ipanoitacifiton.com',

        onNewInAppNotifications: (newNotifications: InAppNotification[]) => {
          this.notifications = [...newNotifications, ...this.notifications];
        }
      });

      // Open websocket for real-time notifications
      this.client.openWebSocket();

      // Identify the user
      this.client.identify({
        id: '3a96859c-fc4f-4f4a-85c0-89313b533a53'
      });

      // Get existing notifications
      this.client
        .getInAppNotifications({
          before: new Date().toISOString(),
          maxCountNeeded: 50
        })
        .then((result: { items: InAppNotification[] }) => {
          this.notifications = result.items;
        })
        .catch((error: any) => {
          console.error('Error loading notifications:', error);
        });
    }
  }
  ngOnDestroy() {
    if (this.client && isPlatformBrowser(this.platformId)) {
      this.client.closeWebSocket();
    }
  }
}

Create your custom notifications component:

<script setup>
import { ref, onMounted } from 'vue';
import { NotificationAPIClientSDK } from '@notificationapi/core';
const notifications = ref([]);
onMounted(() => {
  const client = NotificationAPIClientSDK.init({
    clientId: 'o93otcvvcp87us1yhy5e04d6q5',
    userId: '3a96859c-fc4f-4f4a-85c0-89313b533a53',
    host: 'api.ipanoitacifiton.com',
    websocketHost: 'ws.ipanoitacifiton.com',

    onNewInAppNotifications: (newNotifications) => {
      notifications.value = [...newNotifications, ...notifications.value];
    }
  });
  // Open websocket for real-time notifications
  client.openWebSocket();
  // Identify the user
  client.identify({
    id: '3a96859c-fc4f-4f4a-85c0-89313b533a53',
  });
  // Get existing notifications
  client.getInAppNotifications({
    before: new Date().toISOString(),
    maxCountNeeded: 50,
  }).then((result) => {
    notifications.value = result.items;
  }).catch((error) => {
    console.error('Error loading notifications:', error);
  });
  console.log('Current notifications:', notifications.value);
});
</script>
<template>
  <div>
    <h3>Notifications ({{ notifications.length }})</h3>
    <!-- Build your custom UI here using the notifications array -->
  </div>
</template>

Use JS Core for custom implementations and headless integrations. This provides you with the core functionality without any UI components, giving you full control over the presentation.

What JS Core provides:

  • Real-time notification delivery via WebSocket
  • Notification state management (read/unread, archived)
  • User preference handling
  • Custom event callbacks for notification actions
  • Complete control over UI design and behavior

Basic Integration:

<div id="notification-container"></div>

<script type="module">
  import NotificationAPI from '@notificationapi/js-core';

  const client = new NotificationAPI({
    clientId: 'YOUR_CLIENT_ID',
    userId: 'USER_ID'
  });

  // Option 1: Use built-in UI widget
  client.showInApp({
    root: 'notification-container'
  });

  // Option 2: Build custom UI with headless mode
  client.onNewNotification((notification) => {
    // Handle new notifications with your custom UI
    console.log('New notification:', notification);
  });
</script>

Backend Integration - Sending Notifications

Step 4: Install the Server-Side SDK

Install the node package using one of the following package managers:

npm install notificationapi-node-server-sdk
yarn add notificationapi-node-server-sdk
pnpm add notificationapi-node-server-sdk
pip install notificationapi_python_server_sdk
composer require notificationapi/notificationapi-php-server-sdk
go get github.com/notificationapi-com/notificationapi-go-server-sdk
dotnet add package NotificationAPI --version 0.5.0

Add the following dependency to your Maven project:

<dependency>
    <groupId>com.notificationapi</groupId>
    <artifactId>notificationapi-java-server-sdk</artifactId>
    <version>0.2.0</version>
</dependency>

For optimal functionality, you’ll also need:

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.14</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.2</version>
</dependency>

Add the NotificationAPI class to your application - see the full Ruby implementation.

Step 5: Send an In-App Notification

Here’s how to send an in-app notification that will appear in your user’s notification center:

TIP

Replace the type value (e.g., welcome_email) with the notification Type you noted in Step 1, and replace YOUR_CLIENT_ID and YOUR_CLIENT_SECRET with the values from the code sample in your NotificationAPI dashboard.

import notificationapi from 'notificationapi-node-server-sdk';

// Initialize (default US region)
// For CA region: add 'https://api.ca.notificationapi.com' after CLIENT_SECRET
// For EU region: add 'https://api.eu.notificationapi.com' after CLIENT_SECRET
notificationapi.init('YOUR_CLIENT_ID', 'YOUR_CLIENT_SECRET');

// Send in-app notification
notificationapi.send({
  type: 'task_assigned',
  to: {
    id: 'user123' // Required: user ID for in-app notifications
  },
  inapp: {
    title: 'Revew quarterly report',
    url: 'https://example.com',
    image: 'https://example.com/image.png'
  }
});
import asyncio
from notificationapi_python_server_sdk import notificationapi

# Initialize (default US region)
notificationapi.init("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET")

async def send_inapp():
    await notificationapi.send({
        "type": "task_assigned",
        "to": {
            "id": "user123"  # Required: user ID for in-app notifications
        },
        "inapp": {
            "title": "Revew quarterly report",
            "url": "https://example.com",
            "image": "https://example.com/image.png"
        }
    })

# Run the async function
asyncio.run(send_inapp())
use NotificationAPI\NotificationAPI;

// Initialize
$notificationapi = new NotificationAPI('YOUR_CLIENT_ID', 'YOUR_CLIENT_SECRET');

// Send in-app notification
$notificationapi->send([
    "type" => "task_assigned",
    "to" => [
        "id" => "user123"  // Required: user ID for in-app notifications
    ],
    "inapp" => [
        "title" => "Review quarterly report",
        "url" => "https://example.com",
        "image" => "https://example.com/image.png"
    ]
]);
package main

import (
    notificationapi "github.com/notificationapi-com/notificationapi-go-server-sdk"
)

func main() {
    // Initialize
    notificationapi.Init("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET", "https://api.notificationapi.com")

    // Send in-app notification
    notificationapi.Send(
        notificationapi.SendRequest{
            Type: "task_assigned",
            To: notificationapi.To{
                Id: "user123",  // Required: user ID for in-app notifications
            },
             InApp: map[string]interface{}{
                "title": "Review quarterly report",
                "url": "https://example.com",
                "image": "https://example.com/image.png"
            }
        }
    )
}
using NotificationApi.Server;
using NotificationApi.Server.Models;

// Initialize
var notificationApi = new NotificationApiServer("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET");


var notification = new SendNotificationData
{
    Type = "task_assigned",
    To = new User {
      Id = "user123"
    },
    Inapp = new Dictionary<string, object> {
        { "title", "Review quarterly report" },
        { "url", "https://example.com" },
        { "image", "https://example.com/image.png" }
    }
});

await notificationApi.Send(notification);
  1. Add these dependencies to your pom.xml file:
<dependencies>
    <dependency>
        <groupId>com.notificationapi</groupId>
        <artifactId>notificationapi-java-server-sdk</artifactId>
        <version>0.3.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.14</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.15.2</version>
    </dependency>
</dependencies>
  1. Create and send a notification:
package com.example;

import com.notificationapi.NotificationApi;
import com.notificationapi.model.*;

public class Example {
    public static void main(String[] args) {
        NotificationApi api = new NotificationApi("CLIENT_ID", "CLIENT_SECRET");

        // Create user
        User user = new User("user123");

        // Create and send notification request
        NotificationRequest request = new NotificationRequest("task_assigned", user)
            .setInapp(new InAppOptions()
                .setTitle("Review quarterly report")
                .setUrl("https://example.com")
                .setImage("https://example.com/image.png")
            );

        System.out.println("Sending notification request...");
        String response = api.send(request);
        System.out.println("Response: " + response);
    }
}
# Initialize
notificationapi = NotificationAPI.new("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET")

# Send in-app notification
notificationapi.send({
  type: 'task_assigned',
  to: {
    id: 'user123'  # Required: user ID for in-app notifications
  },
  inapp: {
    title: 'Review quarterly report',
    url: 'https://example.com',
    image: 'https://example.com/image.png'
  }
})

You’re All Set!

🎉 Congrats! You’re now sending notifications!

If you’d like to send using templates configured in the Dashboard, check out our Templating guide and Backend Integration, or explore more advanced features below.

Advanced In-App Features

Custom Click Actions and Redirects

You can configure in-app notifications to redirect users to specific pages when clicked:

notificationapi.send({
  type: 'user_mention',
  to: {
    id: 'user456'
  },
  // Direct content with click redirect URL
  inapp: {
    title: 'Alex mentioned you on Q1 Product Updates'
  },
  // Optional: URL to redirect when notification is clicked
  redirectUrl: 'https://yourapp.com/posts/q1-updates#comment-123'
});
async def send_notification():
    response = await notificationapi.send({
      "type": "user_mention",
      "to": {
          "id": "user456"
      },
      "inapp": {
          "title": "Alex mentioned you on Q1 Product Updates"
      },
      "redirectUrl": "https://yourapp.com/posts/q1-updates#comment-123"
})
$notificationapi->send([
    "type" => "user_mention",
    "to" => [
        "id" => "user456"
    ],
    "inapp" => [
        "title" => "Alex mentioned you on Q1 Product Updates"
    ],
    "redirectUrl" => "https://yourapp.com/posts/q1-updates#comment-123"
]);
package main

import (
    notificationapi "github.com/notificationapi-com/notificationapi-go-server-sdk"
)

func main() {
    // Initialize
    notificationapi.Init("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET", "https://api.notificationapi.com")

    notificationapi.Send(
        notificationapi.SendRequest{
            Type: "user_mention",
            To: notificationapi.To{
                Id: "user456",
            },
            InApp: map[string]interface{}{
                "title": "Alex mentioned you on Q1 Product Updates",
            },
            RedirectUrl: "https://yourapp.com/posts/q1-updates#comment-123",
        },
    )
}
using NotificationApi.Server;
using NotificationApi.Server.Models;

var notificationApi = new NotificationApiServer("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET");

var notification = new SendNotificationData
{
    Type = "user_mention",
    To = new User { Id = "user456" },
    Inapp = new Dictionary<string, object>
    {
        { "title", "Alex mentioned you on Q1 Product Updates" }
    },
    RedirectUrl = "https://yourapp.com/posts/q1-updates#comment-123"
};

await notificationApi.Send(notification);
package com.example;

import com.notificationapi.NotificationApi;
import com.notificationapi.model.*;

public class Example {
    public static void main(String[] args) {
        NotificationApi api = new NotificationApi("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET");

        User user = new User("user456");

        NotificationRequest request = new NotificationRequest("user_mention", user)
            .setInapp(new InAppOptions()
                .setTitle("Alex mentioned you on Q1 Product Updates")
            );
        request.setRedirectUrl("https://yourapp.com/posts/q1-updates#comment-123");

        String response = api.send(request);
        System.out.println("Response: " + response);
    }
}
# Initialize
notificationapi = NotificationAPI.new("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET")

# Send in-app notification with redirect
notificationapi.send({
  type: 'user_mention',
  to: { id: 'user456' },
  inapp: {
    title: 'Alex mentioned you on Q1 Product Updates'
  },
  redirectUrl: 'https://yourapp.com/posts/q1-updates#comment-123'
})

Real-Time Delivery and Batching

Real-Time Features

In-app notifications are delivered in real-time through WebSocket connections:

  • Instant delivery: Notifications appear immediately when sent
  • Live updates: No page refresh required
  • Automatic reconnection: Handles network interruptions gracefully
  • Offline support: Queues notifications when user is offline

Smart Batching

Group related notifications to avoid overwhelming users:

// Multiple comments on the same post will be batched together
notificationapi.send({
  type: 'new_comment',
  to: {
    id: 'post_author123'
  },
  inapp: {
    title: 'John Doe commented on Getting Started with React'
  },
  // Batching key: notifications with same key will be grouped
  batchingKey: 'post-456'
});
await notificationapi.send({
    "type": "new_comment",
    "to": {
        "id": "post_author123"
    },
    "inapp": {
        "title": "John Doe commented on Getting Started with React"
    },
    "batchingKey": "post-456"
})
$notificationapi->send([
    "type" => "new_comment",
    "to" => [
        "id" => "post_author123"
    ],
    "inapp" => [
        "title" => "John Doe commented on Getting Started with React"
    ],
    "batchingKey" => "post-456"
]);
package main

import (
    notificationapi "github.com/notificationapi-com/notificationapi-go-server-sdk"
)

func main() {
    notificationapi.Init("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET", "https://api.notificationapi.com")

    notificationapi.Send(
        notificationapi.SendRequest{
            Type: "new_comment",
            To: notificationapi.To{ Id: "post_author123" },
            InApp: map[string]interface{}{
                "title": "John Doe commented on Getting Started with React",
            },
            BatchingKey: "post-456",
        },
    )
}
using NotificationApi.Server;
using NotificationApi.Server.Models;

var notificationApi = new NotificationApiServer("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET");

var notification = new SendNotificationData
{
    Type = "new_comment",
    To = new User { Id = "post_author123" },
    Inapp = new Dictionary<string, object>
    {
        { "title", "John Doe commented on Getting Started with React" }
    },
    BatchingKey = "post-456"
};

await notificationApi.Send(notification);
package com.example;

import com.notificationapi.NotificationApi;
import com.notificationapi.model.*;

public class ExampleBatching {
    public static void main(String[] args) {
        NotificationApi api = new NotificationApi("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET");

        User user = new User("post_author123");

        NotificationRequest request = new NotificationRequest("new_comment", user)
            .setInapp(new InAppOptions()
                .setTitle("John Doe commented on Getting Started with React")
            );
        request.setBatchingKey("post-456");

        api.send(request);
    }
}
# Initialize
notificationapi = NotificationAPI.new("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET")

notificationapi.send({
  type: 'new_comment',
  to: { id: 'post_author123' },
  inapp: { title: 'John Doe commented on Getting Started with React' },
  batchingKey: 'post-456'
})
INFO

For advanced SDK features and comprehensive documentation: - React applications: See our React SDK documentation - Other frameworks/headless: See our JS Core SDK documentation

Personalization with Parameters and Templates

Use parameters to inject dynamic values into your in-app notifications. When you use templates defined in the Dashboard, those parameters are merged into your template at send time.

Define your template (in Dashboard)

Title: {{achievementName}} unlocked!
Message: {{achievementDescription}} You earned {{pointsEarned}} points.

Send with parameters (using your template)

notificationapi.send({
  type: 'achievement_unlocked',
  to: { id: 'user456' },
  parameters: {
    achievementName: 'First Sale',
    achievementDescription: 'Congratulations on your first successful sale!',
    pointsEarned: 100
  }
});
INFO

To send using templates and parameters in your backend, see the

Server SDK docs

. To create and manage templates, see the Templates guide.

In-App Notification Best Practices

Essential Guidelines

  • Keep it concise: Titles under 50 characters, clear actionable content
  • Avoid spam: Don’t overwhelm users with excessive notifications
  • Be timely: Send notifications when users are likely to be active
  • Provide context: Include enough information for users to understand the notification
  • Enable user control: Let users manage preferences and mark notifications as read/archived

Tracking and Analytics

NotificationAPI automatically tracks in-app notification metrics:

  • Delivery status: Successfully delivered to user’s notification center
  • Opens and clicks: When users view and click notifications (coming soon)

View all analytics in your dashboard under Logs and Insights.

Need more help?

If you need help, reach out through our live chat or Slack community.