Chat SDK reference
The API surface for @getuserfeedback/chat and @getuserfeedback/chat-react.
- Last reviewed
Chat SDK reference
The Chat SDK is a headless client for user-facing conversation UIs. Use it when your app should show conversation history and let a signed-in user reply from your own UI.
If you're setting up for the first time, start with the React Chat SDK guide or JavaScript Chat SDK guide.
Packages
| Package | Use it when |
|---|---|
@getuserfeedback/chat | You want a TypeScript client for the Chat API. Works in browsers, React Native, and server-side proxy code with fetch. |
@getuserfeedback/chat-react | You want React or React Native hooks. |
Authentication
Every request needs a JWT bearer token created by your app. Configure your backend or auth provider to issue a token for the signed-in user with this audience:
aud: https://getuserfeedback.com/v1/apps/{appId}sub: your user idIf your getuserfeedback.com app uses a custom JWT claim mapping, include
exactly one claim that maps to userId. The examples use sub, which is the
default.
Pass that token to the SDK. The SDK sends it as a bearer token:
Authorization: Bearer <token>getuserfeedback.com verifies the token and uses the signed user id to decide which conversations the user can read or reply to.
createChatClient(options)
import { createChatClient } from "@getuserfeedback/chat";const chat = createChatClient({auth: {jwt: {token,},},});Options
| Option | Type | Default | Description |
|---|---|---|---|
auth.jwt.token | string | required | JWT bearer token for the current user session. |
baseUrl | string | https://api.getuserfeedback.com/v1 | Absolute API base URL. Custom values are used exactly. |
fetch | typeof fetch | globalThis.fetch | Custom fetch implementation. Required only in runtimes without global fetch. |
baseUrl must be absolute. If you proxy through your backend, include the
full path your proxy expects:
createChatClient({baseUrl: "https://app.example.com/api/chat/v1",auth: { jwt: { token: appSessionToken } },});In proxy mode, auth.jwt.token is the bearer token your backend expects. Your
backend should authenticate that token, then call getuserfeedback.com with a JWT
minted for your getuserfeedback.com app and that user.
chat.configure(updates)
Update auth after the client has been created.
await chat.configure({auth: {jwt: {token: refreshedToken,},},});Clear auth on logout:
await chat.configure({auth: {jwt: null,},});After auth is cleared, SDK requests fail with missing_auth_jwt until a new
token is configured.
chat.conversations.list(input?)
Lists conversations visible to the signed user.
const page = await chat.conversations.list({limit: 25,});Input
| Field | Type | Description |
|---|---|---|
limit | number | Page size. Defaults to the API default. |
cursor | string | Cursor returned by a previous page. |
signal | AbortSignal | Optional cancellation signal. |
Response
type ChatConversationListResponse = {conversations: ChatConversation[];limit: number;nextCursor: string | null;};chat.messages.list(input)
Lists messages in one conversation.
const page = await chat.messages.list({conversationId: "conv_123",limit: 50,});Input
| Field | Type | Description |
|---|---|---|
conversationId | string | Conversation to read. |
limit | number | Page size. Defaults to the API default. |
cursor | string | Cursor returned by a previous page. |
signal | AbortSignal | Optional cancellation signal. |
Response
type ChatMessageListResponse = {conversationId: string;limit: number;messages: ChatMessage[];nextCursor: string | null;};chat.messages.send(input)
Sends a message from the signed user into an existing conversation.
const { message } = await chat.messages.send({conversationId: "conv_123",text: "Thanks — that helps.",});Input
| Field | Type | Description |
|---|---|---|
conversationId | string | Conversation to send into. |
text | string | Message text, from 1 to 10,000 characters. |
clientMessageId | string | Optional idempotency key for this message. Set this only when you manage send retries yourself, such as in a proxy or non-React client. Reuse the same value when retrying the same send after a timeout or lost response. |
signal | AbortSignal | Optional cancellation signal. |
Response
type ChatMessageSendResponse = {message: ChatMessage;};Message shape
type ChatMessage = {author: "system" | "team" | "unknown" | "user";content:| { type: "text"; text: string }| { type: "flow_response"; responseId: string }| { type: "unsupported" };conversationId: string;id: string;receivedAt: string;sentAt: string;timestamp: string;};Render unsupported with a quiet fallback. It means the conversation contains
a message type this SDK version doesn't know how to display yet.
React provider
import { GetUserFeedbackChatProvider } from "@getuserfeedback/chat-react";<GetUserFeedbackChatProviderclientOptions={{auth: {jwt: {token,},},}}><App /></GetUserFeedbackChatProvider>The provider creates the chat client and owns an in-memory store for the hooks
below it. When clientOptions.auth.jwt.token changes, the provider updates auth
and resets the store so the next user doesn't see the previous user's cached
conversations.
Props
| Prop | Type | Description |
|---|---|---|
clientOptions | ChatClientOptions | Recommended. Provider-owned client options. |
client | ChatClient | Advanced. Pass an explicitly created client instead of clientOptions. |
Use clientOptions.baseUrl when proxying through your backend:
<GetUserFeedbackChatProviderclientOptions={{baseUrl: "https://app.example.com/api/chat/v1",auth: { jwt: { token: appSessionToken } },}}><App /></GetUserFeedbackChatProvider>useConversationList(options?)
Loads conversations on mount by default.
const { conversations, error, hasMore, loadMore, refresh, status } =useConversationList({ limit: 25 });Options
| Field | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Set to false to disable the first load. |
limit | number | 25 | Page size for the initial load and pagination. |
Return value
| Field | Description |
|---|---|
conversations | Loaded conversations. |
status | Load state for the list. |
error | Last load error, if any. |
hasMore | true when another page is available. |
loadMore() | Loads the next page. |
refresh() | Reloads the first page. |
useConversation(options)
Loads one conversation's messages on mount by default.
const {error,hasMore,loadMore,messages,refresh,send,sendError,sendStatus,status,} = useConversation({ conversationId: "conv_123" });Options
| Field | Type | Default | Description |
|---|---|---|---|
conversationId | string | required | Conversation to read and send into. |
enabled | boolean | true | Set to false to disable the first load. |
limit | number | 50 | Page size for the initial load and pagination. |
Return value
| Field | Description |
|---|---|
messages | Loaded messages. |
status | Load state for messages. |
error | Last message load error, if any. |
hasMore | true when older messages are available. |
loadMore() | Loads older messages. |
refresh() | Reloads the first page. |
send({ text }) | Sends a message and returns the saved message. |
sendStatus | Current send state. |
sendError | Last send error, if any. |
Errors
Failed API responses throw ChatApiError.
import { ChatApiError } from "@getuserfeedback/chat";try {await chat.conversations.list();} catch (error) {if (error instanceof ChatApiError) {console.log(error.status, error.code, error.message);}}Common codes:
| Code | Meaning |
|---|---|
missing_auth_jwt | The client has no configured JWT. |
identity_missing | The verified JWT did not include a signed userId identity. |
identity_ambiguous | The verified JWT mapped to more than one signed userId. |
invalid_cursor | The pagination cursor is malformed or belongs to a different request. |
not_found | The conversation does not exist or does not belong to the signed user. |
Current limits
- You can list conversations and send messages into them.
- Realtime updates, typing indicators, and read receipts are not exposed in the SDK yet.