# Proposal: WhatsApp Business Channel

Draft. 2026-05-16. Iter 6 of audit loop.

---

## Why

After the Email Channel proposal (`docs/PROPOSAL-EMAIL-CHANNEL.md`), WhatsApp is the
next biggest omnichannel gap. Three signals:

1. **CodeCanyon buyer mix is global** — heaviest concentration in LATAM, MENA, SE Asia,
   India. WhatsApp Business is the default support channel in those markets; email is
   secondary.
2. **Competitors closing the gap fast**: Intercom Fin (paid add-on), Drift (Premium),
   Crisp ($95/mo Business), Tidio ($59/mo Plus) all ship WhatsApp out of the box.
3. **The pattern: visitor abandons the widget tab → opens WhatsApp → expects same
   conversation thread**. Today Pitchbar can't bridge that.

## Scope (v1)

**In:**
- Inbound visitor WhatsApp message → routed via Twilio Conversations API or Meta
  WhatsApp Business API → creates / reattaches a `Conversation` (whatsapp source)
- AI auto-reply using the agent's knowledge
- Operator can reply from `/app/inbox/{lead}` thread; reply goes back as WhatsApp
- Per-workspace WhatsApp number provisioned via Twilio (buyers bring own number; we
  don't act as middleman to avoid Meta verification overhead)
- Inbox UI shows widget + email + WhatsApp messages in one transcript

**Out (v2+):**
- WhatsApp Business templates (pre-approved messages)
- Click-to-WhatsApp ads
- WhatsApp Flows (interactive forms)
- Multimedia (images, voice notes) — start text-only

## Stack choice

Twilio Conversations API (preferred) vs Meta Cloud API (alternative):

| Factor | Twilio | Meta Cloud API |
|---|---|---|
| Setup friction | High (Twilio account + verified WA sender) | Higher (Meta Business Manager + app review) |
| Cost per msg | ~$0.005-$0.06 (markets vary) | Same; Meta bills you, no middleman |
| Webhook reliability | Industry standard | Spotty; documented edge cases |
| Multi-region SDK | Yes (PHP, Node, etc.) | HTTP only |
| Buyer's own number | Bring number → port to Twilio | Direct Meta number |

**Recommendation: Twilio.** PHP SDK quality is better; webhook reliability matters more
than $0.001/msg margin. Buyers who already have Twilio accounts plug in their
credentials in `/settings/system → Integrations`.

## Data model

New table `whatsapp_threads`:
- `id` (uuid)
- `conversation_id` (fk → conversations)
- `visitor_phone` (E.164, indexed)
- `twilio_conversation_sid` (Twilio-side opaque id)
- `last_inbound_at` / `last_outbound_at` (timestamps)

Extends `Message.channel` enum (already added in email proposal) with `whatsapp`.

Extends `Conversation.source` enum with `whatsapp`.

`workspaces.whatsapp_config` JSON nullable column:
```json
{
  "provider": "twilio",
  "account_sid": "<encrypted>",
  "auth_token": "<encrypted>",
  "phone_number": "+12345678900",
  "webhook_signature_secret": "<encrypted>"
}
```

## Routes

```
POST /api/v1/whatsapp/inbound       — Twilio Conversations webhook
GET  /app/settings/integrations/whatsapp — connect form (Twilio creds)
POST /app/inbox/{lead}/whatsapp-reply — operator-side outbound (mirrors /reply)
```

Inbound webhook auth: HMAC verification using Twilio's `X-Twilio-Signature` header
(same pattern Stripe / Razorpay webhooks already use).

## Hot path

Inbound WhatsApp is async. `HandleInboundWhatsappJob` does:
1. Verify Twilio signature
2. Look up Conversation by visitor_phone → workspace_id (most recent if multiple)
3. If no recent conversation → create new (synthesised visitor from phone number)
4. Persist visitor message (channel=whatsapp)
5. Run normal RAG pipeline (same Retriever, PromptBuilder, OpenAiClient)
6. Twilio API call to send the reply back

Outbound throttling: max 1 msg/second per workspace_phone (Twilio's hard rate limit
on WhatsApp). Implement via Bus chain or per-workspace queue.

## Multi-tenancy

`whatsapp_threads` uses `BelongsToAgent` via the conversation FK chain. Webhook
endpoint extracts the workspace from the inbound message's destination phone
(`workspaces.whatsapp_config.phone_number = $msg->To`).

## Plan-gating

WhatsApp is a premium channel. Reuses `PlanLimits` pattern:
- `plans.whatsapp_channel_enabled` boolean (default false)
- Free / Standard plans: feature disabled, upgrade nudge shown
- Pro+ plans: feature enabled

## Effort estimate

| Phase | Days | What ships |
|---|---|---|
| Twilio SDK + auth + webhook | 2 | inbound + signature verification + HandleInboundWhatsappJob |
| Conversation reattach by phone | 1 | sticky thread mapping |
| Outbound via Twilio API | 1 | operator reply path + rate-limit per workspace |
| Settings UI + Twilio creds form | 1 | encrypted credential store + test-send button |
| Plan-gate + upgrade nudge | 0.5 | mirror existing PlanLimits flow |
| Tests | 1.5 | webhook auth, reattach, outbound, plan gate |
| Docs | 1 | new page + Twilio setup guide |
| **Total** | **8 days** | |

## Open questions

1. **Number provisioning**: assume buyer brings their own Twilio-verified WA number. Pitchbar doesn't act as a middleman. Document the Twilio setup separately.
2. **Marketing vs utility templates**: v1 only handles session messages (within 24h of last inbound). Outside the window → fail with a clear error telling the operator to use a pre-approved template. v2 adds template management.
3. **Phone privacy**: workspace operators see visitor phone numbers. Same exposure as the existing Lead model — already considered fine.
4. **Buyers without Twilio**: ship feature off by default. Don't break installs.

## Why this is the right next bet (after email)

| Signal | Source |
|---|---|
| LATAM, MENA, SE Asia, India buyer concentration | CodeCanyon analytics |
| Competitor parity | Intercom / Drift / Crisp / Tidio all ship it |
| Reuses email-channel architecture (channel/source enums, Inbox UI) | engineering pragmatism |
| Plan-gateable → revenue lever | premium-tier upsell |
| Twilio is industry standard | low-risk vendor pick |

## Sequencing

- **Email Channel** (5 days, `docs/PROPOSAL-EMAIL-CHANNEL.md`) ships first. Establishes the channel enum + Inbox UI multi-source rendering.
- **WhatsApp Channel** (8 days) ships next. Pure addition on top of the channel scaffolding.
- **White-label** (4 days, `docs/PROPOSAL-PLAN-GATED-WHITE-LABEL.md`) ships in parallel — zero code overlap.

Total Q3 omnichannel + monetisation push: ~17 days engineering. Each plan-gated for
revenue lift.
