Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.mavera.io/llms.txt

Use this file to discover all available pages before exploring further.

Scenario

WhatsApp Business messages carry a different conversational register than SMS — longer messages, richer context, and more emotional language. This job pulls WhatsApp messages from Twilio’s Messages API, creates personas representing different customer segments, then runs each persona through Mavera Speak to generate insights about how each segment perceives your brand based on real WhatsApp interactions. Flow: Twilio GET /Messages.json (filter WhatsApp) → Cluster by theme → Mavera POST /personasPOST /speak → Persona insight report

Code

import os, requests, time

TW_SID = os.environ["TWILIO_ACCOUNT_SID"]
TW_TOKEN = os.environ["TWILIO_AUTH_TOKEN"]
TW_AUTH = (TW_SID, TW_TOKEN)
TW_BASE = f"https://api.twilio.com/2010-04-01/Accounts/{TW_SID}"
MV = os.environ["MAVERA_API_KEY"]
MV_BASE = "https://app.mavera.io/api/v1"
MV_H = {"Authorization": f"Bearer {MV}", "Content-Type": "application/json"}

# 1. Fetch WhatsApp messages
r = requests.get(f"{TW_BASE}/Messages.json", auth=TW_AUTH, params={
    "PageSize": 200, "To": "whatsapp:+14155238886",
})
r.raise_for_status()
all_msgs = r.json().get("messages", [])

wa_inbound = [m for m in all_msgs if m.get("direction") == "inbound"
              and "whatsapp:" in m.get("from", "")]
wa_outbound = [m for m in all_msgs if m.get("direction") == "outbound-api"]

print(f"WhatsApp input: {len(wa_inbound)} inbound, {len(wa_outbound)} outbound")

# 2. Build conversation corpus
inbound_corpus = "\n".join(
    f"- [{m.get('date_sent','')[:10]}] {m.get('body','')[:300]}"
    for m in wa_inbound[:80]
)

# 3. Theme extraction via Mave
themes = requests.post(f"{MV_BASE}/mave/chat", headers=MV_H, json={
    "message": f"Analyze {len(wa_inbound)} inbound WhatsApp business messages.\n\n"
        f"MESSAGES:\n{inbound_corpus[:6000]}\n\n"
        "Extract:\n"
        "1. Top 5 conversation themes (with counts)\n"
        "2. Common customer language patterns (phrases, tone, formality)\n"
        "3. Sentiment distribution (positive/negative/neutral %)\n"
        "4. Time-of-day patterns (if dates suggest)\n"
        "5. Unmet needs (what customers ask for that we don't provide)"
}).json()
themes_text = themes.get("content", "")
print(f"\nThemes:\n{themes_text[:1000]}")

# 4. Create customer personas based on message patterns
CUSTOMER_TYPES = [
    {"name": "Urgent Buyer", "desc": "Sends short, direct messages. Wants immediate answers. Price-focused. Uses WhatsApp because it's faster than email. Expects quick responses."},
    {"name": "Relationship Builder", "desc": "Sends longer messages with context. Asks follow-up questions. Wants to feel valued. Uses emojis and greetings. Loyal when treated well."},
    {"name": "Comparison Shopper", "desc": "Asks detailed product questions. Mentions competitors. Wants specs, pricing breakdowns, and guarantees. Analytical. Makes decisions slowly."},
]
persona_ids = []
for ct in CUSTOMER_TYPES:
    p = requests.post(f"{MV_BASE}/personas", headers=MV_H, json={
        "name": f"WhatsApp: {ct['name']}",
        "description": ct["desc"],
    }).json()
    persona_ids.append({"id": p["id"], "name": ct["name"]})
    time.sleep(0.3)

# 5. Speak sessions for persona insights
for persona in persona_ids:
    speak = requests.post(f"{MV_BASE}/speak", headers=MV_H, json={
        "persona_id": persona["id"],
        "input": [
            {"role": "system", "content": f"You are a {persona['name']} who communicates with businesses via WhatsApp. Based on these real customer conversation themes, share your perspective."},
            {"role": "user", "content": f"Here's what customers are saying on WhatsApp:\n\n{themes_text[:1500]}\n\nAs a {persona['name']}, what resonates with you? What would make you buy? What turns you off?"},
            {"role": "user", "content": "How should businesses message you on WhatsApp to earn your trust and get a response?"},
            {"role": "user", "content": "What's the one thing most businesses get wrong when messaging you on WhatsApp?"},
        ],
        "mode": "interview",
    }).json()

    print(f"\n{'='*60}\nPERSONA INSIGHT: {persona['name']}\n{'='*60}")
    for ex in speak.get("exchanges", speak.get("messages", [])):
        if ex.get("role") == "user":
            print(f"\n  Q: {ex['content'][:100]}")
        elif ex.get("role") == "assistant":
            print(f"  A: {ex['content'][:400]}")
    time.sleep(0.3)

# 6. Generate optimized WhatsApp templates
templates = requests.post(f"{MV_BASE}/generations", headers=MV_H, json={
    "prompt": f"Based on these WhatsApp persona insights:\n\n{themes_text[:2000]}\n\n"
        "Generate 5 optimized WhatsApp Business message templates:\n\n"
        "1. Welcome / First Contact\n"
        "2. Product Inquiry Response\n"
        "3. Price Quote\n"
        "4. Follow-up After No Response\n"
        "5. Post-Purchase Check-in\n\n"
        "Each template: max 160 chars for first message, conversational tone, "
        "include a clear next step. Avoid sounding automated. Use WhatsApp formatting "
        "(bold: *text*, italic: _text_).",
}).json()
print(f"\n{'='*60}\nOPTIMIZED WHATSAPP TEMPLATES\n{'='*60}")
print(templates.get("output", templates.get("content", ""))[:1500])

Example Output

WhatsApp messages: 142 inbound, 89 outbound

Themes:
1. Product Availability (38 msgs) — "Do you have X in stock?"
2. Pricing Inquiries (29 msgs) — "How much for X?"
3. Order Status (24 msgs) — "Where's my order?"
4. Returns/Exchanges (18 msgs) — "Can I return this?"
5. Custom Requests (12 msgs) — "Can you make X in size Y?"

PERSONA INSIGHT: Urgent Buyer
============================================================
  Q: What resonates? What makes you buy?
  A: Speed. If you reply in under 5 minutes, I'm 80% likely to buy.
     After 30 minutes, I've already messaged your competitor. Don't
     send me a catalog — answer my specific question. "Yes, we have
     it, here's the price, want me to reserve it?" That's the perfect
     WhatsApp message.

  Q: What do businesses get wrong?
  A: Automated responses that don't answer my question. "Thank you for
     your message, a representative will be with you shortly" — that's
     email energy. This is WhatsApp. Be human or be fast. Ideally both.

OPTIMIZED WHATSAPP TEMPLATES
============================================================
1. WELCOME: Hey! 👋 Thanks for reaching out. I'm [Name] — what
   can I help you find today?

2. INQUIRY: Great question! *[Product]* is available in [options].
   Want me to send photos or pricing?

3. QUOTE: Here's the breakdown:
   *[Product]*: $XX
   *Shipping*: Free over $50
   Ready to order? I can set it up right now.

Error Handling

WhatsApp numbers use whatsapp:+{E.164} format. Filter messages by To or From containing whatsapp: prefix. The Twilio Sandbox uses whatsapp:+14155238886.
WhatsApp Business API requires customers to message first (or opt in). You can only respond within 24 hours of the last customer message. After that, you need pre-approved templates.
WhatsApp messages may include images, documents, and voice notes. The Messages API returns media URLs via MediaUrl fields. This code processes text only — extend with media download for richer analysis.