Skip to content

Send on behalf of a user and SYSTEM messages

Post a message from your backend, for example a reminder that “Ana” sends, or a notice such as “Session moved to 9:00”. You send on behalf of a user with actor_user_id, or as a SYSTEM message with no sender.

Chat permission: messages.sendMachine scope (any of): chat:messages.sendchat:sync
  • The conversation exists and is ACTIVE (create one).
  • For a message on behalf of a user, that user is an eligible tenant member and a member of the conversation.
  • To list messages as well, the scope chat:conversations.read (or chat:sync).
  1. Choose the sender. For a message from a person, set actor_user_id. Chat stores it as sender_user_id, and records your client as sender_client_id, so your messages can be told apart. For a SYSTEM message, set message_type: 'SYSTEM' and leave actor_user_id out.

  2. Send. body is required unless the message carries attachments. Optional fields are reply_to_message_id, mentioned_user_ids and attachments.

  3. Read it back. messages.list returns the newest messages first and pages with next_cursor.

send-messages.ts
import { chat } from './guide-chat-client';
export async function sendMessages(conversationId: string): Promise<void> {
// On behalf of a user: stored with sender_user_id = coach-ana and sender_client_id = your client.
await chat.messages.send(conversationId, { body: 'See you at 9!', actor_user_id: 'coach-ana' });
// SYSTEM message: no sender, so no actor_user_id.
await chat.messages.send(conversationId, { body: 'Session moved to 9:00', message_type: 'SYSTEM' });
// Newest first. Page back with next_cursor.
const page = await chat.messages.list(conversationId, { limit: 20 });
const older = page.next_cursor ? await chat.messages.list(conversationId, { before: page.next_cursor }) : null;
console.log(page.items.length, older?.items.length ?? 0);
}
  • Your backend must name the sender: a message that is not SYSTEM needs actor_user_id, or Chat answers 400 invalid_request.
  • A user cannot send a SYSTEM message. Only a backend client can (system_message_not_allowed).
  • A body is at most 10,000 characters. A message has at most 10 attachments. A request body is at most 256 kB.
  • Mentions are kept only for active members of the conversation.
  • Your backend cannot add reactions, mark messages read or signal typing. Those are user actions.
  • Calls from your backend share one budget: 600 requests per 60 s per client.

List the conversation’s messages. The message you sent is first, with sender_user_id set to coach-ana (or null for a SYSTEM message) and sender_client_id set to your client id. Members connected to realtime receive it as a message.created event.

Symptom Cause and fix
422 conversation_archived The conversation is archived. Reactivate it if the relationship resumes.
422 actor_not_member actor_user_id is not a member of the conversation. Add the user first, or send as a member.
422 target_user_not_eligible actor_user_id is not an active tenant member with access to your application.
400 body_too_long The body is over the limit. Shorten or split it.
422 invalid_reply reply_to_message_id is not a message of this conversation.
403 insufficient_scope The client lacks chat:messages.send.