How to access participant attributes set by Web Messaging inside an Architect Inbound Message flow
What You Will Build
- A Node.js script that sends a Web Messaging conversation with custom participant attributes and verifies their presence in the Architect flow context.
- This tutorial uses the Genesys Cloud CX REST API and the Node.js SDK (
@genesyscloud/purecloud-platform-client-v2). - The programming language covered is JavaScript (Node.js).
Prerequisites
- OAuth Client Type: Confidential Client (Client Credentials Grant) or Public Client (Authorization Code with PKCE). For this tutorial, we assume a Confidential Client for server-to-server automation.
- Required Scopes:
webchat:webchat:read(To inspect webchat configurations)conversations:webchat:write(To programmatically initiate a test conversation)architect:flow:read(To inspect flow definitions)analytics:events:query(To verify attribute persistence in analytics)
- SDK Version:
@genesyscloud/purecloud-platform-client-v2v5.0.0 or later. - Runtime: Node.js 18+ LTS.
- External Dependencies:
@genesyscloud/purecloud-platform-client-v2dotenv(for credential management)
Authentication Setup
Genesys Cloud uses OAuth 2.0. For automated testing and backend integrations, the Client Credentials flow is the most robust method. You must store your Client ID and Client Secret securely.
First, install the SDK:
npm install @genesyscloud/purecloud-platform-client-v2 dotenv
Create a .env file in your project root:
GENESYS_CLIENT_ID=your_client_id
GENESYS_CLIENT_SECRET=your_client_secret
GENESYS_REGION=us-east-1
GENESYS_SUBDOMAIN=your_organization_subdomain
Initialize the SDK client. This example demonstrates proper error handling for authentication failures (401/403).
require('dotenv').config();
const { PlatformClient } = require('@genesyscloud/purecloud-platform-client-v2');
const { OAuthApi } = PlatformClient;
async function initializeClient() {
const oAuthApi = new OAuthApi();
// Configure the OAuth API to use client credentials flow
oAuthApi.loginClientCredentials(
process.env.GENESYS_CLIENT_ID,
process.env.GENESYS_CLIENT_SECRET
);
// Verify the token is valid by fetching the user info
try {
const userInfo = await oAuthApi.getUserMe();
console.log('Authenticated as:', userInfo.email);
return oAuthApi;
} catch (error) {
if (error.status === 401 || error.status === 403) {
console.error('Authentication failed. Check Client ID and Secret.');
process.exit(1);
}
throw error;
}
}
module.exports = { initializeClient };
Implementation
Step 1: Configure the Web Messaging Channel to Allow Custom Attributes
Before sending attributes, you must ensure the Web Messaging channel in your Genesys Cloud organization is configured to accept them. By default, Genesys Cloud allows standard attributes, but custom attributes require explicit configuration in the Web Chat widget or via the API if you are using a custom implementation.
For this tutorial, we assume you are using the standard Genesys Cloud Web Chat widget. The widget sends custom attributes via the attributes object in the message payload.
If you are building a custom client, you must send these attributes during the connection handshake or as part of the first message. The API does not have a direct “set participant attribute” endpoint for active conversations that bypasses the flow; attributes are typically injected at the start of the conversation or updated via the PATCH /api/v2/conversations/webchat/{conversationId} endpoint.
However, the most common pattern for Architect flows is to read attributes that were sent by the client before the agent or flow logic engages.
Let us verify the Web Chat configuration to ensure custom attributes are not being stripped.
const { WebchatApi } = PlatformClient;
async function checkWebchatConfig(oAuthApi) {
const webchatApi = new WebchatApi({ accessToken: oAuthApi.getAccessToken() });
try {
// List all webchat configurations
const configs = await webchatApi.getWebchatWebchatconfig();
if (configs.entities.length === 0) {
console.warn('No Webchat configurations found. Please create one in the Admin console.');
return null;
}
const primaryConfig = configs.entities[0];
console.log('Primary Webchat Config ID:', primaryConfig.id);
// Note: The API does not expose a direct flag for "allow custom attributes"
// in the response object for all versions. This is usually handled by the widget code.
// Ensure your widget HTML includes the data-gen-callback or custom attribute configuration.
return primaryConfig.id;
} catch (error) {
console.error('Error fetching webchat config:', error.message);
throw error;
}
}
module.exports = { checkWebchatConfig };
Step 2: Simulate a Web Messaging Conversation with Custom Attributes
To test the flow, we need to initiate a Web Messaging conversation programmatically and inject custom attributes. This mimics a user sending a message with metadata (e.g., userId, sessionId, preferredLanguage).
We will use the POST /api/v2/conversations/webchat endpoint.
Required OAuth Scope: conversations:webchat:write
const { ConversationsApi } = PlatformClient;
async function createTestWebchatConversation(oAuthApi, webchatConfigId) {
const conversationsApi = new ConversationsApi({ accessToken: oAuthApi.getAccessToken() });
// Define the participant attributes we want to test
// These attributes will be available in Architect as participant attributes
const customAttributes = {
"userId": "user_12345",
"sessionId": "sess_abcdef",
"preferredLanguage": "en-US",
"tier": "premium"
};
// The body for creating a Webchat conversation
const body = {
initialMessage: {
text: "Hello, this is a test message with custom attributes."
},
// The attributes object is where you inject custom data
// These are set on the *participant* (the user)
attributes: customAttributes,
// Optional: You can also set conversation-level attributes
// conversationAttributes: { "source": "api_test" }
// You must provide a valid Webchat Config ID if you want to associate it with a specific widget
// If omitted, Genesys creates a generic webchat conversation
webchatConfigId: webchatConfigId
};
try {
const response = await conversationsApi.postConversationsWebchat(body);
console.log('Conversation created with ID:', response.id);
console.log('Initial Message ID:', response.messages[0].id);
return response;
} catch (error) {
// Handle 400 Bad Request (invalid body) or 429 Too Many Requests
if (error.status === 400) {
console.error('Bad Request. Check the body structure.');
console.error('Details:', error.body);
} else if (error.status === 429) {
console.error('Rate limited. Wait before retrying.');
} else {
console.error('Error creating conversation:', error.message);
}
throw error;
}
}
module.exports = { createTestWebchatConversation };
Step 3: Verify Attributes in the Conversation Context
Once the conversation is created, the attributes are attached to the participant. In an Architect flow, you access these via the participant context object.
To verify they are present without manually checking the UI, we can fetch the conversation details.
Required OAuth Scope: conversations:webchat:read
async function getConversationDetails(oAuthApi, conversationId) {
const conversationsApi = new ConversationsApi({ accessToken: oAuthApi.getAccessToken() });
try {
const conversation = await conversationsApi.getConversationWebchatConversationid(conversationId);
console.log('--- Conversation Details ---');
console.log('ID:', conversation.id);
console.log('State:', conversation.state);
// Iterate through participants to find the user (not the bot/agent)
if (conversation.participants) {
conversation.participants.forEach(participant => {
// Identify the user participant (usually role is 'user')
if (participant.role === 'user') {
console.log('--- User Participant ---');
console.log('Participant ID:', participant.id);
console.log('Attributes:', JSON.stringify(participant.attributes, null, 2));
// Verify specific attributes
if (participant.attributes && participant.attributes.userId) {
console.log('SUCCESS: userId attribute found:', participant.attributes.userId);
} else {
console.warn('WARNING: userId attribute not found on participant.');
}
}
});
}
return conversation;
} catch (error) {
console.error('Error fetching conversation:', error.message);
throw error;
}
}
module.exports = { getConversationDetails };
Step 4: Architect Flow Integration Logic
In your Architect flow, you do not need to write code to “fetch” these attributes. They are automatically available in the context of the flow when the event is a Webchat message.
How to access in Architect:
- Add a Set Data or Log step in your flow.
- Use the expression syntax to access the participant attributes.
- The standard path is:
{{ participant.attributes.userId }}
If you are using the Data Action to merge attributes, ensure you are mapping the correct source.
Important Note on Attribute Types:
Genesys Cloud stores attributes as strings, numbers, booleans, or objects. If you send a JSON object as a value, Architect may treat it as a string unless explicitly parsed.
Example Architect Expression:
// Accessing a simple string attribute
{{ participant.attributes.userId }}
// Accessing a nested object attribute (if sent as JSON string, you may need to parse)
// However, if sent as a proper object via API, you can access nested fields directly if the schema allows
{{ participant.attributes.metadata.source }}
To ensure the flow receives the attributes, the message event must trigger the flow. Attributes set on the participant are available immediately upon the first message if they are present in the initial request.
Step 5: Handling Attribute Updates During Conversation
Attributes can be updated during the conversation. In Architect, you can update participant attributes using a Set Data step with the target Participant.
API Equivalent for Updating Attributes:
If you need to update attributes via API (e.g., from an external system), you use PATCH /api/v2/conversations/webchat/{conversationId}/participants/{participantId}.
Required OAuth Scope: conversations:webchat:write
async function updateParticipantAttributes(oAuthApi, conversationId, participantId, newAttributes) {
const conversationsApi = new ConversationsApi({ accessToken: oAuthApi.getAccessToken() });
const body = {
attributes: newAttributes
};
try {
// This updates the participant's attributes
const response = await conversationsApi.patchConversationWebchatConversationidParticipantsParticipantid(
conversationId,
participantId,
body
);
console.log('Attributes updated successfully.');
console.log('Updated Attributes:', JSON.stringify(response.attributes, null, 2));
return response;
} catch (error) {
if (error.status === 404) {
console.error('Conversation or Participant not found.');
} else if (error.status === 400) {
console.error('Invalid attribute update body.');
}
throw error;
}
}
module.exports = { updateParticipantAttributes };
Complete Working Example
This script combines all steps: authenticates, checks config, creates a test conversation with custom attributes, and verifies they are present.
require('dotenv').config();
const { PlatformClient } = require('@genesyscloud/purecloud-platform-client-v2');
const { OAuthApi, WebchatApi, ConversationsApi } = PlatformClient;
async function runTest() {
console.log('Starting Genesys Webchat Attribute Test...');
// 1. Initialize Authentication
const oAuthApi = new OAuthApi();
oAuthApi.loginClientCredentials(
process.env.GENESYS_CLIENT_ID,
process.env.GENESYS_CLIENT_SECRET
);
try {
const userInfo = await oAuthApi.getUserMe();
console.log('Authenticated as:', userInfo.email);
} catch (error) {
console.error('Auth failed:', error.message);
return;
}
const accessToken = oAuthApi.getAccessToken();
const webchatApi = new WebchatApi({ accessToken });
const conversationsApi = new ConversationsApi({ accessToken });
// 2. Get Webchat Config ID (Optional but recommended for consistency)
let webchatConfigId = null;
try {
const configs = await webchatApi.getWebchatWebchatconfig();
if (configs.entities && configs.entities.length > 0) {
webchatConfigId = configs.entities[0].id;
console.log('Using Webchat Config ID:', webchatConfigId);
}
} catch (error) {
console.warn('Could not fetch Webchat Config. Proceeding without it.');
}
// 3. Create Conversation with Custom Attributes
const customAttributes = {
userId: "test_user_999",
sessionId: "session_xyz",
tier: "vip"
};
const body = {
initialMessage: {
text: "Testing custom attributes in Architect."
},
attributes: customAttributes,
webchatConfigId: webchatConfigId
};
let conversationId;
let participantId;
try {
const createdConv = await conversationsApi.postConversationsWebchat(body);
conversationId = createdConv.id;
console.log('Created Conversation:', conversationId);
// Extract participant ID for the user
if (createdConv.participants && createdConv.participants.length > 0) {
// The first participant is usually the user in this creation flow
participantId = createdConv.participants[0].id;
console.log('User Participant ID:', participantId);
}
} catch (error) {
console.error('Failed to create conversation:', error.message);
return;
}
// 4. Verify Attributes
try {
const convDetails = await conversationsApi.getConversationWebchatConversationid(conversationId);
// Find user participant
const userParticipant = convDetails.participants.find(p => p.role === 'user');
if (userParticipant) {
console.log('\n--- Verification ---');
console.log('Participant Attributes:', JSON.stringify(userParticipant.attributes, null, 2));
if (userParticipant.attributes && userParticipant.attributes.userId === 'test_user_999') {
console.log('SUCCESS: Attributes correctly set and retrieved.');
console.log('In Architect, use: {{ participant.attributes.userId }}');
} else {
console.error('FAILURE: Attributes do not match expected values.');
}
} else {
console.error('User participant not found in conversation.');
}
} catch (error) {
console.error('Failed to verify conversation:', error.message);
}
}
runTest().catch(console.error);
Common Errors & Debugging
Error: 400 Bad Request - Invalid Attribute Structure
Cause: The attributes object in the request body contains invalid data types or exceeds size limits. Genesys Cloud attributes are generally limited to 255 characters for simple strings, but complex objects may have different constraints.
Fix: Ensure all attribute values are serializable to JSON. Avoid sending binary data or extremely large strings. Check the API documentation for attribute size limits.
Error: Attributes Not Visible in Architect Flow
Cause:
- The attributes were set on the conversation object instead of the participant object.
- The flow is reading from the wrong context (e.g.,
conversation.attributesinstead ofparticipant.attributes). - The attributes were updated after the flow step that reads them.
Fix:
- In the API call, ensure
attributesis at the root level of the request body (for participant) or insideconversationAttributes(for conversation). - In Architect, explicitly check
{{ participant.attributes.key }}. - If updating attributes dynamically, ensure the flow waits for the update (via a Data Action or API step) before reading them.
Error: 403 Forbidden - Insufficient Scopes
Cause: The OAuth token lacks the conversations:webchat:write or conversations:webchat:read scope.
Fix: Regenerate the OAuth token with the correct scopes. Verify your Client Credentials configuration in the Genesys Cloud Admin console under Security > OAuth Clients.
Error: 429 Too Many Requests
Cause: Rate limiting on the Conversations API.
Fix: Implement exponential backoff in your retry logic. Do not loop rapidly.