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.
Prerequisites
Section titled “Prerequisites”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(orchat:sync).
-
Choose the sender. For a message from a person, set
actor_user_id. Chat stores it assender_user_id, and records your client assender_client_id, so your messages can be told apart. For a SYSTEM message, setmessage_type: 'SYSTEM'and leaveactor_user_idout. -
Send.
bodyis required unless the message carries attachments. Optional fields arereply_to_message_id,mentioned_user_idsandattachments. -
Read it back.
messages.listreturns the newest messages first and pages withnext_cursor.
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);}curl -s -X POST "$CHAT_API_URL/tenants/$CCS_TENANT_ID/applications/$CCS_APPLICATION_ID/conversations/$CONVERSATION_ID/messages" \ -H "Authorization: Bearer $CHAT_MACHINE_TOKEN" \ -H "Content-Type: application/json" \ -d '{"body":"Session moved to 9:00","message_type":"SYSTEM"}'{ "message_id": "0d9e6a52-8b0c-4c47-b1f2-5c9a2c1d7e33", "message_type": "SYSTEM", "sender_user_id": null, "sender_client_id": "2f1c9e5a-7f4d-4f0e-8c35-9b1a3d6e4c21", "body": "Session moved to 9:00", "status": "ACTIVE"}- Your backend must name the sender: a message that is not SYSTEM needs
actor_user_id, or Chat answers 400invalid_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.
Verify
Section titled “Verify”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.
Troubleshooting
Section titled “Troubleshooting”| 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. |