Realtime API

The Realtime API provides access a continuous, up-to-date flow of your TalkJS data without the need to send repeated requests or open a chat UI.

Preview: The Realtime API is safe to use in production, but it is still a work in progress. If we make changes to these methods in the future, we will continue to support the current version forever. However this backwards compatibility will be undocumented and not exposed in TypeScript type definitions.

User

A user is someone who can send and receive messages. Usually, they will map directly to the accounts in your website or app. However, you can also create users to act as bots or for AI agents.

interface UserRef

References the user with a given user ID.

Used in all Realtime API operations affecting that user, such as creating the user, fetching or updating user data, or adding a user to a conversation. Created via Session​.user.

Method Overview

createIfNotExists

Creates a user with this ID, or does nothing if a user with this ID already exists.

get

Fetches a snapshot of the user.

set

Sets properties of this user. The user is created if a user with this ID doesn't already exist.

subscribe

Subscribe to this user's state.

Properties

id
: string

The ID of the referenced user.

Immutable: if you want to reference a different user, get a new UserRef instead.

createIfNotExists

userRef.createIfNotExists(params): Promise<void>

Creates a user with this ID, or does nothing if a user with this ID already exists.

If the user already exists, this operation is still considered successful and the promise will still resolve.

Parameters

Returns

Promise<void>

A promise that resolves when the operation completes. The promise will reject if client-side user syncing is disabled and the user does not already exist.

get

userRef.get(): Promise<UserSnapshot | null>

Fetches a snapshot of the user.

This contains all of a user's public information. Fetching a user snapshot doesn't require any permissions. You can read the public information of any user. Private information, such as email addresses and phone numbers, aren't included in the response.

Supports Automatic Batching and Cached Fetch

Returns

Promise<UserSnapshot | null>

A snapshot of the user's public attributes, or null if the user doesn't exist.

set

userRef.set(params): Promise<void>

Sets properties of this user. The user is created if a user with this ID doesn't already exist.

name is required when creating a user. The promise will reject if you don't provide a name and the user does not exist yet.

Parameters

params
: SetUserParams

Returns

Promise<void>

A promise that resolves when the operation completes. The promise will reject if the request is invalid or if client-side user syncing is disabled.

subscribe

userRef.subscribe(onSnapshot): UserSubscription

Subscribe to this user's state.

Whenever Subscription.state.type is "active" and the user is created or their attributes change, onSnapshot will fire and Subscription.state.latestSnapshot will be updated.

Supports Subscription Sharing and Debounced Unsubscribe

Parameters

onSnapshot (optional)
: (event: UserSnapshot | null) => void

Returns

UserSubscription

A subscription to the user

interface UserSnapshot

A snapshot of a user's attributes at a given moment in time.

Users also have private information, such as email addresses and phone numbers, but these are only exposed on the REST API.

Snapshots are immutable and we try to reuse them when possible. You should only re-render your UI when oldSnapshot !== newSnapshot.

Properties

custom
: Record<string, string>

Custom metadata you have set on the user

id
: string

The unique ID that is used to identify the user in TalkJS

locale
: string | null

An IETF language tag. For more information, see: Localization.

When locale is null, the app's default locale will be used

name
: string

The user's name, which is displayed on the TalkJS UI

photoUrl
: string | null

An optional URL to a photo that is displayed as the user's avatar

role
: string

TalkJS supports multiple sets of settings for users, called "roles". Roles allow you to change the behavior of TalkJS for different users. You have full control over which user gets which configuration.

welcomeMessage
: string | null

The default message a person sees when starting a chat with this user

interface UserSubscription

A subscription to a specific user

Get a UserSubscription by calling UserRef​.subscribe

Method Overview

unsubscribe

Unsubscribe from this resource and stop receiving updates.

Properties

connected
: Promise<UserActiveState>

Resolves when the subscription starts receiving updates from the server.

state
: PendingState | UserActiveState | UnsubscribedState | ErrorState

The current state of the subscription

An object with the following fields:

type is one of "pending", "active", "unsubscribed", or "error".

When type is "active", includes latestSnapshot: UserSnapshot | null. It is the current state of the user, or null if they don't exist.

When type is "error", includes the error: Error field. It is a JS Error object explaining what caused the subscription to be terminated.

terminated
: Promise<UnsubscribedState | ErrorState>

Resolves when the subscription permanently stops receiving updates from the server.

This is either because you unsubscribed or because the subscription encountered an unrecoverable error.

unsubscribe

userSubscription.unsubscribe()

Unsubscribe from this resource and stop receiving updates.

If the subscription is already in the "unsubscribed" or "error" state, this is a no-op.

Returns

void

interface CreateUserParams

Parameters you can pass to UserRef​.createIfNotExists.

Properties that are undefined will be set to the default.

Properties

name
: string

The user's name which is displayed on the TalkJS UI

custom (optional)
: Record<string, string>

Custom metadata you have set on the user. Default = no custom metadata

email (optional)
: string[]

An array of email addresses associated with the user. Default = no email addresses

locale (optional)
: string

An IETF language tag. See the localization documentation Default = the locale selected on the dashboard

phone (optional)
: string[]

An array of phone numbers associated with the user. Default = no phone numbers

photoUrl (optional)
: string

An optional URL to a photo that is displayed as the user's avatar. Default = no photo

pushTokens (optional)
: Record<string, true>

An object of push registration tokens to use when notifying this user.

Keys in the object have the format 'provider:token_id', where provider is either "fcm" for Android (Firebase Cloud Messaging), or "apns" for iOS (Apple Push Notification Service).

Default = no push registration tokens

role (optional)
: string

TalkJS supports multiple sets of settings, called "roles". These allow you to change the behavior of TalkJS for different users. You have full control over which user gets which configuration. Default = the default role

welcomeMessage (optional)
: string

The default message a person sees when starting a chat with this user. Default = no welcome message

interface SetUserParams

Parameters you can pass to UserRef​.set.

Properties that are undefined will not be changed. To clear / reset a property to the default, pass null.

Properties

custom (optional)
: Record<string, string | null> | null

Custom metadata you have set on the user. This value acts as a patch. Remove specific properties by setting them to null. Default = no custom metadata

email (optional)
: string[] | null

An array of email addresses associated with the user. Default = no email addresses

locale (optional)
: string

An IETF language tag. See the localization documentation Default = the locale selected on the dashboard

name (optional)
: string

The user's name which will be displayed on the TalkJS UI

phone (optional)
: string[] | null

An array of phone numbers associated with the user. Default = no phone numbers

photoUrl (optional)
: string | null

An optional URL to a photo which will be displayed as the user's avatar. Default = no photo

pushTokens (optional)
: Record<string, true | null> | null

An object of push registration tokens to use when notifying this user.

Keys in the object have the format 'provider:token_id', where provider is either "fcm" for Android (Firebase Cloud Messaging), or "apns" for iOS (Apple Push Notification Service).

The value for each key can either be true to register the device for push notifications, or null to unregister that device.

Setting pushTokens to null unregisters all the previously registered devices.

Default = no push tokens

role (optional)
: string | null

TalkJS supports multiple sets of settings, called "roles". These allow you to change the behavior of TalkJS for different users. You have full control over which user gets which configuration. Default = the default role

welcomeMessage (optional)
: string | null

The default message a person sees when starting a chat with this user. Default = no welcome message

Conversation

A conversation is a chat channel where messages can be sent. Users can participate in many conversations at once.

interface ConversationRef

References the conversation with a given conversation ID, from the perspective of the current user.

Used in all Realtime API operations affecting that conversation, such as fetching or updating conversation attributes. Created via Session​.conversation.

Method Overview

createIfNotExists

Creates this conversation if it does not already exist. Adds you as a participant in this conversation, if you are not already a participant.

get

Fetches a snapshot of the conversation.

markAsRead

Marks the conversation as read.

markAsUnread

Marks the conversation as unread.

message

Get a reference to a message in this conversation

participant

Get a reference to a participant in this conversation

send

Sends a message in the conversation

set

Sets properties of this conversation and your participation in it.

subscribe

Subscribes to the conversation.

subscribeMessages

Subscribes to the messages in the conversation.

Properties

id
: string

The ID of the referenced conversation.

Immutable: if you want to reference a different conversation, get a new ConversationRef instead.

createIfNotExists

conversationRef.createIfNotExists(params): Promise<void>

Creates this conversation if it does not already exist. Adds you as a participant in this conversation, if you are not already a participant.

If the conversation already exists or you are already a participant, this operation is still considered successful and the promise will still resolve.

Parameters

params (optional)
: CreateConversationParams

Returns

Promise<void>

A promise that resolves when the operation completes. The promise rejects if you are not already a participant and client-side conversation syncing is disabled.

get

conversationRef.get(): Promise<ConversationSnapshot | null>

Fetches a snapshot of the conversation.

This contains all of the information related to the conversation and the current user's participation in the conversation.

Returns

Promise<ConversationSnapshot | null>

A snapshot of the current user's view of the conversation, or null if the current user is not a participant (including if the conversation doesn't exist).

markAsRead

conversationRef.markAsRead(): Promise<void>

Marks the conversation as read.

Returns

Promise<void>

A promise that resolves when the operation completes. The promise rejects if you are not a participant in the conversation.

markAsUnread

conversationRef.markAsUnread(): Promise<void>

Marks the conversation as unread.

Returns

Promise<void>

A promise that resolves when the operation completes. The promise rejects if you are not a participant in the conversation.

message

conversationRef.message(id): MessageRef

Get a reference to a message in this conversation

Parameters

id
: string

Returns

MessageRef

participant

conversationRef.participant(user): ParticipantRef

Get a reference to a participant in this conversation

Parameters

user
: string | UserRef

the user's ID or a reference to the user

Returns

ParticipantRef

send

conversationRef.send(params): Promise<MessageRef>

Sends a message in the conversation

Parameters

Returns

Promise<MessageRef>

A promise that resolves with a reference to the newly created message. The promise will reject if you do not have permission to send the message.

set

conversationRef.set(params): Promise<void>

Sets properties of this conversation and your participation in it.

The conversation is created if a conversation with this ID doesn't already exist. You are added as a participant if you are not already a participant in the conversation.

Parameters

Returns

Promise<void>

A promise that resolves when the operation completes. When client-side conversation syncing is disabled, you may only set your notify property, when you are already a participant. Everything else requires client-side conversation syncing to be enabled, and will cause the promise to reject.

subscribe

conversationRef.subscribe(onSnapshot): ConversationSubscription

Subscribes to the conversation.

Whenever Subscription.state.type is "active" and something about the conversation changes, onSnapshot will fire and Subscription.state.latestSnapshot will be updated. This includes changes to nested data. As an extreme example, onSnapshot would be called if snapshot.lastMessage.referencedMessage.sender.name changes.

The snapshot is null if you are not a participant in the conversation (including when the conversation doesn't exist)

Parameters

onSnapshot (optional)
: (snapshot: ConversationSnapshot | null) => void

Returns

ConversationSubscription

subscribeMessages

conversationRef.subscribeMessages(onSnapshot): MessageSubscription

Subscribes to the messages in the conversation.

Initially, you will be subscribed to the 30 most recent messages and any new messages. Call loadMore to load additional older messages.

Whenever Subscription.state.type is "active" and a message is sent, edited, deleted, or you load more messages, onSnapshot will fire and Subscription.state.latestSnapshot will be updated. loadedAll is true when the snapshot contains all the messages in the conversation.

The snapshot is null if you are not a participant in the conversation (including when the conversation doesn't exist)

Parameters

onSnapshot (optional)
: ( snapshot: MessageSnapshot[] | null, loadedAll: boolean ) => void

Returns

MessageSubscription

interface ConversationSnapshot

A snapshot of a conversation's attributes at a given moment in time.

Also includes information about the current user's view of that conversation, such as whether or not notifications are enabled.

Snapshots are immutable and we try to reuse them when possible. You should only re-render your UI when oldSnapshot !== newSnapshot.

Properties

access
: "Read" | "ReadWrite"

The current user's permission level in this conversation.

createdAt
: number

The date that the conversation was created, as a unix timestamp in milliseconds.

custom
: Record<string, string>

Custom metadata you have set on the conversation

id
: string

The ID of the conversation

isUnread
: boolean

Whether the conversation should be considered unread.

This can be true even when unreadMessageCount is zero, if the user has manually marked the conversation as unread.

joinedAt
: number

The date that the current user joined the conversation, as a unix timestamp in milliseconds.

lastMessage
: MessageSnapshot | null

The last message sent in this conversation, or null if no messages have been sent.

notify
: boolean | "MentionsOnly"

The current user's notification settings for this conversation.

false means no notifications, true means notifications for all messages, and "MentionsOnly" means that the user will only be notified when they are mentioned with an @.

photoUrl
: string | null

Contains the URL of a photo was set using ConversationBuilder​.subject.

subject
: string | null

Contains the conversation subject if it was set using ConversationBuilder​.subject.

unreadMessageCount
: number

The number of messages in this conversation that the current user hasn't read.

welcomeMessages
: string[]

One or more welcome messages that will display to the user as a SystemMessage

interface ConversationSubscription

A subscription to a specific conversation.

Get a ConversationSubscription by calling ConversationRef​.subscribe

Method Overview

unsubscribe

Unsubscribe from this resource and stop receiving updates.

Properties

connected
: Promise<ConversationActiveState>

Resolves when the subscription starts receiving updates from the server.

state
: PendingState | ConversationActiveState | UnsubscribedState | ErrorState

The current state of the subscription

An object with the following fields:

type is one of "pending", "active", "unsubscribed", or "error".

When type is "active", includes latestSnapshot: ConversationSnapshot | null, the current state of the conversation. latestSnapshot is null when you are not a participant or the conversation does not exist.

When type is "error", includes the error field. It is a JS Error object explaining what caused the subscription to be terminated.

terminated
: Promise<UnsubscribedState | ErrorState>

Resolves when the subscription permanently stops receiving updates from the server.

This is either because you unsubscribed or because the subscription encountered an unrecoverable error.

unsubscribe

conversationSubscription.unsubscribe()

Unsubscribe from this resource and stop receiving updates.

If the subscription is already in the "unsubscribed" or "error" state, this is a no-op.

Returns

void

interface CreateConversationParams

Parameters you can pass to ConversationRef​.createIfNotExists.

Properties that are undefined will be set to the default.

Properties

access (optional)
: "Read" | "ReadWrite"

Your access to the conversation. Default = "ReadWrite" access.

custom (optional)
: Record<string, string>

Custom metadata you have set on the conversation. This value acts as a patch. Remove specific properties by setting them to null. Default = no custom metadata

notify (optional)
: boolean | "MentionsOnly"

Your notification settings. Default = true

photoUrl (optional)
: string

The URL for the conversation photo to display in the chat header. Default = no photo, show a placeholder image.

subject (optional)
: string

The conversation subject to display in the chat header. Default = no subject, list participant names instead.

welcomeMessages (optional)
: string[]

System messages which are sent at the beginning of a conversation. Default = no messages.

interface SetConversationParams

Parameters you can pass to ConversationRef​.set.

Properties that are undefined will not be changed. To clear / reset a property to the default, pass null.

Properties

access (optional)
: "Read" | "ReadWrite" | null

Your access to the conversation. Default = "ReadWrite" access.

custom (optional)
: Record<string, string | null> | null

Custom metadata you have set on the conversation. This value acts as a patch. Remove specific properties by setting them to null. Default = no custom metadata

notify (optional)
: boolean | "MentionsOnly" | null

Your notification settings. Default = true

photoUrl (optional)
: string | null

The URL for the conversation photo to display in the chat header. Default = no photo, show a placeholder image.

subject (optional)
: string | null

The conversation subject to display in the chat header. Default = no subject, list participant names instead.

welcomeMessages (optional)
: string[] | null

System messages which are sent at the beginning of a conversation. Default = no messages.

Participant

A participant is a resource that represents the relationship between a user and a conversation they are part of. The participant resource contains information about that user's activity in that conversation, such as whether they should receive notifications.By creating a participant representing a specific user and conversation, we are adding that user to the conversation.

interface ParticipantRef

References a given user's participation in a conversation.

Used in all Realtime API operations affecting that participant, such as joining/leaving a conversation, or setting their access. Created via ConversationRef​.participant.

Method Overview

createIfNotExists

Adds the user as a participant, or does nothing if they are already a participant.

delete

Removes the user as a participant, or does nothing if they are already not a participant.

edit

Edits properties of a pre-existing participant. If the user is not already a participant in the conversation, the promise will reject.

get

Fetches a snapshot of the participant.

set

Sets properties of this participant. If the user is not already a participant in the conversation, they will be added.

Properties

conversationId
: string

The ID of the conversation the user is participating in.

Immutable: if you want to reference the user in a different conversation, get a new ParticipantRef instead.

userId
: string

The ID of the user who is participating.

Immutable: if you want to reference a different participant, get a new ParticipantRef instead.

createIfNotExists

participantRef.createIfNotExists(params): Promise<void>

Adds the user as a participant, or does nothing if they are already a participant.

If the participant already exists, this operation is still considered successful and the promise will still resolve.

Supports Automatic Batching

Parameters

params (optional)
: CreateParticipantParams

Returns

Promise<void>

A promise that resolves when the operation completes. The promise will reject if client-side conversation syncing is disabled and the user is not already a participant.

delete

participantRef.delete(): Promise<void>

Removes the user as a participant, or does nothing if they are already not a participant.

Deleting a nonexistent participant is treated as success, and the promise will resolve.

Returns

Promise<void>

A promise that resolves when the operation completes. This promise will reject if client-side conversation syncing is disabled.

edit

participantRef.edit(params): Promise<void>

Edits properties of a pre-existing participant. If the user is not already a participant in the conversation, the promise will reject.

Supports Automatic Batching

Parameters

Returns

Promise<void>

A promise that resolves when the operation completes. When client-side conversation syncing is disabled, you may only set your notify property, when you are already a participant. Everything else requires client-side conversation syncing to be enabled, and will cause the promise to reject.

get

participantRef.get(): Promise<ParticipantSnapshot | null>

Fetches a snapshot of the participant.

This contains all of the participant's public information.

Returns

Promise<ParticipantSnapshot | null>

A snapshot of the participant's attributes, or null if the user is not a participant. The promise will reject if you are not a participant and try to read information about someone else.

set

participantRef.set(params): Promise<void>

Sets properties of this participant. If the user is not already a participant in the conversation, they will be added.

Supports Automatic Batching

Parameters

Returns

Promise<void>

A promise that resolves when the operation completes. When client-side conversation syncing is disabled, you may only set your notify property, when you are already a participant. Everything else requires client-side conversation syncing to be enabled, and will cause the promise to reject.

interface ParticipantSnapshot

A snapshot of a participant's attributes at a given moment in time.

Automatically expanded to include a snapshot of the user who is a participant.

Snapshots are immutable and we try to reuse them when possible. You should only re-render your UI when oldSnapshot !== newSnapshot.

Properties

access
: "ReadWrite" | "Read"

The level of access this participant has in the conversation.

joinedAt
: number

The date that this user joined the conversation, as a unix timestamp in milliseconds.

notify
: boolean | "MentionsOnly"

When the participant will be notified about new messages in this conversation.

false means no notifications, true means notifications for all messages, and "MentionsOnly" means that the user will only be notified when they are mentioned with an @.

The user who this participant snapshot is referring to

interface CreateParticipantParams

Parameters you can pass to ParticipantRef​.createIfNotExists.

Properties that are undefined will be set to the default.

Properties

access (optional)
: "ReadWrite" | "Read"

The level of access the participant should have in the conversation. Default = "ReadWrite" access.

notify (optional)
: boolean | "MentionsOnly"

When the participant should be notified about new messages in this conversation. Default = true

false means no notifications, true means notifications for all messages, and "MentionsOnly" means that the user will only be notified when they are mentioned with an @.

interface SetParticipantParams

Parameters you can pass to ParticipantRef​.set or ParticipantRef​.edit.

Properties that are undefined will not be changed. To clear / reset a property to the default, pass null.

Properties

access (optional)
: "ReadWrite" | "Read" | null

The level of access the participant should have in the conversation. Default = "ReadWrite" access.

notify (optional)
: boolean | "MentionsOnly" | null

When the participant should be notified about new messages in this conversation. Default = ReadWrite access.

false means no notifications, true means notifications for all messages, and "MentionsOnly" means that the user will only be notified when they are mentioned with an @.

Message

Users can send messages in conversations.

interface MessageRef

References the message with a given message ID.

Used in all Realtime API operations affecting that message, such as fetching or editing the message attributes, or deleting the message. Created via ConversationRef​.message.

Method Overview

delete

Deletes this message, or does nothing if they are already not a participant.

edit

Edits this message.

get

Fetches a snapshot of the message.

Properties

conversationId
: string

The ID of the conversation that the referenced message belongs to.

Immutable: if you want to reference a message from a different conversation, get a new MessageRef from that conversation.

id
: string

The ID of the referenced message.

Immutable: if you want to reference a different message, get a new MessageRef instead.

delete

messageRef.delete(): Promise<void>

Deletes this message, or does nothing if they are already not a participant.

Deleting a nonexistent message is treated as success, and the promise will resolve.

Returns

Promise<void>

A promise that resolves when the operation completes. This promise will reject if you are not a participant in the conversation or if your role does not give you permission to delete this message.

edit

messageRef.edit(params): Promise<void>

Edits this message.

Parameters

Returns

Promise<void>

A promise that resolves when the operation completes. The promise will reject if the request is invalid, the message doesn't exist, or you do not have permission to edit that message.

get

messageRef.get(): Promise<MessageSnapshot | null>

Fetches a snapshot of the message.

Supports Cached Fetch

Returns

Promise<MessageSnapshot | null>

A snapshot of the message's attributes, or null if the message doesn't exist, the conversation doesn't exist, or you're not a participant in the conversation.

interface MessageSnapshot

A snapshot of a message's attributes at a given moment in time.

Automatically expanded to include a snapshot of the user that sent the message, and a snapshot of the referenced message, if this message is a reply.

Snapshots are immutable and we try to reuse them when possible. You should only re-render your UI when oldSnapshot !== newSnapshot.

Properties

type
: "UserMessage" | "SystemMessage"

Whether this message was "from a user" or a general system message without a specific sender.

The sender property is always present for "UserMessage" messages and never present for "SystemMessage" messages.

content
: ContentBlock[]

The main body of the message, as a list of blocks that are rendered top-to-bottom.

createdAt
: number

Time at which the message was sent, as a unix timestamp in milliseconds

custom
: Record<string, string>

Custom metadata you have set on the message

editedAt
: number | null

Time at which the message was last edited, as a unix timestamp in milliseconds. null if the message has never been edited.

id
: string

The unique ID that is used to identify the message in TalkJS

origin
: "web" | "rest" | "import" | "email"

Where this message originated from:

- "web" = Message sent via the UI or via ConversationBuilder​.sendMessage

- "rest" = Message sent via the REST API's "send message" endpoint or ConversationRef​.send

- "import" = Message sent via the REST API's "import messages" endpoint

- "email" = Message sent by replying to an email notification

plaintext
: string

The contents of the message, as a plain text string without any formatting or attachments. Useful for showing in a conversation list or in notifications.

referencedMessage
: ReferencedMessageSnapshot | null

A snapshot of the message that this message is a reply to, or null if this message is not a reply.

Only UserMessages can reference other messages. The referenced message snapshot does not have a referencedMessage field. Instead, it has referencedMessageId. This prevents TalkJS fetching an unlimited number of messages in a long chain of replies.

sender
: UserSnapshot | null

A snapshot of the user who sent the message, or null if it is a system message. The user's attributes may have been updated since they sent the message, in which case this snapshot contains the updated data. It is not a historical snapshot.

interface MessageSubscription

A subscription to the messages in a specific conversation.

Get a MessageSubscription by calling ConversationRef​.subscribeMessages

The subscription is 'windowed'. It includes all messages since a certain point in time. By default, you subscribe to the 30 most recent messages, and any new messages are sent after you subscribe.

You can expand this window by calling loadMore, which extends the window further into the past.

Method Overview

unsubscribe

Unsubscribe from this resource and stop receiving updates.

Properties

connected
: Promise<MessageActiveState>

Resolves when the subscription starts receiving updates from the server.

Wait for this promise if you want to perform some action as soon as the subscription is active.

The promise rejects if the subscription is terminated before it connects.

loadMore
: (count?: number) => Promise<void>

Expand the window to include older messages

Calling loadMore multiple times in parallel will still only load one page of messages.

state
: PendingState | MessageActiveState | UnsubscribedState | ErrorState

The current state of the subscription

An object with the following fields:

type is one of "pending", "active", "unsubscribed", or "error".

When type is "active", includes latestSnapshot and loadedAll.

- latestSnapshot: MessageSnapshot[] | null the current state of the messages in the window, or null if you're not a participant in the conversation

- loadedAll: boolean true when latestSnapshot contains all the messages in the conversation

When type is "error", includes the error field. It is a JS Error object explaining what caused the subscription to be terminated.

terminated
: Promise<UnsubscribedState | ErrorState>

Resolves when the subscription permanently stops receiving updates from the server.

This is either because you unsubscribed or because the subscription encountered an unrecoverable error.

unsubscribe

messageSubscription.unsubscribe()

Unsubscribe from this resource and stop receiving updates.

If the subscription is already in the "unsubscribed" or "error" state, this is a no-op.

Returns

void

interface ReferencedMessageSnapshot

A snapshot of a message's attributes at a given moment in time, used in MessageSnapshot​.referencedMessage.

Automatically expanded to include a snapshot of the user that sent the message. Since this is a snapshot of a referenced message, its referenced message is not automatically expanded, to prevent fetching an unlimited number of messages in a long chain of replies. Instead, contains the referencedMessageId field.

Snapshots are immutable and we try to reuse them when possible. You should only re-render your UI when oldSnapshot !== newSnapshot.

Properties

type
: "UserMessage"

Referenced messages are always "UserMessage" because you cannot reply to a system message.

content
: ContentBlock[]

The main body of the message, as a list of blocks that are rendered top-to-bottom.

createdAt
: number

Time at which the message was sent, as a unix timestamp in milliseconds

custom
: Record<string, string>

Custom metadata you have set on the message

editedAt
: number | null

Time at which the message was last edited, as a unix timestamp in milliseconds. null if the message has never been edited.

id
: string

The unique ID that is used to identify the message in TalkJS

origin
: "web" | "rest" | "import" | "email"

Where this message originated from:

- "web" = Message sent via the UI or via ConversationBuilder.sendMessage

- "rest" = Message sent via the REST API's "send message" endpoint

- "import" = Message sent via the REST API's "import messages" endpoint

- "email" = Message sent by replying to an email notification

plaintext
: string

The contents of the message, as a plain text string without any formatting or attachments. Useful for showing in a conversation list or in notifications.

referencedMessageId
: string | null

The ID of the message that this message is a reply to, or null if this message is not a reply.

Since this is a snapshot of a referenced message, we do not automatically expand its referenced message. The ID of its referenced message is provided here instead.

sender
: UserSnapshot

A snapshot of the user who sent the message. The user's attributes may have been updated since they sent the message, in which case this snapshot contains the updated data. It is not a historical snapshot.

Guaranteed to be set, unlike in MessageSnapshot, because you cannot reference a SystemMessage

interface SendTextMessageParams

Parameters you can pass to ConversationRef​.send.

Properties that are undefined will be set to the default.

This is a simpler version of SendMessageParams that only supports text messages.

Properties

text
: string

The text to send in the message.

This is parsed the same way as the text entered in the message field. For example, *hi* will appear as hi in bold.

See the message formatting documentation for more details.

custom (optional)
: Record<string, string>

Custom metadata you have set on the user. Default = no custom metadata

referencedMessage (optional)
: string | MessageRef

The message that you are replying to. Default = not a reply

interface SendMessageParams

Parameters you can pass to ConversationRef​.send.

Properties that are undefined will be set to the default.

This is the more advanced method for editing a message, giving full control over the message content. You can decide exactly how a text message should be formatted, edit an attachment, or even turn a text message into a location.

Properties

content
: [SendContentBlock]

The most important part of the message, either some text, a file attachment, or a location.

By default users do not have permission to send LinkNode, ActionLinkNode, or ActionButtonNode, as they can be used to trick the recipient.

custom (optional)
: Record<string, string>

Custom metadata you have set on the user. Default = no custom metadata

referencedMessage (optional)
: string | MessageRef

The message that you are replying to. Default = not a reply

interface EditTextMessageParams

Parameters you can pass to MessageRef​.edit.

Properties that are undefined will not be changed. To clear / reset a property to the default, pass null.

This is a simpler version of EditMessageParams that only supports setting the message content to text.

Properties

custom (optional)
: Record<string, string | null> | null

Custom metadata you have set on the message. This value acts as a patch. Remove specific properties by setting them to null. Default = no custom metadata

text (optional)
: string

The new text to set in the message body.

This is parsed the same way as the text entered in the message field. For example, *hi* will appear as hi in bold.

See the message formatting documentation for more details.

interface EditMessageParams

Parameters you can pass to MessageRef​.edit.

Properties that are undefined will not be changed. To clear / reset a property to the default, pass null.

This is the more advanced method for editing a message. It gives you full control over the message content. You can decide exactly how a text message should be formatted, edit an attachment, or even turn a text message into a location.

Properties

content (optional)
: [SendContentBlock]

The new content for the message.

Any value provided here will overwrite the existing message content.

By default users do not have permission to send LinkNode, ActionLinkNode, or ActionButtonNode, as they can be used to trick the recipient.

custom (optional)
: Record<string, string | null> | null

Custom metadata you have set on the message. This value acts as a patch. Remove specific properties by setting them to null. Default = no custom metadata

Message content

Every message has "content" which specifies the information in the message. This could be some formatted text, a file attachment, or a shared location.

type ContentBlock

The content of a message is structured as a list of content blocks.

Currently, each message can only have one content block, but this will change in the future. This will not be considered a breaking change, so your code should assume there can be multiple content blocks.

These blocks are rendered in order, top-to-bottom.

Currently the available Content Block types are:

- type: "text" (TextBlock)

- type: "file" (FileBlock)

- type: "location" (LocationBlock)

interface TextBlock

A block of formatted text in a message's content.

Each TextBlock is a tree of TextNode children describing the structure of some formatted text. Each child is either a plain text string, or a node representing some text with additional formatting.

For example, if the user typed:

> *This first bit* is bold, and *_the second bit_* is bold and italics

Then this would become a Text Block with the structure:

1{
2 type: "text",
3 children: [
4 {
5 type: "text",
6 children: [
7 { type: "bold", children: ["This first bit"] },
8 " is bold, and ",
9 {
10 children: [
11 { type: "italic", children: ["the second bit"] }
12 ],
13 type: "bold",
14 },
15 " is bold and italics",
16 ],
17 },
18 ],
19}

Rather than relying the automatic message parsing, you can also specify the TextBlock directly using ConversationRef​.send with SendMessageParams.

Properties

type
: "text"
children
: TextNode[]

type TextNode

Any node that can exist inside a TextBlock.

The simplest TextNode is a plain text string. Using "hello" as an example message, the TextBlock would be:

1{
2 type: 'text';
3 children: ['hello'];
4}

Other than plain text, there are many different kinds of node which render some text in a specific way or with certain formatting.

1type TextNode =
2 | string
3 | MarkupNode
4 | BulletListNode
5 | BulletPointNode
6 | CodeSpanNode
7 | LinkNode
8 | AutoLinkNode
9 | ActionLinkNode
10 | ActionButtonNode
11 | CustomEmojiNode
12 | MentionNode;

If the text node is not a plain string, it will have a type field indicating what kind of node it is, and either a property text: string or a property children: TextNode[]. This will be true for all nodes added in the future as well.

Full documentation of each TextNode variant

interface MarkupNode

A node in a TextBlock that renders its children with a specific style.

Properties

type
: "bold" | "italic" | "strikethrough"

The kind of formatting to apply when rendering the children

- type: "bold" is used when users type *text* and is rendered with HTML <strong>

- type: "italic" is used when users type _text_ and is rendered with HTML <em>

- type: "strikethrough" is used when users type ~text~ and is rendered with HTML <s>

children
: TextNode[]

interface BulletListNode

A node in a TextBlock that adds indentation for a bullet-point list around its children (HTML <ul>).

Used when users send a bullet-point list by starting lines of their message with - or *.

Properties

type
: "bulletList"
children
: TextNode[]

interface BulletPointNode

A node in a TextBlock that renders its children with a bullet-point (HTML <li>).

Used when users start a line of their message with - or *.

Properties

type
: "bulletPoint"
children
: TextNode[]

interface LinkNode

A node in a TextBlock that renders its children as a clickable link (HTML <a>).

By default, users do not have permission to send messages containing LinkNode as it can be used to maliciously hide the true destination of a link.

Properties

type
: "link"
children
: TextNode[]
url
: string

The URL to open when the node is clicked.

interface AutoLinkNode

A node in a TextBlock that renders text as a link (HTML <a>).

Used when user-typed text is turned into a link automatically.

Unlike LinkNode, users do have permission to send AutoLinkNodes by default, because the text and url properties must match. Specifically:

- If text is an email, url must contain a mailto: link to the same email address

- If text is a phone number, url must contain a tel: link to the same phone number

- If text is a website, the domain name including subdomains must be the same in both text and url. If text includes a protocol (such as https), path (/page), query string (?page=true), or url fragment (#title), they must be the same in url. If text does not specify a protocol, url must use either https or http.

This means that the following AutoLink is valid:

1{
2 type: "autoLink",
3 text: "talkjs.com"
4 url: "https://talkjs.com/docs/Reference/JavaScript_Chat_SDK/Realtime_API/#AutoLinkNode"
5}

That link will appear as talkjs.com and link you to the specific section of the documentation that explains how AutoLinkNodes work.

These rules ensure that the user knows what link they are clicking, and prevents AutoLinkNode being used for phishing. If you try to send a message containing an AutoLink that breaks these rules, the request will be rejected.

Properties

type
: "autoLink"
text
: string

The text to display in the link.

url
: string

The URL to open when a user clicks this node.

interface ActionLinkNode

A node in a TextBlock that renders its children as a clickable action link which triggers a custom action.

By default, users do not have permission to send messages containing ActionLinkNode as it can be used maliciously to trick others into invoking custom actions. For example, a user could send an "accept offer" action link, but disguise it as a link to a website.

Properties

type
: "actionLink"
action
: string

The name of the custom action to invoke when the link is clicked.

children
: TextNode[]
params
: Record<string, string>

The parameters to pass to the custom action when the link is clicked.

interface ActionButtonNode

A node in a TextBlock that renders its children as a clickable action button which triggers a custom action.

By default, users do not have permission to send messages containing action buttons as they can be used maliciously to trick others into invoking custom actions. For example, a user could send an "accept offer" action button, but disguise it as "view offer".

Properties

type
: "actionButton"
action
: string

The name of the custom action to invoke when the button is clicked.

children
: TextNode[]
params
: Record<string, string>

The parameters to pass to the custom action when the button is clicked.

interface CodeSpanNode

A node in a TextBlock that renders text in an inline code span (HTML <code>).

Used when a user types ```text```.

Properties

type
: "codeSpan"
text
: string

interface CustomEmojiNode

A node in a TextBlock that is used for custom emoji.

Properties

type
: "customEmoji"
text
: string

The name of the custom emoji to show.

interface MentionNode

A node in a TextBlock that is used when a user is mentioned.

Used when a user types @name and selects the user they want to mention.

Properties

type
: "mention"
id
: string

The ID of the user who is mentioned.

text
: string

The name of the user who is mentioned.

type FileBlock

A file attachment received in a message's content.

All FileBlock variants contain url, size, and fileToken. Some file blocks have additional metadata, in which case they will have the subtype property set.

Currently the available FileBlock subtypes are:

- No subtype set (GenericFileBlock)

- subtype: "video" (VideoBlock)

- subtype: "image" (ImageBlock)

- subtype: "audio" (AudioBlock)

- subtype: "voice" (VoiceBlock)

Full documentation of each FileBlock variant

interface GenericFileBlock

The most basic FileBlock variant, used whenever there is no additional metadata for a file.

Do not try to check for subtype === undefined directly, as this will break when we add new FileBlock variants in the future.

Instead, treat GenericFileBlock as the default. For example:

1if (block.subtype === "video") {
2 handleVideoBlock(block);
3} else if (block.subtype === "image") {
4 handleImageBlock(block);
5} else if (block.subtype === "audio") {
6 handleAudioBlock(block);
7} else if (block.subtype === "voice") {
8 handleVoiceBlock(block);
9} else {
10 handleGenericFileBlock(block);
11}

Properties

type
: "file"
fileToken
: FileToken

An encoded identifier for this file. Use in SendFileBlock to send this file in another message.

filename
: string

The name of the file, including file extension

size
: number

The size of the file in bytes

url
: string

The URL where you can fetch the file

subtype (optional)
: undefined

Never set for generic file blocks.

interface VideoBlock

A FileBlock variant for a video attachment, with additional video-specific metadata.

You can identify this variant by checking for subtype: "video".

Includes metadata about the height and width of the video in pixels, and the duration of the video in seconds, where available.

Videos that you upload with the TalkJS UI will include the dimensions and duration as long as the sender's browser can preview the file. Videos that you upload with the REST API or Session​.uploadVideo will include this metadata if you specified it when uploading. Videos attached in a reply to an email notification will not include any metadata.

Properties

type
: "file"
fileToken
: FileToken

An encoded identifier for this file. Use in SendFileBlock to send this video in another message.

filename
: string

The name of the video file, including file extension.

size
: number

The size of the file in bytes.

subtype
: "video"
url
: string

The URL where you can fetch the file.

duration (optional)
: number

The duration of the video in seconds, if known.

height (optional)
: number

The height of the video in pixels, if known.

width (optional)
: number

The width of the video in pixels, if known.

interface ImageBlock

A FileBlock variant for an image attachment, with additional image-specific metadata.

You can identify this variant by checking for subtype: "image".

Includes metadata about the height and width of the image in pixels, where available.

Images that you upload with the TalkJS UI will include the image dimensions as long as the sender's browser can preview the file. Images that you upload with the REST API or Session​.uploadImage will include the dimensions if you specified them when uploading. Image attached in a reply to an email notification will not include the dimensions.

Properties

type
: "file"
fileToken
: FileToken

An encoded identifier for this file. Use in SendFileBlock to send this image in another message.

filename
: string

The name of the image file, including file extension.

size
: number

The size of the file in bytes.

subtype
: "image"
url
: string

The URL where you can fetch the file.

height (optional)
: number

The height of the image in pixels, if known.

width (optional)
: number

The width of the image in pixels, if known.

interface AudioBlock

A FileBlock variant for an audio attachment, with additional audio-specific metadata.

You can identify this variant by checking for subtype: "audio".

The same file could be uploaded as either an audio block, or as a VoiceBlock. The same data will be available either way, but they will be rendered differently in the UI.

Includes metadata about the duration of the audio file in seconds, where available.

Audio files that you upload with the TalkJS UI will include the duration as long as the sender's browser can preview the file. Audio files that you upload with the REST API or Session​.uploadAudio will include the duration if you specified it when uploading. Audio files attached in a reply to an email notification will not include the duration.

Properties

type
: "file"
fileToken
: FileToken

An encoded identifier for this file. Use in SendFileBlock to send this file in another message.

filename
: string

The name of the audio file, including file extension

size
: number

The size of the file in bytes

subtype
: "audio"
url
: string

The URL where you can fetch the file

duration (optional)
: number

The duration of the audio in seconds, if known

interface VoiceBlock

A FileBlock variant for a voice recording attachment, with additional voice-recording-specific metadata.

You can identify this variant by checking for subtype: "voice".

The same file could be uploaded as either a voice block, or as an AudioBlock. The same data will be available either way, but they will be rendered differently in the UI.

Includes metadata about the duration of the recording in seconds, where available.

Voice recordings done in the TalkJS UI will always include the duration. Voice recording that you upload with the REST API or Session​.uploadVoice will include this metadata if you specified it when uploading.

Voice recordings will never be taken from a reply to an email notification. Any attached audio file will become an AudioBlock instead of a voice block.

Properties

type
: "file"
fileToken
: FileToken

An encoded identifier for this file. Use in SendFileBlock to send this voice recording in another message.

filename
: string

The name of the file, including file extension

size
: number

The size of the file in bytes

subtype
: "voice"
url
: string

The URL where you can fetch the file

duration (optional)
: number

The duration of the voice recording in seconds, if known

interface LocationBlock

A block showing a location in the world, typically because a user shared their location in the chat.

In the TalkJS UI, location blocks are rendered as a link to Google Maps, with the map pin showing at the specified coordinate. A thumbnail shows the surrounding area on the map.

Properties

type
: "location"
latitude
: number

The north-south coordinate of the location.

Usually listed first in a pair of coordinates.

Must be a number between -90 and 90

longitude
: number

The east-west coordinate of the location.

Usually listed second in a pair of coordinates.

Must be a number between -180 and 180

type SendContentBlock

The version of ContentBlock that is used when sending or editing messages.

This is the same as ContentBlock except it uses SendFileBlock instead of FileBlock

SendContentBlock is a subset of ContentBlock. This means that you can re-send the content from an existing message without any issues:

1const existingMessage: MessageSnapshot = ...;
2
3const convRef = session.conversation('example_conversation_id');
4convRef.send({ content: existingMessage.content });

interface SendFileBlock

The version of FileBlock that is used when sending or editing messages.

When a user receives the message you send with SendFileBlock, this block will have turned into one of the FileBlock variants.

For information on how to obtain a file token, see FileToken.

The SendFileBlock interface is a subset of the FileBlock interface. If you have an existing FileBlock received in a message, you can re-use that block to re-send the same attachment:

1const existingFileBlock = ...;
2const imageToShare = existingFileBlock.content[0] as ImageBlock
3
4const convRef = session.conversation('example_conversation_id');
5convRef.send({ content: [imageToShare] });

Properties

type
: "file"
fileToken
: FileToken

The encoded identifier for the file, obtained by uploading a file with Session​.sendFile, or taken from another message.

type FileToken

A token representing a file uploaded to TalkJS.

You cannot create a FileToken yourself. Get a file token by uploading your file to TalkJS with Session​.uploadFile, or one of the subtype-specific variants like Session​.uploadImage.

For example:

1// From `<input type="file">`
2const file: File = fileInputElement.files[0];
3const myFileToken = await session.uploadFile(file, { filename: file.name });

Alternatively, take a file token from an existing FileBlock to re-send an attachment you received, without having to download and re-upload the file.

You can also upload files using the REST API.

Passed in SendFileBlock when you send a message containing a file attachment:

1const block: SendFileBlock = {
2 type: 'file',
3 fileToken: myFileToken,
4};
5
6const convRef = session.conversation('example_conversation_id');
7convRef.send({ content: [block] });

We may change the FileToken format in the future. Do not store old file tokens for future use, as these may stop working.

This system ensures that all files must be uploaded to TalkJS before being sent to users, limiting the risk of malware.

Performance

The Realtime API has various optimisations to allow you to use it in a simple way, while still getting maximum performance. Our design philosophy is that the "naive solution" should also be best-practice.

Automatic batching

To perform a large number of actions at once, you do not need to do anything differently. There is no getMany or subscribeMany method. Send the actions one at a time, like this:

1for (let i = 0; i < 1000; i++) {
2 session.user(`user ${i}`).subscribe(...);
3}

The Realtime API is based on websockets, meaning that there is little overhead on each additional call. Unlike HTTP requests, there is no limit to the number of calls you can have in-flight at a time.

Some calls (like UserRef.subscribe) support "automatic batching" when you send them multiple times in a row. TalkJS will combines these calls into one batched call which is sent to the backend. You will get the exact same response as you would if the requests were sent one at a time, except it's faster.

Batching will never change the order that your calls are sent in. This means that if you interleave different kinds of requests:

1session.user("Alice").get();
2session.user("Bob").set({ name: "Robert" });
3session.user("Bob").get();

Then TalkJS will send these calls one at a time. If the GET Alice and GET Bob requests were combined into a batch, then SET Bob could not happen in-between the two GET calls.

In technical terms, when you do a call that supports automatic batching, we wait until the next microtask in the JavaScript event loop before actually sending the call. If you send another call before then, we check to see if the second call can be sent in a batch with the first call. If the two calls are compatible, we combine them into a batch. Otherwise, we send the first call and wait for the next microtask before sending the second call.

Subscription sharing

There is no subscription.addSnapshotListener method, where you can attach a new listener to a pre-existing subscription. So when you want to attach 5 different listeners to a user, you can do:

1for (let i = 0; i < 5; i++) {
2 session.currentUser.subscribe(() => console.log(i))
3}

This will result in only one subscription on the backend, with your 5 listeners attached to it. We won't officially unsubscribe until all 5 of your subscriptions have unsubscribed.

Debounced unsubscribe

When you unsubscribe from a subscription, we wait a little bit before officially unsubscribing. This means that if you unsubscribe and then immediately resubscribe, it happens instantly without sending any requests to the backend. For example, if you are subscribed to a user and want to change the callback to something else:

1const subscription = session.currentUser.subscribe(...);
2
3// Later
4subscription.unsubscribe();
5const subscription2 = session.currentUser.subscribe(...);

This will not trigger any call to the backend, because internally we are still subscribed to currentUser when you resubscribe. This is important because staying subscribed is generally much more efficient than subscribing in the first place. The amount of time the client will stay subscribed is different for each resource. Simpler resources that change less often (like users) stay subscribed for longer, because being subscribed to something that rarely changes is almost free.

Cached fetch

When you fetch a resource that you are subscribed to, we already know the current state without having to ask the backend. This means that the method becomes synchronous and essentially free. For example:

1session.currentUser.subscribe();
2
3// Later
4await session.currentUser.get();

This get call will not trigger any request to the backend and will return the data instantly. If you know you are going to get some data repeatedly, consider subscribing to improve performance.

Subscriptions reuse snapshots

Snapshots are considered immutable, and we try to reuse them as much as possible. This means that you can skip rendering a UI component if oldSnapshot === newSnapshot.

For example:

  • If a message was edited, we would create a new MessageSnapshot but reuse the old UserSnapshot for the sender property.
  • If 10 messages all reference the same message, they will all use the same ReferencedMessageSnapshot.
  • When a new message is received, we output a new array of messages with the extra message. Pre-existing messages reuse their MessageSnapshot.

Specifically, we guarantee that snapshots are immutable. If something changed, we will return a new object. However, we do not guarantee that snapshots are always reused. If nothing changed, we try to reuse the old snapshot. In edge cases such as network loss, we may create new snapshots despite nothing changing.

You should only re-render your UI when oldSnapshot !== newSnapshot. However, if you need to be certain that nothing changed, do a deep-equality check.