Direct Messages

Send a direct message to a single user's private chat, delivered by a bot user. The 1:1 room between the bot and the user is created on first use and reused afterwards, so repeated messages land in the same conversation. Resolve the target user first via the Users endpoints — for example, match by email.

This is the authenticated equivalent of a direct_message incoming webhook: use this endpoint for one-off sends from your backend, and incoming webhooks when you want a standing per-user URL.

Required scope: write:chat_messages

Endpoints

POST
/api/open/v1/users/{id}/messages

Send a direct message to the user

POST
/api/open/v1/chat-messages/{id}/pin

Pin a bot-sent message at the top of its room

DELETE
/api/open/v1/chat-messages/{id}/pin

Remove the pin

Send a message

curl -X POST https://customer.monotree.com/api/open/v1/users/4012/messages \
  -H "Authorization: Bearer mono_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "bot_user_id": 873,
    "text": "Hi Alex, Sam has replied to your thread. Follow up before Thursday: https://example.com/threads/123"
  }'
FieldTypeNotes
bot_user_idintegerRequired. The bot user that sends the message. A non-bot id returns 422.
textstringRequired. The message body.
mediaarrayOptional. { url, type } pairs — same rules as incoming webhook media (same type, max 10, publicly reachable URLs).

The target user ({id} in the path) must be a regular, registered user; a kiosk, bot, or unregistered id returns 404.

Response

{
  "data": {
    "id": 5512,
    "room_id": 240,
    "text": "Hi Alex, Sam has replied to your thread. Follow up before Thursday: https://example.com/threads/123",
    "bot_user_id": 873,
    "pinned_at": null,
    "pinned_until": null,
    "created_at": "2026-06-13T10:00:00+00:00"
  }
}

pinned_at and pinned_until are always present and null unless the message is currently pinned (see below).

Pin a message

Pin one of the bot's messages at the top of its room. Every member sees it above the conversation in the app and the CMS until it is unpinned or lapses. Use the id returned when the message was sent.

curl -X POST https://customer.monotree.com/api/open/v1/chat-messages/5512/pin \
  -H "Authorization: Bearer mono_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{ "pinned_until": "2026-09-01T08:00:00+00:00" }'
FieldTypeNotes
pinned_untildatetimeOptional. ISO 8601. Omit it for a pin that stays until removed; when given it must be in the future, otherwise 422.

Remove the pin again with DELETE /chat-messages/{id}/pin (no body). Unpinning a message that isn't pinned is a no-op.

Both calls return the message in the same shape as above, with pinned_at (and pinned_until when set) filled in while the pin is active:

{
  "data": {
    "id": 5512,
    "room_id": 240,
    "text": "Hi Alex, Sam has replied to your thread. Follow up before Thursday: https://example.com/threads/123",
    "bot_user_id": 873,
    "pinned_at": "2026-08-26T09:30:00+00:00",
    "pinned_until": "2026-09-01T08:00:00+00:00",
    "created_at": "2026-06-13T10:00:00+00:00"
  }
}
  • Only messages authored by a bot user can be pinned — direct messages always are, incoming webhook messages are when the webhook posts as its bot. Any other message id returns 404.
  • A room holds one pinned message. Pinning another message in the same room replaces the current pin.
  • The pin is attributed to the sending bot, so the clients show it as pinned by the bot.