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.

Note: Token pair generation is a server-side operation that requires admin-level authentication. You must call getTokenPair() from a Catalyst Advanced I/O function and return the token pair to the client for WebSocket connection. Never expose token generation logic in client-side code.

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.
copy
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 }));
};
copy
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
copy
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:

  1. Deploy your Advanced I/O function
  2. Call the function endpoint from your client application
  3. The client receives the token pair response:
copy

{
    "url": "wss://datastreams.zoho.com",
    "wss-id": "abc123sessionid",
    "key": "authentication_key_here",
    "channel-id": "1234567890"
}

Example Implementation

Server (Advanced I/O Function):

copy

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):

copy

// 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