Endpoint
chat:messages:send. Each send costs 1 credit (CHAT_MESSAGE).
POST /v1/chat/conversations/{id}/messages still works: conversation id is in the URL and the body is the same (type + payload), without to.
Fields
With a member JWT, do not send
senderExternalUserId: the sender is the token.
The response uses uppercase type (TEXT, IMAGE, AUDIO, FILE).
Text
Image
payload.message (or payload.caption) is the caption. Missing payload.mediaUrl → 400.
Audio
File
Reply to a message
replyToId can also go in payload.replyToId.
Member JWT
The app authenticated with the JWT does not send an API Key.Several conversations in one request
to accepts a list. Each id is a conversation in the same workspace.
data is the message object. Several → data is an array.
WebSocket (user app)
The socket does not use the PIV1 body. Afterauth:
messageType (image | audio | file) and HTTPS mediaUrl, or payload.type / payload.mediaUrl. The frame type stays message.send.
REST (backend) → POST /v1/chat/messages. Realtime in the app → WebSocket.
Type outside the app ceiling or the room switch → 403 CHAT_CAPABILITY_DISABLED. DIRECT with a user block → 403 CHAT_USER_BLOCKED. Details: Capabilities and blocking.
On WebSocket, message.send also accepts type (text | image | audio | file) and mediaUrl (HTTPS). recording.start only works if the room has audio on.
Next steps
- User and agent: who shows up as sender
- Webhook events
- API Key scopes

