Posting thread messages via the API
Team Messaging posts can be grouped into threads. A threaded reply is still a post in the same chat, but the post response includes thread metadata that lets your app find the parent post and retrieve the other posts in the thread.
Use threaded posts when a bot or app needs to keep follow-up messages attached to a specific conversation inside a chat.
Creating a thread reply
Create the first reply to a post by passing the parent post ID in the parentPostId request property when you call Create Post.
{
"text": "First reply in the thread",
"parentPostId": "1234567890"
}
If parentPostId identifies a reply that is already in a thread, the new post is added to the original parent post's thread.
Adding a reply to a thread
If your app already has a thread ID, you can add a reply by passing threadId instead.
{
"text": "Reply using a thread ID",
"threadId": "9876543210"
}
Use one of parentPostId or threadId for a threaded reply. To create a regular top-level post, omit both fields.
Reading thread metadata
Post responses from Create Post, Get Post, Update Post, and List Posts can include these thread fields:
| Field | Description |
|---|---|
isParent |
Returned for a post that is the parent post of a thread. |
parentPostId |
The parent post ID when the post belongs to a thread. |
threadId |
The thread ID shared by posts in the same thread. |
Listing posts in a thread
Call List Thread Posts to fetch posts that belong to a specific thread.
GET /team-messaging/v1/chats/{chatId}/threads/{threadId}/posts?recordCount=30
The response uses the same Team Messaging pagination model as other list endpoints. If the response contains navigation.nextPageToken or navigation.prevPageToken, pass the token as the pageToken query parameter in the next request.
GET /team-messaging/v1/chats/{chatId}/threads/{threadId}/posts?pageToken={pageToken}
Example
The following example finds the authenticated user's personal chat, creates a parent post, creates a threaded reply using parentPostId, and then lists posts from the returned threadId.
const RC = require('@ringcentral/sdk').SDK
require('dotenv').config();
var rcsdk = new RC({
'server': process.env.RC_SERVER_URL,
'clientId': process.env.RC_APP_CLIENT_ID,
'clientSecret': process.env.RC_APP_CLIENT_SECRET
});
var platform = rcsdk.platform();
platform.login({ 'jwt': process.env.RC_USER_JWT })
platform.on(platform.events.loginSuccess, () => {
create_threaded_posts()
})
async function create_threaded_posts() {
try {
let chatId = await get_personal_chat_id()
let parentPost = await create_post(chatId, {
text: "Thread parent post"
})
console.log("Parent post ID: " + parentPost.id)
let reply = await create_post(chatId, {
text: "First reply in the thread",
parentPostId: parentPost.id
})
console.log("Reply post ID: " + reply.id)
console.log("Thread ID: " + reply.threadId)
let threadPosts = await list_thread_posts(chatId, reply.threadId)
console.log("Posts in thread:")
threadPosts.records.forEach((post) => {
console.log(`- ${post.id}: ${post.text}`)
})
} catch (e) {
console.log(e.message)
}
}
async function get_personal_chat_id() {
let endpoint = "/team-messaging/v1/chats"
let resp = await platform.get(endpoint, { type: 'Personal' })
let jsonObj = await resp.json()
if (jsonObj.records.length === 0) {
throw new Error("Personal chat not found")
}
return jsonObj.records[0].id
}
async function create_post(chatId, bodyParams) {
let endpoint = `/team-messaging/v1/chats/${chatId}/posts`
let resp = await platform.post(endpoint, bodyParams)
return await resp.json()
}
async function list_thread_posts(chatId, threadId) {
let endpoint = `/team-messaging/v1/chats/${chatId}/threads/${threadId}/posts`
let resp = await platform.get(endpoint, { recordCount: 30 })
return await resp.json()
}