message.comDevelopers

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.

Notes are their own database table, not a message with a special kind. They don't appear in the Messages list at all.

List notes on a conversation

GET/api/v1/conversations/:id/notesAuth: Bearer

Not paginated. Returns every note on the conversation, newest first.

Post a note

POST/api/v1/conversations/:id/notesAuth: Bearer

Append-only: every call adds a new note row, authored by the caller. This is the endpoint for free-form, one-comment-per-agent collaboration notes.

FieldTypeDescription
bodyrequiredstringNote body, 1 to 10,000 characters.

There is no mentions field and no @-mention parsing. A note is plain text; mentioning a teammate does not notify them.

Body
{ "body": "Customer is a Series A founder; escalate to lead." }

Code samples

cURL
curl -X POST 'https://app.message.com/api/v1/conversations/:id/notes' \
  -H 'Authorization: Bearer YOUR_WORKSPACE_JWT' \
  -H 'Content-Type: application/json' \
  -d '{"body":"Customer is a Series A founder"}'
JavaScript
const res = await fetch(`https://app.message.com/api/v1/conversations/${conversationId}/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();
Python
import requests
r = requests.post(
    f"https://app.message.com/api/v1/conversations/{conversation_id}/notes",
    headers={"Authorization": f"Bearer {token}"},
    json={"body": "Customer is a Series A founder"},
)
note = r.json()["note"]
Ruby
require "net/http"
require "json"
uri = URI("https://app.message.com/api/v1/conversations/#{conversation_id}/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)["note"]
PHP
<?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/{$conversationId}/notes", false, $ctx), true)["note"];
200 OK
{
  "notes": [
    {
      "id": "uuid",
      "conversationId": "uuid",
      "visitorId": "uuid",
      "authorAgentId": "uuid",
      "authorName": "Alex Lee",
      "authorAvatarUrl": null,
      "body": "Customer is a Series A founder; escalate to lead.",
      "createdAt": "2026-05-13T15:30:00Z",
      "updatedAt": "2026-05-13T15:30:00Z"
    }
  ]
}

Your working note (upsert)

PATCH/api/v1/conversations/:id/notesAuth: Bearer

Not a general note editor. This is a single-textarea "working memory" surface, built for the call view: it always targets the calling agent's own most recent note on this conversation, not a note chosen by ID.

  • Empty or omitted body: deletes the agent's existing note on this conversation, if any.
  • Non-empty body, agent already has a note here: updates it in place.
  • Non-empty body, agent has no note yet: creates one.

There is no PATCH by note ID, and no editedAt field: an updated note just carries a newer updatedAt.

Delete a note

DELETE/api/v1/notes/:idAuth: Bearer

Hard delete, by note ID. Author or admin only. No soft-delete, no [note removed] tombstone: the row is gone.

Errors

CodeWhen
400 invalid_bodyEmpty body on POST, or body too long (10K chars max).
404 not_foundConversation or note does not exist, or is outside the agent's department scope.

Common pitfalls

  • Leaking customer-sensitive info in notes. Notes are visible to every agent in scope. Avoid full credit-card numbers, SSNs, full passwords.
  • Expecting @-mentions to notify anyone. They don't. There is no mention parsing or notification on this resource.
  • Calling PATCH expecting to edit a specific note by ID. It doesn't take a note ID at all; it always targets the caller's own latest note on the conversation. Use POST for a new, separate note.