Message codes from GoHighLevel
When you send an outbound message from GoHighLevel that should go to WhatsApp through WhatGHL, you can add special codes (usually starting with #) in the message body. WhatGHL reads them, changes how the message is sent, and removes them from what the contact sees (except where noted).
These codes are not a GHL feature—they are interpreted by WhatGHL on the path GHL → WhatsApp.
Composer (placeholder)
Placeholder — replace with a screenshot of the GHL composer where codes are typed.
Video walkthrough (placeholder)
Placeholder — short video showing #WH, #POLL, #voice, etc.
Use these in the conversation message (or automation that posts the same kind of outbound body) for a contact that has a phone number and is linked to your WhatsApp session routing.
Order of processing
WhatGHL applies rules in a fixed order. When combining codes, follow this sequence from the start of the message:
| Step | What is read | Notes |
|---|---|---|
| 1 | #WH + number | Session by priority (e.g. #WH1). Can appear as a token in the message; it is removed before the next steps. |
| 2 | #NOPRESENCE| | Must be right at the current start (after step 1). Enables burst-style sending without presence simulation for that message. |
| 3 | #MSGALL| | Must be at the current start. For group chats, mentions everyone (@all). See WhatsApp group management. |
| 4 | #POLL / #POLL:MULTIPLE | Message must start with #POLL (after steps 1–3). |
| 5 | #EVENT| | Same idea: must start with #EVENT if there is no poll. |
| 6 | #BUTTON or #BUTTONS | Interactive reply buttons (up to 3). |
| 7 | #LIST| | Interactive list message. |
| 8 | #CONTACT| | vCard-style contact card. Can appear anywhere in the text, but is only handled if the message is not already a poll, event, buttons, or list. |
Media-only extras (video note shape) are handled when there is an attachment; see Circle / video note below.
If you use the wrong order (for example #MSGALL| before #NOPRESENCE|), the second prefix may no longer be at the “start” and will not be detected.
Routing and sessions
#WH + priority number
- Example:
#WH2 Hello, this is support. - Effect: Sends through the WhatsApp session whose priority matches that number (e.g.
2), among sessions in WORKING state for the sub-account. - Removed from text: Yes (
#WH2is stripped).
If no session matches, the message may fail or log an error depending on your setup. Configure priorities in WhatsApp numbers and sessions.
If you omit #WH, WhatGHL walks your sub-account outbound session routing rules in order (see below). The default order is: #WH code in the message (if present), phone digits in contact tags matched to a session, GHL user who sent the message (when the webhook exposes their user id), user assigned to the contact, then the first WORKING session by session priority, then the same fallback again as the final step. You can reorder and disable rules (except the last fallback stays last) under Sub-account → Connection → Outbound session selection.
Rule ids (for API / support): wh_code, contact_tag_phone, ghl_message_sender_phone, contact_assigned_user_phone, default_working_session, any_working_session. Until per-session “default” flags exist, the last two behave the same (first WORKING session by ascending priority).
#|id prefixIf text at the very start of the message still looks like #|id + digits + space (from old templates), WhatGHL strips it so it is not sent to the contact, but it does not select a session. Use #WH for explicit routing.
Sending modes
#NOPRESENCE|
- Example:
#NOPRESENCE|Your code is 482910. - Effect: Sends that outbound message without the usual “presence” behaviour (useful for fast or scripted sends).
- Removed from text: Yes (including the
|).
Put #NOPRESENCE| before #MSGALL| if you use both.
#MSGALL|
- Example:
#MSGALL|Team: meeting at 10:00. - Effect: In WhatsApp group conversations, triggers a mention of everyone; the prefix is removed from the visible text.
- Removed from text: Yes.
Interactive messages
Polls: #POLL and #POLL:MULTIPLE
- Single choice:
#POLL|Question|Option 1|Option 2|Option 3 - Multiple choice:
#POLL:MULTIPLE|Question|Opt A|Opt B|Opt C
The line must begin with #POLL or #POLL:MULTIPLE (after routing / #NOPRESENCE / #MSGALL if you use them). Options are separated by |. Up to 12 options are used.
The question becomes the poll title; the options are what recipients tap.
Calendar event: #EVENT|
Format (fields separated by |):
#EVENT|Event name|START_UNIX_TIMESTAMP|Description|Location|true_or_false
- START_UNIX_TIMESTAMP: Seconds since Unix epoch for the event start.
- Description / Location: Can be empty but placeholders are still separated by
|. - Last field:
trueorfalsefor allowing extra guests (when supported by the channel).
The whole #EVENT|… block is removed from the normal text; the client receives an event message.
Reply buttons: #BUTTON or #BUTTONS
- Pattern:
#BUTTON|Visible text|id*Title 1|id*Title 2|id*Title 3 - Also accepted:
#BUTTONS|(same idea).
Visible text is the message body. After the third |, each button is Title*optional_id (split by *). Up to 3 buttons. Titles are limited in length (20 characters enforced server-side).
List: #LIST|
Format:
#LIST|Body text|Button label|Section title|Row title*description*rowId||Next section|...
- Sections can be separated with
||. - Rows use
title*description*id(description and id optional in the parser). - Maximum 10 rows total across sections.
Contact card: #CONTACT|
- Example:
Thanks for reaching out. #CONTACT|Jane Doe|5215512345678 - Effect: Sends a contact card with the given name and phone (digits are normalized).
- Removed from text: The
#CONTACT|Name|Phonesegment is removed from the visible message.
Not processed if the message was already treated as poll, event, buttons, or list.
Circle / PTV: the #CIRCLE code
When the GHL message includes a video attachment and the body contains #CIRCLE (case-insensitive), WhatGHL’s webhook handling:
- Detects
#CIRCLEin the message text. - Sends the video as a PTV (“video note” / circle-style video) when the integration supports it.
- Strips from the caption tokens that look like
#CIRCLEimmediately followed by digits (e.g.#CIRCLE1,#CIRCLE12), using spacing rules—so those tokens are not sent as visible caption text.
If you use #CIRCLE without trailing digits, the media type may still switch to PTV, but the literal #CIRCLE might remain in the caption. Prefer a form like #CIRCLE1 when you want a clean caption after processing.
The #CIRCLE / #CIRCLE + digits cleanup in the current server path is tied to outbound video handling. It is not a general “remove from any SMS body” rule for plain text without video.
Internal-only: #note
If the message body matches internal GHL notes that contain the token #note as a word boundary match (case-insensitive, e.g. #note or … #note …), WhatGHL skips forwarding that payload GHL → WhatsApp as a normal outbound message. Use this so internal team notes in the thread stay in GHL only.
Translation (inline): #traslate
Outbound messages to WhatsApp can force translation with a hashtag in the composer. Type the spelling #traslate exactly (not #translate).
| Code | Use in GHL |
|---|---|
#traslate | When outbound translation is enabled for the sub-account and AI (provider + key + model) is configured, forces translation of that message. The target language comes from the sub-account’s outbound translation settings. |
#traslate:xx | Same as above, but xx sets the target language for this message: es, en, pt, fr, de, it. The hashtag (and optional :xx) is removed from the text that is sent to WhatsApp. |
Requirements (typical): translation toggles on, valid outbound translation language, and AI config present. If the hashtag is missing, this inline trigger does not apply for that send (other translation rules may still apply depending on settings).
Text-to-speech: #voice
To send spoken audio instead of plain text on WhatsApp, include #voice in the message body. This is separate from #traslate (translation does not by itself generate audio).
| Code | Use in GHL |
|---|---|
#voice | If TTS is enabled for the sub-account, there is no attachment and no interactive payload (buttons, list, poll, event, link preview), and TTS (e.g. ElevenLabs) is configured, the system generates an MP3, sends it as audio, and removes #voice from the text used for synthesis. |
#voice:xx | Same as #voice, but xx selects the voice / language route for TTS. Besides the core language codes es, en, pt, fr, de, it, WhatGHL supports two-letter Latin American country codes (e.g. mx, ar, co, br) when configured under Sub-account → Voice → Voices by language. If you omit :xx, the effective language comes from translation / sub-account defaults. |
WhatGHL looks for #voice in the original message body (before translation removes hashtags), so the trigger still works if the translated text no longer contains it.
Audio generated for TTS must be reachable over the internet so WhatsApp can deliver it to the contact. If audio never plays, ask your agency or support to review the setup.
Configure voice and translation under Sub-account settings tabs (Voice (TTS) and AI & Translation).
Quick reference
| Code | Purpose |
|---|---|
#note | Do not send to WhatsApp (internal note; GHL → WhatsApp forwarding skipped). |
#WHN | Route via session priority N. |
#NOPRESENCE| | Send without presence simulation; strip prefix. |
#MSGALL| | Group: mention all; strip prefix. |
#POLL|… / #POLL:MULTIPLE|… | WhatsApp poll. |
#EVENT|… | WhatsApp calendar-style event. |
#BUTTON(S)|… | Up to 3 reply buttons. |
#LIST|… | List message. |
#CONTACT|Name|Phone | Contact card. |
#CIRCLE / #CIRCLE + digits | Video outbound: PTV; webhook strips #CIRCLE+digits from caption when present. |
#traslate / #traslate:xx | WhatsApp outbound: force translation; strip hashtag; :xx = target language (es/en/…/it). |
#voice / #voice:xx | WhatsApp outbound: TTS MP3; strip marker; :xx = language or regional voice key. |
For many copy-paste examples (especially polls), your team can also use the in-repo examples file app/docs/interactive-messages-examples.md as a cookbook.
Related docs
- WhatsApp numbers and sessions — priorities and sessions.
- WhatsApp group management — groups tab and
#MSGALL|. - GoHighLevel integration overview — connecting GHL and sub-accounts.
- Sub-account settings tabs — AI & Translation (used with
#traslate) and Voice (TTS) (used with#voice). - Features overview — proxy, outbound session routing (
#WH), interactive messages, TTS, and translation guides.