# API Reference Source: https://docs.eusate.com/modules/devspace/api-reference API documentation for DevSpace callback endpoints ## Authentication Callback This endpoint receives authentication data from your login system after a customer successfully authenticates. ### Base URL All API endpoints use the following base URL: POST `{api_base_url}/api/v1/lab/login/callback/` You must authenticate this request using your API key from the platform settings. ### Header ``` Authorization: Bearer YOUR_API_KEY ``` You can find your API key in the platform settings. Create one if you haven't already. ### Request Body The authentication token for the customer. This token will be used by Sate to make authenticated requests to your functions. The expiration time of the authentication token as a Unix timestamp in seconds. The state parameter that was included in the original login URL. This is used to match the authentication response with the correct session. ### Example Request ```json theme={null} { "auth_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "auth_token_expires_at_seconds": 1693440000, "state": "abc123def456" } ``` ### Response #### Success Response Returns HTTP status `200` when the authentication is processed successfully: ```json theme={null} { "success": true } ``` #### Error Responses Returns HTTP status `400` or `403` with error details when there are issues: ```json theme={null} { "detail": "Error description explaining what went wrong" } ``` ### Status Codes Authentication token processed successfully Missing required parameters, invalid data format, or validation errors Authentication failed or access denied ## Security Considerations Always validate the state parameter to ensure the authentication response corresponds to a legitimate login request initiated by your system. Store minimal information in tokens and implement proper token rotation and revocation mechanisms. ### Best Practices 1. **API Key Security**: Store your API key securely and never expose it in client-side code 2. **Validate State**: Always verify the state parameter matches an active login session 3. **Token Security**: Use secure token generation and storage practices 4. **Expiration**: Set appropriate token expiration times 5. **HTTPS Only**: Ensure all communication uses HTTPS 6. **Error Handling**: Implement proper error handling and logging ## Testing the Integration ### Using cURL ```bash theme={null} API_BASE_URL="{api_base_url}" curl -X POST ${API_BASE_URL}/api/v1/lab/login/callback/ \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{ "auth_token": "test_token_123", "auth_token_expires_at_seconds": 1693440000, "state": "test_state_456" }' ``` ### Testing Checklist * [ ] Callback endpoint accepts all required parameters * [ ] State parameter validation works correctly * [ ] Token expiration is handled properly * [ ] Error responses are returned for invalid requests * [ ] HTTPS is enforced for all requests ## Troubleshooting ### Common Issues **400 Bad Request**: Check that all required fields are included and properly formatted **403 Forbidden**: Verify the API key is correct and has proper permissions ### Debug Mode During development, you can enable debug logging to see detailed request/response information in your DevSpace dashboard. # Authentication Configuration Source: https://docs.eusate.com/modules/devspace/authentication Configure how Sate authenticates with your protected endpoints ## Overview Authentication configuration allows Sate to access your protected endpoints on behalf of your customers. This enables secure, personalized interactions while maintaining proper authorization controls. ## Authentication Types DevSpace supports both authenticated and unauthenticated functions: * **Unauthenticated functions**: Public endpoints that don't require user credentials * **Authenticated functions**: Protected endpoints that require customer authentication ## Configuration Settings Set up authentication on the DevSpace platform by providing: The endpoint where customers will authenticate Where the auth token should be placed (header, query, body) The type of authentication (Bearer, API Key, etc.) Label and value format for authorization headers ## Authentication Flow Here's how Sate handles authentication when executing protected functions: Sate determines it needs to call an authenticated function to help the customer If the customer isn't authenticated, Sate sends them your configured login URL Customer clicks the link and enters their credentials on your platform Your platform validates credentials and sends authentication data to our callback Sate uses the received token to execute the function on the customer's behalf ## Implementation Requirements To use authenticated functions, your login endpoint must: ### 1. Accept State Parameter Your login URL must accept a `state` parameter that we'll include: ``` https://yourapp.com/login?state=ABC123 ``` ### 2. Implement Callback Integration After successful authentication, send a POST request to our callback endpoint: **Endpoint**: `https://api.eusate.com/api/v1/lab/login/callback/` **Authentication**: You must include your API key in the Authorization header. Get your API key from the platform settings. **Required Headers**: * `Authorization: Bearer YOUR_API_KEY` * `Content-Type: application/json` **Required Body Parameters**: * `auth_token`: The customer's authentication token * `auth_token_expires_at_seconds`: Token expiration time (Unix timestamp) * `state`: The state parameter from the original login URL ## Security Considerations Always validate the state parameter to prevent CSRF attacks and ensure tokens are properly scoped to the authenticated user. Tokens should have appropriate expiration times and be invalidated after use when possible. ## Next Steps * [Create your first function](/modules/devspace/functions) * [Review the callback API reference](/modules/devspace/api-reference) * [Test your authentication flow](/modules/devspace/testing) # Functions Source: https://docs.eusate.com/modules/devspace/functions Create HTTP endpoints that SATE can execute to perform actions ## Overview Functions are HTTP endpoints that SATE can call to perform actions on your behalf. They extend your SATE capabilities beyond simple knowledge retrieval to include real-time data access and system interactions. ## Current Capabilities Currently, only `GET` functions are supported. Support for `POST`, `PATCH`, and `DELETE` methods is coming soon. MCP (Model Context Protocol) support is also planned. ## Creating a Function Navigate to the DevSpace platform and follow these steps: Click the "Functions" tab in your DevSpace dashboard Click "Add new function" to start the creation process Fill in the required function details ## Function Configuration When creating a function, provide the following information: ### Basic Information A clear, descriptive name for your function (e.g., "get\_order\_status") Detailed description of what the function does and when Sate should use it The complete URL of your HTTP endpoint. Path and query parameters will be automatically extracted from the URL. ### Parameter Configuration For each parameter automatically detected from your URL, you need to configure: Clear description of what this parameter represents The parameter data type: `string`, `boolean`, or `number` Who provides this parameter value: * `organisation`: You provide the value * `sate`: SATE determines the value from context #### Organization-Provided Parameters When you select `organisation` as the provider, you have two options: 1. **Direct Value**: Provide a static value for the parameter 2. **Leaf Function**: Reference another function that returns the parameter value ##### Using Leaf Functions A leaf function is a simple function without any parameters that returns data. Requirements: * Must be a function without path or query parameters * If the main function is unauthenticated, the leaf function must also be unauthenticated * You can optionally specify a `response_path` to extract specific data from the leaf function's response ### Security & Environment Whether this function requires customer authentication Set to "live" for customer use or "dev" for testing only ## Function Examples ### Simple Function (No Parameters) ```http theme={null} GET /api/store-hours ``` **Configuration:** * **Name**: `get_store_hours` * **Description**: "Returns current store operating hours and holiday schedules" * **Authentication**: Not required * **Environment**: Live ### Function with Sate-Provided Parameters ```http theme={null} GET /api/orders/{order_id} ``` **Configuration:** * **Name**: `get_order_details` * **Description**: "Retrieves detailed information about a specific customer order" * **Authentication**: Required * **Environment**: Live **Parameter Configuration:** * `order_id` (string): The unique order identifier * **Provider**: `SATE` will extract from customer conversation * **Description**: "Customer's order ID they're asking about" ### Function with Organization-Provided Parameters ```http theme={null} GET /api/products?category={category}&limit={limit} ``` **Configuration:** * **Name**: `get_products_by_category` * **Description**: "Retrieves products filtered by category with pagination" * **Authentication**: Not required * **Environment**: Live **Parameter Configuration:** * `category` (string): Product category to filter by * **Provider**: `SATE` determines from customer request * **Description**: "Product category the customer is interested in" * `limit` (number): Maximum number of products to return * **Provider**: `organisation` (you set a static value like 20) * **Description**: "Number of products to return per request" ### Function Using Leaf Function ```http theme={null} GET /api/user/{user_id}/preferences?store_id={store_id} ``` **Configuration:** * **Name**: `get_user_preferences` * **Description**: "Retrieves user preferences for a specific store" * **Authentication**: Required * **Environment**: Live **Parameter Configuration:** * `user_id` (string): The user's unique identifier * **Provider**: `SATE` gets from authentication context * **Description**: "ID of the authenticated user" * `store_id` (string): The store location identifier * **Provider**: `organisation` (use leaf function) * **Leaf Function**: `get_default_store` (returns store information) * **Response Path**: `store.id` (extracts store ID from response) ## Best Practices ### Function Naming * Use clear, action-oriented names * Follow consistent naming conventions * Include the resource being accessed (e.g., `get_user_orders`, `check_inventory_status`) ### Descriptions * Explain when Sate should use this function * Describe the expected response format * Include any important limitations or requirements ### Parameter Configuration * Choose the appropriate provider (`sate` vs `organisation`) for each parameter * Use leaf functions for dynamic organization-provided values * Provide clear descriptions to help Sate understand parameter usage * Use appropriate data types (string, number, boolean) for validation ## Response Handling Your endpoints should return structured JSON responses that Sate can easily interpret: ```json theme={null} { "success": true, "data": { // Your response data }, "message": "Optional human-readable message" } ``` Ensure your endpoints handle errors gracefully and return appropriate HTTP status codes. ## Testing Functions Before deploying functions to production: 1. **Test endpoints independently** - Verify your APIs work correctly 2. **Use development environment** - Set functions to "dev" mode initially 3. **Test authentication flow** - Ensure auth integration works properly 4. **Validate with Sate** - Test the complete interaction flow ## Monitoring and Debugging Monitor your function usage through: * Server logs for your endpoints * DevSpace analytics (coming soon) * Customer interaction feedback ## Next Steps * [Set up authentication](/modules/devspace/authentication) for protected functions * [Review API reference](/modules/devspace/api-reference) for callback endpoints # DevSpace Overview Source: https://docs.eusate.com/modules/devspace/introduction Enable SATE to interact with your infrastructure DevSpace enables SATE to go beyond knowledge base responses by executing custom functions that interact with your infrastructure. ## What is DevSpace? DevSpace allows you to create tools and functions that give Sate enhanced capabilities for customer support. Instead of escalating complex requests to humans, Sate can perform actions directly through your APIs. ### Example Use Case Consider an e-commerce scenario: 1. A customer requests a refund through your support channels 2. Sate needs to verify the order exists and check refund eligibility 3. With DevSpace functions like `get_order` and `process_refund`, Sate can handle this automatically 4. The customer gets immediate assistance without human intervention ## Core Components DevSpace consists of two main sections: Configure how Sate authenticates with your protected endpoints Create HTTP endpoints that Sate can call to perform actions ## Getting Started 1. **Set up authentication** - Configure how Sate will authenticate with your APIs 2. **Create functions** - Define the endpoints Sate can call 3. **Test and deploy** - Validate your setup before going live Configure your DevSpace settings on the platform ## What's Next? * Learn about [authentication configuration](/modules/devspace/authentication) * Create your first [function](/modules/devspace/functions) * Review the [API reference](/modules/devspace/api-reference) for callback endpoints # API Integration Source: https://docs.eusate.com/modules/helpdesk/api Integrate Eusate Helpdesk using RESTful API and real-time Socket.IO ## Overview The Helpdesk API provides a comprehensive solution for integrating customer support functionality into your applications. It combines RESTful HTTP endpoints for data retrieval with Socket.IO for real-time messaging. While API integration offers maximum flexibility, we recommend using our [SDK](/modules/helpdesk/sdk) for faster implementation and built-in best practices. ## Prerequisites To integrate with the Helpdesk API, you need: * Ability to make HTTP requests * Socket.IO client library for real-time communication * Valid API key from your api key settings ## Integration Flow Build a support interface where customers can send messages Create a unique session\_id for each customer using your interface Use the session\_id to retrieve existing customer conversations Get individual messages for each conversation Establish Socket.IO connection for live messaging Listen and respond to real-time events for seamless communication ## Authentication All API requests require authentication using your API key: ```http theme={null} Authorization: Bearer YOUR_API_KEY ``` Keep your API key secure and never expose it in client-side code. Store it as an environment variable on your server. ## Base URL All API endpoints use the following base URL: ## Quick Start Example Here's a basic implementation flow: ```javascript theme={null} const API_BASE_URL = '{api_base_url}'; // 1. Fetch customer conversations const conversations = await fetch(`${API_BASE_URL}/api/v1/helpdesk/customer/${sessionId}/conversations/`, { headers: { 'Authorization': `Bearer ${API_KEY}` } }); // 2. Connect to Socket.IO for real-time messaging const socket = io(`${API_BASE_URL}/helpdesk?token_source=api&token=${API_KEY}`); // 3. Handle connection socket.on('connect', () => { console.log('Connected to helpdesk'); }); // 4. Send customer message socket.emit('support', { session_id: sessionId, message: customerMessage, attachment: false, ticket_chat_id: conversationId || null }); // 5. Listen for responses socket.on('support', (response) => { if (response.status_code === 200) { displayMessage(response.data); } }); ``` ## Next Steps Explore all available REST API endpoints Learn about real-time messaging events ## Implementation Guides * [Complete API Reference](/modules/helpdesk/api-reference) - All endpoints and parameters * [Socket.IO Events](/modules/helpdesk/socketio) - Real-time messaging guide * [SDK Alternative](/modules/helpdesk/sdk) - Easier integration option # API Reference Source: https://docs.eusate.com/modules/helpdesk/api-reference Complete reference for Helpdesk REST API endpoints ## Authentication All API requests require authentication using your API key in the Authorization header: ```http theme={null} Authorization: Bearer YOUR_API_KEY ``` ## Base URL ## Endpoints ### Get Conversations Retrieve all conversations for a customer session. GET `{api_base_url}/api/v1/helpdesk/customer/{session_id}/conversations/` #### Parameters Unique identifier for the customer session #### Query Parameters Filter conversations by status. Accepts: `true`, `t`, `yes`, `1` (true), anything else is false #### Response Array of conversation objects **Conversation Object:** Unique conversation identifier ISO timestamp of creation ISO timestamp of last update Whether the conversation is closed Whether support closure was requested Customer read status Agent read status Current responder: `"agent"` or `"sate"` Ticket identifier Ticket slug for URLs Most recent message in the conversation #### Example Response ```json theme={null} [ { "id": "conv_123", "date_created": "2024-01-15T10:30:00Z", "date_updated": "2024-01-15T11:45:00Z", "closed": false, "close_support": false, "read_by_customer": true, "read_by_agent": false, "responder": "sate", "ticket": "ticket_456", "ticket_slug": "customer-inquiry-456", "latest_message": { "id": "msg_789", "date_created": "2024-01-15T11:45:00Z", "date_updated": "2024-01-15T11:45:00Z", "message": "I can help you with that issue.", "sender": "sate", "is_attachment": false, "attachment_metadata": null, "ticket_chat": "conv_123" } } ] ``` #### Status Codes Conversations retrieved successfully Invalid parameters or malformed request Invalid or missing API key Access denied for this resource *** ### Get Conversation Messages Retrieve all messages for a specific conversation. GET `{api_base_url}/api/v1/helpdesk/customer/{session_id}/conversations/{conversation_id}/messages/` #### Parameters Unique identifier for the customer session Unique identifier for the conversation #### Response Conversation identifier ISO timestamp of creation ISO timestamp of last update Whether the conversation is closed Whether support closure was requested Customer read status Agent read status Current responder: `"agent"` or `"sate"` Ticket identifier Array of message objects in chronological order **Message Object:** Unique message identifier ISO timestamp of creation ISO timestamp of last update Message content Message sender: `"sate"`, `"agent"`, or `"customer"` Whether this message contains an attachment Attachment details (if is\_attachment is true) Associated conversation ID #### Example Response ```json theme={null} { "id": "conv_123", "date_created": "2024-01-15T10:30:00Z", "date_updated": "2024-01-15T11:45:00Z", "closed": false, "close_support": false, "read_by_customer": true, "read_by_agent": false, "responder": "sate", "ticket": "ticket_456", "messages": [ { "id": "msg_001", "date_created": "2024-01-15T10:30:00Z", "date_updated": "2024-01-15T10:30:00Z", "message": "Hello, I need help with my order", "sender": "customer", "is_attachment": false, "attachment_metadata": null, "ticket_chat": "conv_123" }, { "id": "msg_002", "date_created": "2024-01-15T10:31:00Z", "date_updated": "2024-01-15T10:31:00Z", "message": "I'd be happy to help you with your order. Could you provide your order number?", "sender": "sate", "is_attachment": false, "attachment_metadata": null, "ticket_chat": "conv_123" } ] } ``` #### Status Codes Messages retrieved successfully Invalid parameters or malformed request Invalid or missing API key Access denied for this resource ## Error Responses All error responses follow this format: ```json theme={null} { "detail": "Error description explaining what went wrong" } ``` ## Next Steps * [Socket.IO Events](/modules/helpdesk/socketio) for real-time messaging * [SDK Integration](/modules/helpdesk/sdk) for easier implementation # Discord Integration Source: https://docs.eusate.com/modules/helpdesk/discord Connect your Discord server for AI-powered customer support ## Overview Integrate Eusate with your Discord server to provide AI-powered support through direct messages. Perfect for gaming communities, developer servers, and any Discord-based customer support. ## Setup Process Setting up Discord integration is simple and takes just a few minutes: Go to integration settings on the platform Click the Discord integration option to start the connection process You'll be redirected to Discord to select your server and approve bot permissions Return to the platform where the status will show as "Connected" ## Customer Experience Once set up, your customers can get support by: Customer sends a direct message to the Eusate bot Bot asks customer to select which server they need help with A private thread is created for the customer's support conversation SATE provides assistance and can escalate to human agents if needed ## Managing Discord Support All Discord conversations are managed through your helpdesk dashboard: * **View all tickets** - See Discord conversations alongside other channels * **Monitor responses** - Track SATE and human agent interactions * **Escalate when needed** - Transfer conversations to human agents * **Analytics and insights** - Understand support patterns and performance Need help with Discord integration? The setup process is designed to be simple, but our support team is available if you encounter any issues. # Helpdesk Overview Source: https://docs.eusate.com/modules/helpdesk/introduction Manage customer support tickets and conversations across multiple channels The Helpdesk module enables you to manage customer support tickets and conversations across multiple integration channels. View, track, and respond to customer inquiries from a centralized dashboard. ## What is Helpdesk? Helpdesk aggregates support tickets created from customer interactions across all your integrated channels. Whether customers reach out through your website, Discord, or other platforms, all conversations are unified in one place. To know more channels, check integrations settings on the platform. ### Key Features * **Unified ticket management** - All customer conversations in one dashboard * **Multi-channel support** - SDK, API, Discord, and more integrations * **Real-time messaging** - Instant communication with customers * **AI and human agents** - Seamless handoff between SATE and human support * **Conversation tracking** - Monitor ticket status and resolution progress ## Integration Channels Choose how customers can reach your support team: Easy-to-implement JavaScript SDK for web and mobile apps RESTful API with real-time Socket.IO for custom implementations Connect your Discord server for community support ## Getting Started Select SDK, API, or Discord based on your platform needs Set up API keys and authentication for secure communication Create the support interface for your customers Use the helpdesk dashboard to monitor and respond to tickets View and manage customer support tickets on the platform ## What's Next? * Learn about [SDK integration](/modules/helpdesk/sdk) for quick setup * Explore [API integration](/modules/helpdesk/api) for custom implementations * Review [Discord bot setup](/modules/helpdesk/discord) for community support * Check the [API reference](/modules/helpdesk/api-reference) for technical details # SDK Integration Source: https://docs.eusate.com/modules/helpdesk/sdk Add AI-powered customer support to your website in minutes with a single script ## Overview The Eusate Messenger SDK is an embeddable chat widget. Drop it into any website and your customers get a fully functional, AI-powered support chat — no backend code required on your end. It works as a floating button that opens a chat window. Everything inside (messages, calls, agent handover) is handled automatically. Paste one line into your HTML. Best for static sites, plain HTML, or any site where you just want to get started. Install via npm or yarn. Best for React, Next.js, Vue, Angular, Svelte, or any modern framework. *** ## Installation ### Script Tag (Quickest) Paste this into your HTML, just before ``: ```html theme={null} ``` That's it — the chat widget will appear on your page. The `v0` path auto-updates with bug fixes and new features within the current major version. To pin to an exact release for maximum stability, use a full version path: `https://cdn.eusate.com/messenger/v0.2.7/eusate-sdk.min.js` ### Node Packages ```bash theme={null} npm install @eusate/messenger-sdk # or yarn add @eusate/messenger-sdk # or pnpm add @eusate/messenger-sdk # or bun add @eusate/messenger-sdk ``` *** ## Quick Start ### Plain HTML ```html theme={null} My Website

Welcome

``` ### React ```tsx theme={null} import { useEffect } from 'react' import Eusate from '@eusate/messenger-sdk' function App() { useEffect(() => { Eusate.init({ apiKey: process.env.REACT_APP_EUSATE_API_KEY!, }) return () => { Eusate.destroy() } }, []) return
{/* your content */}
} ``` ### Next.js (App Router) ```tsx theme={null} // app/components/ChatWidget.tsx 'use client' import { useEffect } from 'react' import Eusate from '@eusate/messenger-sdk' export default function ChatWidget() { useEffect(() => { Eusate.init({ apiKey: process.env.NEXT_PUBLIC_EUSATE_API_KEY!, onReady: () => console.log('Chat ready'), onError: (error) => console.error('Chat error:', error), }) return () => { Eusate.destroy() } }, []) return null } ``` ```tsx theme={null} // app/layout.tsx import ChatWidget from './components/ChatWidget' export default function RootLayout({ children }) { return ( {children} ) } ``` The `'use client'` directive is required — the SDK uses browser APIs (`window`, `document`) that are not available during server-side rendering. ### Vue 3 ```vue theme={null} ``` *** ## Configuration ### `Eusate.init(config)` Your API key. Get it from API Key Settings. Target environment. `"production"` (default) or `"development"`. Use `"development"` while testing. Callback fired when the widget is loaded and ready to use. Callback fired if initialization fails (invalid API key, network issues, etc.). ```javascript theme={null} Eusate.init({ apiKey: 'your-api-key', environment: 'production', onReady: () => { console.log('Eusate is ready') }, onError: (error) => { console.error('Eusate failed to load:', error) }, }) ``` ### Environment Variables ```env Next.js theme={null} # .env.local NEXT_PUBLIC_EUSATE_API_KEY=your-api-key-here ``` ```env React (CRA) theme={null} # .env REACT_APP_EUSATE_API_KEY=your-api-key-here ``` ```env Vue / Vite theme={null} # .env VITE_EUSATE_API_KEY=your-api-key-here ``` *** ## Methods ### `Eusate.open()` Programmatically open the chat window. ```javascript theme={null} Eusate.open() // Example: open on button click document.getElementById('help-btn').onclick = () => Eusate.open() ``` *** ### `Eusate.close()` Programmatically close the chat window. ```javascript theme={null} Eusate.close() ``` *** ### `Eusate.destroy()` Remove the widget from the page entirely. Useful for cleanup in single-page apps when navigating away. ```javascript theme={null} Eusate.destroy() ``` After calling `destroy()`, you must call `init()` again to re-add the widget. *** ### `Eusate.isInitialized()` Returns `true` if the widget has loaded and is ready. ```javascript theme={null} if (Eusate.isInitialized()) { Eusate.open() } ``` *** ### `Eusate.isOpen()` Returns `true` if the chat window is currently visible. ```javascript theme={null} if (!Eusate.isOpen()) { showPrompt('Need help? Chat with us!') } ``` *** ### `Eusate.version` The current SDK version string. ```javascript theme={null} console.log(Eusate.version) // "0.2.7" ``` *** ## Advanced Usage ### Custom Trigger Button Use your own button to open the chat instead of the default floating button: ```html theme={null} ``` ### Conditional Loading Only load the widget for certain users: ```javascript theme={null} if (user.isAuthenticated) { Eusate.init({ apiKey: process.env.NEXT_PUBLIC_EUSATE_API_KEY }) } ``` ### Route Change Handling (SPAs) Close the chat when navigating between pages: ```javascript theme={null} // Next.js App Router useEffect(() => { return () => Eusate.close() }, [pathname]) ``` *** ## Security Never hardcode your API key in client-side code or commit it to version control. Always use environment variables. ### Content Security Policy (CSP) If your site enforces CSP headers, add these directives to allow the widget: ``` Content-Security-Policy: frame-src https://chat.eusate.com; script-src https://cdn.eusate.com; connect-src https://api.eusate.com; ``` *** ## Troubleshooting ### Widget not appearing ```javascript theme={null} // Add callbacks to see exactly what's happening Eusate.init({ apiKey: 'your-key', onReady: () => console.log('✅ SDK ready'), onError: (error) => console.error('❌ SDK error:', error), }) console.log('Initialized?', Eusate.isInitialized()) ``` Also check: * API key is correct and active in your dashboard * No browser extensions (ad blockers) are intercepting the script * JavaScript is enabled ### Next.js: "window is not defined" You're importing the SDK in a server component. Add `'use client'` at the top of the file, or use dynamic import: ```tsx theme={null} import dynamic from 'next/dynamic' const ChatWidget = dynamic(() => import('./components/ChatWidget'), { ssr: false, }) ``` ### Widget appears more than once You're calling `init()` multiple times. Use an empty dependency array in React: ```tsx theme={null} // ✅ Correct — runs once on mount useEffect(() => { Eusate.init({ apiKey: 'key' }) return () => Eusate.destroy() }, []) // ❌ Wrong — re-runs when someValue changes useEffect(() => { Eusate.init({ apiKey: 'key' }) }, [someValue]) ``` *** ## More Frameworks ```tsx theme={null} // pages/_app.tsx import { useEffect } from 'react' import Eusate from '@eusate/messenger-sdk' export default function App({ Component, pageProps }) { useEffect(() => { Eusate.init({ apiKey: process.env.NEXT_PUBLIC_EUSATE_API_KEY! }) return () => Eusate.destroy() }, []) return } ``` ```typescript theme={null} // app.component.ts import { Component, OnInit, OnDestroy } from '@angular/core' import Eusate from '@eusate/messenger-sdk' import { environment } from '../environments/environment'; @Component({ selector: 'app-root', templateUrl: './app.component.html' }) export class AppComponent implements OnInit, OnDestroy { ngOnInit() { Eusate.init({ apiKey: environment.eusateApiKey }) } ngOnDestroy() { Eusate.destroy() } } ``` ```svelte theme={null} ``` *** ## Next Steps * [Socket.IO Events](/modules/helpdesk/socketio) — build a fully custom chat UI from scratch * [REST API Reference](/modules/helpdesk/api-reference) — fetch conversations and messages via HTTP # Socket.IO Events Source: https://docs.eusate.com/modules/helpdesk/socketio Real-time messaging, voice calls, and notification events for Helpdesk integration ## Overview Socket.IO enables real-time bidirectional communication between your application and the Helpdesk system. This allows instant messaging, voice calls, live notifications, and seamless customer support experiences. ## Connection ### Authentication Connect to the Socket.IO server using your API key: ```javascript theme={null} const API_BASE_URL = '{api_base_url}'; const socket = io(`${API_BASE_URL}/helpdesk?token_source=api&token=YOUR_API_KEY`); ``` Never expose your API key in client-side code. Fetch it from your backend and pass it to the socket connection. ### Connection Response Upon successful connection, you'll receive: ```json theme={null} { "status_code": 200, "sid": "socket_session_id", "message": "Connected", "data": {} } ``` If authentication fails, the connection is refused with `status_code` 400 or 401. ### Response Envelope All event responses follow this envelope: ```json theme={null} { "status_code": 200, "sid": "socket_session_id", "message": "Human-readable status", "data": {} } ``` ## Event Flow Authenticate and establish a connection using your API key. Call `enter_customer_support` with the customer's session ID immediately after connecting. This subscribes the customer to their personal room so they can receive messages from agents even before a conversation starts. Use `support` to send customer messages. Listen on `support` for SATE (AI) replies and on `customer_support` for agent replies. After the first message returns a `ticket_chat_id`, call `enter_support` to subscribe to that conversation room for all subsequent broadcasts. Call `mark_conversation_read` whenever the customer views messages. Use `call_support` to start a voice call with SATE and `close_call_support` to end it. When resolved, call `close_support` to end the conversation and `review_support` to collect feedback. *** ## Events Reference ### Emitting Events (Client → Server) *** #### Enter Customer Room Subscribe the customer to their personal room. Call this immediately after connecting so the customer can receive agent messages (`customer_support`) and auto-close notifications (`customer_support_closed`) regardless of which conversation is active. **Event Name:** `enter_customer_support` ##### Request Schema Unique identifier for the customer — use the same value you send in the `support` event ##### Example Request ```javascript theme={null} socket.on('connect', () => { socket.emit('enter_customer_support', { session_id: 'customer_123' }); }); ``` ##### Response Schema ```json theme={null} { "status_code": 200, "sid": "socket_session_id", "message": "Joined customer support room", "data": {} } ``` *** #### Enter Conversation Room Join a specific conversation room to receive real-time updates for that conversation. **Event Name:** `enter_support` Call this after the first `support` response returns a `ticket_chat_id`. You only need to call it once per conversation. ##### Request Schema The conversation ID returned from the first `support` response ##### Example Request ```javascript theme={null} socket.emit('enter_support', { ticket_chat_id: 'conv_abc123' }); ``` ##### Response Schema ```json theme={null} { "status_code": 200, "sid": "socket_session_id", "message": "Joined support room", "data": {} } ``` *** #### Leave Conversation Room Unsubscribe from a conversation room. **Event Name:** `leave_support` ##### Request Schema The conversation ID to leave ##### Example Request ```javascript theme={null} socket.emit('leave_support', { ticket_chat_id: 'conv_abc123' }); ``` ##### Response Schema ```json theme={null} { "status_code": 200, "sid": "socket_session_id", "message": "Left support room", "data": {} } ``` *** #### Send Message The primary event for sending customer messages. SATE (AI) replies come back on the `support` event; agent replies come on `customer_support`. **Event Name:** `support` ##### Request Schema Unique identifier for the customer The message content to send Whether this message includes an attachment Conversation ID. Set to `null` for the first message in a new conversation; use the returned ID for all follow-ups. Attachment details. Required when `attachment` is `true`. ##### Example Request ```javascript theme={null} // Start a new conversation socket.emit('support', { session_id: 'customer_123', message: 'Hello, I need help with my order', attachment: false, ticket_chat_id: null }); // Continue an existing conversation socket.emit('support', { session_id: 'customer_123', message: 'My order number is #4567', attachment: false, ticket_chat_id: 'conv_abc123' }); ``` ##### Response Schema After sending, the server emits two separate events: **1. `support_echo`** — Acknowledges that your message was received and queued: ```json theme={null} { "status_code": 200, "sid": "socket_session_id", "message": "support_echo", "data": {} } ``` **2. `support`** — The AI or agent reply, broadcast to the conversation room: 200 for success Session identifier Status message Response data **`data` object:** The reply message from SATE or an agent Conversation ID — store this from the first response to continue the conversation Who sent the reply: `"sate"` or `"agent"` Whether the reply includes an attachment Attachment details if present `true` when SATE signals that the issue appears resolved and the conversation can be closed `true` when the conversation has been confirmed closed ISO 8601 timestamp ISO 8601 timestamp ##### Example Response ```javascript theme={null} socket.on('support', (response) => { // { // "status_code": 200, // "sid": "socket_session_id", // "message": "Message sent successfully", // "data": { // "message": "Happy to help! Could you share your order number?", // "ticket_chat_id": "conv_abc123", // "sender": "sate", // "attachment": false, // "attachment_metadata": null, // "close_support": false, // "closed_support": false, // "date_created": "2024-01-15T10:31:00Z", // "date_updated": "2024-01-15T10:31:00Z" // } // } }); ``` When `close_support` is `true` but `closed_support` is `false`, SATE is suggesting the issue looks resolved. Ask the customer to confirm, then call `close_support` if they agree. ##### Important Notes * **New conversations**: Set `ticket_chat_id` to `null`. Save the `ticket_chat_id` from the response — you need it for every follow-up message. * **Conversation limit**: Each customer session can have a maximum of 3 open conversations at a time. * **Attachments**: Only available when the responder is `"agent"`. SATE does not send attachments. *** #### Mark Conversation Read Mark all messages in a conversation as read by the customer. **Event Name:** `mark_conversation_read` ##### Request Schema The conversation ID to mark as read Who is marking as read. Always use `"customer"` for customer-side integrations. ##### Example Request ```javascript theme={null} socket.emit('mark_conversation_read', { ticket_chat_id: 'conv_abc123', entity: 'customer' }); ``` ##### Response Schema ```json theme={null} { "status_code": 200, "sid": "socket_session_id", "message": "Marked as read", "data": {} } ``` *** #### Start Voice Call Initiate a voice call with SATE. The server responds with a LiveKit token you use to join the audio room. **Event Name:** `call_support` ##### Request Schema Unique identifier for the customer Existing conversation ID. Set to `null` to start a new conversation via call. ##### Example Request ```javascript theme={null} // Start a call on a new conversation socket.emit('call_support', { session_id: 'customer_123', ticket_chat_id: null }); // Start a call on an existing conversation socket.emit('call_support', { session_id: 'customer_123', ticket_chat_id: 'conv_abc123' }); ``` ##### Response Schema The server broadcasts a `call_support` event to the conversation room with the call details: LiveKit access token — use this with the LiveKit SDK to join the voice room LiveKit room name (matches the `ticket_chat_id`) Conversation ID Unique ID for this call ISO 8601 timestamp of when the call started ##### Example Response ```javascript theme={null} socket.on('call_support', (response) => { if (response.status_code === 200) { const { token, room } = response.data; // Connect to the voice room using the LiveKit client SDK connectToLiveKitRoom(token, room); } }); ``` ##### Important Notes * **Availability**: Voice calls are only available while SATE is the active responder and no other call is in progress. * **Voice room**: Pass the `token` to the [LiveKit client SDK](https://docs.livekit.io/realtime/client/) to connect to the audio room. * **Room name**: The LiveKit room name is the same as `ticket_chat_id`. *** #### End Voice Call End an active voice call. **Event Name:** `close_call_support` ##### Request Schema The conversation ID for the active call ##### Example Request ```javascript theme={null} socket.emit('close_call_support', { ticket_chat_id: 'conv_abc123' }); ``` ##### Response Schema The server broadcasts a `close_call_support` event to the conversation room: LiveKit room name Conversation ID Call ID — `null` if no active call was found ISO 8601 call start timestamp ISO 8601 call end timestamp ##### Example Response ```javascript theme={null} socket.on('close_call_support', (response) => { if (response.status_code === 200) { const { call_start_time, call_end_time } = response.data; disconnectFromLiveKit(); showCallSummary(call_start_time, call_end_time); } }); ``` *** #### Close Conversation End a conversation when the issue is resolved. **Event Name:** `close_support` Call this only after SATE sets `close_support: true` in a message and the customer confirms they want to end the conversation. ##### Request Schema The conversation ID to close ##### Example Request ```javascript theme={null} socket.emit('close_support', { ticket_chat_id: 'conv_abc123' }); ``` ##### Response Schema ```json theme={null} { "status_code": 200, "sid": "socket_session_id", "message": "Support conversation closed", "data": { "message": "Thank you for using our support. Your conversation has been closed.", "ticket_chat_id": "conv_abc123", "sender": "sate", "attachment": false, "attachment_metadata": null, "close_support": true, "closed_support": true, "date_created": "2024-01-15T12:00:00Z", "date_updated": "2024-01-15T12:00:00Z" } } ``` *** #### Review Support Collect customer feedback after a conversation ends. **Event Name:** `review_support` ##### Request Schema The conversation ID to review Customer rating: `"1"`, `"2"`, `"3"`, `"4"`, or `"5"` Optional customer feedback text ##### Example Request ```javascript theme={null} socket.emit('review_support', { ticket_chat_id: 'conv_abc123', rating: '5', review: 'Great service, very helpful!' }); ``` ##### Response Schema ```json theme={null} { "status_code": 200, "sid": "socket_session_id", "message": "Review noted", "data": { "rating": "5", "review": "Great service, very helpful!", "ticket_chat_id": "conv_abc123" } } ``` *** ### Server Broadcasts (Server → Client) These are events the server pushes to your client. Set up listeners for them to handle real-time updates. *** #### Agent Message Received Fired when a human agent sends a reply. Agent messages arrive on this event — not on `support` — so you must listen on both. **Listen On:** `customer_support` This event is delivered to the customer's personal room (set up via `enter_customer_support`), so it works even before the customer has joined a specific conversation room. ##### Response Schema Agent's reply message Conversation ID Always `"agent"` for this event Whether the message includes an attachment Attachment details if present Whether the agent is suggesting closure Whether the conversation is closed ISO 8601 timestamp ISO 8601 timestamp ##### Example ```javascript theme={null} socket.on('customer_support', (response) => { if (response.status_code === 200) { const { message, sender, ticket_chat_id } = response.data; displayMessage(message, sender); socket.emit('mark_conversation_read', { ticket_chat_id, entity: 'customer' }); } }); ``` *** #### Conversation Auto-Closed Fired when SATE closes a conversation automatically — without waiting for the customer to confirm. Update your UI to reflect the closed state. **Listen On:** `customer_support_closed` ##### Response Schema The parent ticket ID The conversation ID that was closed Updated ticket status ##### Example ```javascript theme={null} socket.on('customer_support_closed', (response) => { if (response.status_code === 200) { const { ticket_chat_id } = response.data; showConversationClosed(ticket_chat_id); } }); ``` *** #### Handler Changed Fired when a human agent takes over a conversation from SATE. Use this to show a notification like "You are now chatting with a human agent." **Listen On:** `support_handler_changed` ##### Response Schema The conversation ID The new handler type: `"agent"` Details of the agent who took over **`agent` object:** Agent's unique ID Agent's display name ##### Example ```javascript theme={null} socket.on('support_handler_changed', (response) => { if (response.status_code === 200) { const { handler, agent } = response.data; if (handler === 'agent') { showNotification(`You're now chatting with ${agent.username}`); } } }); ``` *** #### SATE Left Call Fired when SATE disconnects from an active voice call. Handle this to update your call UI and give the customer the option to end or wait. **Listen On:** `sate_left_call` ##### Response Schema The conversation ID The call ID ##### Example ```javascript theme={null} socket.on('sate_left_call', (response) => { if (response.status_code === 200) { disconnectFromLiveKit(); showNotification('The call has ended'); } }); ``` *** ## Implementation Example A complete example showing the full conversation and call flow: ```javascript theme={null} const API_BASE_URL = '{api_base_url}'; const socket = io(`${API_BASE_URL}/helpdesk?token_source=api&token=${API_KEY}`); let currentConversationId = null; // 1. On connect — immediately subscribe to the customer's personal room socket.on('connect', () => { socket.emit('enter_customer_support', { session_id: CUSTOMER_SESSION_ID }); }); // 2. Send a message function sendMessage(message, attachmentData = null) { socket.emit('support', { session_id: CUSTOMER_SESSION_ID, message: message, attachment: !!attachmentData, attachment_metadata: attachmentData, ticket_chat_id: currentConversationId }); } // 3. Receive SATE replies socket.on('support', (response) => { if (response.status_code === 200) { const { data } = response; if (!currentConversationId) { currentConversationId = data.ticket_chat_id; // Join the conversation room for all future broadcasts socket.emit('enter_support', { ticket_chat_id: currentConversationId }); } displayMessage(data.message, data.sender); socket.emit('mark_conversation_read', { ticket_chat_id: currentConversationId, entity: 'customer' }); // SATE suggests the issue is resolved — ask the customer to confirm if (data.close_support && !data.closed_support) { askCustomerToClose(currentConversationId); } } }); // 4. Receive agent replies (separate event from SATE replies) socket.on('customer_support', (response) => { if (response.status_code === 200) { displayMessage(response.data.message, response.data.sender); socket.emit('mark_conversation_read', { ticket_chat_id: response.data.ticket_chat_id, entity: 'customer' }); } }); // 5. Notify customer when a human agent takes over socket.on('support_handler_changed', (response) => { if (response.status_code === 200 && response.data.handler === 'agent') { showBanner(`You're now chatting with ${response.data.agent.username}`); } }); // 6. Handle auto-close by SATE socket.on('customer_support_closed', (response) => { if (response.status_code === 200) { showConversationClosed(response.data.ticket_chat_id); } }); // 7. Voice call function startVoiceCall() { socket.emit('call_support', { session_id: CUSTOMER_SESSION_ID, ticket_chat_id: currentConversationId }); } socket.on('call_support', (response) => { if (response.status_code === 200) { // Use the LiveKit SDK to connect to the voice room connectToLiveKitRoom(response.data.token, response.data.room); } }); socket.on('sate_left_call', () => { disconnectFromLiveKit(); showNotification('The call has ended'); }); function endVoiceCall() { socket.emit('close_call_support', { ticket_chat_id: currentConversationId }); } socket.on('close_call_support', (response) => { if (response.status_code === 200) { disconnectFromLiveKit(); showCallSummary(response.data.call_start_time, response.data.call_end_time); } }); // 8. Customer confirms close function closeConversation() { socket.emit('close_support', { ticket_chat_id: currentConversationId }); } // 9. Collect review function submitReview(rating, feedback) { socket.emit('review_support', { ticket_chat_id: currentConversationId, rating: rating, review: feedback }); } ``` ## Next Steps * [Complete API Reference](/modules/helpdesk/api-reference) for HTTP endpoints * [SDK Integration](/modules/helpdesk/sdk) for easier implementation