Chatbot WebSocket API (Live chat)
WebSocket API
Gebruik de WebSocket API voor realtime live chat: directe berichtbezorging, typindicatoren, aanwezigheid, automatische vertaling en sessielevenscyclus. Dezelfde socket voedt bezoekerswidgets en het agent-dashboard, zodat je een aangepaste agent-console kunt bouwen of live chat vanuit je eigen backend kunt aansturen.
Eindpunt
wss://webchatagent.com/api/livechat
Al het verkeer is JSON. Je verstuurt client:*-gebeurtenissen; de server stuurt livechat:*-gebeurtenissen terug. Elk bericht bevat een type-veld.
Verbindingsrollen
Wanneer je deelneemt, declareer je een rol met het as-veld:
| Rol | Beschrijving |
|---|---|
user | Een websitebezoeker in een chat. |
admin | Een menselijke agent die livechatsessies beheert. |
widget | De ingesloten chatwidget in monitoringmodus (vóór een overname). |
De rol bepaalt wat je ontvangt: admin-clients ontvangen de volledige berichtengeschiedenis en events die alleen voor admins zijn bedoeld; user-clients ontvangen alleen nieuwe live-events (bezoekers laden hun eigen geschiedenis via het REST history endpoint, niet via de socket).
Korte flow
- Open de socket en verstuur
client:joinmet jechatbotId,sessionIdenas. - De server antwoordt met
{ "type": "livechat:status", "ok": true }om de deelname te bevestigen. Admins ontvangen vervolgens de berichtengeschiedenis en een actuelelivechat:status-momentopname. - Verstuur
client:messageom te plaatsen; ontvanglivechat:messagevoor elk nieuw bericht. - Verstuur
client:typing/ ontvanglivechat:typingvoor typindicatoren. - Sluit af met
client:end, of ontvanglivechat:endedwanneer de andere partij sluit.
Client-events (die jij verstuurt)
client:join
Het eerste event na het verbinden. Neemt deel aan de sessieruimte (en, voor admins, de chatbotruimte).
{
"type": "client:join",
"chatbotId": "YOUR_CHATBOT_ID",
"sessionId": "SESSION_ID",
"as": "user",
"lang": "en",
"translateEnabled": true,
"retranslateBacklog": false
}
| Veld | Type | Verplicht | Beschrijving |
|---|---|---|---|
chatbotId | string | Ja | De UUID van je chatbot. Voor een admin die alle bots monitort, zorgt de speciale waarde "all" voor deelname zonder een specifieke ruimte. |
sessionId | string | Ja | Het chatsessie-ID. |
as | string | Ja | user, admin of widget. |
lang | string | Nee | Voorkeurstaalcode (bijv. en, de, fr). Stelt het vertaaldoel in. |
translateEnabled | boolean | Nee | Schakel automatische vertaling in voor deze sessie (standaard: ingeschakeld). |
retranslateBacklog | boolean | Nee | Vertaal bestaande backlog-berichten opnieuw naar lang bij het deelnemen (admin). |
client:message
Plaats een bericht in de sessie. De server slaat het op, vertaalt het indien ingeschakeld, en zendt livechat:message uit.
{
"type": "client:message",
"chatbotId": "YOUR_CHATBOT_ID",
"sessionId": "SESSION_ID",
"sender": "user",
"content": "I need help with my order",
"lang": "en"
}
| Veld | Type | Verplicht | Beschrijving |
|---|---|---|---|
chatbotId | string | Ja | De UUID van je chatbot. |
sessionId | string | Ja | Het chatsessie-ID. |
sender | string | Ja | user of admin. |
content | string | Ja | De berichttekst. Een lege of ontbrekende content wordt genegeerd. |
lang | string | Nee | Taalsuggestie van het bericht voor vertaling. |
Het eerste admin-bericht in een sessie die wachtend is opent deze (status → open) en voegt automatisch een "agent toegetreden"-systeembericht in.
client:typing
Zend een typindicator uit naar iedereen in de sessie.
{
"type": "client:typing",
"chatbotId": "YOUR_CHATBOT_ID",
"sessionId": "SESSION_ID",
"sender": "user",
"isTyping": true
}
client:meta
Werk sessiemetadata (huidige pagina) bij zodat agents zien waar de bezoeker zich bevindt.
{
"type": "client:meta",
"chatbotId": "YOUR_CHATBOT_ID",
"sessionId": "SESSION_ID",
"pageUrl": "https://example.com/pricing",
"pageTitle": "Pricing - Example",
"referrer": "https://google.com",
"browserLanguage": "en-US"
}
client:agent_takeover
Admin neemt proactief een AI-sessie over (zet deze op open / human). Alleen voor admins.
{
"type": "client:agent_takeover",
"chatbotId": "YOUR_CHATBOT_ID",
"sessionId": "SESSION_ID"
}
client:end
Beëindig de sessie.
{
"type": "client:end",
"chatbotId": "YOUR_CHATBOT_ID",
"sessionId": "SESSION_ID",
"reason": "resolved"
}
client:widget_open / client:widget_close
Verzonden door de widget om een actieve sessie te registreren/af te melden voor zichtbaarheid door admins (dit vult livechat:widget_sessions).
{
"type": "client:widget_open",
"chatbotId": "YOUR_CHATBOT_ID",
"sessionId": "SESSION_ID",
"pageUrl": "https://example.com",
"pageTitle": "Home",
"browserLanguage": "en-US"
}
Server-events (die jij ontvangt)
livechat:status
Twee vormen: een eenvoudige { "type": "livechat:status", "ok": true } ontvangstbevestiging van deelname, en een momentopname van de sessiestatus (hieronder).
{
"type": "livechat:status",
"chatbotId": "YOUR_CHATBOT_ID",
"sessionId": "SESSION_ID",
"status": "open",
"mode": "human",
"userName": "John",
"userEmail": "john@example.com",
"userLanguage": "en"
}
| Veld | Type | Beschrijving |
|---|---|---|
status | string | waiting (nog geen agent), open (agent verbonden) of closed. |
mode | string | bot of human. |
userName | string | null | Naam van de bezoeker, indien verzameld via Leads. |
userEmail | string | null | E-mailadres van de bezoeker, indien verzameld. |
userLanguage | string | null | Gedetecteerde taal van de bezoeker. |
livechat:message
Een nieuw (of backlog-)bericht.
{
"type": "livechat:message",
"id": 1024,
"sessionId": "SESSION_ID",
"sender": "admin",
"content": "Hello! How can I help you today?",
"country": "DE",
"createdAt": "2025-01-15T10:30:00Z",
"file": null,
"audience": "admin",
"historical": false
}
| Veld | Type | Beschrijving |
|---|---|---|
id | number | Bericht-ID (komt overeen met de REST-geschiedenis-id). |
sender | string | user, admin of system. |
content | string | Berichttekst. Voor admin-clients met vertaling ingeschakeld is dit al vertaald naar de taal van de admin. |
country | string | null | Landcode van de afzender, indien gedetecteerd. |
createdAt | string | ISO 8601-tijdstempel. |
file | object | null | Metadata van het bijgevoegde bestand (uploadId, name, mimeType, size, url, isImage) wanneer het bericht een upload is. |
audience | string | null | "admin" op het exemplaar van een bericht voor de admin. Het exemplaar voor de gebruiker laat dit weg. |
historical | boolean | true voor backlog-berichten die opnieuw worden afgespeeld bij deelname. |
Systeemberichten: wanneer
sendergelijk is aansystem, iscontenteen token dat je client moet lokaliseren en niet letterlijk moet weergeven:__agent_joined__,__livechat_ended__of__livechat_timeout__.
livechat:typing
Typindicator van een andere deelnemer: { type, chatbotId, sessionId, sender, isTyping }.
livechat:presence
Online/offline-status van de bezoeker in een sessie: { type, chatbotId, sessionId, online } (boolean).
livechat:meta
Bijgewerkte sessiemetadata (huidige pagina, titel, referrer), alleen voor admins.
livechat:ended
De sessie is gesloten.
{
"type": "livechat:ended",
"sessionId": "SESSION_ID",
"reason": "admin_closed"
}
reason is een van admin_closed, already_closed of timeout.
Events alleen voor admins
| Event | Payload | Doel |
|---|---|---|
livechat:active_count | { chatbotId, count } | Actieve sessies (wachtend + open). |
livechat:waiting_count | { chatbotId, count } | Wachtende sessies (badge voor onbeantwoorde chats). |
livechat:new_request | { chatbotId, sessionId, status, mode, ... } | Een nieuwe livechat heeft een agent nodig. |
livechat:widget_sessions | { chatbotId, chatbotName, sessions } | Huidige lijst van actieve widget-sessies. |
livechat:notification | { chatbotId, sessionId, content, sender } | Nieuw bericht terwijl de agent zich elders in het dashboard bevindt. |
Automatische vertaling
De socket kan automatisch vertalen tussen de talen van de bezoeker en de agent:
- Neem deel met
translateEnabled: trueen stellangin op jouw taal. - Berichten van de andere partij komen al vertaald binnen in jouw
lang. Elke partij behoudt de originele tekst; de vertaalde versie wordt aan de andere partij bezorgd. - Vertaling verloopt via Gemini, zodat een agent met een bezoeker in elke taal kan chatten zonder handmatig te vertalen.
Voorbeeld: Aangepaste livechat-client
const ws = new WebSocket('wss://webchatagent.com/api/livechat');
ws.onopen = () => {
ws.send(JSON.stringify({
type: 'client:join',
chatbotId: 'YOUR_CHATBOT_ID',
sessionId: 'SESSION_ID',
as: 'user',
lang: 'en'
}));
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
switch (data.type) {
case 'livechat:status':
// Join ack ({ ok: true }) or a session snapshot ({ status, mode, ... })
if (data.ok) console.log('Joined');
else console.log(`Status: ${data.status}, mode: ${data.mode}`);
break;
case 'livechat:message':
if (data.sender === 'system') {
// Localize tokens like __agent_joined__ / __livechat_ended__
console.log('[system]', data.content);
} else {
console.log(`${data.sender}: ${data.content}`);
}
break;
case 'livechat:typing':
console.log(`${data.sender} is typing: ${data.isTyping}`);
break;
case 'livechat:ended':
console.log(`Session ended: ${data.reason}`);
ws.close();
break;
}
};
function sendMessage(text) {
ws.send(JSON.stringify({
type: 'client:message',
chatbotId: 'YOUR_CHATBOT_ID',
sessionId: 'SESSION_ID',
sender: 'user',
content: text,
lang: 'en'
}));
}
function sendTyping(isTyping) {
ws.send(JSON.stringify({
type: 'client:typing',
chatbotId: 'YOUR_CHATBOT_ID',
sessionId: 'SESSION_ID',
sender: 'user',
isTyping
}));
}
