JavaScript
Notiflows JavaScript SDK for client-side notification integration
The JavaScript SDK (@notiflows/client) provides a client for interacting with the Notiflows User API. Use it to fetch notifications, manage notification state, and subscribe to real-time updates.
For React applications, we recommend using the React SDK which provides hooks and pre-built components on top of this client.
Installation
npm install @notiflows/client
# or
pnpm add @notiflows/client
# or
yarn add @notiflows/clientQuick Start
import { Notiflows } from '@notiflows/client';
// Initialize the client
const client = new Notiflows({
apiKey: 'pk_your_public_key',
userId: 'user_123',
userKey: 'jwt_token_from_backend',
});
// Get the notification feed
const feed = client.feed({ channelId: 'your-channel-id' });
// Fetch notifications
const collection = await feed.getEntries();
console.log(collection.items, collection.total_unread);
// Subscribe to real-time updates
feed.onDelivery = (entry) => {
console.log('New notification:', entry);
};
feed.subscribeToRealtimeNotifications();
// Mark as read
await feed.markAsRead('entry_id');Configuration
const client = new Notiflows({
// Required
apiKey: string, // Your public API key (starts with pk_)
userId: string, // The user's external ID
userKey: string, // JWT token signed with your signing key
// Optional
apiUrl?: string, // Custom API URL (default: https://api.notiflows.com/user/v1)
wsUrl?: string, // Custom WebSocket URL (default: wss://api.notiflows.com/ws/v1)
});The userKey must be generated on your backend using your Application Signing Key. Never expose your signing key in client-side code. See Generating User Tokens for instructions.
Feed
The Feed resource manages notification entries for a specific channel.
Creating a Feed Instance
const feed = client.feed({
channelId: 'your-in-app-channel-id',
});Fetching Entries
import { FeedEntryStatus } from '@notiflows/client';
// Get all notifications
const collection = await feed.getEntries();
// Access the data
const { items, total_unread, total_unseen } = collection;
// With filters
const unreadOnly = await feed.getEntries({
status: FeedEntryStatus.Unread,
limit: 20,
});
// With pagination
const collection = await feed.getEntries({ limit: 10 });
if (collection.has_more_after) {
const nextPage = await feed.getEntries({
limit: 10,
after: collection.after,
});
}
// Filter by notiflow
const welcomeNotifs = await feed.getEntries({
notiflowId: 'welcome-flow',
});
// Filter by topic
const orderNotifs = await feed.getEntries({
topic: 'order:123',
});
// Include archived
const withArchived = await feed.getEntries({
includeArchived: true,
});Real-time Updates
Subscribe to receive notifications as they're delivered:
// Set up handlers before subscribing
feed.onDelivery = (entry) => {
console.log('New notification:', entry);
// Add to your UI, play a sound, etc.
};
// Start listening for real-time updates
feed.subscribeToRealtimeNotifications();
// Stop listening when done
feed.stop();Updating Entry State
Mark notifications as seen, read, clicked, or archived:
// Single entry updates
await feed.markAsSeen(entryId);
await feed.markAsRead(entryId);
await feed.markAsClicked(entryId);
await feed.markAsArchived(entryId);
await feed.markAsUnarchived(entryId);
// Batch updates
await feed.batchMarkAsSeen([entryId1, entryId2]);
await feed.batchMarkAsRead([entryId1, entryId2]);
await feed.batchMarkAsClicked([entryId1, entryId2]);
await feed.batchMarkAsArchived([entryId1, entryId2]);
await feed.batchMarkAsUnarchived([entryId1, entryId2]);
// Generic update with multiple fields
await feed.updateEntry(entryId, {
read: true,
seen: true,
});
await feed.batchUpdateEntries([entryId1, entryId2], {
archived: true,
});User Preferences
Manage user notification preferences:
const preferences = client.userPreferences();
// Get current preferences
const prefs = await preferences.get();
console.log(prefs.notiflows); // Per-notiflow preferences
// Update preferences
await preferences.update({
notiflows: {
'marketing-emails': {
enabled: false,
},
},
});Types
FeedEntry
interface FeedEntry {
id: string;
data: {
body: string;
actionUrl?: string;
};
actor?: {
id: string;
email?: string;
first_name?: string;
last_name?: string;
avatar?: string;
};
seen_at: string | null;
read_at: string | null;
clicked_at: string | null;
archived_at: string | null;
created_at: string;
}FeedEntryCollection
interface FeedEntryCollection {
items: FeedEntry[];
total_unread: number;
total_unseen: number;
has_more_after: boolean;
after: string | null;
}FeedEntryStatus
enum FeedEntryStatus {
Unseen = 'unseen',
Unread = 'unread',
Read = 'read',
Archived = 'archived',
}Preferences
interface Preferences {
notiflows: {
[notiflowId: string]: {
name: string;
enabled: boolean;
};
};
}Error Handling
The SDK provides typed errors for different API responses:
import {
isApiError,
BadRequestError,
UnauthenticatedError,
ForbiddenError,
NotFoundError,
RateLimitedError,
ValidationFailedError,
ConflictError,
InternalError,
ServiceUnavailableError,
} from '@notiflows/client';
try {
await feed.getEntries();
} catch (error) {
if (isApiError(error)) {
console.log(error.code); // Error code
console.log(error.message); // Error message
console.log(error.details); // Additional details
if (error instanceof UnauthenticatedError) {
// Redirect to login or refresh token
} else if (error instanceof RateLimitedError) {
// Back off and retry
} else if (error instanceof ValidationFailedError) {
// Check error.details for field-level errors
}
}
}Error Types
| Error | HTTP Status | Description |
|---|---|---|
BadRequestError | 400 | Invalid request parameters |
UnauthenticatedError | 401 | Invalid or missing authentication |
ForbiddenError | 403 | Insufficient permissions |
NotFoundError | 404 | Resource not found |
ConflictError | 409 | Resource state conflict |
ValidationFailedError | 422 | Validation errors on request body |
RateLimitedError | 429 | Too many requests |
InternalError | 500 | Server error |
ServiceUnavailableError | 503 | Service temporarily unavailable |
TypeScript
The SDK is written in TypeScript and exports all types:
import type {
FeedEntry,
FeedEntryCollection,
FeedEntryStatus,
GetEntriesParams,
EntryStateUpdate,
Preferences,
NotiflowsOptions,
} from '@notiflows/client';Browser Support
The SDK supports all modern browsers (ES2022+) and Node.js 18+.
For older browsers, you may need to polyfill:
Promisefetch(if using Node.js < 18)
Next Steps
- React SDK - Pre-built components and hooks for React
- Authentication - Learn about user token generation
- API Reference - Full User API documentation