Generate Token Pair
A token pair provides the authentication credentials required for subscribers to establish WebSocket connections to a Data Streams channel.
Before you begin, ensure you have created a channel, configured access control, and an Advanced I/O function to host the token generation endpoint.
A token pair contains the WebSocket server URL (url), session identifier (wss-id, passed as zuid when you open the WebSocket), authentication key (key), and channel ID (channel-id).
Create Token Generation Endpoint
Create an Advanced I/O function that generates and returns token pairs to clients. Which identifier you use depends on the channel’s access control: use User ID for channels with User Roles (authenticated users with Catalyst Authentication), and Connection Name for channels with Custom Logic. For Custom Logic channels, generate the token pair from the Advanced I/O function configured as the channel’s access control source.
| Parameter | Type | Description |
|---|---|---|
| channelId | string | The unique identifier of the channel to subscribe to |
| userId | string / Long (Java) | The Catalyst project user ID. Use for channels with User Roles access control. |
| connectionName | string | Custom connection identifier. Use for channels with Custom Logic access control, from the configured function. |
const { zcAuth } = require('@zcatalyst/auth');
const { DataStreams } = require('@zcatalyst/datastreams');
module.exports = async (req, res) => {
// Initialize the SDK from the incoming request before using any component
const app = await zcAuth.init(req);
const datastreams = new DataStreams(app);
// Option 1: Using a user ID (for authenticated users)
const tokenByUser = await datastreams.getTokenPair('YOUR_CHANNEL_ID', {
userId: 'YOUR_USER_ID'
});
// Option 2: Using a connection name (for anonymous users)
const tokenByName = await datastreams.getTokenPair('YOUR_CHANNEL_ID', {
connectionName: 'YOUR_CONNECTION_NAME'
});
// Return token pair to client
res.setHeader('Content-Type', 'application/json');
res.writeHead(200);
res.end(JSON.stringify({ status: 'success', data: tokenByUser }));
};
import com.zc.component.datastream.ZCDatastream;
import com.zc.component.datastream.beans.ZCTokenResponse;
ZCDatastream datastream = ZCDatastream.getInstance();
// Option 1: Using a user ID (Long type for authenticated users)
Long userId = 30772000000631094L;
ZCTokenResponse tokenByUser = datastream.getTokenPair("YOUR_CHANNEL_ID", userId);
// Option 2: Using a connection name (String type for anonymous users)
ZCTokenResponse tokenByName = datastream.getTokenPair("YOUR_CHANNEL_ID", "YOUR_CONNECTION_NAME");
// Return tokenByUser or tokenByName to client
import zcatalyst_sdk
app = zcatalyst_sdk.initialize_app()
data_streams = app.datastreams()
# Option 1: Using a user ID (for authenticated users)
token_by_user = data_streams.get_token_pair("YOUR_CHANNEL_ID", user_id="YOUR_USER_ID")
# Option 2: Using a connection name (for anonymous users)
token_by_name = data_streams.get_token_pair("YOUR_CHANNEL_ID", connection_name="YOUR_CONNECTION_NAME")
# Return token to client
Deploy and Test
To deploy and test your token generation endpoint:
- Deploy your Advanced I/O function
- Call the function endpoint from your client application
- The client receives the token pair response:
{
"url": "wss://datastreams.zoho.com",
"wss-id": "abc123sessionid",
"key": "authentication_key_here",
"channel-id": "1234567890"
}
Example Implementation
Server (Advanced I/O Function):
const { zcAuth } = require('@zcatalyst/auth');
const { DataStreams } = require('@zcatalyst/datastreams');
// Advanced I/O functions receive Node’s raw request and response objects,
// so read the JSON body and write the JSON response yourself.
const readJson = (req) => new Promise((resolve, reject) => {
let raw = ‘’;
req.on(‘data’, (chunk) => (raw += chunk));
req.on(’end’, () => {
try { resolve(raw ? JSON.parse(raw) : {}); } catch (e) { reject(e); }
});
});
const sendJson = (res, status, body) => {
res.writeHead(status, { ‘Content-Type’: ‘application/json’ });
res.end(JSON.stringify(body));
};
module.exports = async (req, res) => {
try {
const app = await zcAuth.init(req);
const datastreams = new DataStreams(app);
const { channelId, userId, connectionName } = await readJson(req);
// Generate token pair
const tokenPair = await datastreams.getTokenPair(channelId, {
userId: userId || undefined,
connectionName: connectionName || undefined
});
sendJson(res, 200, { success: true, token: tokenPair });
} catch (error) {
sendJson(res, 500, { success: false, error: error.message });
}
};
Client (Request token from server):
// Client-side: Fetch token pair from your server
const response = await fetch('https://your-function-url.com/get-token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
channelId: 'YOUR_CHANNEL_ID',
userId: 'current_user_id' // or connectionName: 'device_123'
})
});
const { token } = await response.json();
// Now use token to create WebSocket connection
Always validate subscriber identity before generating tokens. Use User ID for channels with User Roles, and Connection Name for channels with Custom Logic. Tokens are scoped to specific channels.
You can find further steps on subscribing with WebSocket to create connections using the token pair, testing data flow to verify token generation, Token Pairs in Key Concepts, and WebSocket Connections.
Last Updated 2026-10-25 11:37:56 +0530 IST
Yes
No
Send your feedback to us