Skip to main content
Chat send uses the same contract as other channels: from, to, type, and payload. The difference: to is the conversation id, not a phone number.

Endpoint

Scope: 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

Response (200)

Image

payload.message (or payload.caption) is the caption. Missing payload.mediaUrl400.

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.
One conversation → data is the message object. Several → data is an array.

WebSocket (user app)

The socket does not use the PIV1 body. After auth:
Media on the socket: 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