curl --request POST \
--url https://api.initdesk.com/organizations/{organization_id}/tickets/{ticket_id}/messages/ \
--header 'Content-Type: application/json' \
--header 'X-Initdesk-Token: <api-key>' \
--data '
{
"next_assignee_id": 123,
"content": "<string>",
"content_html": "<string>",
"is_visible_to_customer": true,
"external_recipient_emails": [
"jsmith@example.com"
],
"bcc_recipient_emails": [
"jsmith@example.com"
],
"attachment_ids": [
"3c90c3cc-0d44-4b50-8888-8dd25736052a"
]
}
'import requests
url = "https://api.initdesk.com/organizations/{organization_id}/tickets/{ticket_id}/messages/"
payload = {
"next_assignee_id": 123,
"content": "<string>",
"content_html": "<string>",
"is_visible_to_customer": True,
"external_recipient_emails": ["jsmith@example.com"],
"bcc_recipient_emails": ["jsmith@example.com"],
"attachment_ids": ["3c90c3cc-0d44-4b50-8888-8dd25736052a"]
}
headers = {
"X-Initdesk-Token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-Initdesk-Token': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
next_assignee_id: 123,
content: '<string>',
content_html: '<string>',
is_visible_to_customer: true,
external_recipient_emails: ['jsmith@example.com'],
bcc_recipient_emails: ['jsmith@example.com'],
attachment_ids: ['3c90c3cc-0d44-4b50-8888-8dd25736052a']
})
};
fetch('https://api.initdesk.com/organizations/{organization_id}/tickets/{ticket_id}/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.initdesk.com/organizations/{organization_id}/tickets/{ticket_id}/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([
'next_assignee_id' => 123,
'content' => '<string>',
'content_html' => '<string>',
'is_visible_to_customer' => true,
'external_recipient_emails' => [
'jsmith@example.com'
],
'bcc_recipient_emails' => [
'jsmith@example.com'
],
'attachment_ids' => [
'3c90c3cc-0d44-4b50-8888-8dd25736052a'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Initdesk-Token: <api-key>"
],
]);
$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.initdesk.com/organizations/{organization_id}/tickets/{ticket_id}/messages/"
payload := strings.NewReader("{\n \"next_assignee_id\": 123,\n \"content\": \"<string>\",\n \"content_html\": \"<string>\",\n \"is_visible_to_customer\": true,\n \"external_recipient_emails\": [\n \"jsmith@example.com\"\n ],\n \"bcc_recipient_emails\": [\n \"jsmith@example.com\"\n ],\n \"attachment_ids\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Initdesk-Token", "<api-key>")
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.initdesk.com/organizations/{organization_id}/tickets/{ticket_id}/messages/")
.header("X-Initdesk-Token", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"next_assignee_id\": 123,\n \"content\": \"<string>\",\n \"content_html\": \"<string>\",\n \"is_visible_to_customer\": true,\n \"external_recipient_emails\": [\n \"jsmith@example.com\"\n ],\n \"bcc_recipient_emails\": [\n \"jsmith@example.com\"\n ],\n \"attachment_ids\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.initdesk.com/organizations/{organization_id}/tickets/{ticket_id}/messages/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Initdesk-Token"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"next_assignee_id\": 123,\n \"content\": \"<string>\",\n \"content_html\": \"<string>\",\n \"is_visible_to_customer\": true,\n \"external_recipient_emails\": [\n \"jsmith@example.com\"\n ],\n \"bcc_recipient_emails\": [\n \"jsmith@example.com\"\n ],\n \"attachment_ids\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": 123,
"author": {
"id": 123,
"email": "jsmith@example.com",
"profile_picture_url": "<string>",
"name": "<string>"
},
"role": "customer",
"sender": {
"email": "jsmith@example.com",
"name": "<string>",
"user_id": 123,
"profile_picture": "<string>"
},
"next_assignee": {
"id": 123,
"email": "jsmith@example.com",
"profile_picture_url": "<string>",
"name": "<string>"
},
"next_priority": "not_set",
"kind": "text",
"has_raw_content": true,
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"delivery_status": "pending",
"sent_at": "2023-11-07T05:31:56Z",
"read_at": "2023-11-07T05:31:56Z",
"failed_at": "2023-11-07T05:31:56Z",
"delivery_failure_reason": "<string>",
"merged_from_ticket": {
"id": 123,
"public_id": "<string>",
"subject": "<string>"
},
"attachments": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"size": 123,
"content_type": "<string>",
"download_url": "<string>"
}
],
"next_action": "",
"content": "<string>",
"content_html": "<string>",
"is_visible_to_customer": true,
"external_recipient_emails": [
"jsmith@example.com"
],
"bcc_recipient_emails": [
"jsmith@example.com"
]
}{
"detail": "<string>",
"code": "whatsapp_window_closed_attachments_only"
}Reply or create internal note
Add a reply or internal note to the ticket. For customer-visible replies, optional external_recipient_emails sets CC recipients for that message; omit or null to reuse CC recipients from the previous customer-visible message or from ticket creation. Internal notes ignore this field. Optional attachment_ids claims files previously uploaded via POST .../tickets/{ticket_id}/attachments/ (see Tickets tag for the upload flow). A channel may reject a customer-visible reply with 400 {detail, code}. WhatsApp uses whatsapp_window_closed_no_template and whatsapp_window_closed_attachments_only.
curl --request POST \
--url https://api.initdesk.com/organizations/{organization_id}/tickets/{ticket_id}/messages/ \
--header 'Content-Type: application/json' \
--header 'X-Initdesk-Token: <api-key>' \
--data '
{
"next_assignee_id": 123,
"content": "<string>",
"content_html": "<string>",
"is_visible_to_customer": true,
"external_recipient_emails": [
"jsmith@example.com"
],
"bcc_recipient_emails": [
"jsmith@example.com"
],
"attachment_ids": [
"3c90c3cc-0d44-4b50-8888-8dd25736052a"
]
}
'import requests
url = "https://api.initdesk.com/organizations/{organization_id}/tickets/{ticket_id}/messages/"
payload = {
"next_assignee_id": 123,
"content": "<string>",
"content_html": "<string>",
"is_visible_to_customer": True,
"external_recipient_emails": ["jsmith@example.com"],
"bcc_recipient_emails": ["jsmith@example.com"],
"attachment_ids": ["3c90c3cc-0d44-4b50-8888-8dd25736052a"]
}
headers = {
"X-Initdesk-Token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-Initdesk-Token': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
next_assignee_id: 123,
content: '<string>',
content_html: '<string>',
is_visible_to_customer: true,
external_recipient_emails: ['jsmith@example.com'],
bcc_recipient_emails: ['jsmith@example.com'],
attachment_ids: ['3c90c3cc-0d44-4b50-8888-8dd25736052a']
})
};
fetch('https://api.initdesk.com/organizations/{organization_id}/tickets/{ticket_id}/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.initdesk.com/organizations/{organization_id}/tickets/{ticket_id}/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([
'next_assignee_id' => 123,
'content' => '<string>',
'content_html' => '<string>',
'is_visible_to_customer' => true,
'external_recipient_emails' => [
'jsmith@example.com'
],
'bcc_recipient_emails' => [
'jsmith@example.com'
],
'attachment_ids' => [
'3c90c3cc-0d44-4b50-8888-8dd25736052a'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Initdesk-Token: <api-key>"
],
]);
$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.initdesk.com/organizations/{organization_id}/tickets/{ticket_id}/messages/"
payload := strings.NewReader("{\n \"next_assignee_id\": 123,\n \"content\": \"<string>\",\n \"content_html\": \"<string>\",\n \"is_visible_to_customer\": true,\n \"external_recipient_emails\": [\n \"jsmith@example.com\"\n ],\n \"bcc_recipient_emails\": [\n \"jsmith@example.com\"\n ],\n \"attachment_ids\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Initdesk-Token", "<api-key>")
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.initdesk.com/organizations/{organization_id}/tickets/{ticket_id}/messages/")
.header("X-Initdesk-Token", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"next_assignee_id\": 123,\n \"content\": \"<string>\",\n \"content_html\": \"<string>\",\n \"is_visible_to_customer\": true,\n \"external_recipient_emails\": [\n \"jsmith@example.com\"\n ],\n \"bcc_recipient_emails\": [\n \"jsmith@example.com\"\n ],\n \"attachment_ids\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.initdesk.com/organizations/{organization_id}/tickets/{ticket_id}/messages/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Initdesk-Token"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"next_assignee_id\": 123,\n \"content\": \"<string>\",\n \"content_html\": \"<string>\",\n \"is_visible_to_customer\": true,\n \"external_recipient_emails\": [\n \"jsmith@example.com\"\n ],\n \"bcc_recipient_emails\": [\n \"jsmith@example.com\"\n ],\n \"attachment_ids\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": 123,
"author": {
"id": 123,
"email": "jsmith@example.com",
"profile_picture_url": "<string>",
"name": "<string>"
},
"role": "customer",
"sender": {
"email": "jsmith@example.com",
"name": "<string>",
"user_id": 123,
"profile_picture": "<string>"
},
"next_assignee": {
"id": 123,
"email": "jsmith@example.com",
"profile_picture_url": "<string>",
"name": "<string>"
},
"next_priority": "not_set",
"kind": "text",
"has_raw_content": true,
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"delivery_status": "pending",
"sent_at": "2023-11-07T05:31:56Z",
"read_at": "2023-11-07T05:31:56Z",
"failed_at": "2023-11-07T05:31:56Z",
"delivery_failure_reason": "<string>",
"merged_from_ticket": {
"id": 123,
"public_id": "<string>",
"subject": "<string>"
},
"attachments": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"size": 123,
"content_type": "<string>",
"download_url": "<string>"
}
],
"next_action": "",
"content": "<string>",
"content_html": "<string>",
"is_visible_to_customer": true,
"external_recipient_emails": [
"jsmith@example.com"
],
"bcc_recipient_emails": [
"jsmith@example.com"
]
}{
"detail": "<string>",
"code": "whatsapp_window_closed_attachments_only"
}Authorizations
Body
- `` - (none)
close_and_mark_resolved- Close and Mark Resolvedclose_and_mark_invalid- Close and Mark Invalidclose_and_mark_customer_inactivity- Close and Mark Customer Inactivityreopen_waiting_customer- Reopen Waiting Customerreopen_waiting_associate- Reopen Waiting Associateclose_and_mark_other- Close and Mark Otherreport_spam- Report Spamremove_from_spam- Remove from Spam
, close_and_mark_resolved, close_and_mark_invalid, close_and_mark_customer_inactivity, reopen_waiting_customer, reopen_waiting_associate, close_and_mark_other, report_spam, remove_from_spam On create with CC email routing: for customer-visible messages, a list (empty or not) sets this message's external CC snapshot only; the ticket row is not updated. Omitted or null copies the last customer-visible message's snapshot, or the ticket's creation-time list if none. Internal messages (not visible to customer) always store an empty list; this field is ignored for them. The ticket requester is always kept when a list is sent. On read: snapshot stored on this message.
1On create with CC email routing: for customer-visible messages, optional BCC list for this send only (SMTP Bcc). Omitted, null, or empty means no BCC — prior message BCC is never carried forward. Internal messages and orgs without CC routing always store an empty list. Cannot overlap the requester (To) or this message's CC list. On read: audit snapshot.
1List of attachment IDs to associate with this message.
Response
Legacy author object; may be deprecated for display in a future API version in favor of sender.
Show child attributes
Show child attributes
customer- Customercc- Ccassociate- Associatesystem- System
customer, cc, associate, system Who sent the message. Shape is one of the MessageSender variants in the schema; use top-level role to select it. Each variant includes nullable profile_picture for that author only. null when role is system, or for associate without author.
- Option 1
- Option 2
- Option 3
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Priority this message sets on the ticket. Null means no change.
not_set- No prioritylow- Lowmedium- Mediumhigh- Highurgent- Urgent
not_set, low, medium, high, urgent, null Message body kind. text or audio. audio: transcript lives in content; empty content means pending STT; content_html stays empty.
text- Textaudio- Audio
text, audio True when message raw content is available for see-entire-message.
Consolidated outbound delivery state. Null when not applicable (inbound, internal notes, or pre-rollout messages).
pending- Pendingsent- Sentread- Readfailed- Failed
pending, sent, read, failed, null When the message was first handed to the delivery platform (email, WhatsApp, or Telegram). Null until sent or read.
When a read receipt was observed. Null until read; may be best-effort depending on channel.
When delivery permanently failed. Null until failed.
Short diagnostic for failed delivery. Content is unstable and must not be branched on in client code.
Ticket this message was originally created on, when a merge moved it here. Null for messages created on this ticket.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
- `` - (none)
close_and_mark_resolved- Close and Mark Resolvedclose_and_mark_invalid- Close and Mark Invalidclose_and_mark_customer_inactivity- Close and Mark Customer Inactivityreopen_waiting_customer- Reopen Waiting Customerreopen_waiting_associate- Reopen Waiting Associateclose_and_mark_other- Close and Mark Otherreport_spam- Report Spamremove_from_spam- Remove from Spam
, close_and_mark_resolved, close_and_mark_invalid, close_and_mark_customer_inactivity, reopen_waiting_customer, reopen_waiting_associate, close_and_mark_other, report_spam, remove_from_spam On create with CC email routing: for customer-visible messages, a list (empty or not) sets this message's external CC snapshot only; the ticket row is not updated. Omitted or null copies the last customer-visible message's snapshot, or the ticket's creation-time list if none. Internal messages (not visible to customer) always store an empty list; this field is ignored for them. The ticket requester is always kept when a list is sent. On read: snapshot stored on this message.
On create with CC email routing: for customer-visible messages, optional BCC list for this send only (SMTP Bcc). Omitted, null, or empty means no BCC — prior message BCC is never carried forward. Internal messages and orgs without CC routing always store an empty list. Cannot overlap the requester (To) or this message's CC list. On read: audit snapshot.
Was this page helpful?

