Hi
Thank you for the lengthy response!
On your item a)
That's exactly our thinking to stamp on custom attributes. We have created our own schema.
You said to check these:
Media Type => this is voice whether it is VOIP or normal.
Direction => voice is also inbound.
ANI / Address format => we use the same number for voice and WA.
None of those give me a clear way of identifying.
What we did find is the protocolCallId that carries a piece of text "wacid" - which seems to be "WhatsAppCallId".
Let me know if I misunderstood.
"ani": "tel:+27#########",
"direction": "inbound",
"dnis": "tel:+27#########",
"edgeId": "2f3616da-bf1c-4704-96b4-0c1aa794b###",
"mediaType": "voice",
"protocolCallId": "outgoing:wacid.IhggQUMwNjk2QTQ0NjREN0RGODQ4N##########################################",
I still need to work through item b).
Regards
Japie
------------------------------
Japie Teunissen
Partner
------------------------------
Original Message:
Sent: 06-30-2026 09:43
From: Cesar Padilla
Subject: WhatsApp identification and external transfers
Hi Japie,
Great questions - both are very common when combining WhatsApp and voice in the same routing model π
β
a) Identifying WhatsApp "voice" vs regular PSTN calls
In Genesys Cloud, the cleanest way is to rely on conversation attributes at the Architect / routing level:
- Check
Conversation > Media Type and channel context - For WhatsApp voice (via Cloud Voice / BYOC CC scenarios), also inspect:
Direction- ANI / Address format
- External Tagging / Attributes (if you're injecting metadata upstream)
π A practical approach:
- Set a custom participant attribute in Architect at entry (e.g.
channel=whatsapp_voice) - Use that attribute throughout routing, scripting, and transfer decisions
This gives you a deterministic way to separate logic without depending only on trunks.
β
b) Preventing PSTN transfers (while keeping same agents)
You're right - trunk/site/number plans can solve this, but they impact everything and aren't always elegant.
Here are better scoped options:
1. Control at Architect (recommended)
- Before any transfer action:
- Check your channel attribute (e.g. whatsapp_voice)
- Block or reroute external transfers conditionally
Example logic:
IF channel == "whatsapp_voice" β route to internal queue / flow onlyELSE β allow external transfer
2. Agent-level control via Scripts / UI policy
- Use Agent Script + Data Actions
- Hide or disable external transfer options dynamically based on channel
π This avoids backend restrictions and gives more flexibility.
3. Use Division / Queue-based segmentation
- Same agents, but:
- Separate queues for WhatsApp vs Voice
- Apply:
- Different transfer permissions
- Different flow logic
4. Last resort: API / Trigger enforcement
If you need hard governance:
- Use Triggers (conversation or transfer events)
- Detect invalid transfers and:
π§ Recommendation
Best balance between control and simplicity:
β
Use Architect + attributes for channel identification
β
Enforce transfer rules at flow level (not trunk level)
β
Optionally complement with Agent Scripts for UX control
This avoids global telephony side effects while keeping agents unified.
------------------------------
Cesar Padilla
INDRA COLOMBIA
------------------------------