Skip to main content
Business & GrowthCustomer Support Services278 lines

LiveChat

"LiveChat: real-time chat, ticket system, agent management, chat archives, customer SDK, REST API v3, webhooks, rich messages"

Quick Summary9 lines
You are an expert in integrating LiveChat for real-time customer communication, ticket management, and chat-based support workflows.

## Key Points

- Set session variables (`set_session_variables`) with user context before the chat starts so agents see account details, plan tier, and recent activity immediately without asking the customer.
- Implement the `chat_deactivated` webhook to trigger post-chat workflows such as satisfaction surveys, CRM updates, or ticket creation for unresolved issues.
- The widget's `set_customer_email` and `set_customer_name` calls must happen before a chat starts; calling them mid-conversation has no effect on the active chat session.
skilldb get customer-support-services-skills/LiveChatFull skill: 278 lines
Paste into your CLAUDE.md or agent config

LiveChat — Customer Support Integration

You are an expert in integrating LiveChat for real-time customer communication, ticket management, and chat-based support workflows.

Core Philosophy

Overview

LiveChat is a real-time customer communication platform that provides a chat widget, a ticketing system for offline messages, agent management, chat routing, and canned responses. The LiveChat Platform API v3 covers chat operations, agent configuration, customer management, and webhook registration. The Customer Chat SDK enables building custom chat interfaces, and the Agent Chat SDK allows building custom agent dashboards.

Setup & Configuration

Authenticate using a Personal Access Token (PAT) or OAuth2:

import axios, { AxiosInstance } from "axios";

function createLiveChatClient(accessToken: string): AxiosInstance {
  return axios.create({
    baseURL: "https://api.livechatinc.com/v3.5",
    headers: {
      Authorization: `Bearer ${accessToken}`,
      "Content-Type": "application/json",
    },
  });
}

const livechat = createLiveChatClient(process.env.LIVECHAT_ACCESS_TOKEN!);

// For the Configuration API (agents, groups, etc.)
const livechatConfig = axios.create({
  baseURL: "https://api.livechatinc.com/v3.5/configuration/action",
  headers: {
    Authorization: `Bearer ${process.env.LIVECHAT_ACCESS_TOKEN}`,
    "Content-Type": "application/json",
  },
});

// Verify connection
async function verifyConnection(): Promise<void> {
  const response = await livechatConfig.post("/list_agents", {});
  console.log(`Connected. ${response.data.length} agents configured.`);
}

Embed the chat widget on your frontend:

<script>
  window.__lc = window.__lc || {};
  window.__lc.license = YOUR_LICENSE_ID;
  window.__lc.integration_name = "custom_integration";
  window.__lc.product_name = "livechat";
  ;(function(n,t,c){
    function i(n){return e._h?e._h.apply(null,n):e._q.push(n)}
    var e={_q:[],_h:null,_v:"2.0",on:function(){i(["on",c.call(arguments)])},
    once:function(){i(["once",c.call(arguments)])},off:function(){i(["off",c.call(arguments)])},
    get:function(){if(!e._h)throw new Error("[LiveChatWidget] You cannot use getters before load.");
    return i(["get",c.call(arguments)])},call:function(){i(["call",c.call(arguments)])}};
    window.LiveChatWidget=e;
    var s=t.createElement("script");
    s.async=!0;s.type="text/javascript";
    s.src="https://cdn.livechatinc.com/tracking.js";
    t.head.appendChild(s);
  })(window,document,[].slice);
</script>

Pass visitor identity to LiveChat:

declare global {
  interface Window {
    LiveChatWidget: {
      call: (method: string, ...args: any[]) => void;
      on: (event: string, callback: (...args: any[]) => void) => void;
    };
  }
}

function identifyVisitor(name: string, email: string, customVars: Record<string, string> = {}): void {
  window.LiveChatWidget.call("set_customer_name", name);
  window.LiveChatWidget.call("set_customer_email", email);

  // Set custom session variables visible to agents
  const variables = Object.entries(customVars).map(([key, value]) => ({
    name: key,
    value,
  }));
  window.LiveChatWidget.call("set_session_variables", variables);
}

// Example
identifyVisitor("Jane Doe", "jane@acme.com", {
  plan: "enterprise",
  accountId: "acc_12345",
  region: "us-east-1",
});

Core Patterns

List Chat Archives

interface ChatFilters {
  dateFrom?: string;  // ISO 8601
  dateTo?: string;
  agentId?: string;
  tagName?: string;
  pageId?: string;
}

async function listChats(filters: ChatFilters = {}): Promise<any> {
  const response = await livechat.post("/agent/action/list_archives", {
    filters: {
      from: filters.dateFrom,
      to: filters.dateTo,
      agents: filters.agentId ? [filters.agentId] : undefined,
      tags: filters.tagName ? [filters.tagName] : undefined,
    },
    page_id: filters.pageId,
  });
  return {
    chats: response.data.chats,
    nextPageId: response.data.next_page_id,
  };
}

Send a Rich Message (Cards, Buttons)

interface RichMessageButton {
  text: string;
  type: "url" | "message";
  value: string;
}

async function sendRichMessage(
  chatId: string,
  title: string,
  elements: Array<{ title: string; subtitle?: string; buttons: RichMessageButton[] }>
): Promise<void> {
  await livechat.post("/agent/action/send_rich_message_postback", {
    chat_id: chatId,
    template_id: "cards",
    elements: elements.map((el) => ({
      title: el.title,
      subtitle: el.subtitle ?? "",
      buttons: el.buttons.map((btn) => ({
        text: btn.text,
        type: btn.type,
        value: btn.value,
        postback_id: `btn_${Date.now()}`,
      })),
    })),
  });
}

// Example: send a card with action buttons
await sendRichMessage("chat_abc123", "How can we help?", [
  {
    title: "Billing Issue",
    subtitle: "Questions about charges or invoices",
    buttons: [
      { text: "View billing FAQ", type: "url", value: "https://docs.example.com/billing" },
      { text: "Talk to billing team", type: "message", value: "Connect me to billing" },
    ],
  },
]);

Create a Ticket (for Offline Messages)

async function createTicket(
  requesterEmail: string,
  subject: string,
  message: string,
  groupId?: number
): Promise<any> {
  const response = await livechat.post("/agent/action/create_ticket", {
    requester: { email: requesterEmail },
    events: [
      {
        type: "message",
        text: message,
      },
    ],
    subject,
    group_id: groupId,
  });
  return response.data;
}

Webhook Registration and Handling

// Register a webhook
async function registerWebhook(
  url: string,
  action: string,
  secretKey: string
): Promise<void> {
  await livechatConfig.post("/register_webhook", {
    url,
    action,       // e.g. "incoming_chat", "chat_deactivated", "incoming_event"
    secret_key: secretKey,
    type: "license",
  });
}

// Webhook handler
import express, { Request, Response } from "express";
import crypto from "crypto";

function verifyLiveChatWebhook(body: string, signature: string, secret: string): boolean {
  const digest = crypto.createHmac("sha256", secret).update(body).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(digest), Buffer.from(signature));
}

function setupWebhooks(app: express.Application): void {
  app.post("/webhooks/livechat", express.text({ type: "*/*" }), (req: Request, res: Response) => {
    const signature = req.headers["x-livechat-signature"] as string;

    if (!verifyLiveChatWebhook(req.body, signature, process.env.LIVECHAT_WEBHOOK_SECRET!)) {
      res.sendStatus(403);
      return;
    }

    const event = JSON.parse(req.body);

    switch (event.action) {
      case "incoming_chat":
        handleIncomingChat(event.payload);
        break;
      case "incoming_event":
        handleNewMessage(event.payload);
        break;
      case "chat_deactivated":
        handleChatEnded(event.payload);
        break;
    }

    res.sendStatus(200);
  });
}

Best Practices

  • Set session variables (set_session_variables) with user context before the chat starts so agents see account details, plan tier, and recent activity immediately without asking the customer.
  • Use chat tags and groups to route conversations to specialized teams (billing, technical, onboarding); configure automatic routing rules in the LiveChat dashboard rather than building custom routing.
  • Implement the chat_deactivated webhook to trigger post-chat workflows such as satisfaction surveys, CRM updates, or ticket creation for unresolved issues.

Common Pitfalls

  • LiveChat API v3 uses a method-based RPC style (POST to action endpoints like /agent/action/list_archives) rather than RESTful resource URLs. Using GET requests or REST-style paths will return 404 errors.
  • The widget's set_customer_email and set_customer_name calls must happen before a chat starts; calling them mid-conversation has no effect on the active chat session.

Anti-Patterns

Using the service without understanding its pricing model. Cloud services bill differently — per request, per GB, per seat. Deploying without modeling expected costs leads to surprise invoices.

Hardcoding configuration instead of using environment variables. API keys, endpoints, and feature flags change between environments. Hardcoded values break deployments and leak secrets.

Ignoring the service's rate limits and quotas. Every external API has throughput limits. Failing to implement backoff, queuing, or caching results in dropped requests under load.

Treating the service as always available. External services go down. Without circuit breakers, fallbacks, or graceful degradation, a third-party outage becomes your outage.

Coupling your architecture to a single provider's API. Building directly against provider-specific interfaces makes migration painful. Wrap external services in thin adapter layers.

Install this skill directly: skilldb add customer-support-services-skills

Get CLI access →