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 messagesSend a message
Text content plus optional attachments; 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)Send a file or image
Upload first, then pass the upload as an attachment. The server stores a durable reference and mints a fresh URL every time the message is read, so the media never expires.
const upload = await client.uploads.upload(file) // e.g. from an <input type="file">
if (!upload.ok) return
const r = await client.support.sendMessage('New prescription upload from the website', {
attachments: [
{
upload_id: upload.value.id, // what goes on the wire
// The rest only renders your optimistic bubble:
url: upload.value.url,
mime_type: upload.value.content_type,
filename: upload.value.filename,
},
],
})Do not paste upload.value.url into the message text instead — it is a
presigned link that expires after a few days and renders as a wall of URL noise
in the merchant's inbox. Attachments can be images or documents (PDF, Word,
Excel, CSV, plain text), up to 25 MB and 10 per message.
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
| Field | Type | Notes |
|---|---|---|
after | string | Last seen message id; return only newer |
limit | number | Page size |
Method reference
| Method | Returns |
|---|---|
openConversation(opts?) | Result<ChatConversationResponse> |
sendMessage(content, opts?) — opts.attachments?: { upload_id }[], opts.replyToMessageId? | Result<ChatMessage> |
getMessages({ after?, limit? }) | Result<ChatMessage[]> |
Related
-
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
Assets
Build CDN URLs for storefront brand assets, render them through `next/image`, and pass external image hosts (Cloudinary, Unsplash, merchant S3) through untouched. The SDK ships `assetUrl`, `isCimplifyAsset`, and `useImage`: pure functions; no network calls; SSR-safe.
Link
client.link covers saved addresses, saved mobile money, link preferences, and sessions. Customer-scoped surface routed through the SDK's separate linkApiUrl transport, not the per-business storefront API.