Chat Management - POST /external/chat
Create and manage chat sessions for seamless conversations with your Optimly AI agent. Chat sessions provide context continuity and help track user interactions over time.
Create New Chat Session
Endpoint
POST /external/chat
Authentication
Authorization: Bearer YOUR_AGENT_ACCESS_TOKEN
Request Body
{
"client_id": "string",
"ai_enabled": true,
"metadata": {
"source": "string",
"user_agent": "string",
"initial_url": "string"
}
}
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
client_id | string | Yes | Unique identifier for the client/user |
ai_enabled | boolean | No | Whether AI responses are enabled (default: true) |
metadata | object | No | Additional session metadata |
Response
{
"chat_id": "chat_abc123",
"agent_id": "agent_456",
"client_id": "user_789",
"created_at": "2025-06-16T10:30:00Z",
"ai_enabled": true,
"lead_collected": false,
"status": "active"
}
Get Chat Messages
Endpoint
GET /external/chat/{chat_id}/messages
Authentication
Authorization: Bearer YOUR_AGENT_ACCESS_TOKEN
Response
[
{
"message_id": "msg_123",
"chat_id": "chat_abc123",
"sender": "user",
"content": "Hello, I need help with my order",
"timestamp": "2025-06-16T10:30:00Z",
"metadata": {
"source": "website"
}
},
{
"message_id": "msg_124",
"chat_id": "chat_abc123",
"sender": "assistant",
"content": "I'd be happy to help you with your order. Can you provide your order number?",
"timestamp": "2025-06-16T10:30:15Z",
"metadata": {
"processing_time": 1.2,
"tools_used": []
}
}
]
Get Client Chats
Endpoint
GET /external/chat/{client_id}/chats
Authentication
Authorization: Bearer YOUR_AGENT_ACCESS_TOKEN
Response
[
{
"chat_id": "chat_abc123",
"agent_id": "agent_456",
"client_id": "user_789",
"created_at": "2025-06-16T10:30:00Z",
"last_activity": "2025-06-16T11:45:00Z",
"message_count": 8,
"ai_enabled": true,
"lead_collected": true,
"status": "active"
},
{
"chat_id": "chat_def456",
"agent_id": "agent_456",
"client_id": "user_789",
"created_at": "2025-06-15T14:20:00Z",
"last_activity": "2025-06-15T14:35:00Z",
"message_count": 3,
"ai_enabled": true,
"lead_collected": false,
"status": "closed"
}
]
Usage Examples
JavaScript - Create Chat and Send Message
class OptimlyChat {
constructor(accessToken, baseUrl = 'https://api.optimly.io') {
this.accessToken = accessToken;
this.baseUrl = baseUrl;
this.headers = {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
};
}
async createChat(clientId, metadata = {}) {
const response = await fetch(`${this.baseUrl}/external/chat`, {
method: 'POST',
headers: this.headers,
body: JSON.stringify({
client_id: clientId,
ai_enabled: true,
metadata
})
});
if (!response.ok) {
throw new Error(`Failed to create chat: ${response.statusText}`);
}
return await response.json();
}
async getChatMessages(chatId) {
const response = await fetch(`${this.baseUrl}/external/chat/${chatId}/messages`, {
headers: this.headers
});
if (!response.ok) {
throw new Error(`Failed to get messages: ${response.statusText}`);
}
return await response.json();
}
async getClientChats(clientId) {
const response = await fetch(`${this.baseUrl}/external/chat/${clientId}/chats`, {
headers: this.headers
});
if (!response.ok) {
throw new Error(`Failed to get chats: ${response.statusText}`);
}
return await response.json();
}
}
// Usage example
const chat = new OptimlyChat('your_access_token');
// Create a new chat session
const newChat = await chat.createChat('user_123', {
source: 'website',
user_agent: navigator.userAgent,
initial_url: window.location.href
});
console.log('New chat created:', newChat.chat_id);
// Get chat history
const messages = await chat.getChatMessages(newChat.chat_id);
console.log('Chat history:', messages);
Python - Chat Management
import requests
from typing import Dict, List, Optional
class OptimlyChat:
def __init__(self, access_token: str, base_url: str = 'https://api.optimly.io'):
self.access_token = access_token
self.base_url = base_url
self.headers = {
'Authorization': f'Bearer {access_token}',
'Content-Type': 'application/json'
}
def create_chat(self, client_id: str, metadata: Optional[Dict] = None) -> Dict:
"""Create a new chat session."""
payload = {
'client_id': client_id,
'ai_enabled': True
}
if metadata:
payload['metadata'] = metadata
response = requests.post(
f'{self.base_url}/external/chat',
json=payload,
headers=self.headers
)
response.raise_for_status()
return response.json()
def get_chat_messages(self, chat_id: str) -> List[Dict]:
"""Get all messages from a chat session."""
response = requests.get(
f'{self.base_url}/external/chat/{chat_id}/messages',
headers=self.headers
)
response.raise_for_status()
return response.json()
def get_client_chats(self, client_id: str) -> List[Dict]:
"""Get all chats for a specific client."""
response = requests.get(
f'{self.base_url}/external/chat/{client_id}/chats',
headers=self.headers
)
response.raise_for_status()
return response.json()
# Usage example
chat_manager = OptimlyChat('your_access_token')
# Create new chat
new_chat = chat_manager.create_chat(
client_id='user_123',
metadata={
'source': 'python_app',
'version': '1.0.0'
}
)
print(f"Created chat: {new_chat['chat_id']}")
# Get chat history
messages = chat_manager.get_chat_messages(new_chat['chat_id'])
print(f"Found {len(messages)} messages")
React Hook for Chat Management
import { useState, useEffect, useCallback } from 'react';
export function useOptimlyChat(accessToken, clientId) {
const [chats, setChats] = useState([]);
const [currentChat, setCurrentChat] = useState(null);
const [messages, setMessages] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const baseUrl = 'https://api.optimly.io';
const headers = {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
};
const createChat = useCallback(async (metadata = {}) => {
setLoading(true);
setError(null);
try {
const response = await fetch(`${baseUrl}/external/chat`, {
method: 'POST',
headers,
body: JSON.stringify({
client_id: clientId,
ai_enabled: true,
metadata: {
source: 'react_app',
...metadata
}
})
});
if (!response.ok) {
throw new Error(`Failed to create chat: ${response.statusText}`);
}
const newChat = await response.json();
setCurrentChat(newChat);
setMessages([]);
// Refresh chats list
await loadClientChats();
return newChat;
} catch (err) {
setError(err.message);
throw err;
} finally {
setLoading(false);
}
}, [accessToken, clientId]);
const loadChatMessages = useCallback(async (chatId) => {
setLoading(true);
setError(null);
try {
const response = await fetch(`${baseUrl}/external/chat/${chatId}/messages`, {
headers
});
if (!response.ok) {
throw new Error(`Failed to load messages: ${response.statusText}`);
}
const chatMessages = await response.json();
setMessages(chatMessages);
return chatMessages;
} catch (err) {
setError(err.message);
throw err;
} finally {
setLoading(false);
}
}, [accessToken]);
const loadClientChats = useCallback(async () => {
setLoading(true);
setError(null);
try {
const response = await fetch(`${baseUrl}/external/chat/${clientId}/chats`, {
headers
});
if (!response.ok) {
throw new Error(`Failed to load chats: ${response.statusText}`);
}
const clientChats = await response.json();
setChats(clientChats);
return clientChats;
} catch (err) {
setError(err.message);
throw err;
} finally {
setLoading(false);
}
}, [accessToken, clientId]);
const switchToChat = useCallback(async (chat) => {
setCurrentChat(chat);
await loadChatMessages(chat.chat_id);
}, [loadChatMessages]);
// Load client chats on mount
useEffect(() => {
if (accessToken && clientId) {
loadClientChats();
}
}, [accessToken, clientId, loadClientChats]);
return {
chats,
currentChat,
messages,
loading,
error,
createChat,
loadChatMessages,
loadClientChats,
switchToChat
};
}
// Usage in component
function ChatInterface({ accessToken, clientId }) {
const {
chats,
currentChat,
messages,
loading,
error,
createChat,
switchToChat
} = useOptimlyChat(accessToken, clientId);
const handleNewChat = async () => {
try {
await createChat({
page_url: window.location.href,
user_agent: navigator.userAgent
});
} catch (error) {
console.error('Failed to create chat:', error);
}
};
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return (
<div className="chat-interface">
<div className="chat-sidebar">
<button onClick={handleNewChat}>New Chat</button>
<div className="chat-list">
{chats.map(chat => (
<div
key={chat.chat_id}
className={`chat-item ${currentChat?.chat_id === chat.chat_id ? 'active' : ''}`}
onClick={() => switchToChat(chat)}
>
<div className="chat-preview">
Chat {chat.chat_id.slice(-6)}
</div>
<div className="chat-meta">
{chat.message_count} messages
</div>
</div>
))}
</div>
</div>
<div className="chat-main">
{currentChat ? (
<div className="messages">
{messages.map(message => (
<div key={message.message_id} className={`message ${message.sender}`}>
<div className="content">{message.content}</div>
<div className="timestamp">{new Date(message.timestamp).toLocaleTimeString()}</div>
</div>
))}
</div>
) : (
<div className="no-chat">Select a chat or create a new one</div>
)}
</div>
</div>
);
}
Best Practices
1. Client ID Management
Use consistent, unique client IDs to track users across sessions:
// Generate or retrieve client ID
let clientId = localStorage.getItem('optimly_client_id');
if (!clientId) {
clientId = `client_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
localStorage.setItem('optimly_client_id', clientId);
}
2. Chat Session Lifecycle
Manage chat sessions appropriately for your use case:
// For customer support - create new chat per issue
const supportChat = await createChat(clientId, {
type: 'support',
issue_category: 'billing'
});
// For general assistance - reuse existing chat
const existingChats = await getClientChats(clientId);
const activeChat = existingChats.find(chat => chat.status === 'active');
const chatId = activeChat ? activeChat.chat_id : (await createChat(clientId)).chat_id;
3. Message History Management
Load appropriate message history for context:
// Load recent messages for context
const messages = await getChatMessages(chatId);
const recentMessages = messages.slice(-10); // Last 10 messages
// Display in UI with proper formatting
recentMessages.forEach(message => {
displayMessage(message.sender, message.content, message.timestamp);
});
4. Error Handling
Implement robust error handling for chat operations:
async function safeCreateChat(clientId, metadata = {}) {
try {
return await createChat(clientId, metadata);
} catch (error) {
if (error.status === 401) {
// Handle authentication error
console.error('Invalid access token');
return null;
} else if (error.status === 429) {
// Handle rate limiting
console.error('Rate limit exceeded, retrying in 60 seconds');
setTimeout(() => safeCreateChat(clientId, metadata), 60000);
return null;
} else {
console.error('Failed to create chat:', error);
throw error;
}
}
}
Chat Status Management
Chats can have different statuses based on their activity:
Status | Description |
---|---|
active | Currently active conversation |
inactive | No recent activity but not closed |
closed | Explicitly closed conversation |
escalated | Transferred to human support |
Rate Limits
- 50 chat creations per hour per access token
- 200 message retrievals per hour per access token
- 100 chat list requests per hour per access token
Common Use Cases
Website Chat Widget
// Initialize chat for website visitor
const chat = await createChat(getVisitorId(), {
source: 'website',
page_url: window.location.href,
referrer: document.referrer
});
Mobile App Support
// Create support chat in mobile app
const chat = await createChat(getUserId(), {
source: 'mobile_app',
app_version: '2.1.0',
device_type: 'iOS'
});
Customer Portal Integration
// Authenticated customer starting chat
const chat = await createChat(customer.id, {
source: 'customer_portal',
customer_tier: customer.tier,
subscription_status: customer.subscription.status
});
Next Steps
- Agent Interaction - Send messages to your chat sessions
- Message Management - Add messages directly to chats
- Tools Integration - Enable lead capture and appointments
- Authentication - Secure your API access