A TypeScript client library for Salesforce's Messaging for In-App and Web APIs.
This is a personal project and not an official Salesforce product. It is not officially supported by Salesforce.
- TypeScript support with full type definitions
- Token management for both authenticated and unauthenticated sessions
- Conversation management (create, close, end sessions)
- Real-time messaging with Server-Sent Events (SSE)
- Typing indicators
- Message receipts (delivery and read receipts)
- File upload support (up to 5MB)
- Logging support
- Request timeout handling
This project uses npm as its package manager.
npm install miaw-api-clientimport { MessagingClient } from 'miaw-api-client';
// Initialize the client
const client = new MessagingClient({
baseUrl: 'YOUR_BASE_URL',
orgId: 'YOUR_ORG_ID',
developerName: 'YOUR_DEVELOPER_NAME',
// Optional: Custom logger
logger: console,
// Optional: Default request timeout in milliseconds
timeout: 30000,
});
// Create a token
const { accessToken, lastEventId } = await client.createToken();
// Create a conversation
const { id: conversationId } = await client.createConversation(accessToken);
// Send a message
const messageEntries = await client.sendMessage(accessToken, conversationId, {
text: 'Hello, world!',
});
// Stream conversation events
const eventStream = client.createEventStream(accessToken, {
lastEventId: lastEventId || '0',
onEvent: event => {
console.log('Received event:', event);
},
onOpen: () => {
console.log('Connection opened');
},
onError: error => {
console.error('Stream error:', error);
},
});
// Send typing indicator
await client.sendTypingIndicator(accessToken, conversationId, true);
// Send a file
const fileEntries = await client.uploadFile(accessToken, conversationId, {
fileData: new Blob(['Hello World'], { type: 'text/plain' }),
fileName: 'hello.txt',
text: 'Here is a file for you!',
});
// Send delivery receipts
await client.sendReceipt(accessToken, conversationId, {
entries: [
{
type: 'Delivery',
conversationEntryId: 'MESSAGE_ID',
},
],
});
// End session or close conversation
await client.endSession(accessToken, conversationId);
// or
await client.closeConversation(accessToken, conversationId);
// Later, when you need to clean up:
if (eventStream) {
eventStream.close();
}interface MessagingInAppWebConfig {
baseUrl: string; // Required: Custom Client instance URL
orgId: string; // Required: Salesforce organization ID
developerName: string; // Required: Custom Client developer name
logger?: Logger; // Optional: Custom logger implementation
appName?: string; // Application name (defaults to 'MessagingInAppWebClient')
timeout?: number; // Optional: Default request timeout in milliseconds (defaults to 30000)
}Creates a new access token for interacting with the messaging API.
interface TokenCreateParams {
capabilitiesVersion?: string; // API capabilities version (defaults to '1')
platform?: 'Web' | 'Mobile'; // Platform type (defaults to 'Web')
deviceId?: string; // Unique device identifier
context?: {
appName: string; // Application name (defaults to 'MessagingInAppWebClient')
clientVersion: string; // Client version (defaults to '1.0.0')
};
authorizationType?: string; // Required for authenticated sessions
customerIdentityToken?: string; // Required for authenticated sessions
}
const { accessToken, lastEventId } = await client.createToken(params);Refreshes an existing access token.
const { accessToken, lastEventId } = await client.refreshToken(token);Creates a new conversation with optional routing attributes.
interface ConversationCreateParams {
id?: string; // Optional custom ID for the conversation
routingAttributes?: Record<string, unknown>; // Optional routing parameters
}
const { id } = await client.createConversation(token, params);Closes an existing conversation.
const { success } = await client.closeConversation(token, conversationId);Ends the current messaging session for a conversation while keeping the conversation open.
const { success } = await client.endSession(token, conversationId);Sends a text message to a conversation.
interface MessageParams {
text: string; // Required: Message content
id?: string; // Optional: Custom message ID
isNewSession?: boolean; // Optional: Start a new messaging session
routingAttributes?: Record<string, unknown>; // Optional: Custom routing parameters
language?: string; // Optional: Message language code
}
const entries = await client.sendMessage(token, conversationId, params);Sends a typing indicator to a conversation.
// Start typing
await client.sendTypingIndicator(token, conversationId, true);
// Stop typing
await client.sendTypingIndicator(token, conversationId, false);Sends message receipts to a conversation.
interface ReceiptParams {
entries: {
id?: string; // Optional custom ID for the receipt
type?: 'Delivery' | 'Read'; // Type of receipt (defaults to 'Delivery')
conversationEntryId: string; // The message ID being acknowledged
}[];
}
await client.sendReceipt(token, conversationId, params);Uploads a file to a conversation (max 5MB).
interface FileUploadParams {
fileData: Blob; // Required: The file data as a Blob
id?: string; // Optional: Custom message ID
fileId?: string; // Optional: Custom file ID
text?: string; // Optional: Message text accompanying the file
fileName?: string; // Optional: File name
contentType?: string; // Optional: Content type of the file
inReplyToMessageId?: string; // Optional: Message ID this file is in reply to
routingAttributes?: Record<string, string>; // Optional: Custom routing parameters
isNewSession?: boolean; // Optional: Start a new messaging session
language?: string; // Optional: Message language code
}
const entries = await client.uploadFile(token, conversationId, params);Creates a Server-Sent Events (SSE) connection to receive real-time updates.
interface SSEOptions {
lastEventId?: string; // The last event ID received, for resuming the stream
onEvent: (event: MessageEvent) => void; // Callback for each message/event received
onOpen?: () => void; // Callback for when the connection is successfully opened
onError?: (event: Event) => void; // Callback for any error on the EventSource
}
const eventStream = client.createEventStream(token, options);
// To close the stream later:
eventStream.close();The client includes built-in error handling with typed errors. Each error contains a type, operation, and additional details.
try {
await client.sendMessage(token, conversationId, { text: 'Hello' });
} catch (error) {
console.error(`Error type: ${error.type}`);
console.error(`Operation: ${error.operation}`);
console.error(`Status code: ${error.statusCode}`);
console.error(`Details: ${error.details}`);
}Error types:
invalid_request_errorauthentication_errorpermission_errornot_found_errorconflict_errorrate_limit_errorapi_errortimeout_errorunknown_error