Notes Live
Internal notes are private commentary on a conversation, visible only to agents in scope. They live alongside visitor and agent messages in the timeline, but the visitor never sees them. Used for context, escalation handoffs, and audit trail.
Under the hood, a note is a message with kind: "internal_note". The endpoints here exist as convenience wrappers; you can also use /messages with kind: internal_note and get the same result.
List notes on a conversation
Cursor-paginated. Notes ordered newest first.
Post a note
| Field | Type | Description |
|---|---|---|
| bodyrequired | string | Note body. Supports @mentions of agent IDs (resolved as the names in the UI). |
| mentionsoptional | uuid[] | Explicit mention list. If absent, we parse @-mentions from body. |
{
"body": "Customer is a Series A founder; escalate to lead. @lead-uuid"
}Code samples
curl -X POST 'https://app.message.com/api/v1/conversations/abc/notes' \
-H 'Authorization: Bearer YOUR_WORKSPACE_JWT' \
-H 'Content-Type: application/json' \
-d '{"body":"Customer is a Series A founder"}'const res = await fetch('https://app.message.com/api/v1/conversations/abc/notes', {
method: 'POST',
headers: {
Authorization: 'Bearer ' + token,
'Content-Type': 'application/json'
},
body: JSON.stringify({ body: 'Customer is a Series A founder' })
});
const note = await res.json();import requests
r = requests.post(
"https://app.message.com/api/v1/conversations/abc/notes",
headers={"Authorization": f"Bearer {token}"},
json={"body": "Customer is a Series A founder"},
)
note = r.json()require "net/http"
require "json"
uri = URI("https://app.message.com/api/v1/conversations/abc/notes")
req = Net::HTTP::Post.new(uri, {"Authorization" => "Bearer #{token}", "Content-Type" => "application/json"})
req.body = { body: "Customer is a Series A founder" }.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
note = JSON.parse(res.body)<?php
$ctx = stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer $token\r\nContent-Type: application/json",
"content" => json_encode(["body" => "Customer is a Series A founder"])
],
]);
$note = json_decode(file_get_contents("https://app.message.com/api/v1/conversations/abc/notes", false, $ctx), true);{
"id": "uuid",
"conversationId": "uuid",
"agentId": "uuid",
"body": "Customer is a Series A founder; escalate to lead.",
"mentions": ["uuid-of-mentioned-agent"],
"editedAt": null,
"createdAt": "2026-05-13T15:30:00Z"
}Edit a note
Edits the body. No 5-minute window; agents can edit their own notes any time for audit cleanup. Sets editedAt.
Delete a note
Soft-deletes the note. Admins see the original body in the audit log; other agents see [note removed].
Mentions and notifications
Mentioning an agent via @<agentId> in the body, or passing mentions: [agentId], pings that agent. The notification appears in their dashboard and (if configured) by email. Mentions on closed conversations do nothing.
Errors
| Code | When |
|---|---|
400 invalid_body | Empty body or body too long (10K chars max). |
403 forbidden | Agent lacks scope on the conversation. |
404 not_found | Conversation or note does not exist. |
Common pitfalls
- Leaking customer-sensitive info in notes. Notes are visible to every agent in scope. Avoid full credit-card numbers, SSNs, full passwords.
- Mentioning agents in scope-limited conversations. If the mentioned agent does not have access to the channel or department, they receive the notification but cannot open the conversation.
- Editing a note to revise a wrong call. Better to add a new note explaining the correction. Edits hide the original from non-admins, which can disguise the audit trail.