Claude
Skills
Sign in
Back

twilio-whatsapp

Included with Lifetime
$97 forever

WhatsApp Business: template messages, session messages, media, webhooks, opt-in management

Generalwhatsapptwiliomessaging

What this skill does


# twilio-whatsapp

## Purpose

Enable OpenClaw to implement and operate Twilio WhatsApp Business messaging in production:

- Send **template messages** (pre-approved) and **session messages** (24-hour customer care window).
- Attach **media** (images/docs/audio) with correct MIME types and size constraints.
- Receive and validate **webhooks** (incoming messages + message status callbacks).
- Implement **opt-in/opt-out** and compliance controls (STOP handling, consent logging, regional constraints).
- Operate reliably under Twilio production constraints: rate limits, retries, idempotency, error codes, and cost controls via Messaging Services.

Concrete value to an engineer: ship a WhatsApp messaging subsystem that is observable, compliant, resilient to webhook retries, and safe to run at scale with predictable failure modes.

---

## Prerequisites

### Accounts & Twilio-side setup

- Twilio account with WhatsApp sender enabled:
  - Either **Twilio Sandbox for WhatsApp** (dev only) or a **WhatsApp Business Profile** connected to Twilio (prod).
- A Twilio **Messaging Service** (recommended for production) with:
  - WhatsApp sender(s) attached (e.g., `whatsapp:+14155238886` or your approved WA number).
  - Status callback URL configured (optional but recommended).
- WhatsApp templates approved in Meta Business Manager (via Twilio Console template manager).

### Local tooling versions (pinned)

- Node.js **20.11.1** (LTS) or **18.19.1** (LTS)
- Python **3.11.8** or **3.12.2**
- Twilio helper libraries:
  - `twilio` (Node) **4.23.0**
  - `twilio` (Python) **9.0.5**
- Twilio CLI **5.16.0** (for diagnostics; not required at runtime)
- ngrok **3.13.1** (local webhook testing)

### Auth & secrets

Use one of:

1. **API Key (recommended)**:
   - `TWILIO_API_KEY_SID` (starts with `SK...`)
   - `TWILIO_API_KEY_SECRET`
   - `TWILIO_ACCOUNT_SID` (starts with `AC...`)

2. **Account SID + Auth Token**:
   - `TWILIO_ACCOUNT_SID`
   - `TWILIO_AUTH_TOKEN`

Store secrets in:
- Kubernetes: `Secret` + mounted env vars
- AWS: Secrets Manager + IRSA
- GCP: Secret Manager + Workload Identity
- Local dev: `.env` (never commit)

### Network & webhook requirements

- Public HTTPS endpoint for webhooks (Twilio requires HTTPS in most production contexts).
- Allow inbound from Twilio webhook IPs is not stable; validate using **X-Twilio-Signature** instead of IP allowlists.
- Ensure your endpoint can handle retries and out-of-order delivery.

---

## Core Concepts

### WhatsApp message types (Twilio perspective)

1. **Template message** (outside 24-hour window):
   - Must use a pre-approved template.
   - Used for notifications, OTP, shipping updates, etc.
   - In Twilio, templates are typically sent via the **Content API** (preferred) or via template integration depending on account configuration.

2. **Session message** (inside 24-hour window):
   - Free-form text/media allowed (subject to WhatsApp policies).
   - The 24-hour window starts when the user messages you.

3. **Media message**:
   - WhatsApp supports images, documents, audio, video with constraints.
   - Twilio sends media via `MediaUrl` (publicly accessible URL) or via Twilio-hosted media in some flows.

### Identifiers and addressing

- WhatsApp addresses in Twilio use `whatsapp:` prefix:
  - `From`: `whatsapp:+14155238886`
  - `To`: `whatsapp:+14155550123`
- Messaging Service SID: `MGxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`
- Message SID: `SMxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`

### Webhooks

Two primary webhook categories:

1. **Incoming message webhook** (when user sends you a message):
   - Twilio sends an HTTP request with form-encoded parameters like `From`, `To`, `Body`, `NumMedia`, `MediaUrl0`, etc.

2. **Message status callback** (delivery lifecycle):
   - Status values: `queued`, `sent`, `delivered`, `read`, `failed`, `undelivered`
   - Twilio retries on non-2xx responses with backoff.

### Idempotency and retries

- Twilio may retry webhooks; your handler must be idempotent.
- Status callbacks can arrive out of order (e.g., `delivered` then `read`, or `failed` after transient states).
- Use `MessageSid` + `MessageStatus` + timestamp to dedupe.

### Compliance: opt-in/opt-out

- WhatsApp requires user opt-in; you must store consent evidence.
- STOP handling:
  - For SMS, Twilio has built-in STOP.
  - For WhatsApp, you must implement opt-out keywords and respect them (e.g., “STOP”, “UNSUBSCRIBE”).
- Maintain a suppression list keyed by E.164 phone number.

---

## Installation & Setup

### Official Python SDK — WhatsApp

**Repository:** https://github.com/twilio/twilio-python  
**PyPI:** `pip install twilio` · **Supported:** Python 3.7–3.13

```python
from twilio.rest import Client
client = Client()

# Send WhatsApp message (Sandbox: from_ = 'whatsapp:+14155238886')
msg = client.messages.create(
    body="Your order is confirmed!",
    from_="whatsapp:+14155238886",
    to="whatsapp:+15558675309"
)

# Send template message (approved HSM)
msg = client.messages.create(
    from_="whatsapp:+14155238886",
    to="whatsapp:+15558675309",
    content_sid="HX...",          # pre-approved template SID
    content_variables='{"1":"Alice","2":"12345"}'
)
```

Source: [twilio/twilio-python — messages](https://github.com/twilio/twilio-python/blob/main/twilio/rest/api/v2010/account/message/__init__.py)

### Ubuntu 22.04 LTS (x86_64)

```bash
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg jq
```

Node.js 20.11.1 via NodeSource:

```bash
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
node -v
npm -v
```

Python 3.11:

```bash
sudo apt-get install -y python3.11 python3.11-venv python3-pip
python3.11 --version
```

Twilio CLI 5.16.0:

```bash
npm install -g [email protected]
twilio --version
```

ngrok 3.13.1:

```bash
curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc \
  | sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null
echo "deb https://ngrok-agent.s3.amazonaws.com buster main" \
  | sudo tee /etc/apt/sources.list.d/ngrok.list
sudo apt-get update && sudo apt-get install -y ngrok
ngrok version
```

### Fedora 39 (x86_64)

```bash
sudo dnf install -y curl jq nodejs python3 python3-virtualenv
node -v
python3 --version
```

Twilio CLI:

```bash
sudo npm install -g [email protected]
twilio --version
```

ngrok:

```bash
sudo dnf install -y ngrok
ngrok version
```

### macOS 14 (Sonoma) — Intel + Apple Silicon

Homebrew:

```bash
brew update
brew install node@20 [email protected] jq ngrok/ngrok/ngrok
node -v
python3 --version
ngrok version
```

Twilio CLI:

```bash
npm install -g [email protected]
twilio --version
```

### Auth setup (CLI + env)

Twilio CLI login (writes to `~/.twilio-cli/config.json`):

```bash
twilio login
```

Runtime env vars (recommended: API Key):

```bash
export TWILIO_ACCOUNT_SID="AC2f7b9c2b0f1d2e3a4b5c6d7e8f9a0b1"
export TWILIO_API_KEY_SID="SK3f2a1b0c9d8e7f6a5b4c3d2e1f0a9b8"
export TWILIO_API_KEY_SECRET="a_very_long_secret_value"
export TWILIO_MESSAGING_SERVICE_SID="MG0c3d2e1f4a5b6c7d8e9f0a1b2c3d4e5"
```

Local `.env` (example path: `/srv/whatsapp/.env`):

```dotenv
TWILIO_ACCOUNT_SID=AC2f7b9c2b0f1d2e3a4b5c6d7e8f9a0b1
TWILIO_API_KEY_SID=SK3f2a1b0c9d8e7f6a5b4c3d2e1f0a9b8
TWILIO_API_KEY_SECRET=a_very_long_secret_value
TWILIO_MESSAGING_SERVICE_SID=MG0c3d2e1f4a5b6c7d8e9f0a1b2c3d4e5
PUBLIC_BASE_URL=https://wa.example.com
```

---

## Key Capabilities

### Send session messages (text + media)

- Use Twilio Programmable Messaging `Messages` API.
- Ensure `To` and `From` include `whatsapp:` prefix.
- Prefer `MessagingServiceSid` over hardcoding `From` for routing and future sender expansion.

Node (twilio 4.23.0):

```javascript
import twilio from "twilio";

const client = twilio(
  process.env.TWILIO_API_KEY_SID,
  process.env.TWILIO_API_KEY_SECRET,
  { accountSid: process.env.TWILIO_ACCOUNT_SID }
);

export async function sendSessionText(toE164, body) {
  const msg = await client.messages.create({
    to: `whatsapp:${toE164}`,
    messaging

Related in General