Messages
Messages are a sub-resource of conversations.
There are currently two types of messages you can send to a conversation. You can either send messages to a conversation on behalf of one user or on behalf of your app. Users in the conversation must have had their data synchronized first.
The request payload of this endpoint must always be an array, even if you send only one message. This way it's possible for you to send a batch of consecutive messages in a single request. It's also possible to combine user messages and system messages in one request. The maximum amount of messages sent in one request is 10.
This endpoint returns an array of objects, one for each message, that contain the ids of the messages.
1[2 {"id": "msg_abcdefghijklm"},3 {"id": "msg_nopqrstuvwxyz"},4 ...5]
You can programmatically send messages on behalf of a user in a conversation. The behavior is identical to that when sending messages via the UI; notifications are triggered based on the participating user's role. UserMessage also supports sending attachments and locations. See Sending Files.
1[2 {3 text: string4 sender: string5 type: "UserMessage"6 referencedMessageId?: string7 custom?: { [key: string]: string }8 idempotencyKey?: string9 },10 ...11]
1[2 {3 "text": "Meet me outside",4 "sender": "123143551",5 "type": "UserMessage",6 "referencedMessageId": "msg_6TKoWs0Jm8XrjPOmFdOGiX"7 }8]
sender
has to be a participant in the conversation. type
must be "UserMessage"
when sender
is provided or the request fails.
The referencedMessageId
property is used when the message you are sending is meant to be a reply to another message.
System messages are messages which are not sent by a participant, but programmatically by your application. A SystemMessage
is displayed differently in the UI, and doesn't trigger notifications for any user in the conversation. You are expected to handle these notifications in your application if needed. These messages support attachments but don't currently support locations.
System Messages support formatting.
Some example use cases in a marketplace for System Messages are 'order received' and 'payment failed', but these can be anything from payment confirmations to "User left the group" notifications.
1[2 {3 text: string4 type: "SystemMessage"5 custom?: { [key: string]: string }6 idempotencyKey?: string7 },8 ...9]
1[2 {3 "text": "Purchase Complete",4 "type": "SystemMessage"5 }6]
text
field supports the same syntax as Subjects. sender
must not be provided when sending system messages.
If an initial request fails, you may want to retry the request. To avoid message duplication on retries, you can use the idempotencyKey
field when sending the message. If you use an idempotencyKey
, you can try a request any number of times and TalkJS guarantees that the message gets sent exactly once.
Make sure that the idempotencyKey
you use is unique within the conversation in which the message is sent. If two messages in the same conversation have the same idempotencyKey
, the system treats those two messages as if they're the same request, and only the first message with that idempotencyKey
gets processed.
TalkJS associates a message with an idempotencyKey
for 24 hours. After 24 hours, the idempotencyKey
expires and you can reuse the key for a different message.
You can check the status of a certain message from a conversation (for example, after some time to read a readBy
status), by calling:
1type MessageId = string;2type UserId = string;34type UnixMilliseconds = number;56type Message = {7 attachment: { url: string; size: number, dimensions?: {width: number height: number } } | null,8 conversationId: string,9 createdAt: UnixMilliseconds,10 editedAt: UnixMilliseconds | null,11 custom: { [name: string]: string },12 id: MessageId,13 location: [number, number] | null,14 origin: "web" | "rest" | "email" | "import",15 readBy: UserId[],16 senderId: UserId,17 text: string,18 type: "UserMessage" | "SystemMessage"19 referencedMessageId: string | null20}
1{2 "attachment": null,3 "conversationId": "87d70908d90cee5d12bd",4 "createdAt": 1632919967033,5 "editedAt": 16329200167563,6 "custom": {},7 "id": "msg_0UQbqdxnQWkoIw7Db7fZHK",8 "location": null,9 "origin": "web",10 "readBy": [],11 "senderId": "432156789",12 "text": "Hey, I'm in London",13 "type": "UserMessage",14 "referencedMessageId": "msg_6TKoWs0Jm8XrjPOmFdOGiX"1516}
Note that the readBy
field is only used for conversations with at most 300 participants. For conversations with 301 or more participants, the readBy
field will be empty.
This endpoint lets you edit the text field and the custom data in existing message. You first need to know the id of the message you want to edit. Please use the listing messages endpoint to obtain a list of messages along with their IDs or get it via a Webhook. Afterwards, you have to call the following endpoint:
You can also pass a field called markEdited
(defaulting to false). When this field is set to true, the message's editedAt
field will be set to the time of this change,
and depending on your theme, an indicator that the message was edited may appear in the UI.
1{2 custom?: { [key: string]: string },3 text?: string,4 markEdited?: boolean5}
Use this endpoint to irrevocably delete a message of the given conversation. Besides deleting the message from the TalkJS database, it is also deleted in real-time from any potentially connected clients. Additionally, a message.deleted webhook event is sent. If it contains the attachment it is removed from the storage.
You can list messages written in conversations by users in TalkJS. In order to do that you need to call the following endpoint:
1{2 "data": Array<Message>3}
1{2 "data": [3 {4 "attachment": null,5 "conversationId": "87d70908d90cee5d12bd",6 "createdAt": 1632919967033,7 "editedAt": null,8 "custom": {},9 "id": "msg_0UQbqdxnQWkoIw7Db7fZHK",10 "location": null,11 "origin": "web",12 "readBy": [],13 "senderId": "432156789",14 "text": "Hey, I'm in London",15 "type": "UserMessage",16 "referencedMessageId": null17 },18 {19 ...20 }21 ]22}
Note that the readBy
field is only used for conversations with at most 300 participants. For conversations with 301 or more participants, the readBy
field will be empty.
Similarly to other list requests, pagination and limits are applicable to listing messages.
1GET https://api.talkjs.com/v1/{appId}/conversations/{conversationId}2GET https://api.talkjs.com/v1/{appId}/conversations/{conversationId}?limit=503GET https://api.talkjs.com/v1/{appId}/conversations/{conversationId}?startingAfter=c_214GET https://api.talkjs.com/v1/{appId}/conversations/{conversationId}?startingAfter=c_21&limit=10
Sending files (images, documents, etc) is a two-step process. First, you upload the file to our servers. Then, you send a message in the same way as a text message, but with a reference to the uploaded file.
You upload a file using the files
endpoint:
1{2 "attachmentToken": "L0oQOg5DVENGFVQZABpOQVNRCxs...EFFbHxhiXVEYUBw"3}
This is the only resource on the TalkJS REST API that does not accept a JSON payload.
Instead, send multipart/form-data
formatted data with two required parameters:
file
- This is the file data you want to upload.filename
- The name of the file.
This is the usual way files are uploaded over HTTP. Check the docs of your favorite HTTP client for information on how to upload files with it. For example: JavaScript, Python (Requests), PHP, Ruby (RestClient).
This endpoint returns a JSON object with a single property, attachmentToken
.
If you get a 400 Bad Request
response, try the following:
- Check if your code is explicitly setting a
Content-type: multipart/form-data
header somewhere. If so, remove it. Most HTTP libraries will autogenerate this header when uploading files, and they will usually set the header to something likeContent-Type: multipart/form-data; boundary=a3eb698cd620e766f278e52886c572edcb0e4a97
. Without the boundary, TalkJS can't parse the data. - For TalkJS to be able to detect that you're uploading a file, the file needs to have a
filename
directive set. Many HTTP libraries do this automatically. If not, there will be a way for you to set it explicitly. Doing so causes the library to generate a header such asContent-Disposition: form-data; file="This is a txt file."; filename="sample.txt"
inside the HTTP body. You shouldn't need to set this header manually; find a facility in your HTTP library to give an uploaded file a filename.
If you get a 500 Server Error
response, reach out to us through our live chat.
Now, use the usual messages
resource to send a message, but replace the text
field by an attachmentToken
field:
1[2 {3 attachmentToken: string,4 sender: string,5 type: 'UserMessage',6 },7];
Alternatively, images can be sent using a system message by omitting the sender and using SystemMessage
as the message type.
1[2 {3 attachmentToken: string,4 type: 'SystemMessage',5 }6]
Use this endpoint to irrevocably delete all messages of the given conversation. Besides deleting the messages from the TalkJS database, it is also deleted in real-time from any potentially connected clients. Note that this endpoint does not generate any webhooks.