Send a message to a thread
curl --request POST \
--url https://api.hubapi.com/conversations/conversations/2026-09-beta/threads/{threadId}/messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"attachments": [
{
"fileId": "<string>",
"type": "FILE"
}
],
"channelAccountId": "<string>",
"channelId": "<string>",
"recipients": [
{
"deliveryIdentifiers": [
{
"value": "<string>"
}
],
"actorId": "<string>",
"name": "<string>",
"recipientField": "<string>"
}
],
"senderActorId": "<string>",
"text": "<string>",
"type": "MESSAGE",
"richText": "<string>",
"subject": "<string>"
}
'import requests
url = "https://api.hubapi.com/conversations/conversations/2026-09-beta/threads/{threadId}/messages"
payload = {
"attachments": [
{
"fileId": "<string>",
"type": "FILE"
}
],
"channelAccountId": "<string>",
"channelId": "<string>",
"recipients": [
{
"deliveryIdentifiers": [{ "value": "<string>" }],
"actorId": "<string>",
"name": "<string>",
"recipientField": "<string>"
}
],
"senderActorId": "<string>",
"text": "<string>",
"type": "MESSAGE",
"richText": "<string>",
"subject": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
attachments: [{fileId: '<string>', type: 'FILE'}],
channelAccountId: '<string>',
channelId: '<string>',
recipients: [
{
deliveryIdentifiers: [{value: '<string>'}],
actorId: '<string>',
name: '<string>',
recipientField: '<string>'
}
],
senderActorId: '<string>',
text: '<string>',
type: 'MESSAGE',
richText: '<string>',
subject: '<string>'
})
};
fetch('https://api.hubapi.com/conversations/conversations/2026-09-beta/threads/{threadId}/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.hubapi.com/conversations/conversations/2026-09-beta/threads/{threadId}/messages",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'attachments' => [
[
'fileId' => '<string>',
'type' => 'FILE'
]
],
'channelAccountId' => '<string>',
'channelId' => '<string>',
'recipients' => [
[
'deliveryIdentifiers' => [
[
'value' => '<string>'
]
],
'actorId' => '<string>',
'name' => '<string>',
'recipientField' => '<string>'
]
],
'senderActorId' => '<string>',
'text' => '<string>',
'type' => 'MESSAGE',
'richText' => '<string>',
'subject' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.hubapi.com/conversations/conversations/2026-09-beta/threads/{threadId}/messages"
payload := strings.NewReader("{\n \"attachments\": [\n {\n \"fileId\": \"<string>\",\n \"type\": \"FILE\"\n }\n ],\n \"channelAccountId\": \"<string>\",\n \"channelId\": \"<string>\",\n \"recipients\": [\n {\n \"deliveryIdentifiers\": [\n {\n \"value\": \"<string>\"\n }\n ],\n \"actorId\": \"<string>\",\n \"name\": \"<string>\",\n \"recipientField\": \"<string>\"\n }\n ],\n \"senderActorId\": \"<string>\",\n \"text\": \"<string>\",\n \"type\": \"MESSAGE\",\n \"richText\": \"<string>\",\n \"subject\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.hubapi.com/conversations/conversations/2026-09-beta/threads/{threadId}/messages")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"attachments\": [\n {\n \"fileId\": \"<string>\",\n \"type\": \"FILE\"\n }\n ],\n \"channelAccountId\": \"<string>\",\n \"channelId\": \"<string>\",\n \"recipients\": [\n {\n \"deliveryIdentifiers\": [\n {\n \"value\": \"<string>\"\n }\n ],\n \"actorId\": \"<string>\",\n \"name\": \"<string>\",\n \"recipientField\": \"<string>\"\n }\n ],\n \"senderActorId\": \"<string>\",\n \"text\": \"<string>\",\n \"type\": \"MESSAGE\",\n \"richText\": \"<string>\",\n \"subject\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hubapi.com/conversations/conversations/2026-09-beta/threads/{threadId}/messages")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"attachments\": [\n {\n \"fileId\": \"<string>\",\n \"type\": \"FILE\"\n }\n ],\n \"channelAccountId\": \"<string>\",\n \"channelId\": \"<string>\",\n \"recipients\": [\n {\n \"deliveryIdentifiers\": [\n {\n \"value\": \"<string>\"\n }\n ],\n \"actorId\": \"<string>\",\n \"name\": \"<string>\",\n \"recipientField\": \"<string>\"\n }\n ],\n \"senderActorId\": \"<string>\",\n \"text\": \"<string>\",\n \"type\": \"MESSAGE\",\n \"richText\": \"<string>\",\n \"subject\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"archived": true,
"attachments": [
{
"fileId": "<string>",
"type": "FILE",
"name": "<string>",
"url": "<string>"
}
],
"channelAccountId": "<string>",
"channelId": "<string>",
"client": {
"integrationAppId": 123
},
"conversationsThreadId": "<string>",
"createdAt": "2023-11-07T05:31:56Z",
"createdBy": "<string>",
"id": "<string>",
"recipients": [
{
"deliveryIdentifier": {
"value": "<string>"
},
"actorId": "<string>",
"name": "<string>",
"recipientField": "<string>"
}
],
"senders": [
{
"actorId": "<string>",
"deliveryIdentifier": {
"value": "<string>"
},
"name": "<string>",
"senderField": "<string>"
}
],
"text": "<string>",
"type": "MESSAGE",
"inReplyToId": "<string>",
"richText": "<string>",
"status": {
"failureDetails": {
"errorMessageTokens": {},
"errorMessage": "<string>"
}
},
"subject": "<string>",
"updatedAt": "2023-11-07T05:31:56Z"
}{
"message": "Invalid input (details will vary based on the error)",
"correlationId": "aeb5f871-7f07-4993-9211-075dc63e7cbf",
"category": "VALIDATION_ERROR",
"links": {
"knowledge-base": "https://www.hubspot.com/products/service/knowledge-base"
}
}Messages
Create message
Create a new message within a specific conversation thread in your HubSpot account. This endpoint allows you to send messages as part of an ongoing conversation, which can include various types of content such as text, attachments, and more. It is useful for programmatically interacting with conversation threads and ensuring seamless communication flow.
POST
/
conversations
/
conversations
/
2026-09-beta
/
threads
/
{threadId}
/
messages
Send a message to a thread
curl --request POST \
--url https://api.hubapi.com/conversations/conversations/2026-09-beta/threads/{threadId}/messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"attachments": [
{
"fileId": "<string>",
"type": "FILE"
}
],
"channelAccountId": "<string>",
"channelId": "<string>",
"recipients": [
{
"deliveryIdentifiers": [
{
"value": "<string>"
}
],
"actorId": "<string>",
"name": "<string>",
"recipientField": "<string>"
}
],
"senderActorId": "<string>",
"text": "<string>",
"type": "MESSAGE",
"richText": "<string>",
"subject": "<string>"
}
'import requests
url = "https://api.hubapi.com/conversations/conversations/2026-09-beta/threads/{threadId}/messages"
payload = {
"attachments": [
{
"fileId": "<string>",
"type": "FILE"
}
],
"channelAccountId": "<string>",
"channelId": "<string>",
"recipients": [
{
"deliveryIdentifiers": [{ "value": "<string>" }],
"actorId": "<string>",
"name": "<string>",
"recipientField": "<string>"
}
],
"senderActorId": "<string>",
"text": "<string>",
"type": "MESSAGE",
"richText": "<string>",
"subject": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
attachments: [{fileId: '<string>', type: 'FILE'}],
channelAccountId: '<string>',
channelId: '<string>',
recipients: [
{
deliveryIdentifiers: [{value: '<string>'}],
actorId: '<string>',
name: '<string>',
recipientField: '<string>'
}
],
senderActorId: '<string>',
text: '<string>',
type: 'MESSAGE',
richText: '<string>',
subject: '<string>'
})
};
fetch('https://api.hubapi.com/conversations/conversations/2026-09-beta/threads/{threadId}/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.hubapi.com/conversations/conversations/2026-09-beta/threads/{threadId}/messages",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'attachments' => [
[
'fileId' => '<string>',
'type' => 'FILE'
]
],
'channelAccountId' => '<string>',
'channelId' => '<string>',
'recipients' => [
[
'deliveryIdentifiers' => [
[
'value' => '<string>'
]
],
'actorId' => '<string>',
'name' => '<string>',
'recipientField' => '<string>'
]
],
'senderActorId' => '<string>',
'text' => '<string>',
'type' => 'MESSAGE',
'richText' => '<string>',
'subject' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.hubapi.com/conversations/conversations/2026-09-beta/threads/{threadId}/messages"
payload := strings.NewReader("{\n \"attachments\": [\n {\n \"fileId\": \"<string>\",\n \"type\": \"FILE\"\n }\n ],\n \"channelAccountId\": \"<string>\",\n \"channelId\": \"<string>\",\n \"recipients\": [\n {\n \"deliveryIdentifiers\": [\n {\n \"value\": \"<string>\"\n }\n ],\n \"actorId\": \"<string>\",\n \"name\": \"<string>\",\n \"recipientField\": \"<string>\"\n }\n ],\n \"senderActorId\": \"<string>\",\n \"text\": \"<string>\",\n \"type\": \"MESSAGE\",\n \"richText\": \"<string>\",\n \"subject\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.hubapi.com/conversations/conversations/2026-09-beta/threads/{threadId}/messages")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"attachments\": [\n {\n \"fileId\": \"<string>\",\n \"type\": \"FILE\"\n }\n ],\n \"channelAccountId\": \"<string>\",\n \"channelId\": \"<string>\",\n \"recipients\": [\n {\n \"deliveryIdentifiers\": [\n {\n \"value\": \"<string>\"\n }\n ],\n \"actorId\": \"<string>\",\n \"name\": \"<string>\",\n \"recipientField\": \"<string>\"\n }\n ],\n \"senderActorId\": \"<string>\",\n \"text\": \"<string>\",\n \"type\": \"MESSAGE\",\n \"richText\": \"<string>\",\n \"subject\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hubapi.com/conversations/conversations/2026-09-beta/threads/{threadId}/messages")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"attachments\": [\n {\n \"fileId\": \"<string>\",\n \"type\": \"FILE\"\n }\n ],\n \"channelAccountId\": \"<string>\",\n \"channelId\": \"<string>\",\n \"recipients\": [\n {\n \"deliveryIdentifiers\": [\n {\n \"value\": \"<string>\"\n }\n ],\n \"actorId\": \"<string>\",\n \"name\": \"<string>\",\n \"recipientField\": \"<string>\"\n }\n ],\n \"senderActorId\": \"<string>\",\n \"text\": \"<string>\",\n \"type\": \"MESSAGE\",\n \"richText\": \"<string>\",\n \"subject\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"archived": true,
"attachments": [
{
"fileId": "<string>",
"type": "FILE",
"name": "<string>",
"url": "<string>"
}
],
"channelAccountId": "<string>",
"channelId": "<string>",
"client": {
"integrationAppId": 123
},
"conversationsThreadId": "<string>",
"createdAt": "2023-11-07T05:31:56Z",
"createdBy": "<string>",
"id": "<string>",
"recipients": [
{
"deliveryIdentifier": {
"value": "<string>"
},
"actorId": "<string>",
"name": "<string>",
"recipientField": "<string>"
}
],
"senders": [
{
"actorId": "<string>",
"deliveryIdentifier": {
"value": "<string>"
},
"name": "<string>",
"senderField": "<string>"
}
],
"text": "<string>",
"type": "MESSAGE",
"inReplyToId": "<string>",
"richText": "<string>",
"status": {
"failureDetails": {
"errorMessageTokens": {},
"errorMessage": "<string>"
}
},
"subject": "<string>",
"updatedAt": "2023-11-07T05:31:56Z"
}{
"message": "Invalid input (details will vary based on the error)",
"correlationId": "aeb5f871-7f07-4993-9211-075dc63e7cbf",
"category": "VALIDATION_ERROR",
"links": {
"knowledge-base": "https://www.hubspot.com/products/service/knowledge-base"
}
}Supported products
Supported products
Required Scopes
Required Scopes
Authorizations
The access token received from the authorization server in the OAuth 2.0 flow.
Path Parameters
The unique ID of the thread.
Body
application/json
- Option 1
- Option 2
- FILE
- QUICK_REPLIES
- SOCIAL_MEDIA_METADATA
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Available options:
MESSAGE Response
successful operation
- Option 1
- Option 2
- Option 3
- Option 4
- Option 5
- Option 6
attachments
(FILE · object | LOCATION · object | CONTACT · object | UNSUPPORTED_CONTENT · object | MESSAGE_HEADER · object | QUICK_REPLIES · object | WHATSAPP_TEMPLATE_METADATA · object | SOCIAL_MEDIA_METADATA · object)[]
required
- FILE
- LOCATION
- CONTACT
- UNSUPPORTED_CONTENT
- MESSAGE_HEADER
- QUICK_REPLIES
- WHATSAPP_TEMPLATE_METADATA
- SOCIAL_MEDIA_METADATA
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Available options:
INCOMING, OUTGOING Show child attributes
Show child attributes
Show child attributes
Show child attributes
Available options:
NOT_TRUNCATED, TRUNCATED, TRUNCATED_TO_MOST_RECENT_REPLY Available options:
MESSAGE Show child attributes
Show child attributes
Last modified on March 31, 2026
Was this page helpful?
⌘I