The Live Chat system enables agent-based customer conversations with ticket tracking, team assignment, and message history across WhatsApp, Web, and Facebook channels.
All API requests require your Developer Key in the Authorization header. No Bearer prefix — pass the key directly. See Authentication for setup and security best practices.
The Live Chat system is built around three core concepts:
| Concept | Description |
|---|---|
| Chat Participants | Active conversations between a customer and your platform |
| Tickets | Track and manage conversations with status workflows |
| Agents & Teams | Support staff organized with team assignment and supervisor oversight |
Customer Message ──> Unassigned Queue ──> Agent Picks Up ──> Active Chat
│
┌─────────────┼─────────────┐
▼ ▼ ▼
Resolved Transferred Closed
(Ticket) (to team) (Rating widget)Follow this three-step flow to receive an incoming WhatsApp message and retrieve the full conversation history.
Incoming Message ──> Webhook fires ──> Look up ChatParticipant ──> Get messages
(customer) (your server) (by sender number) (by participant ID)When a customer sends a message, your configured incomingMessageURL receives a POST with the message payload. See Webhooks — Incoming message payload for full details.
{
"profileName": "John Smith",
"sender": "+27987654321",
"senderUserId": "ZA.1021033720668862",
"username": "john_smith",
"receiver": "+27123456789",
"text": "Hi, I need help with my order",
"messageType": "INTERACTION",
"messageContentType": "TEXT",
"gstId": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
"participantId": "participant-uuid",
"sentTime": "2026-01-15T10:30:00.000+00:00",
"status": "RECEIVED"
}WhatsApp is rolling out alpha usernames. Each customer now has a durable, business-scoped user id (BSUID, e.g. ZA.1021033720668862) that is stable for your business even if the customer changes their phone number — and that stays present on inbound events even when the phone number is withheld. Customers may also set an optional username (display only).
Incoming, chatbot, and status webhooks carry the customer BSUID as senderUserId / recipientUserId, plus the optional username. The phone number (sender / senderMsisdn) remains the primary identifier today — the BSUID is an additional, more durable key you can store now and rely on as phone numbers become optional. The BSUID is always present on these payloads; username is omitted only when the customer hasn't set one.
Use the sender field without a + to look up the chat participant in Step 2. When the phone number is withheld, match on userId (the customer BSUID) instead — it is present on the chat participant even when the number is not.
The participantId field on the incoming-message webhook payload identifies a participant in the conversation engine. It is not the same as the live-chat chatParticipantId used to fetch messages or send agent replies. Always resolve the live-chat participant by sender (Step 2) before calling any /pl4chat-service/api/v2/messages or /pl4chat-service/api/v2/chats endpoints.
List your chats and filter by the sender's phone number to find the latest conversation. The v2 list endpoint selects which conversations to return with a scope filter — the agent and client are resolved from your API key, so you only choose the tab:
GET /pl4chat-service/api/v2/chats?scope=myscope | Returns |
|---|---|
my | Conversations assigned to you (the authenticated agent) |
team | Conversations assigned to your team members |
unassigned | Conversations waiting in queue |
closed | Closed conversations |
missed-agent | Missed conversations |
missed-after-hours | After-hours missed conversations |
my-missed | Your missed conversations |
open | All open client conversations |
all | All conversations (open and closed) |
| Parameter | Type | Description |
|---|---|---|
scope | string | Which list to return (see above). Required |
page | integer | Page number (0-based). Default: 0 |
size | integer | Page size. Default: 10 |
search | string | Filter by phone number, name, or customer id |
Use the search parameter with the sender's phone number or BSUID (senderUserId) to narrow results directly, or filter client-side after fetching. The response is a page of ChatParticipantResponse objects. Match on phoneNumber or userId — a customer with a withheld phone number is identified only by userId (BSUID).
curl -X GET \
"https://api.payless4messaging.com/pl4chat-service/api/v2/chats?scope=unassigned&page=0&size=50&search=27987654321" \
-H "Authorization: $ECOMM_API_KEY"Use the participant ID from step 2 to retrieve the full message history:
curl -X GET \
"https://api.payless4messaging.com/pl4chat-service/api/v2/messages?participantId=participant-uuid" \
-H "Authorization: $ECOMM_API_KEY"If you have the GSTN (Global System Tracking Number) or CTN (Customer Tracking Number) from the chat participant object, you can retrieve messages directly without needing the participant ID:
GET /pl4chat-service/api/v2/messages/tracking/{trackingNumber}curl -X GET \
"https://api.payless4messaging.com/pl4chat-service/api/v2/messages/tracking/a1b2c3d4-e5f6-7890-a1b2-c3d4e5f67890" \
-H "Authorization: $ECOMM_API_KEY"After retrieving messages, mark the conversation as read — this clears the unread badge and sends a read receipt to the customer in one call:
POST /pl4chat-service/api/v2/messages/read?participantId=cp-a1b2c3d4Each chat participant carries:
| Field | Type | Description |
|---|---|---|
id | string | Chat participant id |
phoneNumber | string | Customer phone number. May be absent when the number is withheld |
userId | string | Customer BSUID (e.g. ZA.1021033720668862), durable across phone-number changes. Present even when phoneNumber is not |
username | string | Customer's optional WhatsApp username (display only) |
name | string | Display name |
Close or reopen a conversation with its id — the acting agent is resolved from your API key, so there's no request body to assemble:
POST /pl4chat-service/api/v2/chats/{id}/terminate # close (sends the rating widget if configured)
POST /pl4chat-service/api/v2/chats/{id}/open # reopen and assign to youBoth return the updated ChatParticipantResponse.
Terminating a chat moves its current assignedTo to lastAssignedAgent and frees the slot in the agent's chat-limit count automatically. (The deprecated PUT /pl4chat-service/ChatParticipant/terminateChatParticipantChat required you to echo the full object back to make that happen — v2 does it server-side.)
Only messages sent through the live-chat send endpoint show up in the live-chat UI. Outbound sends through the notifications endpoint (/whatsapp-api-service/v2/channels/whatsapp) reach the customer but bypass the chat service entirely — agents won't see them. See How the system fits together for the architecture.
One endpoint sends on every channel. Set channel (WHATSAPP, WEB, or FACEBOOK) and text — the agent is resolved from your API key:
POST /pl4chat-service/api/v2/messages{
"participantId": "participant-uuid",
"channel": "WHATSAPP",
"tempId": "unique-temp-uuid",
"text": "Here is the information you requested."
}tempId is optional — supply a client-generated string only if you want it echoed back to reconcile an optimistic UI message; otherwise omit it. The response is the stored MessageResponse (with your tempId echoed back when you sent one). To quote/reply to an earlier message, also set quotedExternalMessageId.
Upload the file, then send the returned mediaUrl — the same flow works for any channel:
POST /pl4chat-service/api/v2/messages/media # multipart/form-data, field "file" -> { mediaUrl, mediaType }
POST /pl4chat-service/api/v2/messages # { participantId, channel, mediaUrl, text? }The content type defaults to MEDIA when a mediaUrl is present, so you don't need to set it.
POST /pl4chat-service/api/v2/messages/typing?participantId=participant-uuidShows a typing bubble to the customer while the agent is composing a reply.
POST /pl4chat-service/api/v2/messages/read?participantId=participant-uuidGET /pl4chat-service/ticket/searchRequired parameters:
| Parameter | Type | Description |
|---|---|---|
page | integer | Page number (0-based) |
size | integer | Page size |
startDateTime | string | Start of date range |
endDateTime | string | End of date range |
clientRef | string | Client reference |
Optional filters:
| Filter | Type | Description |
|---|---|---|
whatsAppNumber | string | Customer WhatsApp number |
rating | enum | poor, average, or excellent |
ticketNumber | string | Specific ticket number (e.g., TCK-001) |
agentId | string | Filter by assigned agent |
selectedStatus | enum | open, closed, awaiting agent, awaiting customer, resolved |
PUT /pl4chat-service/ticket/{ticketId}/status?newStatus=RESOLVEDAvailable statuses:
| Status | Description |
|---|---|
OPEN | Ticket is active and being worked on |
AWAITING_AGENT | Waiting for an agent to respond |
AWAITING_CUSTOMER | Waiting for the customer to respond |
RESOLVED | Issue has been resolved but ticket remains accessible |
CLOSED | Ticket is closed and archived |
GET /pl4chat-service/ticket/by-ticket-number?ticketNumber=TCK-001Manage customer contact records linked to your account.
| Method | Endpoint | Description |
|---|---|---|
GET | /payless4messaging-service/WhatsApp/contacts | Get all contacts (paginated) |
POST | /payless4messaging-service/WhatsApp/contacts | Create a contact |
PUT | /payless4messaging-service/WhatsApp/contacts/{id} | Update a contact |
DELETE | /payless4messaging-service/WhatsApp/contacts/{id} | Delete a contact |
Currently, only the fullName field can be updated on an existing contact. Other fields (phone number, business name, etc.) are read-only after creation.
PUT /payless4messaging-service/WhatsApp/contacts/{id}
{
"fullName": "Jane Smith"
}| Channel | Value | Description |
|---|---|---|
WHATSAPP | WhatsApp conversations via Cloud or Lite | |
| Web | WEB | Web chat widget embedded in your website |
FACEBOOK | Facebook Messenger conversations |
| Type | Description |
|---|---|
TEXT | Plain text message |
IMAGE | Image attachment (JPG, PNG, GIF) |
DOCUMENT | Document attachment (PDF, DOCX, XLSX) |
VIDEO | Video attachment (MP4) |
AUDIO | Audio message |
VOICE | Voice note |
FILE | Generic file attachment |
LOCATION | Location with latitude/longitude |
BUTTON | Button interaction response |
CAROUSEL | Carousel card |
RATING | Customer rating response |