All messages (SMS, WhatsApp, chat or any custom service) live in one module, Messages. Each message has a channel. You add channels yourself and connect each one with two workflows: one that sends and one that fetches new messages. No code is needed.
1. Add a channel
- Open the Messages module and go to the picklist editor for the field Message channel.
- Add a new value, e.g.
Partner Portal. - Pick a color and an icon for the value.
The channel now appears as its own tab in the message composer on records (e.g. Projects, Tickets, Deals, Contacts, Organizations). The tab, its underline and the message bubbles use the channel's color and icon. Internal comments stay separate and are never sent.
2. Send workflow (outgoing messages)
When a user sends a message from the composer, a Messages record is created with direction Outbound. A workflow sends it to the external service.
- Module: Messages
- Trigger: when the record is first created
- Conditions: Message channel =
Partner Portal, Direction = Outbound, Message ID is empty - Task 1 – Webhook:
POSTto the service's API, e.g.https://api.example.com/messages, with a JSON body such as:
{ "conversation": "$conversation_id", "text": "$message_body", "author": "$sender_name" }
Response mapping: the id the service returns (e.g. id) → Message ID.
- Task 2 – Update fields: set Message status with this expression:
if message_id == '' then 'Failed' else 'Sent' end
Put API keys in global variables instead of directly in the workflow.
3. Poll workflow (incoming messages)
A scheduled workflow fetches new messages, e.g. every 5 minutes, and creates them as Messages related to the record.
- Module: the record the messages belong to, e.g. Projects
- Trigger: scheduled, e.g. every 5 minutes
- Task 1 – Webhook:
GETe.g.https://api.example.com/messages?conversation=$cf_external_id. Response mapping: the list of messages (e.g.messages) → a text field on the record. The whole list is stored as JSON text. - Task 2 – Create record (multiple records from JSON):
- Target module: Messages, JSON field: the text field from task 1
- Link field: Related to (
client_id), so each message is related to the record - Unique fields:
message_id,message_channel - Mappings, e.g.
message_id=id,message_body=text,sender_name=author, Message channel =Partner Portal, Direction = Inbound
Unique fields make sure a message is only created once, even if the same list is fetched again, and that your own outgoing messages coming back from the service are not imported twice.
Field names in mappings: you can write just the field name (e.g. message_id). The module name is not needed.
Good to know
- Emails stay in the Emails module.
- Check Workflow health and the webhook log on the workflow if a message is not sent or fetched.