cimplify
TypeScript SDK

Support

Customer-side chat conversation. The server resolves the active conversation from the widget identity on every request; there is no `conversation_id` to thread through. Open, send, and poll.

Open (or resume) a conversation

Idempotent. Calling it twice in the same session returns the same conversation.

const r = await client.support.openConversation()
if (!r.ok) {
  console.error(r.error.code, r.error.message)
  return
}

const { conversation, starters, messages } = r.value
console.log(conversation.id, conversation.status)
console.log(starters)              // ChatWidgetStarter[] of quick-reply prompts
console.log(messages.length)       // most recent messages

Send a message

Just text content; the SDK adds an idempotency key so retries are safe.

const r = await client.support.sendMessage('Hi, is the cherry tee in stock?', {
  idempotencyKey: 'msg-2026-05-07-stock-check', // optional, auto-generated otherwise
})

if (!r.ok) {
  console.error(r.error.code, r.error.message)
  return
}

const message = r.value
console.log(message.id, message.created_at)
console.log(message.sender_type, message.content)

Poll for new messages

let cursor: string | undefined

async function poll() {
  const r = await client.support.getMessages({ after: cursor, limit: 50 })
  if (!r.ok) return

  for (const message of r.value) {
    console.log(message.sender_type, message.content)
    cursor = message.id
  }
}

const intervalId = setInterval(poll, 3000)

React: a chat widget

'use client'
import { useEffect, useState } from 'react'
import { useCimplifyClient } from '@cimplify/sdk/react'
import type { ChatMessage } from '@cimplify/sdk'

export function ChatPanel() {
  const client = useCimplifyClient()
  const [messages, setMessages] = useState<ChatMessage[]>([])
  const [input, setInput] = useState('')

  useEffect(() => {
    let active = true
    client.support.openConversation().then((r) => {
      if (active && r.ok) setMessages(r.value.messages)
    })
    return () => { active = false }
  }, [client])

  async function send() {
    const text = input.trim()
    if (!text) return
    setInput('')

    const r = await client.support.sendMessage(text)
    if (r.ok) setMessages((prev) => [...prev, r.value])
  }

  return (
    <>
      <ul>{messages.map((m) => <li key={m.id}>{m.sender_type}: {m.content}</li>)}</ul>
      <input value={input} onChange={(e) => setInput(e.target.value)} />
      <button onClick={send}>Send</button>
    </>
  )
}

getMessages options

FieldTypeNotes
afterstringLast seen message id; return only newer
limitnumberPage size

Method reference

MethodReturns
openConversation(opts?)Result<ChatConversationResponse>
sendMessage(content, opts?)Result<ChatMessage>
getMessages({ after?, limit? })Result<ChatMessage[]>
  • Activity Session signals that surface contextual messages

  • Uploads Attach images / files to a chat message

  • Auth Logged-in users get conversation continuity

  • Error handling RATE_LIMITED is the most common code here

On this page