In-App Chat SDK
Beta
SDK + REST

Getting Started

Go from zero to a live chat session: mint a user token on your backend, install the client SDK, connect over WebSocket, and send your first message.

1. Server token

Authenticate with Basic Auth and mint a user token via POST /v1/chat-sdk/users/token.

2. Install SDK

Add @sendexa/chat-sdk to your web or React Native app. One package for both runtimes.

3. Connect

Call init with the user token, then connect() to open the managed WebSocket session.

4. Send & listen

Use sendMessage and on('message') to exchange messages in real time.

Install

npm

@sendexa/chat-sdk

First message

<5 min

with a test channel

Runtimes

2

Web + React Native

Transport

WSS

TLS WebSocket

Prerequisites

  • A Sendexa account with Chat SDK enabled (Beta). Copy the Base64 dashboard token from the dashboard for server calls.
  • A backend that can authenticate your app users (session, JWT, OAuth, etc.). Chat tokens must only be issued after that check succeeds.
  • Node.js 18+ (or a modern browser / React Native 0.72+) for the client package.

Step 1 — Mint a user token

Your server calls Sendexa with the dashboard Basic Auth credential and receives a short-lived user token. That token is the only credential the client ever sees.

POST
/v1/chat-sdk/users/token
FieldTypeRequiredDescription
userIdstring
required
Stable id for this user in your system (max 128 chars). Used for membership and message authorship.
displayNamestringoptionalHuman-readable name shown in chat UIs (max 80 chars). Can be updated on later mints.
ttlnumberoptionalToken lifetime in seconds. Default 3600. Allowed range: 300–86400 (5 minutes–24 hours).
Bash
curl -X POST 'https://api.sendexa.co/v1/chat-sdk/users/token' \
-H 'Content-Type: application/json' \
-H 'Authorization: Basic YOUR_DASHBOARD_BASE64_TOKEN' \
-d '{
"userId": "user_01HZX9K2M",
"displayName": "Ama Mensah",
"ttl": 3600
}'
Success response
{
"success": true,
"code": "CHAT_USER_TOKEN_ISSUED",
"message": "User chat token minted.",
"requestId": "REQ-1782001100001",
"timestamp": "2026-07-12T10:00:00.000Z",
"data": {
"userId": "user_01HZX9K2M",
"displayName": "Ama Mensah",
"token": "chat_usr_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJ1c2VyXzAxSFpYOUsyTSIsImV4cCI6MTc4Mzg1NDgwMH0.signature",
"expiresAt": "2026-07-12T11:00:00.000Z",
"ttl": 3600
}
}

Step 2 — Install the client SDK

Bash
npm install @sendexa/chat-sdk

Step 3 — Init, connect, and listen

Fetch the user token from your API, initialise the SDK, open the socket, and subscribe to events before sending.

chat-client.js
import { SendexaChat } from '@sendexa/chat-sdk';
async function startChat() {
// 1) Get a short-lived token from YOUR backend
const { token, expiresAt } = await fetch('/api/chat/token', {
method: 'POST',
credentials: 'include',
}).then((r) => r.json());
// 2) Initialise the SDK
const chat = SendexaChat.init({
token,
// Optional overrides (defaults shown):
// apiUrl: 'https://api.sendexa.co',
// wsUrl: 'wss://chat.sendexa.co/v1/ws',
// autoReconnect: true,
// logLevel: 'warn',
});
// 3) Register handlers BEFORE connect so you never miss events
chat.on('connected', () => {
console.log('Chat connected');
});
chat.on('disconnected', ({ reason }) => {
console.warn('Chat disconnected', reason);
});
chat.on('message', (message) => {
// message: { id, channelId, userId, body, createdAt, metadata? }
console.log(`[${message.channelId}] ${message.userId}: ${message.body}`);
});
chat.on('error', (err) => {
console.error('Chat error', err.code, err.message);
});
// 4) Open the WebSocket
await chat.connect();
// 5) Schedule a refresh before expiry (example: 60s early)
const msUntilRefresh =
new Date(expiresAt).getTime() - Date.now() - 60_000;
if (msUntilRefresh > 0) {
setTimeout(async () => {
const next = await fetch('/api/chat/token', {
method: 'POST',
credentials: 'include',
}).then((r) => r.json());
await chat.updateToken(next.token);
}, msUntilRefresh);
}
return chat;
}
const chat = await startChat();

Step 4 — Create a channel and send

Channels are usually created by your server so membership stays authoritative. Then any member can send messages from the client or REST.

POST
/v1/chat-sdk/channels
Bash
curl -X POST 'https://api.sendexa.co/v1/chat-sdk/channels' \
-H 'Content-Type: application/json' \
-H 'Authorization: Basic YOUR_DASHBOARD_BASE64_TOKEN' \
-d '{
"type": "dm",
"name": "Support · Ama",
"memberIds": ["user_01HZX9K2M", "agent_support_01"],
"metadata": {
"ticketId": "TCK-1042"
}
}'
sendMessage result / on('message') payload
{
"id": "msg_01HZYB8P",
"channelId": "ch_01HZYA3N",
"userId": "user_01HZX9K2M",
"body": "Hi — I need help with my order.",
"type": "text",
"metadata": {
"clientMessageId": "local-uuid-1"
},
"createdAt": "2026-07-12T10:05:12.441Z",
"seq": 1
}

Presence, typing & read receipts

Once connected, the same client instance exposes lightweight real-time helpers. Full detail lives on the Channels & Messages page.

JavaScript
// Presence
chat.on('presence', ({ userId, status, lastSeenAt }) => {
// status: 'online' | 'away' | 'offline'
console.log(userId, status, lastSeenAt);
});
// Typing
await chat.startTyping('ch_01HZYA3N');
// stops automatically after ~3s, or call stopTyping
chat.on('typing', ({ channelId, userId, isTyping }) => {
console.log(channelId, userId, isTyping);
});
// Read receipts
await chat.markRead({
channelId: 'ch_01HZYA3N',
messageId: 'msg_01HZYB8P', // or omit to mark latest
});
chat.on('read', ({ channelId, userId, messageId, readAt }) => {
console.log('Read by', userId, messageId, readAt);
});
Integration Checklist
  1. Enable Chat SDK on your Sendexa business and copy the Basic Auth token
  2. Implement POST /api/chat/token (or equivalent) that calls /v1/chat-sdk/users/token
  3. Install @sendexa/chat-sdk and wire init + connect
  4. Create at least one channel with known member ids for testing
  5. Send a message from the client and confirm on('message') on a second device/session
  6. Configure webhooks for server-side events