Package-level declarations

Types

Link copied to clipboard
@Serializable
data class AgentAvatar(val name: String = "", val avatarUrl: String? = null)

A team member shown in the chat header.

Link copied to clipboard
@Serializable
data class AgentSummary(val name: String = "", val avatarUrl: String? = null)

The human handling a conversation.

Link copied to clipboard
data class AppContext(val installId: String, val version: String? = null, val sdk: String? = null, val os: String? = null, val osVersion: String? = null, val deviceModel: String? = null, val locale: String? = null)

Install and build details sent on bootstrap and auth.

Link copied to clipboard
@Serializable
data class Attachment(val id: String = "", val name: String = "", val size: Long = 0, val type: String = "application/octet-stream", val url: String? = null)

A file attached to a message.

Link copied to clipboard
@Serializable
data class Availability(val online: Boolean = false, val withinHours: Boolean = true, val nextOpenAt: Instant? = null, val agentsOnline: Int = 0)

Whether the team can answer right now.

Link copied to clipboard
data class AvailabilityFrame(val availability: Availability, val id: String? = null) : ServerFrame

Team availability changed.

Link copied to clipboard
data class BootstrapResponse(val visitorToken: String, val visitor: VisitorDto, val config: SiteConfig, val availability: Availability, val timeline: List<TimelineItem>, val wsUrl: String, val conversation: ConversationSummary? = null, val protocolVersion: Int = 1, val timelineHasMore: Boolean? = null, val appId: String? = null, val appPlatform: String? = null)

What POST /bootstrap returns.

Link copied to clipboard
data class ClientFrame(val t: String, val d: JsonElement? = null)

A frame the SDK sends: {t, d, id?, v: 1}.

Link copied to clipboard
data class ClientInfo(val sdk: String, val version: String)

The SDK identifying itself on the socket.

Link copied to clipboard
object CloseCodes

Socket close codes the gateway uses.

Link copied to clipboard
@Serializable
data class ContactButton(val kind: ContactButtonKind, val url: String = "", val label: String = "")

Another way to reach the shop, resolved to a link by the gateway.

Link copied to clipboard
Link copied to clipboard
@Serializable
data class ConversationEventDto(val id: String = "", val conversationId: String = "", val seq: Int = 0, val type: String = "", val createdAt: Instant = Instant.EPOCH, val actorType: SenderType = SenderType.SYSTEM, val actorId: String? = null, val data: JsonObject = EmptyJsonObject) : TimelineItem

Something that happened in a conversation (status change, handoff, notice, ...).

Link copied to clipboard
data class ConversationStartFrame(val conversation: ConversationSummary, val open: Boolean, val id: String? = null) : ServerFrame

The team started a conversation with the visitor.

Link copied to clipboard

Conversation lifecycle status.

Link copied to clipboard
data class ConversationSummary(val id: String = "", val siteId: String = "", val visitorId: String = "", val status: ConversationStatus = ConversationStatus.OPEN, val seq: Int = 0, val visitorUnread: Int = 0, val lastMessageAt: Instant? = null, val lastMessagePreview: String? = null, val lastMessageSenderType: SenderType? = null, val assigneeKind: String? = null, val assigneeId: String? = null, val firstResponseAt: Instant? = null, val resolvedAt: Instant? = null, val subject: String? = null, val createdAt: Instant? = null, val updatedAt: Instant? = null, val raw: JsonObject = EmptyJsonObject)

A conversation as the gateway reports it on ready / conversation.start.

Link copied to clipboard
data class ConversationUpdateFrame(val conversation: VisitorConversationDto, val id: String? = null) : ServerFrame

One of the visitor's conversations changed status or handler.

Link copied to clipboard
data class ConversationUpsertFrame(val conversation: ConversationSummary, val id: String? = null) : ServerFrame

A conversation summary changed (team-side shape; tolerated).

Link copied to clipboard
data class CsatCard(val options: List<String>, val answered: Boolean = false) : MessageCard

A rating prompt after resolve.

Link copied to clipboard
data class ErrorFrame(val code: String, val message: String, val forId: String? = null, val id: String? = null) : ServerFrame

A request failed (with the request id) or an unsolicited error.

Link copied to clipboard
data class EventFrame(val event: ConversationEventDto, val id: String? = null) : ServerFrame

A conversation event visible to visitors.

Link copied to clipboard
sealed class FormatToken

One piece of a formatted message (port of format.ts). Never HTML.

Link copied to clipboard
@Serializable
data class GreetingOptions(val enabled: Boolean = true, val onMobile: Boolean = true, val sender: GreetingSender = GreetingSender.NONE, val teaserSeconds: Int = 0)

How the greeting is shown (dashboard: website settings → greeting).

Link copied to clipboard

Who signs the greeting.

Link copied to clipboard

The name hosts see for Availability.

Link copied to clipboard
class HatangException(val code: String, val message: String, val status: Int? = null, cause: Throwable? = null) : Exception

An error reported by the Hatang gateway (REST or socket) or by the SDK itself.

Link copied to clipboard

Languages the Hatang widget and SDK speak.

Link copied to clipboard
@Serializable
data class HeaderConfig(val subtitle: Map<String, String> = emptyMap(), val logoUrl: String? = null, val profile: HeaderProfile = HeaderProfile.AGENTS)

The chat header: a subtitle per language, the business logo and what the avatar spot shows.

Link copied to clipboard

Who the chat header shows (dashboard: website settings → header).

Link copied to clipboard
@Serializable
data class LauncherConfig(val icon: LauncherIcon = LauncherIcon.CHAT, val imageUrl: String? = null, val label: Map<String, String> = emptyMap())

How the launcher button looks: a preset icon or the site's own image, and an optional short label per language that turns it into a pill ("Hỗ trợ").

Link copied to clipboard

The launcher's preset icon (dashboard: website settings → launcher button).

Link copied to clipboard
object Limits

Size limits the gateway enforces.

Link copied to clipboard
data class MessageAckFrame(val clientId: String, val messageId: String, val seq: Int, val conversationId: String, val id: String? = null) : ServerFrame

Reply to message.send.

Link copied to clipboard
sealed class MessageCard

A rich card carried in MessageDto.metadata (kind + payload). Every channel degrades to the message text; the SDK renders the card under the bubble.

Link copied to clipboard
@Serializable
data class MessageDto(val id: String = "", val conversationId: String = "", val seq: Int = 0, val senderType: SenderType = SenderType.SYSTEM, val content: String = "", val createdAt: Instant = Instant.EPOCH, val senderId: String? = null, val senderName: String? = null, val visibility: String = "public", val contentType: String = "text", val attachments: List<Attachment> = emptyList(), val clientId: String? = null, val metadata: JsonObject? = null, val deliveryStatus: String? = null, val deliveryError: String? = null, val readAt: Instant? = null) : TimelineItem

A chat message.

Link copied to clipboard
data class MessageFrame(val message: MessageDto, val id: String? = null) : ServerFrame

A message in one of the visitor's conversations.

Link copied to clipboard

What the site asks for before a visitor writes while nobody is online.

Link copied to clipboard
data class OrderCard(val id: String, val code: String, val status: String, val items: List<OrderCardItem>, val subtotal: Double, val discount: Double, val shipping: Double, val total: Double, val currency: String, val paymentStatus: String) : MessageCard

An order summary.

Link copied to clipboard
data class OrderCardItem(val name: String, val quantity: Int, val price: Double, val variant: String? = null)

One line of an order.

Link copied to clipboard
data class PaidMarks(val orderIds: Set<String> = emptySet(), val paymentIds: Set<String> = emptySet())

Orders and payments the timeline says are paid: an order_paid system message (metadata.order_id) or an order_paid event (data.order_id, data.payment_id). The payment card message is not updated live when the customer pays, so the card checks these too (see PaymentCard.isPaid).

Link copied to clipboard
data class PaymentCard(val id: String, val amount: Double, val currency: String, val checkoutUrl: String, val qrImageUrl: String, val code: String, val status: String, val orderId: String? = null, val orderCode: String? = null, val expiresAt: Instant? = null, val qrPayload: String? = null) : MessageCard

A payment request (VietQR).

Link copied to clipboard
object PaymentQR

Finds the VietQR code of a payment card.

Link copied to clipboard
class PaymentQRException(val reason: String, val status: Int? = null) : Exception

Why no QR code could be found. Network failures surface as IOException instead.

Link copied to clipboard
sealed class PaymentQRSource

What the payment card draws its VietQR code from.

Link copied to clipboard
data class PongFrame(val now: Instant?, val id: String? = null) : ServerFrame

Reply to ping.

Link copied to clipboard
data class ProductCard(val products: List<ProductCardItem>, val intro: String? = null) : MessageCard

A product carousel.

Link copied to clipboard
data class ProductCardItem(val id: String, val name: String, val price: Double, val currency: String, val compareAtPrice: Double? = null, val imageUrl: String? = null, val url: String? = null, val sku: String? = null, val appStoreProductId: String? = null, val googlePlayProductId: String? = null, val basePlanId: String? = null, val offerId: String? = null, val billingPeriod: String? = null, val trialDays: Int? = null)

One product in a ProductCard.

Link copied to clipboard
data class QuickRepliesCard(val options: List<String>) : MessageCard

Buttons under a bot message; tapping one sends its label.

Link copied to clipboard
data class ReadFrame(val conversationId: String, val side: String, val upToSeq: Int, val id: String? = null) : ServerFrame

The other side read up to a sequence number.

Link copied to clipboard
data class ReadyFrame(val visitor: VisitorDto, val timeline: List<TimelineItem>, val availability: Availability, val conversation: ConversationSummary? = null, val timelineHasMore: Boolean? = null, val id: String? = null) : ServerFrame

Auth succeeded: the visitor, the active conversation and its tail.

Link copied to clipboard
data class ReloadFrame(val reason: String, val id: String? = null) : ServerFrame

The gateway asks the client to start over (browsers reload).

Link copied to clipboard
data class ResumeFrame(val conversationId: String, val items: List<TimelineItem>, val hasMore: Boolean, val id: String? = null) : ServerFrame

Reply to resume.

Link copied to clipboard
data class ScreenInfo(val name: String, val params: Map<String, String>? = null)

The screen the app shows (the native counterpart of a page).

Link copied to clipboard

Who wrote a message or caused an event.

Link copied to clipboard
sealed class ServerFrame

A frame the gateway sends. Unknown types decode to UnknownFrame and are ignored.

Link copied to clipboard
data class SessionFrame(val visitorToken: String, val visitorId: String, val reason: String, val id: String? = null) : ServerFrame

The session moved to another visitor record; store the token and start over.

Link copied to clipboard
@Serializable(with = SiteConfig.Serializer::class)
data class SiteConfig(val siteId: String = "", val name: String = "", val color: String = "#0ea5e9", val position: String = "right", val localeDefault: String = "auto", val greeting: Map<String, String> = emptyMap(), val awayMessage: Map<String, String> = emptyMap(), val offlineCapture: OfflineCapture = OfflineCapture.OFF, val hideWhenOffline: Boolean = false, val theme: SiteTheme = SiteTheme.AUTO, val botEnabled: Boolean = false, val agentAvatars: List<AgentAvatar> = emptyList(), val launcher: LauncherConfig = LauncherConfig(), val header: HeaderConfig? = null, val greetingOptions: GreetingOptions? = null, val contactButtons: List<ContactButton> = emptyList(), val raw: JsonObject = EmptyJsonObject)

Site settings the widget and SDK render from.

Link copied to clipboard
@Serializable(with = SiteThemeSerializer::class)
enum SiteTheme : Enum<SiteTheme>

The site's preferred colour scheme.

Link copied to clipboard
@Serializable(with = TimelineItemSerializer::class)
sealed class TimelineItem

One row of a conversation: a MessageDto or a ConversationEventDto.

Link copied to clipboard
data class TypingFrame(val conversationId: String, val side: String, val on: Boolean, val name: String? = null, val id: String? = null) : ServerFrame

Someone is typing.

Link copied to clipboard
data class UnknownFrame(val t: String, val d: JsonElement?, val id: String? = null) : ServerFrame

A frame type this SDK does not know; ignored for forward compatibility.

Link copied to clipboard
@Serializable
data class VisitorAppInfo(val id: String = "", val platform: String = "", val version: String? = null, val sdk: String? = null)

Which registered app and build a visitor uses.

Link copied to clipboard
data class VisitorConversationDto(val id: String = "", val status: ConversationStatus = ConversationStatus.UNKNOWN, val siteId: String = "", val seq: Int = 0, val visitorUnread: Int = 0, val lastMessageAt: Instant? = null, val lastMessagePreview: String? = null, val lastMessageSenderType: SenderType? = null, val firstResponseAt: Instant? = null, val resolvedAt: Instant? = null, val subject: String? = null, val createdAt: Instant? = null, val updatedAt: Instant? = null, val agent: AgentSummary? = null, val raw: JsonObject = EmptyJsonObject)

The visitor-safe view of one of their conversations (history list, conversation.update).

Link copied to clipboard
@Serializable(with = VisitorDto.Serializer::class)
data class VisitorDto(val id: String = "", val siteId: String = "", val email: String? = null, val name: String? = null, val phone: String? = null, val avatarUrl: String? = null, val externalId: String? = null, val customData: JsonObject = EmptyJsonObject, val locale: HatangLocale? = null, val identifiedAt: Instant? = null, val client: String = "app", val app: VisitorAppInfo? = null, val currentScreen: String? = null, val visits: Int = 1, val raw: JsonObject = EmptyJsonObject)

The visitor (this app's user as the site sees them).

Properties

Link copied to clipboard
const val PROTOCOL_VERSION: Int = 1

The wire protocol version this SDK speaks.

Functions

Link copied to clipboard
fun cardBubbleText(content: String, card: MessageCard?, intro: String? = null): String

The text to show in the bubble of a message that carries card.

Link copied to clipboard
fun cardOf(metadata: JsonObject?): MessageCard?

Port of cardOf from @hatang/chat-protocol: the card in metadata, if any. Unknown kinds are null.

Link copied to clipboard

Parses a frame from the wire.

Link copied to clipboard
fun encodeFrame(frame: ClientFrame, id: String? = null): String

Serialises frame for the wire.

Link copied to clipboard

Tokenises text: links, **bold**, _italic_, ` `code` ` and line breaks. HTML is never interpreted.

Link copied to clipboard

The plain text of tokens (labels for links, no markers).

Link copied to clipboard
fun previewOf(text: String, max: Int = 200): String

Plain-text preview (one line, trimmed, at most max characters).

Link copied to clipboard

Like decodeFrame but returns null instead of throwing.