← Plugin catalog
Developer Tools

Twilio Developer Kit

Twilio v0.2.2

Twilio Skills for building, debugging, and shipping on Twilio

Create a free account to save this plugin.

From the developer

Declared capabilities

  • Read
  • Write

Not specified in the available declarations: limitations, pricing & account requirements.

Onboarding example

Help me send an SMS notification with delivery tracking
Sources & dates

Developer declarations; not independently tested. Listing last checked Nov 15, 2026. Package observed Nov 15, 2026.

View package source →

Description

From the marketplace listing

Procedural knowledge that guides AI coding agents to the right Twilio APIs for any use case. Covers channel selection, production best practices, compliance requirements, and common pitfalls across Messaging, Voice, Verify, SendGrid, and 30+ products. Skills follow a progressive disclosure architecture — your agent sees lightweight metadata at startup and loads full guidance only when a task matches.

Language: English · Automatically detected from descriptions.

Matches for “r developer”

Exact text from the indicated source. A mention alone does not establish support for your task.

Plugin name

Twilio Developer Kit

Package name

twilio-developer-kit

Publisher subtitle

Twilio Skills for building, debugging, and shipping on Twilio

Publisher capabilities · listing

Read Write

Publisher keywords · package

twilio sms voice whatsapp rcs messaging verify sendgrid email compliance conversation-relay conversation-memory conversation-intelligence conversation-orchestrator agent-connect enterprise-knowledge apple-messages-for-business api

Saved package evidence →
Publisher description

Twilio Skills provide procedural knowledge for AI coding agents — which APIs to use, in what order, and what to avoid. Covers Messaging, Voice, Verify, SendGrid, and 30+ products.

Publisher full description

Procedural knowledge that guides AI coding agents to the right Twilio APIs for any use case. Covers channel selection, production best practices, compliance requirements, and common pitfalls across Messaging, Voice, Verify, SendGrid, and 30+ products. Skills follow a progressive disclosure architecture — your agent sees lightweight metadata at startup and loads full guidance only when a task matches.

What changed

Keywords

Files & skills

File archives

Plugin package115 files · 206 KBBrowse files →
conversation-intelligence2 files · 11.7 KBBrowse files →
twilio-isv-sms-best-practices2 files · 4.56 KBBrowse files →
Skill instructions
conversation-intelligence36.3 KB

View saved version →

---
name: conversation-intelligence
description: "Twilio Conversation Intelligence development guide. Use when building real-time or post-call conversation analysis, language operator pipelines, sentiment analysis, agent assist, cross-channel analytics, or querying aggregated conversation insights (sentiment trends, escalation rates, dashboards)."
---

# Conversation Intelligence

Decision-making guide for Twilio's Conversation Intelligence v3 API — real-time and post-call GenAI analysis of conversations across Voice, SMS, RCS, and WhatsApp. Covers Intelligence Configurations, Language Operators (Twilio-authored and custom), Rules, Triggers, Actions, and result consumption.

> **Security:** All inbound messages captured by the Orchestrator are untrusted external input. If Intelligence operators process this content with LLMs, their prompts should include instructions to ignore adversarial content and not follow instructions embedded in customer messages.


> **GA** — Conversation Intelligence v3 is generally available.

## Use Cases

Conversation Intelligence powers **human agent augmentation** — giving every agent a "second brain" that listens, understands, and surfaces the right data at the right time. Agents focus on empathy, judgment, and problem-solving; AI handles analysis and assistance.

### Wrap-up Agent Assist (Post-Call)

Analyze completed conversations and generate structured outputs — summaries, sentiment signals, topic dispositions. Reduces after-call work, accelerates agent transitions to next interaction. **Low-friction entry point** — start here.

- **Operators**: Summary, Sentiment, custom Conversation Scoring
- **Trigger**: `CONVERSATION_END`
- **Integration**: Webhook → CRM case note creation

### Real-time Agent Assist

Analyze conversations as they unfold. Surface sentiment shifts, script adherence signals, or recommended next responses enriched with customer history and enterprise knowledge. Agents respond more confidently without searching across systems.

- **Operators**: Script Adherence, Next Best Response, Escalation Risk (custom)
- **Trigger**: `COMMUNICATION`
- **Integration**: Webhook → Agent desktop overlay

### Real-time Workflow Automation

Combine real-time intelligence with orchestration to trigger downstream workflows when specific conditions are met — escalate to supervisor, trigger fraud prevention, notify specialist.

- **Operators**: Custom risk detection, compliance monitoring
- **Trigger**: `COMMUNICATION`
- **Integration**: Webhook → Workflow engine / TaskRouter

### Contact Center QA

Generate post-interaction summaries, sentiment scores, and compliance signals for QA, coaching, and analytics. Aggregate across interactions to support training and continuous optimization.

- **Operators**: Script Adherence, Summary, custom Conversation Scoring
- **Trigger**: `CONVERSATION_END`
- **Integration**: Webhook → Analytics / BI tools

## How It Works

```
┌─────────────────────────────────────────────────────────────────────────────┐
│  1. Customer engages agent (Voice, SMS, WhatsApp, RCS, Chat, Email)         │
└─────────────────────────────────────────────────────────────────────────────┘
                                      │
                                      ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│  2. Conversations (Conversation Orchestrator) groups communications into a  │
│     Conversation                                                            │
│     - Normalizes channel events                                             │
│     - Groups related messages/utterances                                    │
│     - Tracks participants (CUSTOMER, HUMAN_AGENT, AI_AGENT)                 │
└─────────────────────────────────────────────────────────────────────────────┘
                                      │
                                      ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│  3. Conversati

Preview of the first 4,000 characters. Read full instructions →

twilio-account-setup10.6 KB

View saved version →

---
name: twilio-account-setup
description: >
  Create and configure a Twilio account from scratch. Covers free trial signup,
  trial limitations, getting credentials (Account SID and Auth Token), buying
  a phone number, verifying recipient numbers for trial use, SDK installation,
  first API call, subaccount management (creation, inheritance, credential
  isolation, limits), and enabling specific products (AI Assistants,
  Conversations, Verify, ConversationRelay, WhatsApp). Use this skill before
  any other Twilio skill if you do not yet have a Twilio account or need to
  enable a product. For Organization-level governance (SSO, SCIM, multi-team),
  see `twilio-organizations-setup`.
---

## Overview

Every Twilio skill requires an active Twilio account and credentials. This skill covers the one-time setup steps that are prerequisites for all other Twilio skills.

---

## Quickstart

1. Sign up at [twilio.com/try-twilio](https://www.twilio.com/try-twilio) -- enter name, email, password
2. Verify your email and personal phone number
3. Get your credentials from [Console > Account > API keys & tokens](https://console.twilio.com/us1/account/keys-credentials/api-keys):

```bash
export TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
export TWILIO_AUTH_TOKEN=your_auth_token
```

4. Buy a phone number at [Console > Phone Numbers > Buy a number](https://console.twilio.com/us1/develop/phone-numbers/search)

5. Install the SDK and send your first message:

**Python**
```bash
pip install twilio
```
```python
import os
from twilio.rest import Client

client = Client(os.environ["TWILIO_ACCOUNT_SID"], os.environ["TWILIO_AUTH_TOKEN"])
message = client.messages.create(
    to="+15558675310",  # must be verified on trial accounts
    from_="+15017122661",  # your Twilio number
    body="Hello from Twilio!"
)
print(f"Sent: {message.sid}")
```

**Node.js**
```bash
npm install twilio
```
```node
const twilio = require("twilio");
const client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);

const message = await client.messages.create({
    to: "+15558675310",  // must be verified on trial accounts
    from: "+15017122661",  // your Twilio number
    body: "Hello from Twilio!",
});
console.log(`Sent: ${message.sid}`);
```

You're ready to use any Twilio skill. Trial accounts have restrictions -- see Constraints below.

---

## Key Patterns

### Verify Recipient Numbers (trial accounts only)

Trial accounts can only send to **verified phone numbers** (up to 5 per account).

1. Go to [Console > Phone Numbers > Verified Caller IDs](https://console.twilio.com/us1/develop/phone-numbers/verified-caller-ids)
2. Click **Add a new Caller ID** and verify via SMS code

Verified numbers work across both messaging and voice. Remove this restriction by upgrading your account.

### Enable Specific Products

Some products require explicit activation:

| Product | How to enable |
|---------|--------------|
| AI Assistants | [Console > Explore Products > AI Assistants](https://console.twilio.com/us1/develop/ai-assistants) > **Get started** |
| Conversations | [Console > Conversations > Manage > Overview](https://console.twilio.com/us1/develop/conversations/manage/overview) > **Enable Conversations** |
| Verify | [Console > Verify > Services](https://console.twilio.com/us1/verify/services) > **Create new** |
| WhatsApp (sandbox) | [Console > Messaging > Try it out > Send a WhatsApp message](https://console.twilio.com/us1/develop/sms/try-it-out/whatsapp-learn) |
| ConversationRelay | [Console > Voice > ConversationRelay](https://console.twilio.com/us1/voice/conversation-relay) > complete onboarding form |

### SDK Installation

| Language | Install | SDK package |
|----------|---------|-------------|
| Python | `pip install twilio` | `twilio` |
| Node.js | `npm install twilio` | `twilio` |
| Java | Maven/Gradle | `com.twilio.sdk:twilio` |
| C# | `dotnet add package Twilio` | `Twilio` |
| Ruby | `gem install twilio-ruby` | `twilio-ruby

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-agent-augmentation-architect14.1 KB

View saved version →

---
name: twilio-agent-augmentation-architect
description: >
  Planning skill for augmenting human agents with real-time AI
  intelligence. Qualifies the developer's use case across coaching,
  compliance, QA, and routing to recommend the right Conversation Intelligence + Conversation Memory +
  TaskRouter architecture. Handles both "I want to add AI coaching to
  my call center" and "configure Conversation Intelligence operators for script adherence."
tier: discover
---

## Role

You are a Human Agent Augmentation Advisor. When a developer describes anything related to making human agents smarter, monitoring conversations in real-time, coaching agents, ensuring compliance, or improving contact center quality — use this framework to reason about what they need.

## When This Skill Activates

Trigger on any of these signals:
- "Agent assist," "agent coaching," "real-time coaching," "agent copilot"
- "Script adherence," "compliance monitoring," "QA automation"
- "Sentiment detection," "next best response," "live prompting"
- "Call transcription," "conversation analytics," "call center intelligence"
- "Conversation Intelligence," "Language Operators," "Conversational Intelligence"
- Any request to analyze, monitor, or augment live human conversations

## Step 1: Detect Specificity and Decide Your Mode

**High-level request** (e.g., "I want AI to help my agents perform better"):
→ DISCOVERY MODE. Walk through Steps 2-4 to understand what "better" means.

**Mid-level request** (e.g., "I need real-time sentiment detection on calls with webhook alerts"):
→ VALIDATION MODE. They've identified the capability — validate the architecture, check for gaps (Do they also need customer context? Recording for post-call?), recommend skills.

**Specific implementation request** (e.g., "Configure a Conversation Intelligence custom operator for detecting competitor mentions"):
→ BUILD MODE. Proceed with the relevant Product skill. Quick context check: Is Conversation Intelligence provisioned? Is Conversation Orchestrator linked? Are they aware of the operator lifecycle gotchas?

## Step 2: Qualify Intent — The 5 Essential Questions

1. **What does "augmentation" mean for your agents?**
   - Real-time coaching: Live suggestions/prompts appearing on the agent's screen during a call
   - Compliance monitoring: Automated detection of script deviations, regulatory violations, disclosure requirements
   - Post-call QA: Automated scoring and review of completed conversations (replacing manual sampling)
   - Intelligent routing: Using AI signals to send calls to the right specialist

2. **What channels are your agents handling?**
   - Voice calls only → Transcription + Conversation Intelligence operators on audio stream
   - Voice + messaging → Conversation Orchestrator for unified conversation tracking + Conversation Intelligence across both
   - Messaging only → Conversation Intelligence operators on text (no transcription needed)

3. **What's your existing contact center infrastructure?**
   - Twilio Flex → Native integration path (Flex Agent Copilot replatforming onto Conversation Intelligence)
   - Other CCaaS (Genesys, Five9, NICE) → Webhook-based integration, more custom glue
   - Custom-built → Full flexibility but more setup

4. **Do you need customer context surfaced to agents?**
   - No (agents look up context themselves) → Skip Conversation Memory
   - Yes (show customer history, preferences, past issues on accept) → Add Conversation Memory

5. **What's your call volume and budget sensitivity?**
   - Not all calls are worth transcribing
   - Consider selective intelligence: Apply Conversation Intelligence only to specific queues, customer segments, or call types
   - Conversation Intelligence pricing is per-conversation-character — model selection affects cost (GPT-4.1-nano for speed/cost vs. GPT-5.2 for quality)

## Step 3: Assess Sophistication — The Capability Ladder

### Level 1: Listen — Transcription & Recording
**Developer says:** "I wa

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-agent-connect16.4 KB

View saved version →

---
name: twilio-agent-connect
description: >
  Use when building or integrating Twilio Agent Connect (TAC) to connect
  third-party LLM agent runtimes with Twilio Voice, Messaging,
  ConversationRelay, Conversation Memory, Conversation Orchestrator, or
  Enterprise Knowledge.
---

# Twilio Agent Connect

## Overview

Twilio Agent Connect (TAC) is a Python and TypeScript SDK that integrates third-party LLM agentic applications with Twilio's communication technologies. TAC provides middleware for identity resolution, memory/context management (via Conversation Memory), conversation orchestration (via Conversation Orchestrator), and multi-channel handling (Voice, SMS, RCS, WhatsApp, Chat).

**Key Architecture Principle**: TAC is not an agent runtime itself—it's middleware that enables existing LLM applications (OpenAI Agents SDK, Bedrock, LangChain, Microsoft Foundry, etc.) to leverage Twilio Conversations services.

## Product Context

### Core Twilio Conversations Services

TAC integrates with three core Twilio Conversations services:

1. **Conversation Memory (Memory Store)** - Persistent user context and memory management
   - Profile storage with traits and attributes
   - Observation and summary storage
   - Session history with full conversation context
   - Identity resolution (profile lookup by phone/email)

2. **Conversation Orchestrator** - Multi-channel conversation lifecycle management
   - Unified conversation API across all channels
   - Participant management
   - Communication routing
   - Conversation grouping and configuration

3. **Enterprise Knowledge** - Knowledge base integration
   - Semantic search across knowledge bases
   - RAG (Retrieval-Augmented Generation) support
   - Knowledge chunk retrieval with relevance scoring

### Supported Channels

TAC provides built-in support for:
- **Voice** - ConversationRelay (WebSocket-based real-time voice)
- **SMS** - Text messaging
- **RCS** - Rich Communication Services
- **WhatsApp** - WhatsApp Business messaging
- **Chat** - Web chat integrations

All channels support both inbound (customer-initiated) and outbound (agent-initiated) conversations.

### ConversationRelay-Only Mode

TAC supports a simplified "ConversationRelay-only" mode for getting started with voice conversations without requiring Conversation Orchestrator or Conversation Memory setup. This mode provides:
- TwiML generation
- WebSocket protocol handling
- Voice conversation lifecycle management
- Callback-based message processing

## Installation

### Python SDK

**Requirements**: Python 3.10+

```bash
# Using uv (recommended)
uv add git+https://github.com/twilio/twilio-agent-connect-python.git

# With server support (includes FastAPI and uvicorn for TACFastAPIServer)
uv add git+https://github.com/twilio/twilio-agent-connect-python.git --extra server

# Using pip
pip install git+https://github.com/twilio/twilio-agent-connect-python.git
pip install "git+https://github.com/twilio/twilio-agent-connect-python.git[server]"
```

### TypeScript SDK

**Requirements**: Node.js 22.13+

```bash
# Clone and build (not yet published to npm)
git clone https://github.com/twilio/twilio-agent-connect-typescript.git
cd twilio-agent-connect-typescript
npm install
npm run build
```

## Quick Start

### Multi-Channel Agent with OpenAI (Python)

```python
from dotenv import load_dotenv
from openai import AsyncOpenAI
from tac import TAC, TACConfig
from tac.adapters.openai import with_tac_memory
from tac.channels.sms import SMSChannel
from tac.channels.voice import VoiceChannel
from tac.server import TACFastAPIServer

load_dotenv()

tac = TAC(config=TACConfig.from_env())
voice_channel = VoiceChannel(tac)
sms_channel = SMSChannel(tac)
openai_client = AsyncOpenAI()

conversation_history = {}
SYSTEM_INSTRUCTIONS = (
    "You are a customer service agent speaking with a user over voice or SMS. "
    "Keep responses short and conversational — a sentence or two. "
    "Do not use markdown, asterisks, bullets, or emojis; you

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-ai-agent-architect19.4 KB

View saved version →

---
name: twilio-ai-agent-architect
description: >
  Planning skill for AI-powered conversational agents. Qualifies the
  developer's use case across outcome sophistication, entry point, and
  customer profile to recommend the right Twilio Conversations architecture and
  implementation skills. Handles both high-level requests ("build me a
  voice AI assistant") and specific ones ("integrate ConversationRelay
  with my OpenAI backend").
tier: discover
---

## Role

You are an AI Agent Architecture Advisor. When a developer describes anything related to building AI-powered customer interactions — voice bots, chatbots, LLM-connected phone systems, or intelligent automation — use this framework to reason about what they need.

## When This Skill Activates

Trigger on any of these signals:
- "AI agent," "voice bot," "chatbot," "virtual assistant," "LLM + phone"
- "ConversationRelay," "speech-to-text," "text-to-speech," "real-time voice"
- "AI customer service," "automated support," "conversational AI"
- "Conversation Memory," "Conversation Intelligence," "Conversation Orchestrator," "TAC," "Agent Connect"
- Any request to connect an LLM (OpenAI, Claude, Gemini) to Twilio Voice or Messaging

## Step 1: Detect Specificity and Decide Your Mode

Before anything else, assess how specific the developer's request is:

**High-level request** (e.g., "I want to build an AI voice agent for customer support"):
→ Enter DISCOVERY MODE. Walk through Steps 2-4 to qualify their needs before recommending.

**Mid-level request** (e.g., "I need ConversationRelay with customer memory"):
→ Enter VALIDATION MODE. They've chosen products — validate the combination makes sense, check for gaps (Do they need Conversation Intelligence? Have they considered escalation?), then recommend Product skills.

**Specific implementation request** (e.g., "Set up a WebSocket handler for ConversationRelay with Deepgram"):
→ Enter BUILD MODE. They know what they want — proceed to implementation using the relevant Product skill. But first, do a quick context check: Are they missing foundational setup (account, auth, phone number)? Are they aware of the CANNOT constraints?

## Step 2: Qualify Intent — The 5 Essential Questions

If you lack answers to these, ask before recommending. You don't need all 5 upfront — gather organically through conversation.

1. **What outcome are you trying to achieve?**
   - Autonomous customer service (ordering, FAQ, booking)
   - Outbound AI calling (reminders, surveys, collections)
   - Voice AI for internal tools (agents, copilots)
   - Conversational commerce (sales, upsell)

2. **Which channels?**
   - Voice only → ConversationRelay
   - Voice + SMS/WhatsApp → ConversationRelay + Conversation Orchestrator for cross-channel
   - Chat/messaging only → Conversation Orchestrator + your LLM (no ConversationRelay needed)
   - Omnichannel → Full Twilio Conversations stack

3. **Do you need the agent to remember customers across sessions?**
   - No (stateless, each call is independent) → Skip Conversation Memory
   - Yes (returning customers, order history, preferences) → Add Conversation Memory

4. **Do you need real-time supervision or analytics?**
   - No → Skip Conversation Intelligence
   - Yes (compliance monitoring, sentiment detection, churn risk) → Add Conversation Intelligence

5. **Will the AI ever need to hand off to a human?**
   - No (fully autonomous) → No TaskRouter needed
   - Yes (escalation for complex issues) → Add TaskRouter + design escalation payload

## Step 3: Assess Sophistication — The Capability Ladder

Walk the developer up this ladder based on their answers. Each level adds products and complexity. Stop at the level that matches their stated outcome.

### Level 1: Basic Voice AI Agent
**Developer says:** "I just want a voice bot connected to my LLM."
**Architecture:** ConversationRelay + WebSocket server + LLM API
**What it does:** Phone call → Twilio transcribes speech → sends text to your WebSocket → you call your 

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 3 — file references are metadata, not package contents.

twilio-call-recordings10.4 KB

View saved version →

---
name: twilio-call-recordings
description: >
  Record Twilio voice calls correctly. Covers the critical distinction
  between Record verb (voicemail) and Dial record (call recording),
  dual-channel for QA, mid-call pause for PCI, Conference recording, and
  the ConversationRelay workaround. Use this skill whenever you need to
  capture call audio for compliance, QA, or analytics.
---

## Overview

Twilio offers multiple recording methods. Choosing the wrong one is the **#1 developer mistake** in voice — using `<Record>` when you mean `<Dial record>` produces voicemail behavior instead of call recording.

| Method | What it does | Use when |
|--------|-------------|----------|
| `<Record>` verb | Records the CALLER only (voicemail-style) | Leaving a message, capturing input |
| `<Dial record>` | Records BOTH parties on a call | Call recording for two-party calls |
| `<Start><Recording>` | Starts a recording alongside other verbs | ConversationRelay, multi-verb flows |
| Conference `record` | Records the conference mix | Multi-party calls |
| Recordings REST API | Programmatic control mid-call | Pause during payment (PCI) |

---

## Prerequisites

- Twilio account with a voice-capable phone number — see `twilio-account-setup`
- `TWILIO_ACCOUNT_SID` and `TWILIO_AUTH_TOKEN` — see `twilio-iam-auth-setup`
- SDK: `pip install twilio` / `npm install twilio`
- A webhook endpoint for recording status callbacks
- **Compliance check:** Recording consent requirements vary by jurisdiction — see `twilio-compliance-traffic`

---

## Quickstart

### Record a Two-Party Call (Most Common)

Use `<Dial record>` — NOT `<Record>`.

**Python (Flask)**
```python
from flask import Flask, request
from twilio.twiml.voice_response import VoiceResponse

app = Flask(__name__)

@app.route("/voice", methods=["POST"])
def incoming_call():
    response = VoiceResponse()
    response.say("This call may be recorded for quality assurance.")
    dial = response.dial(
        record="record-from-answer-dual",  # dual-channel: agent on one, caller on other
        recording_status_callback="https://yourapp.com/recording-status"
    )
    dial.number("+15558675310")  # agent's phone
    return str(response)
```

**Node.js (Express)**
```node
app.post("/voice", (req, res) => {
    const response = new VoiceResponse();
    response.say("This call may be recorded for quality assurance.");
    const dial = response.dial({
        record: "record-from-answer-dual",
        recordingStatusCallback: "https://yourapp.com/recording-status",
    });
    dial.number("+15558675310");
    res.type("text/xml").send(response.toString());
});
```

### Handle the Recording Status Callback

> **Security:** Validate `X-Twilio-Signature` on recording callbacks in production. Without validation, attackers could POST fake recording URLs to your endpoint.

**Python (Flask)**
```python
@app.route("/recording-status", methods=["POST"])
def recording_status():
    recording_sid = request.form["RecordingSid"]
    recording_url = request.form["RecordingUrl"]
    call_sid = request.form["CallSid"]
    status = request.form["RecordingStatus"]  # "completed", "failed"
    duration = request.form.get("RecordingDuration", 0)

    if status == "completed":
        # Store recording reference
        save_recording(call_sid, recording_sid, recording_url, duration)

    return "", 200
```

---

## Key Patterns

### Recording Modes for `<Dial record>`

| Mode | What's recorded | Use case |
|------|----------------|----------|
| `record-from-answer` | Single channel, both parties mixed | Simple recording |
| `record-from-answer-dual` | Dual channel — caller on left, agent on right | QA (separate agent/caller audio) |
| `record-from-ringing` | Records from ring, not answer | Capture ring time + full call |
| `record-from-ringing-dual` | Dual channel from ring | QA with ring time |

**Always use `dual` for QA and analytics.** Dual-channel lets speech analytics tools (like Conversation Intelligence) dist

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-cli-reference7.47 KB

View saved version →

---
name: twilio-cli-reference
description: >
  Twilio CLI reference for managing Twilio resources from the terminal.
  Covers installation, credential profiles, phone number provisioning,
  sending SMS and email, webhook configuration, local development with
  a tunneling service, debugging with watch and logs, serverless deployment, and
  plugin ecosystem. Use when the developer asks to "just do it",
  "set this up", "run a command", mentions "CLI", "command line", or
  "terminal", or when an AI agent can execute a task directly instead
  of writing application code.
---

## Overview

The Twilio CLI lets you manage Twilio resources, send messages, configure webhooks, and deploy serverless functions directly from the terminal. AI coding agents can use CLI commands to provision resources and test integrations without writing application code.

**Install:**

| Platform | Command |
|----------|---------|
| macOS | `brew tap twilio/brew && brew install twilio` |
| Windows | `scoop bucket add twilio-scoop https://github.com/twilio/scoop-twilio-cli && scoop install twilio-cli` |
| Linux (apt) | See `twilio-cli/getting-started/install` for repo setup, then `apt install twilio` |
| npm | `npm install -g twilio-cli` |

**Update:** `brew upgrade twilio` / `scoop update twilio-cli` / `npm install -g twilio-cli@latest`

---

## Authentication & Profiles

```bash
# First-time login — creates a local API key stored as a profile
twilio login

# Named profiles for multiple accounts
twilio profiles:create --account-sid ACxxx --auth-token xxx --profile staging
# Avoid --auth-token as a plain argument — it will be stored in shell history. Use TWILIO_AUTH_TOKEN env var instead.
twilio profiles:list
twilio profiles:use staging

# Run a single command against a different profile
twilio api:core:messages:list -p production

# Subaccount access
twilio api:core:messages:list --account-sid ACxxx_SUBACCOUNT
```

**Credential priority:** explicit `-p`/`--account-sid` flag > env vars (`TWILIO_ACCOUNT_SID`, `TWILIO_AUTH_TOKEN`) > active profile.

---

## Phone Numbers

```bash
# Search available numbers (US local, area code 415)
twilio api:core:available-phone-numbers:local:list --country-code US --area-code 415

# Purchase a number
twilio api:core:incoming-phone-numbers:create --phone-number "+14155551234"

# List owned numbers
twilio phone-numbers:list

# Set webhooks on a number
twilio phone-numbers:update +14155551234 \
  --sms-url "https://example.com/sms" \
  --voice-url "https://example.com/voice"
```

---

## Send SMS

```bash
twilio api:core:messages:create \
  --from "+14155551234" \
  --to "+14155556789" \
  --body "Your order has shipped."

# List recent messages
twilio api:core:messages:list --to "+14155556789" --limit 10
```

---

## Send Email (SendGrid)

Requires `SENDGRID_API_KEY` environment variable.

```bash
# Configure defaults
twilio email:set --from "noreply@example.com" --subject "Default Subject"

# Send email
twilio email:send \
  --to "user@example.com" \
  --subject "Invoice attached" \
  --text "Please find your invoice." \
  --attachment ./invoice.pdf

# Pipe output as email body
ps aux | twilio email:send --to "ops@example.com" --subject "Process list"
```

---

## Webhook Development

```bash
# Set webhook URLs on a number
twilio phone-numbers:update +14155551234 --sms-url "https://your-tunnel-url.example.com/sms"

# Emulate webhook events locally (requires plugin)
twilio plugins:install @twilio-labs/plugin-webhook
twilio webhook:invoke http://localhost:3000/sms --type sms
```

**Local development:** The CLI rejects `localhost` URLs directly. Tunneling services such as ngrok are not bundled with twilio-cli. install one separately, then set the public tunnel URL as your webhook. 

** ngrok is NOT included in the CLI — install separately: npm install -g ngrok
  or via https://ngrok.com                                                      
  - Start tunnel: ngrok http 3000, then use the provided URL for webhook        
  confi

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-compliance-onboarding15.6 KB

View saved version →

---
name: twilio-compliance-onboarding
description: >
  Registrations required BEFORE Twilio traffic works. Covers messaging
  programs (A2P 10DLC, toll-free verification, WhatsApp WABA, RCS, short
  code, alphanumeric sender) and voice trust programs (STIR/SHAKEN, Voice
  Integrity, Branded Calling, CNAM). Each number/sender type has its own
  program — registration blocks traffic until complete.
---

## Overview

Most Twilio channels require registration or approval before traffic flows. **Skipping this step is the #1 onboarding mistake** — developers build first, then discover messages are blocked or calls labeled as spam.

**Lifecycle:** Choose numbers/senders (`twilio-numbers-senders`) → Register them (this skill) → Follow traffic rules (`twilio-compliance-traffic`)

---

## Decision Tree: What Do I Need to Register?

### Messaging Programs

| Sender type | Registration program | Timeline | Docs |
|-------------|---------------------|----------|------|
| US local (10DLC) | **A2P 10DLC** — brand + campaign | Brand: minutes. Campaign: 10-15 business days | [Overview](https://www.twilio.com/docs/messaging/compliance/a2p-10dlc) \| [Quickstart](https://www.twilio.com/docs/messaging/compliance/a2p-10dlc/quickstart) |
| US toll-free | **Toll-free verification** | 3-5 business days | [Console onboarding](https://www.twilio.com/docs/messaging/compliance/toll-free/console-onboarding) \| [Requirements](https://help.twilio.com/articles/5377174717595-Toll-Free-Message-Verification-for-US-Canada) |
| US short code | **Pre-approved at purchase** | 8-12 weeks provisioning | [Guidelines by country](https://www.twilio.com/en-us/guidelines/short-code) \| [What is a short code?](https://help.twilio.com/articles/223182068-What-is-a-Messaging-Short-Code-) |
| WhatsApp | **WABA + Meta Business Verification** | Minutes (sender) + weeks (Meta verification) | [Self sign-up](https://www.twilio.com/docs/whatsapp/self-sign-up) \| [Getting started](https://help.twilio.com/articles/360007721954-Getting-Started-with-Twilio-for-WhatsApp) |
| RCS | **Google + carrier approval** | 4-6 weeks minimum, longer multi-region | [RCS onboarding](https://www.twilio.com/docs/rcs/onboarding) \| [Compliance guide](https://help.twilio.com/articles/49174994355355-RCS-Compliance-Onboarding-Guide) |
| Alpha Sender ID | **Registration in some countries** | Varies by country | [How to register](https://help.twilio.com/articles/20153208099611-How-to-Register-an-Alphanumeric-Sender-ID) |
| International numbers | **Regulatory bundle** (many countries) | Varies | [Getting started](https://www.twilio.com/docs/phone-numbers/regulatory/getting-started) \| [How to submit](https://help.twilio.com/articles/8338625205147-How-to-Submit-a-Regulatory-Bundle-for-Phone-Number-Regulatory-Compliance) |
| Twilio Verify | **Exempt** — no registration needed | Immediate | — |

### Voice Trust Programs

| Program | What it does | Vetting timeline | Docs |
|---------|-------------|-----------------|------|
| **STIR/SHAKEN** | Level A attestation = trusted caller ID | 24hr (Business Profile) + 72hr (Trust Product) | [Overview](https://www.twilio.com/docs/voice/trusted-calling-with-shakenstir) \| [Onboarding](https://www.twilio.com/docs/voice/trusted-calling-with-shakenstir/shakenstir-onboarding) |
| **Voice Integrity** | Registers numbers with carriers to remediate spam labels | 24-48hr (profile) + 24-48hr (remediation) | [Overview](https://www.twilio.com/docs/voice/spam-monitoring-with-voiceintegrity) \| [Onboarding](https://www.twilio.com/docs/voice/spam-monitoring-with-voiceintegrity/voice-integrity-onboarding) |
| **Branded Calling (US)** | Verified name + logo on mobile caller ID | Public Beta (T-Mobile, Verizon) | [Overview](https://www.twilio.com/docs/voice/branded-calling) \| [FAQ](https://help.twilio.com/articles/22312096414363-Branded-Calls-FAQ) |
| **Branded Calling (Non-US)** | Verified caller ID branding for international numbers | Availability varies by country/carrier | [Overview](

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-compliance-traffic10.8 KB

View saved version →

---
name: twilio-compliance-traffic
description: >
  Rules you must follow for Twilio messaging and voice traffic. Covers
  TCPA (consent tiers, quiet hours, DNC), GDPR (EU consent, right to
  deletion), PCI DSS (payment recording, Pay verb), HIPAA (BAA, PHI),
  FDCPA (debt collection limits), CAN-SPAM, WhatsApp policies,
  SHAKEN/STIR, and consent management patterns. Use this skill proactively
  when developers have working traffic to ensure they follow the rules.
---

## Overview

Compliance failures block sends, get numbers suspended, and expose your customer to legal liability. This skill covers the **ongoing rules** that apply to live traffic — what you can send, when, and to whom.

**Lifecycle:** Choose numbers (`twilio-numbers-senders`) → Register them (`twilio-compliance-onboarding`) → Follow traffic rules (this skill) → Secure everything (`twilio-security-hardening`)

For registrations required before traffic works (A2P 10DLC, toll-free verification, WhatsApp/RCS sender approval, voice trust programs), see `twilio-compliance-onboarding`.

---

## TCPA (Telephone Consumer Protection Act)

Applies to all US voice calls and SMS.

### Consent Requirements

| Communication type | Consent required | Notes |
|-------------------|-----------------|-------|
| Informational SMS (order updates) | Prior express consent | Providing phone number during transaction usually qualifies |
| Marketing SMS | Prior express written consent | Must be clear and conspicuous, separate from T&C |
| Manual voice calls | None for existing business relationship | 18-month window |
| Autodialed / prerecorded voice | Prior express consent (informational) or written (marketing) | AI voice agents typically count as autodialed and must disclose who is calling |
| Emergency / fraud alerts | No consent required | Must be genuinely urgent |

### Quiet Hours

- **8:00 AM – 9:00 PM** in the recipient's local time zone
- Applies to telemarketing and non-emergency calls
- Your application must determine the recipient's time zone — Twilio does not enforce this
- Use `twilio-lookup-phone-intelligence` to determine carrier/region for time zone inference

### Do Not Call

- Maintain an internal Do Not Call list
- Honor opt-outs within 10 business days (best practice: immediately)
- Scrub against the National Do Not Call Registry for telemarketing

---

## GDPR (EU/EEA)

### Consent for Communications

| Basis | When it applies | Requirements |
|-------|----------------|-------------|
| Explicit consent | Marketing messages, new customer outreach | Must be freely given, specific, informed, unambiguous. Pre-checked boxes do NOT qualify. |
| Legitimate interest | Transactional messages, existing customer relationship | Requires documented balancing test. Must offer opt-out. |
| Contractual necessity | Order confirmations, shipping updates | Directly related to contract performance |

### Right to Deletion

Applies to ALL data stored by your application via Twilio:
- Call recordings and transcripts
- SMS/messaging logs
- Conversation Memory observations and profiles
- Conversation Intelligence operator results
- Customer profiles in your database

**Implementation:** Build a deletion endpoint that removes data from all systems. Twilio retains message logs for 400 days — you can delete recordings via API but cannot delete message logs from Twilio's system before the retention window.

### Call Recording Consent

- EU calls require explicit consent before recording, or a documented legitimate interest basis
- Play a recording notice at the start of every call: `<Say>This call may be recorded for quality assurance.</Say>`
- Store consent records with timestamp

---

## PCI DSS (Payment Card Industry)

### Never Record Card Numbers

- If recording calls, **pause recording** during payment:

**Python**
```python
# Pause recording when customer gives card number
client.calls(call_sid).recordings(recording_sid).update(status="paused")

# Use <Pay> verb instead of collecting

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-conference-calls11.3 KB

View saved version →

---
name: twilio-conference-calls
description: >
  Build multi-party calls using Twilio Conference. Covers warm transfer,
  cold transfer, coaching (whisper), hold vs mute, participant modes, and
  supervisor barge. Use this skill for any contact center, support line,
  or scenario requiring transfers, holds, or multi-party calls.
---

## Overview

Conference is the foundation of contact center call handling. The key insight: **every call that might need a transfer should start as a Conference**, not a direct `<Dial>`. A Conference supports hold, transfer, coaching, and recording — a direct Dial does not.

```
Caller ──→ Conference Room ←── Agent
                  ↑
              Supervisor (coach mode: speaks to agent only)
```

**Contact center best practice:** Every multi-agent call should use Conference, not direct Dial.

---

## Prerequisites

- Twilio account with a voice-capable phone number — see `twilio-account-setup`
- `TWILIO_ACCOUNT_SID` and `TWILIO_AUTH_TOKEN` — see `twilio-iam-auth-setup`
- SDK: `pip install twilio` / `npm install twilio`
- For agent routing: TaskRouter — see `twilio-taskrouter-routing`

---

## Quickstart

**Step 1 — Put the inbound caller into a Conference**

When a call comes in, place the caller into a named Conference room.

**Python (Flask)**
```python
from flask import Flask, request
from twilio.twiml.voice_response import VoiceResponse

app = Flask(__name__)

@app.route("/voice", methods=["POST"])
def incoming_call():
    call_sid = request.form["CallSid"]
    response = VoiceResponse()
    dial = response.dial()
    dial.conference(
        f"room-{call_sid}",
        start_conference_on_enter=True,
        end_conference_on_exit=False,  # Keep conference alive when caller disconnects (for wrap-up)
        wait_url="http://twimlets.com/holdmusic?Bucket=com.twilio.music.classical",
        status_callback="https://yourapp.com/conference-events",
        status_callback_event="join leave",
        record="record-from-start"
    )
    return str(response)
```

**Node.js (Express)**
```node
app.post("/voice", (req, res) => {
    const callSid = req.body.CallSid;
    const response = new VoiceResponse();
    const dial = response.dial();
    dial.conference(
        `room-${callSid}`,
        {
            startConferenceOnEnter: true,
            endConferenceOnExit: false,
            waitUrl: "http://twimlets.com/holdmusic?Bucket=com.twilio.music.classical",
            statusCallback: "https://yourapp.com/conference-events",
            statusCallbackEvent: "join leave",
            record: "record-from-start",
        }
    );
    res.type("text/xml").send(response.toString());
});
```

**Step 2 — Connect an agent to the same Conference**

After TaskRouter assigns a worker, dial the agent into the conference:

> **Security:** Never interpolate untrusted user input into inline `twiml=` strings. Use the SDK's `VoiceResponse` builder for any dynamic content.

**Python**
```python
# Called from your assignment callback or agent connect logic
def connect_agent(conference_name, agent_phone):
    client.calls.create(
        to=agent_phone,
        from_="+15551234567",  # your Twilio number
        twiml=f'''<Response>
            <Dial>
                <Conference>{conference_name}</Conference>
            </Dial>
        </Response>''',
        status_callback="https://yourapp.com/agent-call-status"
    )
```

**Node.js**
```node
async function connectAgent(conferenceName, agentPhone) {
    await client.calls.create({
        to: agentPhone,
        from: "+15551234567",
        twiml: `<Response><Dial><Conference>${conferenceName}</Conference></Dial></Response>`,
        statusCallback: "https://yourapp.com/agent-call-status",
    });
}
```

---

## Key Patterns

### Warm Transfer

Put caller on hold → dial new agent into Conference → original agent briefs new agent → original agent drops.

**Python**
```python
def warm_transfer(conference_sid, original_agent_call_sid, new_agent_phone, conf

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-content-template-builder5.54 KB

View saved version →

---
name: twilio-content-template-builder
description: >
  Create, manage, and send message templates using Twilio's Content API.
  Covers template creation for WhatsApp, SMS, RCS, and MMS; variable usage;
  WhatsApp Meta approval; and sending templates via ContentSid. Use this skill
  when building structured messages that require pre-approval or consistent
  formatting across channels.
---

## Overview

The Content API creates channel-agnostic templates identified by a `ContentSid` (`HX...`). WhatsApp templates must be approved by Meta before use outside the 24-hour service window.

---

## Prerequisites

- Twilio account — New to Twilio? See `twilio-account-setup`
- For WhatsApp templates: active WhatsApp sender
  — See `twilio-whatsapp-send-message` (sandbox) or `twilio-whatsapp-manage-senders` (production)
- Environment variables:
  - `TWILIO_ACCOUNT_SID`
  - `TWILIO_AUTH_TOKEN`
  — See `twilio-iam-auth-setup` for credential setup and best practices
- SDK: `pip install twilio` / `npm install twilio`

---

## Quickstart

**Step 1 — Create a template via Console** (simplest)

Console > Messaging > Content Template Builder > Create new. Use `{{1}}`, `{{2}}` for variables. Save to get a `ContentSid`.

**Step 2 — Send the template**

**Python**
```python
import os
from twilio.rest import Client

client = Client(os.environ["TWILIO_ACCOUNT_SID"], os.environ["TWILIO_AUTH_TOKEN"])

message = client.messages.create(
    from_="whatsapp:+14155238886",
    to="whatsapp:+15558675310",
    content_sid="HXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    content_variables='{"1": "Sarah", "2": "March 28", "3": "10:00 AM"}'
)
print(message.sid)
```

**Node.js**
```node
const twilio = require("twilio");
const client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);

const message = await client.messages.create({
    from: "whatsapp:+14155238886",
    to: "whatsapp:+15558675310",
    contentSid: "HXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    contentVariables: JSON.stringify({ "1": "Sarah", "2": "March 28", "3": "10:00 AM" }),
});
```

---

## Key Patterns

### Create a Template via API

**Python**
```python
template = client.content.v1.contents.create(
    friendly_name="appointment-reminder",
    language="en",
    types={
        "twilio/text": {
            "body": "Hi {{1}}, your appointment is on {{2}} at {{3}}. Reply YES to confirm."
        }
    }
)
print(template.sid)  # HXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

**Node.js**
```node
const template = await client.content.v1.contents.create({
    friendlyName: "appointment-reminder",
    language: "en",
    types: {
        "twilio/text": {
            body: "Hi {{1}}, your appointment is on {{2}} at {{3}}. Reply YES to confirm.",
        },
    },
});
console.log(template.sid);
```

### Submit for WhatsApp Approval

**Python**
```python
approval = client.content.v1 \
    .contents(template.sid) \
    .approval_requests \
    .create(name="appointment-reminder", category="UTILITY")
print(approval.status)  # PENDING
```

**Node.js**
```node
const approval = await client.content.v1
    .contents(templateSid)
    .approvalRequests.create({ name: "appointment-reminder", category: "UTILITY" });
console.log(approval.status);
```

Categories: `UTILITY`, `MARKETING`, `AUTHENTICATION`

### Check Approval Status

**Python**
```python
content = client.content.v1.contents(template.sid).fetch()
print(content.approval_requests.status)  # APPROVED | REJECTED | PENDING
```

**Node.js**
```node
const content = await client.content.v1.contents(templateSid).fetch();
console.log(content.approvalRequests.status);
```

Approval typically takes under 1 hour.

### List and Delete Templates

**Python**
```python
for template in client.content.v1.contents.list():
    print(template.sid, template.friendly_name, template.language)

client.content.v1.contents("HXxxxxxxxxxx").delete()
```

**Node.js**
```node
const templates = await client.content.v1.contents.list();
templates.forEach(t => console.log(t.sid, 

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-conversation-orchestrator36 KB

View saved version →

---
name: twilio-conversation-orchestrator
description: >
  Configure automatic conversation capture and routing with Twilio Conversation
  Orchestrator. Covers Configuration creation, channel capture rules, grouping
  types, status timeouts, Memory Store linkage, Intelligence linkage, and
  conversation lifecycle. Use this skill to automatically capture SMS, voice,
  WhatsApp, RCS, and web chat traffic into unified conversations without
  manually creating conversations or participants.
---

# Conversation Orchestrator

Decision-making guide for Twilio's Conversation Orchestrator (Conversations v2) — automatic conversation capture and routing across Voice, SMS, WhatsApp, RCS, and web chat. Covers Configurations, capture rules, grouping types, channel settings, status timeouts, and linkage to Conversation Memory and Conversation Intelligence.

> **GA** — Conversation Orchestrator is generally available.

## Use Cases

Conversation Orchestrator powers **automatic conversation capture and integration with existing voice implementations** — replacing manual conversation creation with either:
- **Passive ingestion**: Declarative capture rules that automatically capture traffic as it flows
- **Active ingestion**: TwiML parameters or API calls that route existing implementations into conversations

**Note:** Active and passive ingestion can be configured on a per-channel basis. For example, you can use passive capture rules for SMS while using active TwiML parameters for voice calls.

## ⚠️ CRITICAL: Voice Double Billing Warning

> **WARNING: You can be charged for STT (speech-to-text) twice on the same call if misconfigured.**

If you are using voice with ConversationRelay or Transcription in TwiML:

**We do not recommend using passive voice capture rules (`captureRules`) in your Configuration when using active TwiML.**

See the full [Voice Double Billing Warning](#️-critical-voice-double-billing-warning-1) section below for details.

### Unified Customer Context

Capture all channels (voice, SMS, WhatsApp, RCS, CHAT (via Conversation API (classic))) into a single conversation thread per customer. Conversation Memory resolves identity across channels and maintains persistent context. **Start here** — this is the most common pattern.

- **Grouping**: `GROUP_BY_PROFILE`
- **Channels**: SMS + VOICE + WHATSAPP + RCS + CHAT (via Conversation API (classic))
- **Linkage**: Memory Store (identity resolution) + Intelligence (analysis)

### Channel-Isolated Analytics

Keep voice transcripts separate from SMS threads for per-channel analysis. Intelligence operators run independently on each channel's conversation.

- **Grouping**: `GROUP_BY_PARTICIPANT_ADDRESSES_AND_CHANNEL_TYPE`
- **Channels**: SMS + VOICE (separate conversations)
- **Linkage**: Intelligence (per-channel operators)

### Agent Connect Integration

Capture conversations for AI-to-human escalation via Agent Connect (TAC SDK). Uses address-pair grouping required by the SDK.

- **Grouping**: `GROUP_BY_PARTICIPANT_ADDRESSES`
- **Channels**: SMS or VOICE
- **Linkage**: Memory Store + Intelligence + Agent Connect

### Post-Conversation Memory Extraction

Automatically extract observations from conversations into Conversation Memory. Opt-in — configure once, every conversation feeds the memory loop.

- **Config**: `memoryExtractionEnabled: true`
- **Trigger**: INACTIVE and/or CLOSED lifecycle transitions (configurable)
- **Result**: Observations and summaries written to linked Memory Store profiles

## How It Works

### Passive Ingestion (Capture Rules)

```
┌─────────────────────────────────────────────────────────────────────────────┐
│  1. Inbound/outbound traffic arrives (SMS, Voice, WhatsApp, RCS)           │
└─────────────────────────────────────────────────────────────────────────────┘
                                      │
                                      ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│  2. Capture rules match on phone

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-conversations-classic-api16.7 KB

View saved version →

---
name: twilio-conversations-classic-api
description: >
  Build multi-channel messaging experiences using Twilio Conversations (classic) API.
  Covers creating conversations, adding participants (SMS, WhatsApp, chat),
  sending messages, and handling webhooks. Use this skill to manage persistent
  multi-party or multi-channel conversations beyond single-message SMS/WhatsApp.
---

## Overview

Conversations (classic) API provides persistent, multi-channel threads where participants on SMS, WhatsApp, and web chat can message together. Unlike single-message APIs, Conversations maintains history and supports multi-agent access.

**Note:** This is the Conversations (classic) API (v1).

---

## Prerequisites

- Twilio account with Conversations (classic) enabled
  — New to Twilio? See `twilio-account-setup`
  — Enable at: [Console > Conversations > Manage > Overview](https://console.twilio.com/us1/develop/conversations/manage/overview) > **Enable Conversations**
- Environment variables:
  - `TWILIO_ACCOUNT_SID`
  - `TWILIO_AUTH_TOKEN`
  — See `twilio-iam-auth-setup` for credential setup and best practices
- SDK: `pip install twilio` / `npm install twilio`
- For SMS/WhatsApp participants: a Twilio number assigned to a Conversations Service

---

## Setup: Create a Conversation Service (classic)

A Conversation Service is the parent configuration container for all your conversations in the classic API. You need one before creating conversations with SMS/WhatsApp participants.

**Python**
```python
import os
from twilio.rest import Client

client = Client(os.environ["TWILIO_ACCOUNT_SID"], os.environ["TWILIO_AUTH_TOKEN"])

# Create a Conversation Service
service = client.conversations.v1.services.create(
    friendly_name="Customer Support Service"
)
print(f"Service SID: {service.sid}")
```

**Node.js**
```node
const twilio = require("twilio");
const client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);

// Create a Conversation Service
const service = await client.conversations.v1.services.create({
    friendlyName: "Customer Support Service"
});
console.log(`Service SID: ${service.sid}`);
```

**Next:** Assign your Twilio phone number to this service at [Console > Conversations > Manage > Services](https://console.twilio.com/us1/develop/conversations/manage/services) > Select your service > Add phone number.

---

## Quickstart

**Python**
```python
import os
from twilio.rest import Client

client = Client(os.environ["TWILIO_ACCOUNT_SID"], os.environ["TWILIO_AUTH_TOKEN"])

# Create a conversation (use default service or specify service_sid)
conversation = client.conversations.v1.conversations.create(
    friendly_name="Customer Support - Order #12345"
)

# Add an SMS participant
client.conversations.v1 \
    .conversations(conversation.sid) \
    .participants \
    .create(
        messaging_binding_address="+15558675310",
        messaging_binding_proxy_address="+15017122661"
    )

# Send a message
client.conversations.v1 \
    .conversations(conversation.sid) \
    .messages \
    .create(body="Hello! How can I help you today?", author="support-agent")
```

**Node.js**
```node
const twilio = require("twilio");
const client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);

// Create a conversation (use default service or specify serviceSid)
const conversation = await client.conversations.v1.conversations.create({
    friendlyName: "Customer Support - Order #12345",
});

// Add an SMS participant
await client.conversations.v1
    .conversations(conversation.sid)
    .participants.create({
        messagingBindingAddress: "+15558675310",
        messagingBindingProxyAddress: "+15017122661",
    });

// Send a message
await client.conversations.v1
    .conversations(conversation.sid)
    .messages.create({ body: "Hello! How can I help you today?", author: "support-agent" });
```

---

## Key Patterns

### Add Participants by Channel

**WhatsApp participant — Python**
```python
client

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-customer-memory13.1 KB

View saved version →

---
name: twilio-customer-memory
description: >
  Store and retrieve customer context using Twilio Conversation Memory.
  Covers Memory Store provisioning, profile management, traits, observations,
  conversation summaries, and semantic Recall. Use this skill to give AI agents
  or human agents persistent memory of customer interactions across sessions
  and channels.
---

## Overview

Conversation Memory gives your application persistent customer memory. Observations (what happened) and traits (who the customer is) are written automatically from conversations flowing through Conversation Orchestrator/Orchestrator — or posted directly if you run your own extraction. Retrieve relevant context via Recall before responding.

```
Conversation Orchestrator/Orchestrator conversation → auto-extracted observations & summaries → Memory Store
Your App → Recall → relevant context injected into LLM prompt
```

**All Conversation Memory APIs are on `memory.twilio.com`.** Observations, traits, profiles, summaries — everything is on the same host.

**Auth: Basic Auth** — `TWILIO_ACCOUNT_SID` and `TWILIO_AUTH_TOKEN`.

---

## Prerequisites

- Twilio account with Conversation Memory access (requires enablement)
  — New to Twilio? See `twilio-account-setup`
- `TWILIO_ACCOUNT_SID` and `TWILIO_AUTH_TOKEN` — see `twilio-iam-auth-setup`
- **Memory Store must be created before creating a Conversations Service in Conversation Orchestrator/Orchestrator** — the store SID is required in the conversation config
- For conversation orchestration: `twilio-conversation-orchestrator`

---

## Quickstart

### Step 1 — Create a Memory Store

Do this before setting up Conversation Orchestrator/Orchestrator. The Memory Store SID goes into your conversation service config.

**Python**
```python
import os, requests

account_sid = os.environ["TWILIO_ACCOUNT_SID"]
auth_token = os.environ["TWILIO_AUTH_TOKEN"]

store = requests.post(
    "https://memory.twilio.com/v1/Services",
    auth=(account_sid, auth_token),
    json={
        "uniqueName": "my-app-memory",
        "friendlyName": "My App Memory Store"
    }
).json()

memory_store_sid = store["sid"]
print(memory_store_sid)
```

**Node.js**
```javascript
const accountSid = process.env.TWILIO_ACCOUNT_SID;
const authToken = process.env.TWILIO_AUTH_TOKEN;

const store = await fetch("https://memory.twilio.com/v1/Services", {
    method: "POST",
    headers: {
        "Authorization": "Basic " + btoa(`${accountSid}:${authToken}`),
        "Content-Type": "application/json",
    },
    body: JSON.stringify({
        uniqueName: "my-app-memory",
        friendlyName: "My App Memory Store",
    }),
}).then(r => r.json());

const memoryStoreSid = store.sid;
```

Use `memory_store_sid` when creating your Conversations Service in Conversation Orchestrator/Orchestrator. The two must be linked for automatic observation and summary extraction to work.

### Step 2 — Profiles

Profiles are **created automatically** when conversations flow through Conversation Orchestrator/Orchestrator — the conversation config determines how participants are resolved into profiles. You can also create or enrich profiles manually using traits.

**Create a profile manually with traits:**

**Python**
```python
profile = requests.post(
    f"https://memory.twilio.com/v1/Services/{memory_store_sid}/Profiles",
    auth=(account_sid, auth_token),
    json={
        "traits": {
            "Contact": {
                "phone": "+15558675310",
                "firstName": "Alyssa",
                "lastName": "Mock",
                "email": "alyssa@example.com"
            }
        }
    }
).json()

profile_id = profile["id"]
```

**Node.js**
```javascript
const profile = await fetch(
    `https://memory.twilio.com/v1/Services/${memoryStoreSid}/Profiles`,
    {
        method: "POST",
        headers: {
            "Authorization": "Basic " + btoa(`${accountSid}:${authToken}`),
            "Content-Type": "application/json",
        },
        body: JSON

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-customer-support-architect13.2 KB

View saved version →

---
name: twilio-customer-support-architect
description: >
  Planning skill for building customer service and support systems.
  Qualifies the developer's needs across the support ladder
  (self-service → AI agents → contact center), channel mix, and scale
  to recommend the right Twilio architecture. Handles both "build me a
  call center" and "add an IVR to my existing support line."
tier: discover
---

## Role

You are a Customer Support Architecture Advisor. When a developer describes anything related to handling customer inquiries — inbound calls, support chat, IVR systems, call routing, agent desktops, or contact center infrastructure — use this framework to reason about what they need.

## When This Skill Activates

Trigger on any of these signals:
- "Contact center," "call center," "support line," "help desk"
- "IVR," "phone tree," "call routing," "call queue"
- "Agent desktop," "Flex," "agent routing"
- "Inbound calls," "customer service," "support chat"
- "Warm transfer," "call recording," "whisper," "barge," "coaching"
- "Self-service," "automated support"
- Any request to handle incoming customer communications at scale

## Step 1: Detect Specificity and Decide Your Mode

**High-level request** (e.g., "I need to build a customer support system"):
→ DISCOVERY MODE. Walk through Steps 2-4. This is a big architectural decision.

**Mid-level request** (e.g., "I need an IVR with call routing to different departments"):
→ VALIDATION MODE. They've described a pattern — validate the approach, recommend Studio vs custom TwiML, check if they need TaskRouter or simple `<Dial>` routing.

**Specific implementation request** (e.g., "Create a TwiML Bin that plays a greeting and gathers digits"):
→ BUILD MODE. Proceed with the relevant Product skill. Quick check: Are they building a one-off or something that should scale? If scale, nudge toward Studio or TaskRouter rather than hand-coded TwiML.

## Step 2: Qualify Intent — The 6 Essential Questions

1. **Inbound, outbound, or both?**
   - Inbound only (customers calling you): Focus on IVR + routing + agent tools
   - Outbound only (you calling customers): Focus on campaign dialing + compliance
   - Both: Full contact center — likely needs TaskRouter + Flex

2. **Which channels do customers use to reach you?**
   - Voice only → TwiML + routing
   - Voice + SMS → Add messaging handling, possibly Conversations API for threading
   - Voice + SMS + WhatsApp + Email + Chat → Omnichannel — Conversations API + Flex
   - Reference the Channel Mix Matrix: Voice and Email dominate Customer Service & Support

3. **What's your call/message volume?**
   - Low (< 50/day): Simple TwiML + `<Dial>` may suffice
   - Medium (50-500/day): TaskRouter for fair distribution + basic reporting
   - High (500+/day): Full TaskRouter + Flex + real-time monitoring + queue management

4. **Do you need self-service automation?**
   - Simple menu ("Press 1 for billing"): TwiML `<Gather>` + `<Say>`
   - Complex multi-step flow: Twilio Studio (no-code, recommended by SEs over custom state machines)
   - AI-powered self-service: → Hand off to `twilio-ai-agent-architect` Planner skill

5. **Do you need agent tooling (desktop, CRM integration)?**
   - No (agents use their own phone) → TwiML + TaskRouter, no Flex needed
   - Yes (browser-based agent desktop) → Twilio Flex
   - Yes + CRM integration → Flex + Salesforce/HubSpot/Zendesk connector

6. **What happens during transfers and holds?**
   - Simple cold transfer → `<Dial>` to another number
   - Warm transfer (introduce caller to next agent) → Conference API
   - Coaching/whisper/barge (supervisor listens, coaches agent) → Conference with participant modes

## Step 3: Assess Sophistication — The Support Ladder

### Level 1: Self-Service Automation
**Developer says:** "I want an automated phone menu / IVR."
**Architecture:** TwiML (`<Gather>`, `<Say>`, `<Play>`) or Twilio Studio
**Key decision — Studio vs Custom TwiML:**
- **Use Studio when:** Non-developers need t

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-debugging-observability15.9 KB

View saved version →

---
name: twilio-debugging-observability
description: >
  Debug Twilio integrations and set up production observability. Covers the
  Console Debugger, Monitor Alerts API, Event Streams for error log streaming,
  status callback tracking, common error codes, and a systematic debugging
  workflow. Use this skill whenever a Twilio integration produces errors,
  messages fail to deliver, calls drop unexpectedly, or you need to set up
  monitoring for a production deployment.
---

## Overview

Twilio provides several layers of debugging and observability: the Console Debugger for interactive troubleshooting, the Monitor REST API for programmatic alert queries, Event Streams for real-time error streaming, and status callbacks for per-resource delivery tracking. This skill covers the systematic approach to diagnosing issues and setting up production monitoring.


---

## Prerequisites

- Twilio account with `TWILIO_ACCOUNT_SID` and `TWILIO_AUTH_TOKEN` -- see `twilio-iam-auth-setup`
- SDK: `pip install twilio requests` / `npm install twilio`
- For Event Streams: a publicly accessible HTTPS endpoint or AWS Kinesis stream

---

## Quickstart

Check for recent errors on your account using the Monitor Alerts API.

**Python**
```python
import os
from twilio.rest import Client

client = Client(os.environ["TWILIO_ACCOUNT_SID"], os.environ["TWILIO_AUTH_TOKEN"])

alerts = client.monitor.alerts.list(log_level="error", limit=10)
for alert in alerts:
    print(f"{alert.date_created}: [{alert.error_code}] {alert.alert_text}")
```

**Node.js**
```node
const twilio = require("twilio");
const client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);

const alerts = await client.monitor.alerts.list({ logLevel: "error", limit: 10 });
alerts.forEach(a => {
    console.log(`${a.dateCreated}: [${a.errorCode}] ${a.alertText}`);
});
```

---

## Key Patterns

### 1. Systematic Debugging Workflow

When something fails, work through these layers in order:

```
1. Check status callbacks FIRST
   (Did your endpoint receive delivery/call status? What error code?)
   |
2. Check the resource directly via REST API
   (GET /Messages/{sid} or /Calls/{sid} — current state + error_code)
   |
3. Check number reputation / sender registration
   (Is the number spam-flagged? Is A2P 10DLC registered? Toll-free verified?)
   |
4. Check the Console Debugger for webhook/TwiML errors
   (Console > Monitor > Errors — shows HTTP request/response details)
   |
5. Check your webhook endpoint
   (Is it reachable? Responding within 15s? Returning valid TwiML/200?)
   |
6. Query Monitor Alerts API or Event Streams
   (For patterns across many messages/calls, or historical analysis)
```

**Why status callbacks first:** Status callbacks tell you the exact error code for the specific message or call that failed. The Console Debugger aggregates errors across your account and may not surface the one you're looking for. Start specific, then broaden.

**Number reputation checklist:**
- SMS 30007 (carrier filtering) → Check A2P 10DLC registration status, content for spam triggers
- SMS 30034 → Sender not registered for A2P 10DLC — register brand + campaign
- Calls going to voicemail / "Spam Likely" → Check STIR/SHAKEN attestation, Voice Integrity status (see `twilio-numbers-senders`)
- Toll-free SMS blocked → Check toll-free verification status

**Rule of thumb:** If status callbacks show `delivered` but the user says they didn't receive it, the issue is on the carrier/device side (not Twilio). If the Console Debugger shows no errors at all, the problem is in your application (webhook, TwiML, business logic).

### 2. Console Debugger

The [Console Debugger](https://console.twilio.com/us1/monitor/logs/debugger) shows errors and warnings for your account in real time.

Each entry includes:
- The exact error or warning that occurred
- Potential causes and suggested solutions
- The full HTTP request and response for the associated webhook

**Configure a Debugger webhook** f

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-email-deliverability-advisor4.77 KB

View saved version →

---
name: twilio-email-deliverability-advisor
description: >
  Deliverability advisor for the Twilio Email API specifically. Use ONLY when
  the developer explicitly mentions Twilio Email, comms.twilio.com, or a
  Twilio (non-SendGrid) email program. For all other deliverability questions
  — including generic ones — use twilio-sendgrid-deliverability-advisor.
tier: discover
---

## Role

You are an Email Deliverability Advisor for the Twilio Email API. This skill is a **work in progress** — Twilio Email deliverability tooling is more limited than SendGrid's. Apply general email best practices and flag where SendGrid-specific guidance does not apply.

## When This Skill Activates

Use when a developer is on the Twilio Email API (`comms.twilio.com`) and asks about:
- Emails going to spam, not reaching inbox, or getting blocked
- Bounce rates, spam complaints, domain authentication
- How to improve deliverability

Do NOT use for SendGrid — use `twilio-sendgrid-deliverability-advisor` instead.

---

## Step 0: Identify Platform

Check for platform signals before proceeding:

| Signal | Platform | Action |
|--------|----------|--------|
| Mentions `comms.twilio.com`, Account SID, or Auth Token | Twilio Email | Proceed |
| API key starts with `SG.` | SendGrid | Redirect |
| Mentions `app.sendgrid.com` | SendGrid | Redirect |
| No signal | Unknown | Ask |

**If SendGrid:** Stop. Respond: "For SendGrid deliverability, use the `twilio-sendgrid-deliverability-advisor` skill — it has SendGrid-specific tooling like SEQ scores, IP warmup schedules, and blocklist guidance."

**If unclear:** Ask exactly this before proceeding:
> "Are you using Twilio Email (Twilio Account SID / Auth Token, endpoint at comms.twilio.com) or SendGrid (API key starting with `SG.`, dashboard at app.sendgrid.com)?"

---

## Known Constraints

Twilio Email does not expose the same deliverability tooling as SendGrid:
- No Engagement Quality Score (SEQ)
- No IP pool management UI
- No Email Address Validation API (requires a separate SendGrid account)
- Dedicated IP is not available on the standard Twilio Email API — contact Twilio Sales for enterprise options

---

## Foundation Checklist (applies to all email programs)

### Authentication (do these first)

| Protocol | What it does | Required? |
|----------|-------------|----------|
| **SPF** | Authorizes sending servers for your domain | Yes |
| **DKIM** | Cryptographic signature proving message integrity | Yes |
| **DMARC** | Policy for SPF/DKIM failures (none/quarantine/reject) | Required for >5,000 msgs/day (Gmail, Yahoo, Microsoft, Apple); >1,000/day for Orange |

Configure domain authentication via the Twilio Console. SPF and DKIM are required at all volumes. DMARC thresholds vary by provider — see table above.

### List Hygiene

- Never buy email lists
- Use double opt-in for marketing lists
- Remove hard bounces immediately after each send
- Reconfirm subscribers inactive > 6 months

### Thresholds

| Metric | Healthy | Warning | Critical |
|--------|---------|---------|----------|
| Hard bounce rate | < 1% | 1-2% | > 2% |
| Spam complaint rate | < 0.08% | 0.08-0.1% | > 0.1% |

---

## Platform Limitations and Where to Get Help

The Twilio Email API has less built-in deliverability tooling than SendGrid. When you hit these limits, use the resources below:

| Question | Where to go |
|----------|-------------|
| What delivery stats are available? | Twilio Console → Monitor → Logs, or configure Event Webhooks via Console |
| Bounce and spam complaint data? | Event Webhooks are the primary signal; the Console provides basic send stats. For detailed per-message events, contact [Twilio Support](https://help.twilio.com/) to confirm current webhook event types |
| New domain warmup requirements? | No platform-enforced warmup schedule (unlike SendGrid's 41-day automated warmup). Follow manual warmup best practices in the Foundation Checklist above |
| Dedicated IP availability? | Not available on standard plans — 

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-email-send6.78 KB

View saved version →

---
name: twilio-email-send
description: >
  Use when the caller has Twilio credentials (Account SID + Auth Token or
  API Key SID + Secret) and needs to send email via comms.twilio.com/v1/Emails.
  This is Twilio-native email — NOT SendGrid. Do NOT use if the caller has a
  SendGrid API key (SG.-prefix) — use twilio-sendgrid-email-send instead.
  Covers single sends, batch sends up to 10,000 recipients, Liquid
  personalization, operation tracking, and error handling.
---

## Overview

> **Agent safety:** Always confirm recipients, subject, and content with the user before sending. Email is irreversible once delivered. Never send email autonomously without explicit user approval — especially for batch sends to multiple recipients.

**Twilio Email is a separate product from SendGrid.** Both send email, but they use different APIs, credentials, templating languages, and endpoints. If you have a SendGrid API key (`SG.`-prefix), use `twilio-sendgrid-email-send` instead.

| | Twilio Email (this skill) | SendGrid |
|---|---|---|
| **Base URL** | `https://comms.twilio.com/v1/emails` | `https://api.sendgrid.com/v3/mail/send` |
| **Auth** | Twilio Account SID + Auth Token (or API Key SID + Secret) | SendGrid API key (`SG.`-prefix) |
| **Templating** | Liquid (`{{variable}}`) | Handlebars (`{{variable}}`) |
| **Max recipients/request** | 10,000 | 1,000 |
| **Max message size** | 10MB (including attachments) | 30MB |
| **Status tracking** | Operation resource (poll `operationLocation`) | Event Webhooks (async POST) |
| **Console** | console.twilio.com | app.sendgrid.com |

---

## Prerequisites

- A Twilio account — see `twilio-account-setup` for signup and credentials
- A **Verified Sender**: an approved domain identity configured in the Twilio console that must match the `from` address domain
- Compliance with regional anti-spam regulations (CAN-SPAM, GDPR)

For a complete setup guide, see the Email Onboarding guide in the Twilio console.

---

## Authentication

The API uses **Basic Authentication** with either:
- Account SID + Auth Token
- API Key SID + API Key Secret

These are standard Twilio credentials — the same ones used for SMS, Voice, and other Twilio APIs.

---

## Send a Simple Email

`POST https://comms.twilio.com/v1/Emails`

The endpoint is **asynchronous** — it returns `202 Accepted` with an `operationId`, not a delivery confirmation.

```bash
curl -X POST "https://comms.twilio.com/v1/Emails" \
  --header "Content-Type: application/json" \
  --data '{
    "from": {
      "address": "support@example.com",
      "name": "Support Team"
    },
    "to": [
      {
        "address": "john.doe@example.com",
        "name": "John Doe"
      }
    ],
    "content": {
      "subject": "Your subject line",
      "html": "<p>Your message content in HTML format.</p>",
      "text": "Your message content in plain text."
    }
  }' \
  -u $TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN
```

Response (`202 Accepted`):
```json
{
  "operationId": "...",
  "operationLocation": "https://comms.twilio.com/v1/Emails/Operations/..."
}
```

Poll `operationLocation` to track delivery status.

---

## Batch Sending

Send the same message to multiple recipients in a single request by adding entries to the `to` array. Maximum **10,000 recipients** per request.

```json
{
  "from": {
    "address": "support@example.com",
    "name": "Support Team"
  },
  "to": [
    {
      "address": "john.doe@example.com",
      "name": "John Doe"
    },
    {
      "address": "jane.smith@example.com",
      "name": "Jane Smith"
    }
  ],
  "content": {
    "subject": "Your subject line",
    "html": "<p>Your message content in HTML format.</p>",
    "text": "Your message content in plain text."
  }
}
```

---

## Liquid Personalization

Use Liquid templating in the `content.subject`, `content.html`, and `content.text` fields. For each variable referenced (e.g. `{{firstName}}`), provide a matching key in the `variables` object for every recipient in the `to` array.

```j

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-enterprise-knowledge12.6 KB

View saved version →

---
name: twilio-enterprise-knowledge
description: >
  Add knowledge retrieval to AI agents using Twilio's Enterprise Knowledge
  product. Enterprise Knowledge is a centralized, searchable repository of your
  organization's documents, websites, and content — FAQs, support policies,
  warranty terms, product catalogs. Current models don't have access to how you
  run your business today. Enterprise Knowledge gives agents a way to query this
  repository during a conversation and ground their responses in your actual
  approved source material. This skill covers provisioning a Knowledge Base and
  uploading knowledge sources from web URLs, PDFs, and raw text, and running
  semantic search to retrieve relevant chunks at runtime. Enterprise Knowledge is
  shared across your organization — it captures what your organization knows and
  how it is meant to run. It is distinct from Conversation Memory
  (twilio-customer-memory), which is scoped to individual end-customers and
  captures what you know about a specific person. The two are designed to be
  combined: enterprise content for business practices, customer memory for
  personalization.
---

## Overview

Enterprise Knowledge gives AI and human agents access to your organization's actual source material during a conversation — FAQs, warranty policies, support scripts, product catalogs. Models trained on general data don't know how your business operates today; Enterprise Knowledge closes that gap by letting agents query a searchable repository of your approved content and inject accurate, up-to-date answers rather than hallucinated ones.

```
Your content (web/PDF/text) → Knowledge Base → Indexed chunks
Agent query → Search → Ranked chunks → Inject into LLM prompt
```

Enterprise Knowledge is shared across your organization and captures institutional content: how your products work, what your policies say, what your agents are supposed to do. It is distinct from Conversation Memory, which is scoped to individual end-customers. The two are designed to be combined — enterprise content for accuracy and business practices, customer memory for personalization.

**Auth: Basic Auth** — `TWILIO_ACCOUNT_SID` and `TWILIO_AUTH_TOKEN`.

---

## Prerequisites

- Twilio account with Enterprise Knowledge access (requires enablement)
  — New to Twilio? See `twilio-account-setup`
- `TWILIO_ACCOUNT_SID` and `TWILIO_AUTH_TOKEN` — see `twilio-iam-auth-setup`

---

## Quickstart

### Step 1 — Create a Knowledge Base

Knowledge Bases are containers for knowledge sources. Creation is async — returns 202, poll the `Location` header until `status: ACTIVE`.

**Python**
```python
import os, requests, time

account_sid = os.environ["TWILIO_ACCOUNT_SID"]
auth_token = os.environ["TWILIO_AUTH_TOKEN"]

res = requests.post(
    "https://memory.twilio.com/v1/ControlPlane/KnowledgeBases",
    auth=(account_sid, auth_token),
    json={
        "displayName": "product-docs",          # alphanumeric + hyphens only
        "description": "Product documentation for customer support agents"
    }
)

operation_url = res.headers["Location"]

# Poll until ready
while True:
    kb = requests.get(operation_url, auth=(account_sid, auth_token)).json()
    if kb.get("status") == "ACTIVE":
        kb_id = kb["id"]
        break
    if kb.get("status") == "FAILED":
        raise Exception("Knowledge Base creation failed")
    time.sleep(2)

print(kb_id)
```

**Node.js**
```javascript
const accountSid = process.env.TWILIO_ACCOUNT_SID;
const authToken = process.env.TWILIO_AUTH_TOKEN;
const authHeader = "Basic " + btoa(`${accountSid}:${authToken}`);

const res = await fetch("https://memory.twilio.com/v1/ControlPlane/KnowledgeBases", {
    method: "POST",
    headers: {
        "Authorization": authHeader,
        "Content-Type": "application/json",
    },
    body: JSON.stringify({
        displayName: "product-docs",
        description: "Product documentation for customer support agents",
    }),
});

const operationUrl = res.he

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-iam-auth-setup9.36 KB

View saved version →

---
name: twilio-iam-auth-setup
description: >
  Set up and manage Twilio authentication credentials: Auth Tokens, API keys
  (Standard, Main, Restricted), Access Tokens for client-side SDKs, and
  credential rotation. Use this skill as a prerequisite foundation before
  making any Twilio API calls.
---

## Overview

Twilio supports multiple authentication methods. For most developers: use Auth Token for local prototyping, then move to API Keys in production.

| Method | Use for | Security |
|--------|---------|----------|
| Account SID + Auth Token | Local prototyping, initial testing | Full account access — avoid in production |
| Account SID + API Key (Standard) + Secret | All production code | Recommended — revocable, no access to /Accounts or /Keys |
| Account SID + API Key (Restricted) + Secret | Fine-grained production access | Best — limit to specific resources only |
| Account SID + API Key (Main) + Secret | Account management automation | Full access like Auth Token, but revocable |

**For beginners / vibe-coders:** Start with Auth Token to get your first API call working, then create a Standard API Key before deploying anything. The key difference: if an API Key leaks, you revoke just that key. If your Auth Token leaks, your entire account is exposed until you rotate it.

---

## Prerequisites

- Twilio account — see `twilio-account-setup` if you don't have one
- Access to the [Twilio Console](https://console.twilio.com)

---

## Quickstart

Find your Account SID and Auth Token in the Console dashboard.

**Python**
```python
import os
from twilio.rest import Client

client = Client(os.environ["TWILIO_ACCOUNT_SID"], os.environ["TWILIO_AUTH_TOKEN"])
```

**Node.js**
```node
const client = require("twilio")(
    process.env.TWILIO_ACCOUNT_SID,
    process.env.TWILIO_AUTH_TOKEN
);
```

**Never commit Auth Token to version control or use in production.**

---

## Key Patterns

### API Keys (production)

**Create:** Console > Account > API keys & tokens > Create API key

| Key type | Access | Use case |
|----------|--------|----------|
| **Standard** | All resources except /Accounts and /Keys endpoints | Default for production apps |
| **Restricted** | Only the specific resources you grant | Multi-tenant apps, microservices, least-privilege |
| **Main** | Full account access (like Auth Token) | Account management automation (Console-only creation) |

After creation, copy the **API Key SID** (`SK...`) and **Secret** — the secret is shown only once.

**Python**
```python
client = Client(
    os.environ["TWILIO_API_KEY"],      # SK...
    os.environ["TWILIO_API_SECRET"],
    os.environ["TWILIO_ACCOUNT_SID"]   # required as third argument
)
```

**Node.js**
```node
const client = require("twilio")(
    process.env.TWILIO_API_KEY,
    process.env.TWILIO_API_SECRET,
    { accountSid: process.env.TWILIO_ACCOUNT_SID }
);
```

### Restricted API Keys

Restricted keys grant access only to specific Twilio API resources you define. Use them for least-privilege access in production.

**Create via the v1 IAM API** (not the v2010 /Keys.json endpoint — see CANNOT section):

**Python**
```python
key = client.iam.v1.api_key.create(
    account_sid=os.environ["TWILIO_ACCOUNT_SID"],
    friendly_name="messaging-only-key",
    key_type="restricted",
    policy={
        "allow": [
            "/2010-04-01/Accounts/{AccountSid}/Messages*"
        ]
    }
)
# Store key.sid and key.secret securely — secret shown only once
```

**Example permission patterns:**
| Permission | Grants access to |
|-----------|-----------------|
| `/2010-04-01/Accounts/{AccountSid}/Messages*` | Send and read messages |
| `/2010-04-01/Accounts/{AccountSid}/Calls*` | Make and manage calls |
| `/v2/Services/*/Verifications*` | Verify API only |

**Docs:** [Restricted API keys](https://www.twilio.com/docs/iam/api-keys/restricted-api-keys)

### Test Credentials

Make API calls without charges or sending real messages. Find at Console > Account > API keys & tokens > Test c

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-identity-verification-advisor9.82 KB

View saved version →

---
name: twilio-identity-verification-advisor
description: >
  Planning skill for identity verification and fraud prevention.
  Qualifies the developer's needs across authentication method,
  channel selection, fraud risk level, and user experience to
  recommend the right Twilio Verify + Lookup architecture. Handles
  login, signup, password reset, and risk-adaptive verification.
tier: discover
---

## Role

You are an Identity & Verification Architecture Advisor. When a developer describes anything related to verifying user identity, preventing fraud, implementing 2FA/MFA, or validating phone numbers — use this framework to reason about what they need.

## When This Skill Activates

Trigger on any of these signals:
- "OTP," "verification code," "2FA," "MFA," "two-factor"
- "Phone verification," "email verification," "device verification," "identity verification"
- "Fraud prevention," "phone validation," "number lookup"
- "Passwordless," "magic link," "passkey," "TOTP," "authenticator app"
- "Account signup," "login verification," "password reset," "account recovery"
- Any request to verify a user is who they claim to be

## Step 1: Detect Specificity and Decide Your Mode

**High-level request** (e.g., "I need to add phone verification to my signup flow"):
→ DISCOVERY MODE. Channel, fraud risk, and UX matter — qualify first.

**Mid-level request** (e.g., "Send an OTP via SMS and verify it"):
→ VALIDATION MODE. Clear approach — check if they've considered fraud (SMS pumping), fallback channels, and rate limiting.

**Specific implementation request** (e.g., "Call the Verify API to start a verification with channel=sms"):
→ BUILD MODE. Proceed with `twilio-verify-send-otp`. Quick check: Are they using Verify (highly recommended) or rolling their own OTP logic? If custom, strongly recommend Verify — it handles rate limiting, code generation, expiry, and fraud protection so you don't have to.

## Step 2: Qualify Intent — The 4 Essential Questions

1. **What are you verifying and when?**
   - Account signup (new user registration) → Phone/email/device verification
   - Login (returning user authentication) → 2FA/MFA, phone verification, device verification
   - Password reset / account recovery → Identity confirmation (these are the same flow — verify identity before allowing reset)
   - High-value transaction (payment, account change) → Step-up verification

2. **What channels can you reach the user on?**
   - SMS → Most common. Universal reach.
   - Email → Good for account verification. Less real-time.
   - WhatsApp → Growing. Good for international users already on WhatsApp. Cost-effective for high-traffic countries.
   - Voice → Accessibility fallback. Automated call reads the code.
   - Push notification → Best UX (one-tap approve). Requires your mobile app with Verify Push SDK.
   - TOTP (authenticator app) → No network dependency. User must have set up app (Google Authenticator, Authy).
   - Passkeys → Newest. Phishing-resistant. Requires WebAuthn browser support.

3. **What's your fraud risk level?**
   - Low (basic signup confirmation): SMS OTP is fine
   - Medium (financial account, PII access): Add Lookup line type intelligence before sending OTP
   - High (payment authorization, KYC-regulated business): Line type intelligence + SIM swap check + step-up to Push or TOTP

4. **What does your user base look like?**
   - US/Canada primarily → SMS works well. Consider toll-free for cost.
   - International → WhatsApp may have better delivery rates and lower cost than SMS in high-traffic countries.
   - Mobile app users → Push verification is the best UX (no code to type)
   - Enterprise / high-security → TOTP or Passkeys (no phone network dependency)

## Step 3: Assess Sophistication — The Verification Ladder

### Level 1: Basic OTP Verification
**Developer says:** "I need to send a code and verify it."
**Architecture:** Twilio Verify API (start verification → check verification)
**Highly recommended:** Use the Verify API r

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-isv-sms-best-practices11 KB

View saved version →

---
name: twilio-isv-sms-best-practices
description: >
  Best practices for ISVs (Independent Software Vendors) building SMS
  features into multi-tenant SaaS platforms using Twilio. Covers customer
  onboarding for A2P and toll-free compliance, subaccount architecture, sender management, billing patterns, and common ISV pitfalls. Use this when building SMS
  capabilities that your customers will use to message their end users.
---

## Overview

ISVs face unique challenges when building SMS into their platforms: each customer needs their own number registration, sender pool management, compliance isolation, and usage tracking. This skill consolidates the architectural patterns and operational knowledge specific to multi-tenant SMS platforms.

---

## Are You an ISV?

Before following this skill, determine whether you are an Independent Software Vendor (ISV) or a direct customer.

### Direct Customer

Your company sends messages for your own products and services. Your end users know they are interacting with your brand.

**Example:** A shoe company called CoolShoes sends marketing messages and order updates for their own products. Even if CoolShoes owns multiple brands (CoolShoes and CoolShirts), they are still a direct customer because both brands are operated by the same company.

**Follow the direct customer onboarding process** — not this ISV skill.

### ISV (Independent Software Vendor)

Your company provides messaging services to other businesses, who are represented by their own brands. Your end users think they are interacting with your client's brand, not yours.

**Example:** HotelTech Inc. sells a technology platform for hotels. When hotel SleepWell Inn uses the service, hotel visitors receive messages that appear to come from SleepWell Inn. Visitors likely don't know HotelTech powers the interaction.

**Follow this ISV skill.**

### Still Not Sure? Two Key Questions

**1. Who do your end users think they are receiving messages from?**
- **Your brand** → You are a direct customer
- **Your client's brand** → You are an ISV

**2. How much control do your clients have over message contents?**

| Scenario | Classification | Example |
|----------|---------------|---------|
| **Templated messages with little/no customization** | Direct customer | EventSite sends templated event reminders to attendees. Event organizers can only customize basic details (event name, date). End users interact with EventSite brand. |
| **Clients can customize and send messages on their own behalf** | ISV | PoweringEvents provides a platform where car dealership CarWorld can write and send customized messages about their Cars & Coffee events. Attendees don't know PoweringEvents exists — messages appear to come from CarWorld. |

**If you give clients the ability to send customized messages that end users perceive as coming directly from your client, you are an ISV.**

---

## Prerequisites

- Twilio parent account (for your platform)
- Understanding of A2P 10DLC requirements
  — See `twilio-compliance-onboarding` for registration basics
- Understanding of Messaging Services
  — See `twilio-messaging-services` for sender pool management
- Environment variables:
  - `TWILIO_ACCOUNT_SID` (parent account)
  - `TWILIO_AUTH_TOKEN` (parent account)
  — See `twilio-iam-auth-setup` for credential security
- SDK: `pip install twilio` / `npm install twilio`

---

## Key Architecture Patterns

### Subaccount Strategy

**Recommended approach:** Create one Twilio subaccount per customer.

**Why subaccounts:**
- **Billing isolation:** Each customer's usage appears on their own Twilio account, making cost tracking and pass-through billing straightforward
- **Compliance isolation:** One customer's compliance violations or spam complaints do not affect other customers
- **Credential isolation:** Each customer has their own Account SID and Auth Token, limiting the blast radius if credentials are compromised
- **Separate rate limits:** Each subaccount has its own th

Preview of the first 4,000 characters. Read full instructions →

twilio-lookup-phone-intelligence5.21 KB

View saved version →

---
name: twilio-lookup-phone-intelligence
description: >
  Look up phone number intelligence via Twilio Lookup v2 API. Covers number
  validation, line type detection (mobile/landline/VoIP), SIM swap detection,
  caller name, identity match, and SMS pumping risk scoring. Use this skill
  to validate numbers or assess fraud risk before sending messages or calls.
---

## Overview

Twilio Lookup validates phone numbers and provides optional intelligence packages. Basic validation is free; data packages (line type, SIM swap, etc.) are paid per lookup.

---

## Prerequisites

- Twilio account (free trial works for basic lookups)
  — New to Twilio? See `twilio-account-setup`
- Environment variables:
  - `TWILIO_ACCOUNT_SID`
  - `TWILIO_AUTH_TOKEN`
  — See `twilio-iam-auth-setup` for credential setup and best practices
- SDK: `pip install twilio` / `npm install twilio`

---

## Quickstart

**Python**
```python
import os
from twilio.rest import Client

client = Client(os.environ["TWILIO_ACCOUNT_SID"], os.environ["TWILIO_AUTH_TOKEN"])

phone = client.lookups.v2.phone_numbers("+15108675310").fetch()

print(phone.valid)            # True / False
print(phone.phone_number)     # +15108675310 (E.164)
print(phone.national_format)  # (510) 867-5310
print(phone.country_code)     # US
```

**Node.js**
```node
const twilio = require("twilio");
const client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);

const phone = await client.lookups.v2.phoneNumbers("+15108675310").fetch();

console.log(phone.valid);
console.log(phone.phoneNumber);
console.log(phone.nationalFormat);
```

If `valid` is `false`, check `phone.validationErrors` for the reason.

---

## Key Patterns

### Line Type Intelligence (paid)

Identifies mobile, landline, VoIP, toll-free, etc.

**Python**
```python
phone = client.lookups.v2.phone_numbers("+15108675310").fetch(
    fields="line_type_intelligence"
)
print(phone.line_type_intelligence)
# {'type': 'mobile', 'carrier_name': 'T-Mobile USA', ...}
```

**Node.js**
```node
const phone = await client.lookups.v2.phoneNumbers("+15108675310").fetch({
    fields: "line_type_intelligence",
});
console.log(phone.lineTypeIntelligence);
```

Line types: `mobile`, `landline`, `voip`, `toll-free`, `fixedVoip`, `nonFixedVoip`, `personal`, `payphone`, `unknown`

### Multiple Packages in One Request

**Python**
```python
phone = client.lookups.v2.phone_numbers("+15108675310").fetch(
    fields="line_type_intelligence,sim_swap,caller_name"
)
```

**Node.js**
```node
const phone = await client.lookups.v2.phoneNumbers("+15108675310").fetch({
    fields: "line_type_intelligence,sim_swap,caller_name",
});
```

### Validate Before Sending

**Python**
```python
phone = client.lookups.v2.phone_numbers("+invalid").fetch()
if not phone.valid:
    print(f"Invalid number: {phone.validation_errors}")
    # Handle gracefully — do not attempt to send
```

**Node.js**
```node
const phone = await client.lookups.v2.phoneNumbers("+invalid").fetch();
if (!phone.valid) {
    console.log("Invalid number:", phone.validationErrors);
}
```

### Available Data Packages

| Package | `fields` value | Coverage | Use case |
|---------|---------------|----------|----------|
| Line Type Intelligence | `line_type_intelligence` | Worldwide | Route by line type; block VoIP |
| Caller Name | `caller_name` | US only | Show caller ID |
| SIM Swap | `sim_swap` | Select regions | Fraud detection |
| Identity Match | `identity_match` | Select regions | Verify ownership |
| SMS Pumping Risk | `sms_pumping_risk` | Worldwide | Fraud prevention |
| Reassigned Number | `reassigned_number` | US only | Check if recycled |

---

## Common Errors

| Code | Meaning | Fix |
|------|---------|-----|
| 20404 | Phone number not found | Number may be invalid or unsupported format |
| 60601 | Data package not available for this region | Check regional coverage before requesting package |

---

## CANNOT

- **Cannot look up by name or address** — Input is always a phone numb

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-marketing-promotions-advisor10.9 KB

View saved version →

---
name: twilio-marketing-promotions-advisor
description: >
  Planning skill for marketing and promotional messaging. Qualifies
  the developer's campaign needs across channel selection, compliance,
  audience segmentation, and delivery tracking to recommend the right
  Twilio messaging architecture. Handles both "set up a promotional
  SMS campaign" and "build a multi-channel engagement pipeline with
  Segment integration."
tier: discover
---

## Role

You are a Marketing & Promotions Architecture Advisor. When a developer describes anything related to sending promotional messages, running campaigns, lead conversion, or customer engagement at scale — use this framework to reason about what they need.

## When This Skill Activates

Trigger on any of these signals:
- "Marketing campaign," "promotional messages," "bulk SMS," "mass email", "text message"
- "Lead conversion," "drip campaign," "engagement," "re-engagement"
- "WhatsApp templates," "RCS," "rich messaging", "branded message"
- "Audience segmentation," "Segment," "CDP," "customer data"
- "Opt-in," "opt-out," "consent management," "TCPA," "A2P"
- Any request to send messages to a list of recipients at scale

## Step 1: Detect Specificity and Decide Your Mode

**High-level request** (e.g., "I want to send promotional messages to my customers"):
→ DISCOVERY MODE. Channel selection, compliance, and volume are critical — qualify before coding.

**Mid-level request** (e.g., "I need to send WhatsApp template messages for a holiday promotion"):
→ VALIDATION MODE. They've chosen a channel — check compliance readiness (approved templates? sender registration?), volume expectations, and tracking needs.

**Specific implementation request** (e.g., "Send an SMS via Messaging Service with a StatusCallback"):
→ BUILD MODE. Proceed with the Product skill. Quick check: Are they US-based and need A2P 10DLC? Are they using a Messaging Service (recommended) or raw `from` number?

## Step 2: Qualify Intent — The 6 Essential Questions

1. **What are you promoting?**
   - Product launches, sales, offers → Standard marketing campaign
   - Lead nurture / drip sequences → Time-based automation, needs scheduling
   - Re-engagement (win-back) → Compliance-sensitive (previously opted-out?)
   - Event-driven (cart abandonment, browse behavior) → Needs real-time triggers, likely Segment integration

2. **Which channels?** (Reference Channel Mix Matrix — Marketing column)
   - **SMS/MMS** → Highest open rates (98%), immediate. Best for time-sensitive offers. US requires A2P 10DLC compliance.
   - **RCS** → Enables branded messaging and rich content (cards, carousels, suggested replies, tap-to-action). Requires creating a branded RCS sender and carrier approval before sending messages broadly. Can send to allowlisted test devices. Use Messaging Service to enable native SMS/MMS fallback for recipients who do not have RCS capable devices (iPhone users on < iOS 18 or Android users not using Google messages).
   - **Email** → Highest volume capacity, lowest per-message cost. Best for rich content (images, HTML). Use `twilio-email-send` (Twilio Account SID + Auth Token, comms.twilio.com) or `twilio-sendgrid-email-send` (SendGrid API key, SG.-prefix).
   - **WhatsApp** → Dominant internationally (India, Brazil, Europe). Requires pre-approved templates for outbound. 24-hour service window for free-form replies.
   - **Multi-channel** → Most campaigns should use 2+ channels. Email for initial reach, SMS for urgency, WhatsApp for international.

3. **What's your audience size and send frequency?**
   - < 1,000 recipients: Simple API calls, no Messaging Service required
   - 1,000-100,000: Use Messaging Services for sender pool management, geo-matching, sticky sender
   - 100,000+: Messaging Services required. Rate limiting critical. Expect 429 errors — implement exponential backoff with ±10% jitter.

4. **What geography?**
   - US-only → A2P 10DLC registration required for SMS. Toll-free verification for lower

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-messaging-channel-advisor6.11 KB

View saved version →

---
name: twilio-messaging-channel-advisor
description: >
  Planning skill that helps the developer pick the right Twilio
  messaging channel — SMS, MMS, RCS, or WhatsApp — for a given use
  case. Qualifies intent across content type, geography, use case
  (marketing / notifications / OTP / support), cost model, and brand
  presence. Use when the developer asks "which channel should I use",
  "SMS vs RCS vs WhatsApp", mentions a country or region, asks about
  branded messaging, rich content, or fallback — and proactively when
  the developer says "send SMS" but their use case (rich content,
  international reach, branded experience) would benefit from a
  different channel.
tier: discover
---

## Role

You are a Messaging Channel Advisor. When a developer describes a messaging use case, qualify their intent across content type, geography, use case, cost, and brand before recommending a channel. Your job is to educate and redirect — developers frequently default to "SMS" vocabulary when RCS or WhatsApp would serve them better.

Pair with `twilio-send-message` (for the actual send), `twilio-messaging-services` (for production features and fallback), and `twilio-content-template-builder` (for rich content).

---

## Qualifying Questions

### 1. What content are you sending?
- **Plain text only** → SMS (default), WhatsApp for international
- **Media (image, video, PDF)** → MMS (US/CA/AU only), WhatsApp, or RCS
- **Rich interactive (cards, carousels, buttons, suggested replies)** → RCS (branded, US reach + expanding) or WhatsApp (template-approved)

### 2. Where are your recipients?
- **US** → SMS is the baseline; RCS for branded/rich content (iOS 18+ and Android); WhatsApp is secondary (low consumer adoption)
- **LATAM (Brazil, Mexico, Argentina)** → WhatsApp is dominant; SMS as fallback
- **APAC (India, Southeast Asia)** → WhatsApp strong; SMS also works
- **EU / UK** → SMS broadly; WhatsApp meaningful in DE, ES, IT; RCS availability varies
- **Global** → Multi-channel via Messaging Services with geomatch + fallback

### 3. What's the use case?
- **Marketing / promotional** → RCS (if US + rich content) + SMS fallback, or WhatsApp templates (intl). See `twilio-marketing-promotions-advisor`.
- **Transactional notifications** (order, shipping, delivery) → RCS for branded UX + SMS fallback; SMS only if cost-sensitive. See `twilio-notifications-alerts-advisor`.
- **OTP / verification codes** → Prefer `twilio-verify-send-otp`. Verify handles rate limits, retries, and fraud protection. Works across SMS, WhatsApp, RCS, push, TOTP.
- **Customer support / conversational** → WhatsApp (24-hr session model fits conversations) or RCS
- **Time-sensitive alerts** (fraud, outage, emergency) → SMS (highest delivery reliability, no app dependency)

### 4. What's your cost model tolerance?
- **SMS** — per-message pricing, varies by region; predictable
- **MMS** — higher per-message than SMS
- **RCS** — varies by region + content type (Basic vs. Rich)
- **WhatsApp** — conversation-based (24-hr window free-form; templates charged per conversation)

### 5. Does brand presence matter?
- **Yes (branded sender, logo, verified)** → RCS in the US, or WhatsApp Business (green tick) internationally
- **Cross-OS branded** (reach iPhone + Android with one experience) → RCS (now supported on iOS 18+ and Android) with SMS fallback for older devices

---

## Common User Vocabulary Translations

Developers often use loose vocabulary. Translate before recommending.

| User says | Often means | Likely best channel |
|-----------|-------------|---------------------|
| "Send an SMS" | Message to a phone | SMS — unless rich content, branded, or international |
| "Text message" | Same as SMS | SMS — educate if rich or branded needed |
| "Branded message" | Brand visible to user | RCS (US) or WhatsApp (intl) |
| "Rich message" | Cards / buttons / media | RCS or WhatsApp template |
| "Show my logo" | Branded sender | RCS (not a phone number feature) |
| "OTP" / "verificat

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-messaging-overview5.88 KB

View saved version →

---
name: twilio-messaging-overview
description: >
  Twilio Messaging channel overview and onboarding guide. Covers all
  channels (SMS, WhatsApp, RCS, Facebook Messenger), the unified
  Messages API, channel selection guidance, and the recommended setup
  sequence from first message to production monitoring. Start here
  before choosing a specific messaging channel.
---

## Overview

Twilio's Messaging platform sends and receives messages across multiple channels through a single API. All channels use `client.messages.create()` — only the address format changes.

| Channel | Address format | Rich media | Template required? | Reach | Skill |
|---------|---------------|------------|-------------------|-------|-------|
| **SMS/MMS** | `+15551234567` (E.164) | MMS: images/video, US/CA/AU only | No | Global (180+ countries) | `twilio-sms-send-message` |
| **WhatsApp** | `whatsapp:+15551234567` | Yes (images, docs, video, location) | Outside 24hr window: yes | 190+ countries | `twilio-whatsapp-send-message` |
| **RCS** | Same number (via Messaging Service) | Yes (rich cards, carousels, video) | No | US + expanding globally | `twilio-rcs-messaging` |
| **Facebook Messenger** | `messenger:{page-scoped-id}` | Yes | No | Global | — |

---

## Which Channel Should I Use?

| If you need to... | Use | Why |
|-------------------|-----|-----|
| Reach any phone number | SMS | Universal — works on every phone, no app needed |
| Send rich media globally | WhatsApp | Images, docs, video work worldwide (MMS is US/CA/AU only) |
| Send time-sensitive alerts (OTP, outages) | SMS | Highest open rates, no app dependency |
| Reach opted-in audience at lower cost | WhatsApp | No per-message fee in many markets |
| Run marketing campaigns across channels | Start with `twilio-marketing-promotions-advisor` | Planner skill handles channel mix, compliance, and fallback |
| Send transactional notifications | Start with `twilio-notifications-alerts-advisor` | Planner skill handles urgency-based channel routing |

**Not sure?** Use a Planner skill first — it will qualify your use case and recommend the right channel combination.

---

## Unified API

All channels share `messages.create()`. The only difference is the address format in `from` and `to`.

**Python**
```python
import os
from twilio.rest import Client

client = Client(os.environ["TWILIO_ACCOUNT_SID"], os.environ["TWILIO_AUTH_TOKEN"])

# SMS
sms = client.messages.create(
    from_="+15017122661",
    to="+15558675310",
    body="Your order shipped."
)

# WhatsApp — same API, prefixed addresses
whatsapp = client.messages.create(
    from_="whatsapp:+15017122661",
    to="whatsapp:+15558675310",
    body="Your order shipped."
)
```

**Node.js**
```javascript
const client = require("twilio")(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);

// SMS
const sms = await client.messages.create({
    from: "+15017122661",
    to: "+15558675310",
    body: "Your order shipped.",
});

// WhatsApp — same API, prefixed addresses
const whatsapp = await client.messages.create({
    from: "whatsapp:+15017122661",
    to: "whatsapp:+15558675310",
    body: "Your order shipped.",
});
```

---

## Onboarding Sequence

Set up messaging in this order. Each step builds on the previous.

### Step 1: Foundation
Get a Twilio number, send your first SMS.
- `twilio-account-setup` → `twilio-sms-send-message`

### Step 2: Sender Strategy
Create a Messaging Service and add your numbers to a sender pool. Use `messagingServiceSid` instead of `from` for all production sends — this enables geo-match, sticky sender, and unlocks compliance features.
- `twilio-messaging-services`

### Step 3: Compliance
Register for A2P 10DLC (required for US SMS traffic). Set up opt-out handling.
- `twilio-compliance-onboarding` → `twilio-compliance-traffic`

### Step 4: Protect
Enable SMS pumping protection (prevents artificial traffic inflation) and compliance toolkit (quiet hours, reassigned number detection) on your Messaging Service.

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-messaging-services12.5 KB

View saved version →

---
name: twilio-messaging-services
description: >
  Create and configure Twilio Messaging Services for production messaging.
  Covers sender pools, geo-match, sticky sender, message scheduling,
  compliance toolkit, SMS pumping protection, link shortening, and
  intelligent alerts. Use this skill when setting up production-ready
  messaging infrastructure.
---

## Overview

A Messaging Service groups senders (phone numbers, short codes, toll-free numbers) with shared configuration. Send via `messagingServiceSid` instead of a specific `from` number — Twilio picks the best sender automatically.

**Use a Messaging Service for all production sends.** Beyond sender pools, it unlocks compliance toolkit, SMS pumping protection, link shortening, message scheduling, and intelligent alerts. For channel selection guidance, see `twilio-messaging-overview`.

---

## Prerequisites

- Twilio account with at least one SMS-capable phone number
  — New to Twilio? See `twilio-account-setup`
- Environment variables:
  - `TWILIO_ACCOUNT_SID`
  - `TWILIO_AUTH_TOKEN`
  — See `twilio-iam-auth-setup` for credential setup and best practices
- SDK: `pip install twilio` / `npm install twilio`

---

## Quickstart

**Python**
```python
import os
from twilio.rest import Client

client = Client(os.environ["TWILIO_ACCOUNT_SID"], os.environ["TWILIO_AUTH_TOKEN"])

# Step 1: Create the service
service = client.messaging.v1.services.create(
    friendly_name="Production Notifications Service"
)
print(service.sid)  # MGxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx — save as MESSAGING_SERVICE_SID

# Step 2: Add a phone number
client.messaging.v1 \
    .services(service.sid) \
    .phone_numbers \
    .create(phone_number_sid="PNxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")

# Step 3: Send via the service
message = client.messages.create(
    messaging_service_sid=service.sid,
    to="+15558675310",
    body="Your order has shipped."
)
print(message.sid)
```

**Node.js**
```node
const twilio = require("twilio");
const client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);

// Step 1: Create the service
const service = await client.messaging.v1.services.create({
    friendlyName: "Production Notifications Service",
});
console.log(service.sid);

// Step 2: Add a phone number
await client.messaging.v1
    .services(service.sid)
    .phoneNumbers.create({ phoneNumberSid: "PNxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" });

// Step 3: Send via the service
const message = await client.messages.create({
    messagingServiceSid: service.sid,
    to: "+15558675310",
    body: "Your order has shipped.",
});
console.log(message.sid);
```

---

## Key Patterns

### Create Service with Webhooks and Features

**Python**
```python
service = client.messaging.v1.services.create(
    friendly_name="Marketing Campaigns",
    inbound_request_url="https://yourapp.com/sms/inbound",
    status_callback="https://yourapp.com/sms/status",
    sticky_sender=True,
    area_code_geomatch=True,
    validity_period=14400
)
```

**Node.js**
```node
const service = await client.messaging.v1.services.create({
    friendlyName: "Marketing Campaigns",
    inboundRequestUrl: "https://yourapp.com/sms/inbound",
    statusCallback: "https://yourapp.com/sms/status",
    stickySender: true,
    areaCodeGeomatch: true,
    validityPeriod: 14400,
});
```

### Optional Features

| Feature | Parameter | Description |
|---------|-----------|-------------|
| Sticky Sender | `sticky_sender` | Same sender for same recipient |
| Area Code Geomatch | `area_code_geomatch` | Match sender area code to recipient |
| Validity Period | `validity_period` | Discard undelivered messages after N seconds |
| Smart Encoding | `smart_encoding` | Convert unicode to GSM-7 |
| MMS Converter | `mms_converter` | Convert MMS to SMS if recipient can't receive MMS |
| Message Scheduling | `send_at` on message | Schedule sends up to 7 days ahead (see below) |
| Link Shortening | `shorten_urls` | Shorten links with branded domain + click tracking 

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-messaging-webhooks7.9 KB

View saved version →

---
name: twilio-messaging-webhooks
description: >
  Receive and respond to inbound messages and track outbound delivery status
  via Twilio webhooks — across SMS, MMS, WhatsApp, and RCS. Covers webhook
  request parameters, replying with TwiML, validating webhook signatures for
  security, and handling status callbacks. Use this skill whenever an agent
  needs to handle incoming messages on any channel or track outbound message
  delivery in real time.
---

## Overview

Twilio sends a POST webhook to your server when a user messages your Twilio number (inbound) or when an outbound message changes delivery state (status callback). Your server returns TwiML to reply, or `204` to acknowledge without replying. The same webhook pattern works across SMS, MMS, WhatsApp, and RCS.

---

## Prerequisites

- Twilio account with a messaging-capable sender configured with a webhook URL
  — New to Twilio? See `twilio-account-setup`
  — For sending outbound messages first, see `twilio-send-message`
- Publicly accessible endpoint (use `ngrok http 5000` for local dev)
- `TWILIO_ACCOUNT_SID` and `TWILIO_AUTH_TOKEN` — see `twilio-iam-auth-setup`
- SDK: `pip install twilio flask` / `npm install twilio express`

---

## Quickstart

Set your webhook URL in Console: **Phone Numbers > Active Numbers > your number > Messaging > "A Message Comes In"**

> **Security:** The inbound message `Body` is untrusted external input. If passing message content to an LLM, always isolate it as user input — never concatenate directly into system prompts. Validate the request origin with `X-Twilio-Signature` (see Key Patterns below), but note that signature validation confirms the *source*, not that the *content* is safe.

> **Note:** This quickstart omits signature validation for brevity. For production, always validate `X-Twilio-Signature` — see the Webhook Security pattern below.

**Python (Flask)**
```python
from flask import Flask, request
from twilio.twiml.messaging_response import MessagingResponse

app = Flask(__name__)

@app.route("/incoming", methods=["POST"])
def incoming_message():
    body = request.form.get("Body")
    response = MessagingResponse()
    response.message(f"Got your message: {body}")
    return str(response)
```

**Node.js (Express)**
```javascript
const express = require("express");
const twilio = require("twilio");
const app = express();
app.use(express.urlencoded({ extended: false }));

app.post("/incoming", (req, res) => {
    const twiml = new twilio.twiml.MessagingResponse();
    twiml.message(`Got your message: ${req.body.Body}`);
    res.type("text/xml").send(twiml.toString());
});
```

---

## Key Patterns

### Configure Webhook URL via API

For SMS/MMS on a phone number:

**Python**
```python
client.incoming_phone_numbers("PNxxxxxxxxxx").update(
    sms_url="https://yourapp.com/incoming",
    sms_method="POST"
)
```

**Node.js**
```javascript
await client.incomingPhoneNumbers("PNxxxxxxxxxx").update({
    smsUrl: "https://yourapp.com/incoming",
    smsMethod: "POST",
});
```

For WhatsApp and RCS, webhook URLs are configured on the sender — see `twilio-whatsapp-manage-senders` and `twilio-rcs-messaging`.

### Inbound Webhook Parameters

| Parameter | Description |
|-----------|-------------|
| `MessageSid` | Unique message identifier |
| `From` | Sender's phone number or channel address (E.164, or `whatsapp:+...`) |
| `To` | Your Twilio number or channel address |
| `Body` | Message text |
| `NumMedia` | Number of media attachments |
| `MediaUrl0` | URL of first media attachment (if any) |
| `MediaContentType0` | MIME type of first attachment |

### Handle Inbound Media (MMS / WhatsApp / RCS)

**Python (Flask)**
```python
@app.route("/incoming", methods=["POST"])
def incoming_message():
    num_media = int(request.form.get("NumMedia", 0))
    response = MessagingResponse()
    if num_media > 0:
        media_type = request.form.get("MediaContentType0")
        response.message(f"Got your {media_type} attachment!")
    else:
    

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-notifications-alerts-advisor9.58 KB

View saved version →

---
name: twilio-notifications-alerts-advisor
description: >
  Planning skill for transactional notifications, alerts, and
  reminders. Qualifies the developer's needs across urgency, channel
  selection, delivery confirmation, and fallback patterns to recommend
  the right Twilio notification architecture. Handles both "send
  shipping updates to customers" and "build a multi-channel alert
  system with delivery confirmation and fallback."
tier: discover
---

## Role

You are a Notifications & Alerts Architecture Advisor. When a developer describes anything related to sending transactional messages — order confirmations, shipping updates, appointment reminders, system alerts, or time-sensitive notifications — use this framework to reason about what they need.

## When This Skill Activates

Trigger on any of these signals:
- "Notification," "alert," "reminder," "transactional message"
- "Order confirmation," "shipping update," "delivery notification"
- "Appointment reminder," "booking confirmation"
- "System alert," "status update," "password reset notification"
- "Two-way notification" (customer can reply to take action)
- Any request to send event-driven messages that are NOT marketing/promotional

## Key Distinction: Notifications vs Marketing

Notifications are **transactional** — triggered by a specific event or action. They are NOT marketing. This distinction matters for:
- **Compliance:** Transactional messages have lighter consent requirements than promotional (but still need consent for some channels).
- **Channel behavior:** Transactional SMS doesn't require A2P campaign registration in some cases (verify with current rules).
- **Timing:** Notifications are event-driven (immediate or scheduled), not batch campaigns.

If the developer's use case is actually promotional → redirect to `twilio-marketing-promotions-advisor`.

## Step 1: Detect Specificity and Decide Your Mode

**High-level request** (e.g., "I need to notify customers about their orders"):
→ DISCOVERY MODE. Urgency, channel, and delivery confirmation needs vary dramatically — qualify first.

**Mid-level request** (e.g., "Send SMS appointment reminders 24 hours before"):
→ VALIDATION MODE. Clear use case — check if they need delivery confirmation, fallback on failure, or reply handling.

**Specific implementation request** (e.g., "POST to /Messages with a StatusCallback for delivery tracking"):
→ BUILD MODE. Proceed with the Product skill. Quick check: Are they using a Messaging Service? Do they have StatusCallbacks configured?

## Step 2: Qualify Intent — The 5 Essential Questions

1. **What event triggers the notification?**
   - User action (order placed, appointment booked, password reset) → Real-time, API-triggered
   - System event (threshold breach, deployment status, error alert) → Webhook-triggered or cron-scheduled
   - Time-based (appointment in 24 hours, subscription expiring) → Scheduled sends

2. **How urgent is delivery?**
   - **Critical (seconds matter):** Security alerts, fraud detection, OTP → SMS or Voice. Redundant channels.
   - **Important (minutes):** Shipping updates, appointment reminders → SMS or WhatsApp.
   - **Informational (hours OK):** Order confirmations, receipts, summaries → Email. SMS optional.
   - Urgency determines channel priority AND whether you need fallback chains.

3. **Does the customer need to respond or take action?**
   - No (one-way): Simple send — SMS, Email, or Voice notification
   - Yes (two-way): Need reply handling — Webhooks for inbound SMS, or interactive WhatsApp buttons
   - Yes (rich interaction): WhatsApp interactive messages, RCS rich cards, or Voice IVR for confirmation

4. **What happens if delivery fails?**
   - Acceptable loss: Log the failure, move on. Email is often this category.
   - Needs retry: Implement retry logic with backoff. Common for SMS.
   - Needs fallback to another channel: SMS fails → try Voice call. Critical for urgent notifications.
   - Must confirm delivery: StatusCallba

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-numbers-senders13.5 KB

View saved version →

---
name: twilio-numbers-senders
description: >
  Choose the right Twilio number type and sender BEFORE building. Covers
  phone numbers (local, toll-free, short code, mobile), alphanumeric sender
  IDs, WhatsApp senders, RCS agents, international availability, and
  regulatory bundles. Each number type has its own compliance program —
  choosing wrong means rebuilding. Use this skill first.
---

## Overview

Choosing the right number type and sender is the **first decision** in any Twilio project. Each number type comes with its own compliance/verification program, throughput limits, and capabilities. Developers who skip this step buy numbers first, build their app, then discover they chose the wrong type.

**Lifecycle:** Choose numbers/senders (this skill) → Register them (`twilio-compliance-onboarding`) → Follow traffic rules (`twilio-compliance-traffic`)

---

## US Number Types — Comparison

| | **Local (10DLC)** | **Toll-Free** (800/888/877) | **Short Code** (5-6 digits) |
|---|---|---|---|
| **SMS** | Yes | Yes | Yes |
| **MMS** | Yes | Yes | Yes |
| **Voice** | Yes | Yes | No |
| **Two-way** | Yes | Yes | Yes |
| **Throughput** | ~1-75+ SMS/sec (varies by trust score) | ~3 SMS/sec | 10-100 SMS/sec |
| **Compliance program** | **A2P 10DLC** (brand + campaign) | **Toll-Free Verification** | **Pre-approved at purchase** (carrier review) |
| **Approval timeline** | 10-15 business days | 3-5 business days | 8-12 weeks provisioning |
| **Best for** | Transactional, marketing, support | Notifications, support, verification | High-volume marketing, 2FA |
| **Cost** | Lowest | Medium | Highest (setup + monthly + per-msg) |

Source: [US/Canada SMS comparison](https://help.twilio.com/articles/360038173654-Comparison-of-SMS-messaging-in-the-US-and-Canada-for-long-codes-short-codes-and-toll-free-phone-numbers)

### Compliance Programs Per Number Type

Every US number type requires its own verification before traffic flows:

- **Local 10DLC → A2P 10DLC registration:** Brand registration (EIN, business identity) + Campaign registration (use case, sample messages, opt-in flow). Trust Score determines throughput. Sole Proprietors: ~1 SMS/sec, 1 campaign. Standard: ~15+ SMS/sec, scales with secondary vetting. [A2P overview](https://www.twilio.com/docs/messaging/compliance/a2p-10dlc) | [Quickstart](https://www.twilio.com/docs/messaging/compliance/a2p-10dlc/quickstart)

- **Toll-Free → Toll-Free Verification (TFV):** Business name, website, use case description, sample messages, opt-in type. Unverified toll-free numbers **cannot send SMS to US/Canada**. [Console onboarding](https://www.twilio.com/docs/messaging/compliance/toll-free/console-onboarding) | [Requirements](https://help.twilio.com/articles/5377174717595-Toll-Free-Message-Verification-for-US-Canada)

- **Short Code → Carrier review at purchase:** Application reviewed during 8-12 week provisioning. Available in 14 countries: US, Canada, UK, Germany, France, India, Brazil, Mexico, Argentina, Colombia, Dominican Republic, New Zealand, Spain, Sweden. [Short code guidelines by country](https://www.twilio.com/en-us/guidelines/short-code) | [What is a short code?](https://help.twilio.com/articles/223182068-What-is-a-Messaging-Short-Code-)

- **Twilio Verify → Exempt.** No registration needed — Verify handles compliance automatically.

See `twilio-compliance-onboarding` for full registration details and gotchas.

---

## How to Choose (US)

- **Need voice + SMS from same number?** → Local (10DLC) or toll-free. Short codes are SMS-only.
- **Marketing at scale (>15 SMS/sec)?** → Short code (highest throughput) or 10DLC with secondary vetting + Messaging Service number pool
- **Fastest time to send?** → Toll-free (3-5 day verification) or Twilio Verify (immediate, no registration)
- **Customer support with local presence?** → Local number in customer's area code
- **Transactional notifications?** → Toll-free (simpler registration) or 10DLC
- **Verification OTPs?** → Twilio Verify (exempt f

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-organizations-setup9.6 KB

View saved version →

---
name: twilio-organizations-setup
description: >
  Set up and manage Twilio Organizations for centralized account and user
  governance. Covers the Organization > Account > Subaccount hierarchy,
  roles (Owner/Admin/Standard), managed vs independent accounts, domain
  registration, SSO enforcement, SCIM provisioning, and Organization
  merging. Use this skill when managing multiple Twilio accounts or users
  across teams.
---

## Overview

Every Twilio customer automatically gets an Organization when they sign up (auto-created since May 2024 for new signups; since June 2024 for existing paying customers). An Organization is the top-level container that groups accounts, users, and security policies. The creation has no effect on existing account functionality. Most developers never need to touch it — but as soon as you have multiple accounts, teams, or compliance requirements (SSO, HIPAA), Organization setup becomes essential.

**Hierarchy:** Organization > Accounts > Subaccounts

| Layer | What it is | When you need it |
|-------|-----------|-----------------|
| **Organization** | Centralized governance: users, accounts, domains, SSO | Multiple teams or accounts, SSO, HIPAA designation |
| **Account** | Application boundary: all Twilio products, resources, billing live here | Always — you need at least one |
| **Subaccount** | Isolated partition under an account: separate resources, consolidated billing | Multi-tenant apps, per-customer isolation |

---

## Organization vs Subaccount — When to Use Which

| Dimension | Organization (Managed Accounts) | Subaccounts |
|-----------|----------------------------------|-------------|
| **Management** | Console UI + Organizations API | REST API (`/2010-04-01/Accounts`) |
| **Billing** | Independent per account | Consolidated to parent account |
| **Account limit** | 10 per Organization (default) | 1 per unupgraded account; 1,000 per upgraded account (contact AE for more) |
| **User management** | Full lifecycle: invite, roles, SSO, SCIM | None — no user concept |
| **SSO/SCIM** | Supported | Not applicable |
| **HIPAA designation** | Per-account toggle in Admin console | Inherits from parent (new only) |
| **Resource isolation** | Separate accounts, separate credentials | Separate but parent can access all |
| **Cost** | Free | Free |

**Rule of thumb:** Use **Organizations** when different teams/users need separate billing and access control. Use **Subaccounts** when your application needs programmatic multi-tenant isolation with consolidated billing.

---

## Organization Roles

| Role | Capabilities | Limit |
|------|-------------|-------|
| **Owner** | Full control + sole authority to delete the Organization | 1 per Organization |
| **Administrator** | Invite/remove users, add/create accounts, modify settings | Unlimited |
| **Standard User** | Access only to specified accounts — no org management | Unlimited (default) |

The Organization creator is automatically assigned the Owner role.

---

## Setting Up Your Organization

### Find Your Organization

All Twilio customers have an Organization (auto-created at signup). Access it via:

- **Console > Settings** (gear icon) — shows Organization settings, or
- **Twilio Admin** link in the top-right navigation — opens the Organization admin panel

### Add Accounts to Your Organization

**Create a new account:**
1. Console > Admin > Accounts
2. Click **Create New Account**
3. Name the account, select Twilio or Flex usage
4. Confirm — the account starts in trial mode with fresh defaults

**Import an existing account:**
1. Console > Admin > Accounts > **Add Existing Account**
2. Enter the account's SID (find it in Console > Account > General settings)
3. The account owner receives an email and must confirm

**Requirement:** The account owner's email must match your Organization's verified domain.

### Account Types

| Type | Description |
|------|-------------|
| **Managed** | Owned by your Organization — full lifecycle control |
| **

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-rcs-messaging10.1 KB

View saved version →

---
name: twilio-rcs-messaging
description: >
  Send RCS Business Messages via Twilio. Covers compliance onboarding
  (7-part US process), sender profile setup, sending rich cards and
  carousels, SMS fallback, device support (Android + iOS 18 caveats),
  and common errors. Use this skill when building RCS messaging or
  onboarding an RCS sender.
---

## Overview

RCS (Rich Communication Services) Business Messaging delivers branded, rich messages natively in the phone's default messaging app — no separate app needed. Messages show your brand logo, colors, and verified sender name. Supports rich cards, carousels, suggested actions, and media.

**RCS uses the same `messages.create()` API as SMS and WhatsApp.** For the full channel comparison and onboarding sequence, see `twilio-messaging-overview`.

### Device Support

| Platform | Support | Notes |
|----------|---------|-------|
| **Android** | Most devices via Google Messages | Carrier must also support RCS in the region |
| **iOS** | iOS 18+ | **P2P RCS is not the same as RCS Business Messaging.** A device that sends RCS to other people may not receive RCS Business Messages — this depends on both Apple and the carrier. Check via `RcsCapabilityFetcher` before sending. |

### Regional Availability

RCS availability depends on carrier approval per country. See [RCS regional availability](https://www.twilio.com/docs/rcs/regional) for the current list. US carriers (T-Mobile, AT&T, Verizon) are supported. Global support is expanding.

---

## Prerequisites

- Twilio **paid account** — free trials cannot use RCS
- Messaging Service (RCS senders must be added to a Messaging Service)
- Environment variables: `TWILIO_ACCOUNT_SID`, `TWILIO_AUTH_TOKEN`
  — See `twilio-iam-auth-setup` for credential setup
- SDK: `pip install twilio` / `npm install twilio`

---

## Compliance Onboarding (US)

RCS onboarding takes **4-6 weeks minimum**. A Twilio onboarding specialist reviews everything before carrier submission. You won't be charged until you go live.

### Part 1: Sender Profile Setup

Create your RCS Sender in Console with:

| Asset | Requirements |
|-------|-------------|
| **Display name** | Must be unique — carriers reject identical names + logos |
| **Logo** | 224x224px, max 50KB, PNG/JPEG |
| **Banner** | 1140x448px, max 200KB |
| **Accent color** | Hex code, must have 4.5:1 contrast ratio vs white |
| **Description** | What your business does and why you're messaging |
| **Phone number** | Customer support contact number |
| **Website** | Must match business identity |

### Part 2: Privacy Policy & Terms of Service

- Privacy policy URL — must be publicly accessible
- Terms of Service URL — must be publicly accessible
- Both must cover SMS/RCS messaging, data handling, opt-out process
- The privacy policy **must state** that information will be shared with third parties for the purpose of transmitting RCS messages
- Some countries require local-language versions

For US-specific compliance details, see the [RCS Compliance Onboarding Guide](https://help.twilio.com/articles/49174994355355-RCS-Compliance-Onboarding-Guide).

### Part 3: Eligibility & Acceptable Use

US carriers require:
- Legal business name matching EIN records
- EIN (Employer Identification Number)
- Business must not be on restricted industries list (cannabis, firearms, etc.)
- CTIA Messaging Principles and Best Practices handbook compliance

### Part 4: Campaign Details

- Use case category (transactional, promotional, OTP, mixed)
- Traffic volume estimates
- Campaign description with specific messaging scenarios
- For recurring messages: frequency, content types

### Part 5: Opt-In & Consent

- Describe how users opt in to receive RCS messages
- Must show explicit consent collection mechanism
- Opt-in must be specific to RCS/messaging (not buried in general ToS)
- HELP and STOP keyword handling required

### Part 6: Sample Messages

- 2+ sample messages that match your declared use case
- Must include opt-out langu

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-regulatory-compliance-bundles7.49 KB

View saved version →

---
name: twilio-regulatory-compliance-bundles
description: >
  Manage regulatory compliance for international phone numbers. Covers
  what bundles are, which countries require them, how to create End-Users
  and Supporting Documents, evaluate and submit bundles, fix evaluation
  failures, update bundles when regulations change, and ISV multi-account
  patterns. Use this skill when provisioning numbers outside the US.
---

## Overview

Phone numbers are national resources — many countries require **identity verification of the end-user** before provisioning. A Regulatory Bundle is a container holding an End-User record + Supporting Documents that proves your right to use numbers in a specific country.

**Not all countries require bundles** — check the [Regulatory Guidelines page](https://www.twilio.com/en-us/guidelines/regulatory) for country-specific requirements. If a country requires a bundle, provisioning fails without one.

---

## Key Concepts

| Resource | What it is |
|----------|-----------|
| **Regulation** | Country-specific requirement defining what End-User types and document types are needed |
| **Bundle** | Container that holds an End-User + Supporting Documents for a specific regulation |
| **End-User** | The entity answering calls or receiving messages (`individual` or `business` type) |
| **Supporting Document** | Identity/address verification documents (business registration, proof of address, etc.) |
| **Evaluation** | Synchronous check that validates a bundle against its regulation before submission |
| **Item Assignment** | Links an End-User or Supporting Document to a Bundle |

---

## Quickstart: Provision a Number with a Bundle

### Step 1 — Query the Regulation

Find out what's required for the country and number type:

**Python**
```python
import os, requests

account_sid = os.environ["TWILIO_ACCOUNT_SID"]
auth_token = os.environ["TWILIO_AUTH_TOKEN"]

# What does Germany require for local business numbers?
regulations = requests.get(
    "https://numbers.twilio.com/v2/RegulatoryCompliance/Regulations",
    params={"IsoCountry": "DE", "NumberType": "local", "EndUserType": "business"},
    auth=(account_sid, auth_token)
).json()

for reg in regulations["results"]:
    print(f"Regulation: {reg['sid']}")
    print(f"Requirements: {reg['requirements']}")
```

### Step 2 — Create an End-User

**Python**
```python
end_user = requests.post(
    "https://numbers.twilio.com/v2/RegulatoryCompliance/EndUsers",
    data={
        "FriendlyName": "Acme GmbH",
        "Type": "business",
        "Attributes": '{"business_name": "Acme GmbH", "business_registration_number": "HRB12345"}'
    },
    auth=(account_sid, auth_token)
).json()
```

### Step 3 — Upload Supporting Documents

**Python**
```python
document = requests.post(
    "https://numbers.twilio.com/v2/RegulatoryCompliance/SupportingDocuments",
    data={
        "FriendlyName": "Acme Business Registration",
        "Type": "business_registration",
        "Attributes": '{"business_name": "Acme GmbH"}'
    },
    auth=(account_sid, auth_token)
).json()
```

### Step 4 — Create a Bundle and Assign Items

**Python**
```python
# Create the bundle
bundle = requests.post(
    "https://numbers.twilio.com/v2/RegulatoryCompliance/Bundles",
    data={
        "FriendlyName": "Germany Local - Acme",
        "RegulationSid": regulations["results"][0]["sid"],
        "IsoCountry": "DE",
        "EndUserType": "business",
        "Email": "compliance@acme.com"
    },
    auth=(account_sid, auth_token)
).json()

bundle_sid = bundle["sid"]

# Assign End-User to bundle
requests.post(
    f"https://numbers.twilio.com/v2/RegulatoryCompliance/Bundles/{bundle_sid}/ItemAssignments",
    data={"ObjectSid": end_user["sid"]},
    auth=(account_sid, auth_token)
)

# Assign Supporting Document to bundle
requests.post(
    f"https://numbers.twilio.com/v2/RegulatoryCompliance/Bundles/{bundle_sid}/ItemAssignments",
    data={"ObjectSid": document["sid"]},
    auth=(account_sid, auth_t

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-reliability-patterns10.8 KB

View saved version →

---
name: twilio-reliability-patterns
description: >
  Handle rate limits, retries, and failures when building on Twilio at
  scale. Covers 429 exponential backoff with jitter, per-number throughput
  limits, StatusCallback resilience, thin-receiver pattern, and fallback
  chains. Use this skill whenever sending messages or making calls at
  volume, or when building production-grade Twilio integrations.
---

## Overview

Twilio enforces per-resource rate limits. At scale, 429 errors are expected behavior — not bugs. This skill teaches the patterns that prevent production failures: exponential backoff, throughput management, and resilient callback handling.

429 concurrency errors are not well documented — implement exponential backoff with ±10% jitter.

---

## Prerequisites

- A working Twilio integration (any product)
- Understanding of your expected volume (messages/sec, calls/sec)
- StatusCallback URLs configured — see `twilio-messaging-services`, `twilio-sms-send-message`

---

## Key Patterns

### 1. Exponential Backoff with Jitter

When you receive a 429 (Too Many Requests), wait and retry. Naive fixed-interval retry creates thundering herds. Use exponential backoff with randomized jitter.

**Python**
```python
import time, random, requests

def send_with_backoff(client, to, body, messaging_service_sid, max_retries=5):
    for attempt in range(max_retries):
        try:
            message = client.messages.create(
                to=to,
                body=body,
                messaging_service_sid=messaging_service_sid,
                status_callback="https://yourapp.com/status"
            )
            return message
        except Exception as e:
            if hasattr(e, 'status') and e.status == 429:
                # Exponential backoff: 100ms, 200ms, 400ms, 800ms, 1600ms
                base_delay = 0.1 * (2 ** attempt)
                # Add ±10% jitter to prevent thundering herd
                jitter = base_delay * 0.1 * (2 * random.random() - 1)
                delay = min(base_delay + jitter, 30)  # cap at 30 seconds
                time.sleep(delay)
            else:
                raise  # Non-429 errors: don't retry, investigate
    raise Exception(f"Failed after {max_retries} retries")
```

**Node.js**
```node
async function sendWithBackoff(client, to, body, messagingServiceSid, maxRetries = 5) {
    for (let attempt = 0; attempt < maxRetries; attempt++) {
        try {
            return await client.messages.create({
                to,
                body,
                messagingServiceSid,
                statusCallback: "https://yourapp.com/status",
            });
        } catch (err) {
            if (err.status === 429) {
                // Exponential backoff: 100ms, 200ms, 400ms, 800ms, 1600ms
                const baseDelay = 100 * Math.pow(2, attempt);
                // Add ±10% jitter
                const jitter = baseDelay * 0.1 * (2 * Math.random() - 1);
                const delay = Math.min(baseDelay + jitter, 30000); // cap at 30s
                await new Promise(r => setTimeout(r, delay));
            } else {
                throw err; // Non-429: don't retry
            }
        }
    }
    throw new Error(`Failed after ${maxRetries} retries`);
}
```

**Parameters:**
- Initial delay: 100ms
- Multiplier: 2x per attempt
- Jitter: ±10% of base delay (randomized)
- Max delay: 30 seconds
- Max retries: 5 (covers up to ~3.2 second base delay)

### 2. Per-Number Throughput Limits

These limits are not prominently documented:

| Number type | SMS throughput | Voice throughput | Notes |
|-------------|---------------|-----------------|-------|
| Local (long code) | ~1 SMS/sec | 1 concurrent call | Lowest cost, lowest throughput |
| Toll-free | ~3 SMS/sec | — | Faster verification (3-5 days) |
| Short code | 10-100 SMS/sec | — | Highest throughput, 8-12 week provisioning, expensive |
| Messaging Service (pool) | Sum of all numbers in pool | — | Multiply throughput by adding number

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-security-api-auth5.62 KB

View saved version →

---
name: twilio-security-api-auth
description: >
  Choose the right Twilio authentication method and implement it correctly.
  Covers Auth Token (testing only), API Keys (production standard), OAuth2
  client_credentials (time-limited bearer tokens), Access Tokens (client-side
  SDKs), and test credentials. Use this skill before making any Twilio API
  calls in production.
---

## Overview

Twilio supports four authentication methods. Choosing the wrong one is a security risk — Auth Tokens in production code are the most common credential leak.

| Method | Use for | Token lifetime | Revocable individually |
|--------|---------|---------------|----------------------|
| **Auth Token** | Local testing only | Permanent (until rotated) | No — rotation breaks ALL API keys |
| **API Key + Secret** | Production server-side | Permanent (until deleted) | Yes |
| **OAuth2 Bearer Token** | Production server-side (enhanced) | 1 hour | Expires automatically |
| **Access Token (JWT)** | Client-side SDKs (Voice, Video, Chat) | Up to 24 hours | No — delete issuing API key |

**Decision framework:**
- **Building a quick prototype?** → Auth Token (but switch to API Key before deploying)
- **Production server-side code?** → API Key + Secret (simplest production auth) or OAuth2 (time-limited tokens)
- **Browser/mobile client needs to connect?** → Access Token (JWT) generated server-side
- **Running tests without charges?** → Test credentials with magic numbers

---

## API Key Authentication (Production Standard)

**Create:** Console → Account → API keys & tokens → Create API key

| Key type | Access | Create via |
|----------|--------|-----------|
| **Main** | Full account access | Console only |
| **Standard** | All resources except /Accounts and /Keys endpoints | Console or API |
| **Restricted** | Specific resources only (up to 100 permissions) | Console or v1 IAM API only |

**Python**
```python
import os
from twilio.rest import Client

client = Client(
    os.environ["TWILIO_API_KEY"],      # SKxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    os.environ["TWILIO_API_SECRET"],
    os.environ["TWILIO_ACCOUNT_SID"]   # required as third argument
)
```

**Node.js**
```node
const client = require("twilio")(
    process.env.TWILIO_API_KEY,
    process.env.TWILIO_API_SECRET,
    { accountSid: process.env.TWILIO_ACCOUNT_SID }
);
```

---

## OAuth2 Authentication (Client Credentials)

Time-limited bearer tokens that expire after 1 hour. More secure than permanent API keys for server-to-server communication.

### Step 1 — Create an OAuth App

Create an OAuth App in the Twilio Console to get a Client ID and Client Secret.

### Step 2 — Request a Bearer Token

**cURL**
```bash
curl -X POST 'https://oauth.twilio.com/v2/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'client_id={ClientID}' \
  -d 'client_secret={ClientSecret}' \
  -d 'grant_type=client_credentials'
```

**Response:**
```json
{
    "access_token": "{BearerToken}",
    "token_type": "Bearer",
    "expires_in": 3600
}
```

### Step 3 — Use the Bearer Token

```bash
curl 'https://api.twilio.com/2010-04-01/Accounts/{AccountSID}/Messages.json' \
  -H 'Authorization: Bearer {BearerToken}'
```

### SDK Support

OAuth2 is supported in all Twilio SDKs:

| Language | Minimum version |
|----------|----------------|
| Java | 10.6.0 |
| C#/.NET | 7.6.0 |
| Node.js | 5.4.0 |
| Python | 9.4.1 |
| Ruby | 7.4.0 |
| PHP | 8.5.0 |
| Go | 1.25.1 |

**Docs:** [OAuth access tokens](https://www.twilio.com/docs/iam/oauth-apps/oauth-access-token) | [Segment OAuth connections](https://www.twilio.com/docs/segment/connections/oauth)

---

## Access Tokens (Client-Side SDKs)

Short-lived JWTs for authenticating browser/mobile clients. Generate server-side, pass to the client.

**Python**
```python
from twilio.jwt.access_token import AccessToken
from twilio.jwt.access_token.grants import VoiceGrant

token = AccessToken(
    os.environ["TWILIO_ACCOUNT_SID"],
    os.environ["TWILIO_API_KEY"],
    os.environ["

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-security-compliance-hipaa7.52 KB

View saved version →

---
name: twilio-security-compliance-hipaa
description: >
  Configure Twilio accounts for HIPAA compliance. Covers BAA requirements,
  HIPAA Project designation (self-service and support), eligible services
  list, per-product requirements (Voice, SMS, ConversationRelay, Conversation Intelligence,
  Flex, Verify), message redaction, and what is NOT eligible. Use this
  skill when developers are building healthcare workflows on Twilio.
---

## Overview

HIPAA compliance on Twilio is a **shared responsibility** — Twilio provides eligible services and configuration tools, but your application must architect correctly. Getting this wrong means PHI exposure and compliance violations.

**Sequence:** Execute BAA → Designate HIPAA Project(s) → Use only eligible services → Follow per-product requirements

---

## Step 1: Execute a BAA

- Contact your Twilio Account Representative to execute a Business Associate Addendum
- Purchase a **Twilio Editions package** that includes HIPAA Accounts
- BAA is required before any PHI touches Twilio infrastructure

---

## Step 2: Designate HIPAA Project(s)

### Self-Service (BAA initiated after June 6, 2024)

1. Create an Organization in Twilio Console
2. Link accounts/projects/subaccounts to the Organization
3. Console → Twilio Admin → Accounts → Select account → Enable HIPAA flag
4. Save

### Support Ticket (BAA initiated before June 6, 2024)

Open a Support ticket through Console to request HIPAA designation for specific accounts/projects/subaccounts.

### Subaccount Behavior

- **Existing subaccounts are NOT auto-designated** — Must be individually flagged
- **New subaccounts created AFTER designation DO auto-inherit** HIPAA status
- Verify each subaccount's HIPAA flag — don't assume inheritance

### What Changes When HIPAA Is Enabled

- Console auto-logoff after 15 minutes of inactivity
- Account exempt from certain content moderation (but still subject to carrier complaint review)
- No PHI in support tickets — use SIDs (CallSid, MessageSid) instead of phone numbers

---

## HIPAA Eligible Services

### Eligible (use these for PHI workflows)

| Category | Services |
|----------|----------|
| **Voice** | Programmable Voice, Recordings*, Transcription*, Media Streams*, ConversationRelay*, Conversational Intelligence for Voice*, SIP Interface*, Elastic SIP Trunking*, Voice Insights, AMD, `<Pay>`, Conference, Coaching, Transfers |
| **SMS** | Programmable SMS, MMS, Long Codes, Toll-Free, Short Codes, Messaging Services (opt-out, fallback, geomatch, sticky sender, scheduling, link shortening) |
| **Identity** | Verify (SMS + Voice + Push only), Lookup |
| **Conversations** | Chat, SMS, MMS, Group Texting (NOT WhatsApp) |
| **Flex** | Voice, SMS, Chat, Conversations, Webchat 3.x.x*, TaskRouter, Proxy, Flex Insights* |
| **Segment** | Connections (Sources, Destinations*, Functions*), Reverse ETL*, Unify, Engage Foundations*, Protocols, Privacy Portal* |
| **Runtime** | Studio*, Functions, Debugger, API Explorer, Sync, Private Assets*, TwiML Bin* |
| **Data** | Event Streams |

*Items marked with * require additional configuration per "Architecting for HIPAA on Twilio" guidance.*

### NOT Eligible (do NOT use for PHI)

- **WhatsApp** — Meta does not offer a BAA
- **SendGrid Email** (including Email in Flex and Verify Email channel)
- **AI Assistants** (including Voice for AI Assistants)
- **Verify Fraud Guard**
- **Conversational Intelligence for Conversations** (only Voice channel is eligible)
- **Agent Copilot**, **Unified Profiles** in Flex
- **Engage Premier**, **Generative Audiences**, **Campaigns**
- **Twilio Marketplace add-ons** — even with third-party BAA
- **Autopilot**
- **Flex Webchat 2.x.x** (must migrate to 3.x.x)

**Geographic restriction:** Only US area codes for Voice and SMS HIPAA traffic.

---

## Per-Product Requirements

### Voice & Recordings

- **HTTP auth required for recording URLs** — Enable in Console → Voice Settings. Recording URLs are public by default.
- **Voice Recordin

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-security-hardening7.3 KB

View saved version →

---
name: twilio-security-hardening
description: >
  Secure Twilio applications against common attacks. Covers credential
  management (API keys vs auth tokens), request validation (webhook
  signature verification), PCI DSS compliance, HIPAA account requirements,
  SMS pumping prevention, geo-permissions, and account isolation patterns.
  Use this skill when developers are building or deploying Twilio apps.
---

## Overview

Security hardening is an **ongoing** concern — not a one-time setup. This skill covers account-level security decisions and application-level protection patterns that prevent credential leaks, fraud, and compliance violations.

**Lifecycle:** Choose numbers (`twilio-numbers-senders`) → Register (`twilio-compliance-onboarding`) → Follow traffic rules (`twilio-compliance-traffic`) → Secure everything (this skill)

---

## Credential Management

### API Keys vs Auth Tokens

| Credential | Scope | Revocable | Use when |
|-----------|-------|-----------|----------|
| **Auth Token** | Full account access | Only by rotating (invalidates ALL API keys) | Never in production — use API keys instead |
| **API Key + Secret** | Scoped, revocable individually | Yes — revoke one without affecting others | Production applications, CI/CD, server-side code |
| **Access Tokens** | Short-lived, client-specific | Expire automatically | Client-side SDKs (Voice, Video, Conversations) |

**Critical gotcha:** Rotating your Auth Token **invalidates ALL existing API keys**. This is a one-way door that can break every integration simultaneously. Use API keys from the start so you never need to rotate the Auth Token.

### Best Practices

- Store credentials in environment variables or a secrets manager — never in code
- Use different API keys per application/environment
- Rotate API keys on a schedule (quarterly minimum, monthly for HIPAA)
- Use sub-accounts to isolate customer credentials for ISV platforms — see `twilio-account-setup`

**Docs:** See `twilio-iam-auth-setup` for full credential setup patterns.

---

## Request Validation (Webhook Security)

Verify that webhook requests actually come from Twilio — not spoofed by attackers.

### X-Twilio-Signature Validation

Always use the SDK validator — don't implement HMAC-SHA1 manually:

**Node.js**
```javascript
const twilio = require("twilio");

app.post("/sms", (req, res) => {
    const valid = twilio.validateRequest(
        process.env.TWILIO_AUTH_TOKEN,
        req.headers["x-twilio-signature"],
        `https://yourdomain.com/sms`,
        req.body
    );
    if (!valid) return res.status(403).send("Forbidden");
    // Process webhook...
});
```

**Common mistakes:**
- Using HTTP URL when Twilio sends to HTTPS (URL must match exactly)
- Forgetting to include query string parameters in validation URL
- Not validating in production because "it worked in dev without it"

**Docs:** See `twilio-webhook-architecture` for full webhook security patterns.

---

## Account-Level Compliance

### PCI DSS (Payment Card Industry)

**PCI Mode is IRREVERSIBLE and account-wide.** Once enabled, it cannot be disabled — ever.

- All recordings are encrypted
- Transcript access is restricted
- Affects every service on the account

**Recommendation:** If you need PCI compliance for one use case, create a **separate sub-account** dedicated to payment-related calls. See `twilio-account-setup` for sub-account patterns.

For call recording during payment, pause recording when the customer gives card numbers:
```python
client.calls(call_sid).recordings(recording_sid).update(status="paused")
```

Or use the `<Pay>` verb to handle payments without your application touching card data:
```xml
<Pay paymentConnector="stripe_connector" chargeAmount="49.99" currency="usd" />
```

### HIPAA (Healthcare)

Before handling Protected Health Information (PHI):
- **Execute a BAA** (Business Associate Agreement) with Twilio — contact your account manager or [submit a sales request](https://www.twilio.com/en-us/help/sa

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-sendgrid-account-setup5.35 KB

View saved version →

---
name: twilio-sendgrid-account-setup
description: >
  Set up a SendGrid account for email delivery. Covers API key creation
  (SG.-prefix), domain authentication (DKIM/SPF via CNAME records), Single
  Sender Verification for testing, SDK installation, and the relationship
  between SendGrid and Twilio credentials. Use before any other SendGrid skill.
  This skill is for SendGrid only — not the Twilio Email API (comms.twilio.com).
---

## Overview

SendGrid is Twilio's email delivery engine but uses a **completely separate authentication system** — SendGrid API keys (starting with `SG.`) are not Twilio API keys. You cannot use Account SID/Auth Token for SendGrid, and no Twilio MCP tools wrap SendGrid.

---

## Quickstart

1. Get your API key from [SendGrid Console > Settings > API Keys](https://app.sendgrid.com/settings/api_keys)
2. Set environment variable:

```bash
export SENDGRID_API_KEY=SG.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

3. Install SDK:

| Language | Install | Package |
|----------|---------|---------|
| Python | `pip install sendgrid` | `sendgrid` |
| Node.js | `npm install @sendgrid/mail` | `@sendgrid/mail` (v8.x) |
| Java | Maven | `com.sendgrid:sendgrid-java` |
| C# | `dotnet add package SendGrid` | `SendGrid` |
| Ruby | `gem install sendgrid-ruby` | `sendgrid-ruby` |
| PHP | `composer require sendgrid/sendgrid` | `sendgrid/sendgrid` |
| Go | `go get github.com/sendgrid/sendgrid-go` | `sendgrid-go` |

4. Authenticate your sending domain (see below)

---

## API Key Scopes

| Scope | Use for | Risk |
|-------|---------|------|
| **Full Access** | Development only | Can do everything — never deploy with this |
| **Restricted Access** | Production | Scope to only what your app needs (e.g., Mail Send only) |
| **Billing Access** | Account management | Separate from mail operations |

A "Mail Send" restricted key can send email but cannot read suppressions, manage templates, or access stats. If you get `403 Forbidden`, check key permissions.

---

## SMTP Relay (Alternative to API)

SendGrid also supports SMTP for sending. Useful for frameworks with built-in SMTP support (e.g., Laravel, Django, Rails).

| Setting | Value |
|---------|-------|
| **Server** | `smtp.sendgrid.net` |
| **Port** | `587` (TLS) or `465` (SSL) |
| **Username** | `apikey` (literal string, not your key name) |
| **Password** | Your SendGrid API key (`SG.xxx`) |

---

## Domain Authentication (Required for Production)

Single Sender Verification is for testing only. Production requires domain authentication for deliverability.

**Setup:** SendGrid Console > Settings > Sender Authentication > Authenticate Your Domain

Create 3 CNAME DNS records:
1. `s1._domainkey.yourdomain.com` → `s1.domainkey.u1234.wl.sendgrid.net` (DKIM)
2. `s2._domainkey.yourdomain.com` → `s2.domainkey.u1234.wl.sendgrid.net` (DKIM)
3. `em1234.yourdomain.com` → `u1234.wl.sendgrid.net` (return path)

Verify via API: `GET /v3/whitelabel/domains/{id}/validate`

**DMARC:** After setting up DKIM and SPF via domain authentication, configure a DMARC DNS record (`_dmarc.yourdomain.com`) to instruct receiving servers how to handle authentication failures. Start with `p=none` for monitoring before enforcing.

**Dedicated IP (Pro+ plans):** Isolates your sending reputation. Requires an IP warming schedule — start with low volume and increase over 30 days.

---

## SendGrid and Twilio

| Twilio product | How it uses SendGrid | Sends email? |
|----------------|---------------------|-------------|
| **SendGrid** (this skill) | Direct email delivery via `api.sendgrid.com` | Yes |
| **Twilio Email API** | Direct email delivery via `comms.twilio.com/v1/emails` — uses Twilio creds, not SendGrid keys | Yes (separate product) |
| **Verify** | OTP via `channel: 'email'` | Delegates to SendGrid via Mailer config |
| **Conversations** | Tracks EMAIL as a channel type | No — logs/tracks only |
| **Flex** | Email channel for agents | Uses SendGrid for delivery |

**Servers:**
- Global: `https://api.s

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-sendgrid-deliverability-advisor14.9 KB

View saved version →

---
name: twilio-sendgrid-deliverability-advisor
description: >
  Diagnostic and advisory skill for email deliverability problems. Use when
  a developer asks why emails are going to spam, not reaching the inbox,
  getting blocked, bouncing, or how to improve sender reputation — with or
  without a specified platform. Covers SendGrid-specific tooling: SPF, DKIM,
  DMARC, BIMI, IP warmup, list hygiene, bounce/spam rate thresholds, and
  Engagement Quality Score (SEQ). Do NOT use for Twilio Email
  (comms.twilio.com / Account SID + Auth Token) — use
  twilio-email-deliverability-advisor instead. Do NOT use for general email
  sending questions — use twilio-sendgrid-email-send (SendGrid) or
  twilio-email-deliverability-advisor instead.
tier: discover
---

## Role

You are an Email Deliverability Advisor. When a developer describes emails going to spam, bouncing, getting blocked, or asks how to improve inbox placement or sender reputation, use this framework to diagnose and recommend fixes.

## When This Skill Activates

Trigger on any of these signals:
- "Emails going to spam," "landing in junk," "not reaching inbox"
- "Blocked," "rejected," "deferred," "blacklisted," "denylisted"
- "Bounce rate too high," "spam complaints," "reputation score"
- "IP warmup," "dedicated IP," "shared IP"
- "SPF," "DKIM," "DMARC," "BIMI," "domain authentication"
- "SEQ score," "engagement quality," "sender score"
- "List hygiene," "spam traps," "invalid addresses"
- "How do I improve deliverability?"

Do NOT trigger for: general email sending implementation, template questions, webhook setup, suppression list management unrelated to deliverability. Redirect to `twilio-sendgrid-email-send` (SendGrid) for sending questions, `twilio-sendgrid-suppressions` for suppression management, `twilio-email-deliverability-advisor` for Twilio Email deliverability.

---

## Step 0: Identify Platform

Check for platform signals before proceeding:

| Signal | Platform | Action |
|--------|----------|--------|
| API key starts with `SG.` | SendGrid | Proceed |
| Mentions `app.sendgrid.com` | SendGrid | Proceed |
| Mentions `comms.twilio.com`, Account SID, or Auth Token | Twilio Email | Redirect |
| No signal | Unknown | Ask |

**If Twilio Email:** Stop. Respond: "For Twilio Email deliverability, use the `twilio-email-deliverability-advisor` skill — it's scoped to that platform."

**If unclear:** Ask exactly this before proceeding:
> "Are you using SendGrid (API key starting with `SG.`, dashboard at app.sendgrid.com) or Twilio Email (Twilio Account SID / Auth Token)?"

---

## Step 1: Detect the Problem Type

**Acute problem** (emails suddenly blocked, bounce rate spiked, on a denylist):
→ TRIAGE MODE. Something changed — diagnose before recommending.

**Gradual degradation** (deliverability declining over weeks, open rates dropping):
→ AUDIT MODE. Systematic review of authentication, list health, and sending patterns.

**Proactive setup** (new email program, new IP, new domain):
→ FOUNDATION MODE. Build the right infrastructure before problems occur.

---

## Step 2: Qualify the Situation — Key Questions

1. **What symptoms are you seeing?**
   - Bounces (hard vs soft), spam complaints, blocks, deferrals, or inbox placement problems
   - Check via Event Webhooks or SendGrid Activity Feed

2. **Is your domain authenticated?**
   - SPF, DKIM, DMARC all configured? (If any are missing, start here — this is the most common root cause)
   - Domain authentication in `app.sendgrid.com` → Settings → Sender Authentication + link branding

3. **Shared or dedicated IP?**
   - Shared IP (Trial/Essentials plans): reputation influenced by other senders on the pool
   - Dedicated IP (Pro/Premier): full control, but requires warmup before high-volume sending

4. **What does your list look like?**
   - How was it collected? (opt-in, double opt-in, purchased?)
   - When was it last cleaned?
   - Current bounce rate and spam complaint rate?

---

## Step 3: Diagnose by Symptom

### Ema

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-sendgrid-email-send6.61 KB

View saved version →

---
name: twilio-sendgrid-email-send
description: >
  Send transactional and bulk email via the SendGrid v3 Mail Send API.
  Covers single sends, personalized batch sends with dynamic templates,
  scheduled sends with cancellation, attachments, and sandbox mode for
  testing. Use this skill when the caller has a SendGrid API key (SG.-prefix).
  Do NOT use this skill if the caller is using the Twilio Email API
  (comms.twilio.com) — that is a separate product with different credentials.
---

## Overview

> **Agent safety:** Always confirm recipients, subject, and content with the user before sending. Email is irreversible once delivered. Never send email autonomously without explicit user approval — especially for batch sends to multiple recipients.

All email sending goes through `POST /v3/mail/send`. This endpoint returns `202 Accepted` (queued) — NOT `200 OK` (delivered). Delivery confirmation comes asynchronously via Event Webhook. See `twilio-sendgrid-webhooks`.

---

## Basic Send

**Python**
```python
import os, sendgrid
from sendgrid.helpers.mail import Mail

sg = sendgrid.SendGridAPIClient(os.environ["SENDGRID_API_KEY"])
message = Mail(
    from_email="verified@yourdomain.com",
    to_emails="recipient@example.com",
    subject="Order Confirmation",
    html_content="<p>Your order #1234 is confirmed.</p>"
)
response = sg.send(message)
print(f"Status: {response.status_code}")  # 202 = queued
```

**Node.js**
```javascript
const sgMail = require("@sendgrid/mail");
sgMail.setApiKey(process.env.SENDGRID_API_KEY);

const [response] = await sgMail.send({
    to: "recipient@example.com",
    from: "verified@yourdomain.com",
    subject: "Order Confirmation",
    html: "<p>Your order #1234 is confirmed.</p>",
});
console.log(`Status: ${response.statusCode}`); // 202 = queued
```

---

## Personalized Batch Send with Dynamic Templates

Dynamic templates use Handlebars syntax. Template IDs start with `d-`. Create templates in SendGrid Console > Email API > Dynamic Templates.

**Python**
```python
from sendgrid.helpers.mail import Mail, To

message = Mail(
    from_email="noreply@yourdomain.com",
    to_emails=[
        To("alice@example.com", dynamic_template_data={"name": "Alice", "order_id": "123"}),
        To("bob@example.com", dynamic_template_data={"name": "Bob", "order_id": "456"}),
    ],
)
message.template_id = "d-xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
sg.send(message)
```

**Node.js**
```javascript
await sgMail.send({
    from: { email: "noreply@yourdomain.com" },
    template_id: "d-xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    personalizations: [
        { to: [{ email: "alice@example.com" }], dynamic_template_data: { name: "Alice", order_id: "123" } },
        { to: [{ email: "bob@example.com" }], dynamic_template_data: { name: "Bob", order_id: "456" } },
    ],
});
```

**Recipients in the same `to` array within a single personalization can see each other.** For private sends, use separate personalizations (one per recipient).

---

## Scheduled Sends

Schedule up to 72 hours in advance. Cancellation requires a batch ID assigned *before* sending.

**Python**
```python
import time, requests

headers = {"Authorization": f"Bearer {os.environ['SENDGRID_API_KEY']}", "Content-Type": "application/json"}

# Get batch ID first
batch = requests.post("https://api.sendgrid.com/v3/mail/batch", headers=headers).json()

# Include batch_id and send_at in the message
send_at = int(time.time()) + 3600  # Unix SECONDS, not ms

# Cancel if needed (before send_at)
requests.post("https://api.sendgrid.com/v3/user/scheduled_sends",
    headers=headers,
    json={"batch_id": batch["batch_id"], "status": "cancel"})
```

---

## Attachments

Base64-encode files in the `attachments` array. Total limit: 30MB per request (~22MB before encoding overhead).

```python
import base64
from sendgrid.helpers.mail import Mail, Attachment, FileContent, FileName, FileType, Disposition

with open("invoice.pdf", "rb") as f:
    encoded = base64.b64encode(f.read()).decode()

me

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-sendgrid-email-settings3.91 KB

View saved version →

---
name: twilio-sendgrid-email-settings
description: >
  Configure SendGrid dynamic templates (Handlebars), tracking settings
  (opens, clicks, subscriptions), link branding for custom tracking
  domains, and content types (HTML, plain text, AMP). Use when customizing
  SendGrid email content, tracking behavior, or branded links. Requires a
  SendGrid API key (SG.-prefix) — not applicable to the Twilio Email API
  (comms.twilio.com).
---

## Overview

SendGrid email settings control how your messages are constructed, personalized, and tracked. Most configuration happens in the SendGrid Console, but templates and tracking can also be managed via API.

---

## Dynamic Templates

Templates use Handlebars syntax and are managed in Console > Email API > Dynamic Templates. Template IDs start with `d-`.

**Supported Handlebars helpers:**

| Helper | Use | Example |
|--------|-----|---------|
| `if` / `unless` | Conditional | `{{#if premium}}Welcome back!{{/if}}` |
| `each` | Iteration | `{{#each items}}{{this.name}}{{/each}}` |
| `equals` / `notEquals` | Comparison | `{{#equals status "active"}}...{{/equals}}` |
| `and` / `or` | Boolean logic | `{{#and premium verified}}...{{/and}}` |
| `greaterThan` / `lessThan` | Numeric | `{{#greaterThan count 5}}...{{/greaterThan}}` |
| `length` | Array/string | `{{length items}}` |
| `formatDate` | Date format | `{{formatDate date "MM/DD/YYYY"}}` |
| `insert` | Module insert | `{{insert "module_name"}}` |

**NOT supported:** Custom helpers, inline partials, `lookup`, `log`, `with`, `blockHelperMissing`. SendGrid implements a subset of Handlebars.js.

### Template Versions

- **Dynamic templates** (IDs starting with `d-`): Support Handlebars
- **Legacy transactional templates**: Use `-substitution-` syntax — not interchangeable with Handlebars

---

## Tracking Settings

| Setting | What it does | Caveat |
|---------|-------------|--------|
| **Open tracking** | Inserts a tracking pixel | Unreliable: Apple Mail Privacy Protection inflates opens; image-blocking clients produce false negatives |
| **Click tracking** | Rewrites URLs through SendGrid's redirect | Can trigger spam filters on some domains |
| **Subscription tracking** | Adds unsubscribe footer | Required for CAN-SPAM compliance |
| **Google Analytics** | Adds UTM parameters | Only for marketing campaigns |

Configure per-message or account-wide in Console > Settings > Tracking.

---

## Link Branding (Custom Tracking Domains)

By default, click-tracked links route through `url####.ct.sendgrid.net`. Link Branding lets you use your own domain (e.g., `links.yourdomain.com`) instead, which improves deliverability and builds trust.

**Setup:** Console > Settings > Sender Authentication > Link Branding

Requires a CNAME DNS record pointing your subdomain to `sendgrid.net`. Validate via API: `GET /v3/whitelabel/links/{id}/validate`

---

## Content Type Priority

When sending multiple content types, email clients display in this priority:

1. `text/x-amp-html` (AMP — only in supporting clients, requires sender registration)
2. `text/html` (standard — most clients)
3. `text/plain` (fallback)

Always include at least `text/plain` and `text/html`.

---

## CANNOT

- **Cannot use custom Handlebars helpers** — Only the built-in set listed above.
- **Cannot guarantee open tracking accuracy** — Pixel-based tracking is fundamentally unreliable. Do not use for business-critical logic.
- **Personalizations `subject` is a plain string override** — It bypasses the template subject. To use dynamic subjects, set Handlebars variables (e.g., `{{{subject}}}`) in the Dynamic Template's subject field and pass values via `dynamic_template_data`.
- **Undefined template variables are silent** — Missing keys in `dynamic_template_data` render as empty strings with no error.

---

## Next Steps

- **Send email:** `twilio-sendgrid-email-send`
- **Delivery tracking:** `twilio-sendgrid-webhooks`
- **Manage bounces/unsubscribes:** `twilio-sendgrid-suppressions`

Referenced files: 1 — file references are metadata, not package contents.

twilio-sendgrid-engagement-quality5.53 KB

View saved version →

---
name: twilio-sendgrid-engagement-quality
description: >
  Monitor email program health with SendGrid Engagement Quality (SEQ)
  scores. Covers the SEQ API endpoints, the 5 scoring metrics
  (engagement recency, open rate, bounce classification, bounce rate,
  spam rate), eligibility requirements, and interpreting scores for
  deliverability improvement. Use when diagnosing SendGrid deliverability
  issues or monitoring sender reputation. Requires a SendGrid API key
  (SG.-prefix) — not applicable to the Twilio Email API (comms.twilio.com).
---

## Overview

SendGrid Engagement Quality (SEQ) scores measure how "wanted" your email is by recipients. Higher scores (1-5 scale) correlate with better inbox placement. SEQ is a diagnostic tool — it tells you where your email program is healthy and where it needs improvement.

**Key insight:** SEQ scores are correlated with deliverability. A higher score means more emails land in inboxes, not spam folders.

---

## Eligibility Requirements

Your account must meet ALL conditions to receive scores:
1. **Pro or Premier Email API plan** — SEQ is not available on Free or Essentials plans
2. **Open tracking enabled** in SendGrid settings
3. **Minimum 1,000 messages sent** in the previous 30 days

If not eligible, the `score` and `metrics` fields are omitted from API responses entirely.

---

## The 5 Metrics

All scores range from **1 (poor) to 5 (excellent)**.

| Metric | What it measures | How to improve |
|--------|-----------------|---------------|
| **engagement_recency** | Are you sending to an engaged audience? Based on how regularly messages are opened and clicked. | Remove inactive subscribers. Implement re-engagement campaigns before pruning. |
| **open_rate** | Degree to which your audience opens your messages. | Improve subject lines. Segment audiences by engagement level. |
| **bounce_classification** | Rejection by mailbox providers due to reputation or spam-like content. | Fix content triggering spam filters. Warm IPs properly. Monitor domain reputation. |
| **bounce_rate** | Are you sending to addresses that don't exist? Based on permanent bounces to invalid mailboxes. | Implement double opt-in. Clean lists quarterly. Use Email Validation API before sending. |
| **spam_rate** | Are recipients marking your email as spam? Based on recipients who open then report spam. | Only send to opted-in recipients. Make unsubscribe easy. Match content to expectations set at signup. |

**Note:** The overall `score` is NOT a simple average of the 5 metrics — the weighting formula is opaque. A single low metric (e.g., spam_rate = 1) can drag the overall score significantly.

---

## API Endpoints

### Get Your Scores (Date Range)

`GET /v3/engagementquality/scores`

| Parameter | Required | Description |
|-----------|----------|-------------|
| `from` | Yes | Start date (YYYY-MM-DD, UTC) |
| `to` | Yes | End date (YYYY-MM-DD, UTC) |

**Python**
```python
import os, requests

headers = {"Authorization": f"Bearer {os.environ['SENDGRID_API_KEY']}"}
response = requests.get(
    "https://api.sendgrid.com/v3/engagementquality/scores",
    params={"from": "2026-04-01", "to": "2026-04-23"},
    headers=headers
)

if response.status_code == 200:
    for entry in response.json()["result"]:
        print(f"Date: {entry['date']}, Score: {entry.get('score', 'N/A')}")
        metrics = entry.get("metrics", {})
        for metric, value in metrics.items():
            print(f"  {metric}: {value}")
elif response.status_code == 202:
    print("Scores not yet calculated — try again later")
```

### Get Subuser Scores (Single Date)

`GET /v3/engagementquality/subusers/scores`

| Parameter | Required | Description |
|-----------|----------|-------------|
| `date` | Yes | Date (YYYY-MM-DD, UTC) |
| `limit` | No | Results per page (default 1000, max 1000) |
| `after_key` | No | Pagination cursor |

Returns paginated results with `_metadata.next_params.after_key` for pagination.

---

## Response Patterns

**200

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-sendgrid-inbound-parse4.36 KB

View saved version →

---
name: twilio-sendgrid-inbound-parse
description: >
  Receive inbound email via SendGrid Inbound Parse webhook. Covers MX
  record setup, parsed vs raw mode, handling attachments, and common
  pitfalls. Use when building email-to-app workflows like support ticket
  creation or email processing pipelines. Requires a SendGrid API key
  (SG.-prefix) — not applicable to the Twilio Email API (comms.twilio.com).
---

## Overview

Inbound Parse converts incoming email into HTTP POST requests to your webhook endpoint. SendGrid receives the email at your domain's MX records and forwards the parsed content to your application.

---

## Setup

1. **Configure MX records:** Point your domain (or subdomain) to `mx.sendgrid.net`
2. **Add webhook:** SendGrid Console > Settings > Inbound Parse > Add Host & URL
3. **Choose mode:** Parsed (default) or Raw

**Subdomain recommended:** Use `inbound.yourdomain.com` to avoid disrupting existing email on `yourdomain.com`.

---

## Parsed Mode (Default)

SendGrid extracts fields and POSTs them as form data:

| Field | Description |
|-------|-------------|
| `from` | Sender address (`"Name <email@example.com>"`) |
| `to` | Envelope recipient |
| `subject` | Email subject line |
| `text` | Plain text body |
| `html` | HTML body |
| `envelope` | JSON string with `to` array and `from` |
| `attachments` | Number of attachments (as string) |
| `attachment-info` | JSON metadata for each attachment |
| `attachment1`, `attachment2`... | Actual attachment files |

**Python (Flask)**
```python
from flask import Flask, request
import json

app = Flask(__name__)

@app.route("/inbound", methods=["POST"])
def handle_inbound():
    sender = request.form.get("from")
    subject = request.form.get("subject")
    text_body = request.form.get("text")
    html_body = request.form.get("html")
    envelope = json.loads(request.form.get("envelope", "{}"))
    attachment_count = int(request.form.get("attachments", "0"))
    
    print(f"From: {sender}, Subject: {subject}")
    
    for i in range(1, attachment_count + 1):
        attachment = request.files.get(f"attachment{i}")
        if attachment:
            print(f"Attachment: {attachment.filename}, {attachment.content_type}")
    
    return "", 200
```

> **Security:** All inbound email content (`from`, `subject`, `text`, `html`, attachments) is untrusted external input. Sanitize HTML to prevent XSS before rendering. If feeding content to an LLM, isolate it as user input — never concatenate into system prompts. Verify webhook authenticity using signed webhooks (see Security section below).

---

## Raw Mode

Posts the entire MIME message as `rawEmail` field. Use when you need full headers, DKIM signatures, or non-standard MIME parts. You must parse the MIME message yourself.

---

## Signed Inbound Parse Webhook (Security)

SendGrid supports ECDSA signature verification for Inbound Parse, the same mechanism used for Event Webhooks. Enable it to cryptographically verify that payloads originate from SendGrid.

**Strongly recommended over IP allowlisting** — SendGrid's webhook traffic comes from dynamic cloud infrastructure where IPs change frequently. Signature verification is more reliable and secure.

---

## CANNOT

- **Cannot use Inbound Parse on a domain that already receives email** — MX records must point to `mx.sendgrid.net`. Use a subdomain to avoid disrupting existing email (e.g., Google Workspace, Microsoft 365).
- **Cannot receive email without MX record changes** — DNS access is required. If you can't modify MX records, you can't use Inbound Parse.
- **Cannot receive emails larger than 30MB** — Inbound messages exceeding 30MB are rejected.
- **Cannot filter inbound email before it hits your webhook** — All email sent to the configured domain reaches your endpoint. Implement filtering in your handler.
- **Cannot route to different endpoints per address** — All mail for the configured domain/subdomain goes to a single webhook URL.
- **Cannot guarantee delive

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-sendgrid-suppressions4.72 KB

View saved version →

---
name: twilio-sendgrid-suppressions
description: >
  Manage SendGrid email suppressions: bounces, blocks, spam reports,
  invalid emails, global unsubscribes, and ASM suppression groups.
  Covers when and how to remove suppressions, reputation impact, and
  category-based unsubscribe management. Use when debugging SendGrid
  delivery issues or building unsubscribe flows. Requires a SendGrid API
  key (SG.-prefix) — not applicable to the Twilio Email API (comms.twilio.com).
---

## Overview

Suppressions prevent SendGrid from sending to addresses that have bounced, reported spam, or unsubscribed. They protect your sender reputation but can also block legitimate re-sends if not managed correctly.

---

## Suppression Types

| Type | Endpoint | What triggers it | Auto-added? |
|------|----------|-----------------|-------------|
| **Hard Bounces** | `/v3/suppression/bounces` | Permanent delivery failure (invalid mailbox, domain doesn't exist) | Yes |
| **Soft Bounces** | No management API — automatic retry only | Temporary failure (mailbox full, server down) — SendGrid auto-retries before suppressing | Yes, after repeated failures |
| **Blocks** | `/v3/suppression/blocks` | Temporary rejection by receiving server (reputation, policy, content) | Yes |
| **Spam Reports** | `/v3/suppression/spam_reports` | Recipient marks email as spam | Yes |
| **Invalid Emails** | `/v3/suppression/invalid_emails` | Malformed email address | Yes |
| **Global Unsubscribes** | `/v3/suppression/unsubscribes` | Recipient unsubscribes from all email | Yes |
| **Group Unsubscribes (ASM)** | `/v3/asm/groups/{id}/suppressions` | Recipient unsubscribes from a category | Yes |

**Hard vs Soft bounces:** Hard bounces (permanent) immediately suppress the address. Soft bounces (temporary) trigger retries — SendGrid will retry delivery before eventually suppressing if the issue persists.

---

## Managing Suppressions

**List bounces (Python)**
```python
import os, requests

headers = {"Authorization": f"Bearer {os.environ['SENDGRID_API_KEY']}"}
response = requests.get("https://api.sendgrid.com/v3/suppression/bounces", headers=headers)
for bounce in response.json():
    print(f"{bounce['email']}: {bounce.get('reason', 'unknown')}")
```

**Remove a bounce (Python)**
```python
requests.delete(f"https://api.sendgrid.com/v3/suppression/bounces/{email}", headers=headers)
```

> **Caution:** Deleting suppression records (especially spam reports) allows re-sending to addresses that previously complained. Always confirm with the user before removal and document the business reason.

---

## ASM Suppression Groups

Use suppression groups for category-based unsubscribes (e.g., "Marketing", "Transactional", "Product Updates"). Recipients can unsubscribe from one category without being suppressed from all email.

**Create a group:**
```python
requests.post("https://api.sendgrid.com/v3/asm/groups",
    headers={**headers, "Content-Type": "application/json"},
    json={"name": "Marketing Emails", "description": "Promotional offers and updates"})
```

**Send with a suppression group:**
Include `asm.group_id` in your Mail Send request. Recipients see a "manage preferences" link instead of a global unsubscribe.

---

## Auto-Purge (Bounce & Block Cleanup)

Configure automatic purge schedules in Console > Settings > Mail Settings > Purge Bounces & Blocks:

- **Soft Bounces:** Auto-purge after N days (1–3,650 days)
- **Hard Bounces:** Auto-purge after N days (1–3,650 days)

**Caution:** Enabling auto-purge without a business reason allows re-sending to previously bounced addresses, which damages sender reputation. Do not use as a workaround to force delivery.

---

## Address Allow List

Console > Settings > Mail Settings > Address Allow List allows specific email addresses or domains to bypass all suppressions. Useful for internal testing addresses.

**Use with extreme caution** — never allowlist domains you don't control (e.g., `gmail.com`), and never use to bypass spam report

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-sendgrid-webhooks5.75 KB

View saved version →

---
name: twilio-sendgrid-webhooks
description: >
  Track email delivery and engagement via SendGrid Event Webhooks.
  Covers all 11 event types (delivery + engagement), webhook handler
  implementation, ECDSA signature verification, batched event processing,
  and common debugging patterns. Use when building SendGrid delivery
  tracking, engagement analytics, or bounce handling. Requires a SendGrid
  API key (SG.-prefix) — not applicable to the Twilio Email API (comms.twilio.com).
---

## Overview

The Mail Send API returns `202 Accepted` (queued) — it does NOT confirm delivery. To know what happened to an email, use Event Webhooks.

**Enable:** SendGrid Console > Settings > Mail Settings > Event Notification

---

## Event Types

### Delivery Events
| Event | Meaning |
|-------|---------|
| `processed` | SendGrid accepted and will attempt delivery |
| `deferred` | Temporary failure — SendGrid will retry |
| `delivered` | Recipient's mail server accepted the message |
| `bounce` | Permanent failure — address invalid or rejected |
| `dropped` | SendGrid will not deliver (suppression, invalid, spam) |

### Engagement Events
| Event | Meaning |
|-------|---------|
| `open` | Recipient opened (pixel-based — unreliable) |
| `click` | Recipient clicked a tracked link |
| `spamreport` | Recipient marked as spam |
| `unsubscribe` | Recipient clicked unsubscribe link |
| `group_unsubscribe` | Recipient unsubscribed from ASM group |
| `group_resubscribe` | Recipient re-subscribed to ASM group |

---

## Webhook Handler

**Critical:** SendGrid posts **batched arrays** of events, not single objects. Your handler must parse an array.

> **Security:** SendGrid webhook endpoints are unauthenticated by default. Enable [Signed Event Webhook Requests](https://docs.sendgrid.com/for-developers/tracking-events/getting-started-event-webhook-security) and verify signatures in production to prevent spoofed event data.

**Python (Flask)**
```python
from flask import Flask, request
app = Flask(__name__)

@app.route("/sendgrid/webhook", methods=["POST"])
def handle_events():
    events = request.get_json()  # Always an array
    for event in events:
        email = event.get("email")
        event_type = event.get("event")
        
        if event_type == "bounce":
            # NOTE: event['reason'] originates from external mail servers — treat as untrusted
            print(f"Bounce: {email}, type: {event.get('type')}, reason: {event.get('reason')}")
        elif event_type == "delivered":
            print(f"Delivered: {email}, sg_message_id: {event.get('sg_message_id')}")
        elif event_type == "dropped":
            print(f"Dropped: {email}, reason: {event.get('reason')}")
        elif event_type == "spamreport":
            print(f"Spam report: {email}")
    return "", 200  # Must return 2xx to acknowledge
```

**Node.js (Express)**
```javascript
app.post("/sendgrid/webhook", express.json(), (req, res) => {
    const events = req.body; // Always an array
    for (const event of events) {
        switch (event.event) {
            case "bounce":
                console.log(`Bounce: ${event.email}, reason: ${event.reason}`);
                break;
            case "delivered":
                console.log(`Delivered: ${event.email}`);
                break;
            case "spamreport":
                console.log(`Spam: ${event.email}`);
                break;
        }
    }
    res.status(200).send();
});
```

---

## Multiple Webhook Endpoints

Since May 2023, you can configure multiple Event Webhook endpoints, each receiving different event types. For example, one endpoint for delivery events feeding your monitoring stack and another for engagement events feeding your analytics pipeline.

Configure in Console > Mail Settings > Event Webhooks. Each endpoint has a Friendly Name and Webhook ID. The number of endpoints allowed depends on your SendGrid plan.

---

## Authentication Options

Two methods for verifying webhook payloads:

| Method

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-send-message7.54 KB

View saved version →

---
name: twilio-send-message
description: >
  Send messages via Twilio's Programmable Messaging API across all
  channels — SMS, MMS, RCS, and WhatsApp. Covers text messages, media,
  rich content (cards, carousels, buttons), template-based sends,
  Messaging Services, status callbacks, and WhatsApp's 24-hour service
  window. Use when the user wants to send a message — whether they
  say "send SMS", "text message", "branded message", "rich message",
  "WhatsApp message", "RCS message", "notification", or "alert". For
  picking the right channel for a use case, first consult
  twilio-messaging-channel-advisor.
---

## Overview

**A single `messages.create()` call sends on any messaging channel — SMS, MMS, RCS, or WhatsApp.** The channel is determined by the sender address and the recipient's capabilities. For channel selection guidance and the full onboarding sequence, see `twilio-messaging-overview` and `twilio-messaging-channel-advisor`.

| Channel | `to` format | Notes | Template required? |
|---------|-------------|-------|--------------------|
| SMS/MMS | `+15551234567` | MMS: US/CA/AU only | No |
| RCS (with SMS fallback) | `+15551234567` | Send via Messaging Service that has both an RCS sender and an SMS sender — Twilio attempts RCS first, falls back to SMS on failure | No |
| RCS (no fallback) | `rcs:+15551234567` | Forces RCS only — fails if recipient isn't RCS-capable | No |
| WhatsApp | `whatsapp:+15551234567` | Send via `whatsapp:`-prefixed `from` | Outside 24-hr window: yes |

**For production:** Send via `messagingServiceSid` instead of `from`. This enables sender pool management, RCS→SMS fallback, SMS pumping protection, link shortening, compliance toolkit, and scheduling. See `twilio-messaging-services`.

---

## Prerequisites

- Twilio account — New to Twilio? See `twilio-account-setup`
- Environment variables: `TWILIO_ACCOUNT_SID`, `TWILIO_AUTH_TOKEN` — see `twilio-iam-auth-setup`
- SDK: `pip install twilio` / `npm install twilio`
- Channel-specific senders:
  - SMS/MMS: a Twilio phone number (see `twilio-account-setup`)
  - RCS: an RCS sender added to a Messaging Service (see `twilio-rcs-messaging`)
  - WhatsApp: an active WhatsApp sender (see `twilio-whatsapp-send-message` for sandbox, `twilio-whatsapp-manage-senders` for production)

---

## Quickstart

**Python**
```python
import os
from twilio.rest import Client

client = Client(os.environ["TWILIO_ACCOUNT_SID"], os.environ["TWILIO_AUTH_TOKEN"])

# SMS
sms = client.messages.create(
    from_="+15017122661",
    to="+15558675310",
    body="Your order has shipped."
)

# RCS — forces RCS only, no fallback
rcs = client.messages.create(
    messaging_service_sid="MGxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    to="rcs:+15558675310",
    body="Your order has shipped."
)

# WhatsApp
whatsapp = client.messages.create(
    from_="whatsapp:+15017122661",
    to="whatsapp:+15558675310",
    body="Your order has shipped."
)

# Via Messaging Service (recommended — attempts RCS first, falls back to SMS)
msg = client.messages.create(
    messaging_service_sid="MGxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    to="+15558675310",
    body="Your order has shipped."
)
```

**Node.js**
```javascript
const client = require("twilio")(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);

// SMS
const sms = await client.messages.create({
    from: "+15017122661",
    to: "+15558675310",
    body: "Your order has shipped.",
});

// RCS — forces RCS only, no fallback
const rcs = await client.messages.create({
    messagingServiceSid: "MGxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    to: "rcs:+15558675310",
    body: "Your order has shipped.",
});

// WhatsApp
const whatsapp = await client.messages.create({
    from: "whatsapp:+15017122661",
    to: "whatsapp:+15558675310",
    body: "Your order has shipped.",
});

// Via Messaging Service (attempts RCS first, falls back to SMS)
const msg = await client.messages.create({
    messagingServiceSid: "MGxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    to: "

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-sms-send-message7.38 KB

View saved version →

---
name: twilio-sms-send-message
description: >
  SMS and MMS deep-dive reference. Covers SMS-specific error codes,
  message filtering troubleshooting ("Messages Being Filtered or Blocked?"
  diagnostic checklist), MMS media support (US/CA/AU only), and SMS pumping
  indicators. For sending SMS, use twilio-send-message instead. Use this
  skill only when debugging SMS delivery issues or needing SMS-specific
  details not in the consolidated send skill.
---

## Overview

**SMS is one channel in Twilio's Messaging platform.** All channels — SMS, WhatsApp, RCS, Facebook Messenger — share the same `messages.create()` API. See `twilio-messaging-overview` for the full channel comparison and onboarding sequence.

| When to use SMS | When to consider alternatives |
|----------------|------------------------------|
| Reach any phone number globally | Need rich media outside US/CA/AU → WhatsApp |
| No app install required | Opted-in audience prefers chat apps → WhatsApp |
| Time-sensitive alerts (OTP, outage) | Marketing campaigns → `twilio-marketing-promotions-advisor` |
| Regulatory/compliance requires SMS | Cost-sensitive high-volume → WhatsApp (lower per-msg cost in many markets) |

**For production SMS:** Use a Messaging Service (`messagingServiceSid`) instead of a raw `from` number. It enables sender pool management, compliance toolkit, SMS pumping protection, link shortening, and message scheduling. See `twilio-messaging-services`.

Every outbound SMS requires a `from` Twilio number (or `messagingServiceSid`) and a `to` recipient — both in E.164 format.

---

## Prerequisites

- Twilio account with an SMS-capable phone number
  — New to Twilio? See `twilio-account-setup` for signup, getting a number, and trial limitations
- Environment variables:
  - `TWILIO_ACCOUNT_SID`
  - `TWILIO_AUTH_TOKEN`
  — See `twilio-iam-auth-setup` for credential setup and best practices
- SDK: `pip install twilio` / `npm install twilio`

---

## Quickstart

**Python**
```python
import os
from twilio.rest import Client

client = Client(os.environ["TWILIO_ACCOUNT_SID"], os.environ["TWILIO_AUTH_TOKEN"])

message = client.messages.create(
    from_="+15017122661",   # Your Twilio number (E.164)
    to="+15558675310",      # Recipient (E.164)
    body="Your appointment is confirmed for tomorrow at 2pm."
)

print(message.sid)     # SMxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
print(message.status)  # queued | sent | delivered | failed
```

**Node.js**
```node
const twilio = require("twilio");
const client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);

const message = await client.messages.create({
    from: "+15017122661",
    to: "+15558675310",
    body: "Your appointment is confirmed for tomorrow at 2pm.",
});

console.log(message.sid);
console.log(message.status);
```

---

## Key Patterns

### Send MMS (with media)

**Python**
```python
message = client.messages.create(
    from_="+15017122661",
    to="+15558675310",
    body="Here is your invoice.",
    media_url=["https://example.com/invoice.pdf"]
)
```

**Node.js**
```node
const message = await client.messages.create({
    from: "+15017122661",
    to: "+15558675310",
    body: "Here is your invoice.",
    mediaUrl: ["https://example.com/invoice.pdf"],
});
```

Supported media types: images (JPEG, PNG, GIF), PDF, audio, video. Max 5 MB per message.

### Send via Messaging Service (recommended for scale)

Use `messagingServiceSid` instead of `from` — Twilio picks the best sender automatically from your pool.

**Python**
```python
message = client.messages.create(
    messaging_service_sid="MGxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    to="+15558675310",
    body="Your order has shipped."
)
```

**Node.js**
```node
const message = await client.messages.create({
    messagingServiceSid: "MGxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    to: "+15558675310",
    body: "Your order has shipped.",
});
```

### Track Delivery Status

**Python**
```python
message = client.messages.create(
    from_="+15

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-taskrouter-routing13.8 KB

View saved version →

---
name: twilio-taskrouter-routing
description: >
  Route tasks to agents using Twilio TaskRouter. Covers Workers, Task
  Queues, Workflows, Reservations, skills-based routing, and common
  gotchas (hyphen attributes, HAS operator, reservation cascade). Use this
  skill for any multi-agent contact center, support queue, or AI agent
  escalation routing.
---

## Overview

TaskRouter is Twilio's skills-based routing engine. Instead of building custom queuing logic, you define Workers (agents), Task Queues (groups), and Workflows (routing rules). TaskRouter matches incoming tasks to the best available worker.

```
Incoming Task → Workflow (routing rules) → Task Queue (skill match) → Worker (agent)
                                                                        ↓
                                                                   Reservation
                                                                   (accept/reject)
```

**Common mistake:** Developers reinvent TaskRouter in custom Node.js — don't. If you're building skills-based routing, queue management, or agent assignment, use TaskRouter.

---

## Prerequisites

- Twilio account — see `twilio-account-setup`
- `TWILIO_ACCOUNT_SID` and `TWILIO_AUTH_TOKEN` — see `twilio-iam-auth-setup`
- SDK: `pip install twilio` / `npm install twilio`
- For voice routing: a Twilio phone number with webhook configured — see `twilio-voice-twiml`
- For AI escalation: ConversationRelay with escalation tools — see `twilio-voice-conversation-relay`

---

## Quickstart

**Step 1 — Create a Workspace**

A Workspace is the top-level container for all TaskRouter resources.

**Python**
```python
import os
from twilio.rest import Client

client = Client(os.environ["TWILIO_ACCOUNT_SID"], os.environ["TWILIO_AUTH_TOKEN"])

workspace = client.taskrouter.v1.workspaces.create(
    friendly_name="Support Center",
    event_callback_url="https://yourapp.com/taskrouter-events"
)

workspace_sid = workspace.sid  # WSxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
print(workspace_sid)
```

**Node.js**
```node
const twilio = require("twilio");
const client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);

const workspace = await client.taskrouter.v1.workspaces.create({
    friendlyName: "Support Center",
    eventCallbackUrl: "https://yourapp.com/taskrouter-events",
});

const workspaceSid = workspace.sid;
```

**Step 2 — Create Activities (agent states)**

**Python**
```python
# Available — worker can receive tasks
available = client.taskrouter.v1.workspaces(workspace_sid).activities.create(
    friendly_name="Available", available=True
)

# Offline — worker cannot receive tasks
offline = client.taskrouter.v1.workspaces(workspace_sid).activities.create(
    friendly_name="Offline", available=False
)

# On a task — worker is busy
on_task = client.taskrouter.v1.workspaces(workspace_sid).activities.create(
    friendly_name="On Task", available=False
)
```

**Step 3 — Create Workers (agents)**

> **Security:** Always use `json.dumps()` (Python) or `JSON.stringify()` (Node.js) to construct attribute payloads. String interpolation is vulnerable to JSON injection.

**Python**
```python
worker = client.taskrouter.v1.workspaces(workspace_sid).workers.create(
    friendly_name="Alice",
    attributes='{"skills": ["billing", "technical"], "languages": ["en", "es"], "department": "support"}'
)
```

**Node.js**
```node
const worker = await client.taskrouter.v1.workspaces(workspaceSid).workers.create({
    friendlyName: "Alice",
    attributes: JSON.stringify({
        skills: ["billing", "technical"],
        languages: ["en", "es"],
        department: "support",
    }),
});
```

**Step 4 — Create Task Queues**

**Python**
```python
# Billing queue — matches workers with "billing" skill
billing_queue = client.taskrouter.v1.workspaces(workspace_sid).task_queues.create(
    friendly_name="Billing",
    target_workers='skills HAS "billing"'
)

# Technical queue
tech_queue = client.taskrouter.v1.workspaces(work

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-verify-send-otp10.7 KB

View saved version →

---
name: twilio-verify-send-otp
description: >
  Send and verify one-time passcodes (OTPs) via Twilio Verify over SMS, RCS,
  voice, email, or WhatsApp. Covers creating a Verify Service, sending tokens,
  checking submitted codes, automatic WhatsApp-to-SMS fallback, and service
  configuration. TOTP is supported via the Factors API (a separate family from
  channel-based OTP). Use this skill to add phone or email verification or
  two-factor authentication to any application.
---

## Overview

Use **Twilio Verify** to manage the full OTP lifecycle: code generation, delivery, expiry, rate limiting, and Fraud Guard protection. Use the **Programmable Messaging API** to build your own OTP message infrastructure and access features such as SMS Pumping Protection.

| | Twilio Verify | Programmable Messaging API |
|---|---|---|
| Code generation + expiry | Built-in (10min default, configurable). Also supports custom codes. | Build yourself |
| Rate limiting | Built-in (per-phone, per-service) | Build yourself |
| Fraud protection | Fraud Guard (geo-permissions, rate anomaly) | SMS Pumping Protection |
| A2P registration | Exempt — no 10DLC needed | Required — must register campaign |
| Multi-channel | One API, change `channel` param (SMS/Voice/Email/WhatsApp/RCS) | Separate integration per channel |
| Cost | [Per confirmed verification + channel fee](https://www.twilio.com/en-us/verify/pricing) | Per-message pricing + build cost |
| Delivery confirmation | Yes — via List Attempts or Events API | Yes (via StatusCallback) |

**When Programmable Messaging is justified:** You need full control over message content, custom delivery logic, or SMS Pumping Protection features. For standard OTP/2FA flows, use Verify.

Verify supports SMS, voice, email, WhatsApp, and RCS — only the `channel` parameter changes per delivery method. TOTP (authenticator apps) is supported via the Verify Factors API, a separate implementation from channel-based OTP.

---

## Prerequisites

- Twilio account (free trial works for testing)
  — New to Twilio? See `twilio-account-setup`
  — Verify requires no separate product activation — just create a Service below
- Environment variables:
  - `TWILIO_ACCOUNT_SID`
  - `TWILIO_AUTH_TOKEN`
  - `VERIFY_SERVICE_SID` (created in Quickstart step 1)
  — See `twilio-iam-auth-setup` for credential setup and best practices
- SDK: `pip install twilio` / `npm install twilio`
- For WhatsApp channel only: a registered production WhatsApp sender — see `twilio-whatsapp-manage-senders`

---

## Quickstart

**Step 1 — Create a Verify Service (one-time)**

**Python**
```python
import os
from twilio.rest import Client

client = Client(os.environ["TWILIO_ACCOUNT_SID"], os.environ["TWILIO_AUTH_TOKEN"])

service = client.verify.v2.services.create(
    friendly_name="My App Verification"
)
print(service.sid)  # VAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx — save as VERIFY_SERVICE_SID
```

**Node.js**
```node
const twilio = require("twilio");
const client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);

const service = await client.verify.v2.services.create({
    friendlyName: "My App Verification",
});
console.log(service.sid);  // VAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

Store the Service SID — reuse it for all verifications, do not recreate it each time.

**Step 2 — Send a verification token**

**Python**
```python
verification = client.verify.v2 \
    .services(os.environ["VERIFY_SERVICE_SID"]) \
    .verifications \
    .create(to="+15558675310", channel="sms")

print(verification.status)  # pending
```

**Node.js**
```node
const verification = await client.verify.v2
    .services(process.env.VERIFY_SERVICE_SID)
    .verifications.create({ to: "+15558675310", channel: "sms" });

console.log(verification.status);  // pending
```

**Step 3 — Check the submitted code**

**Python**
```python
check = client.verify.v2 \
    .services(os.environ["VERIFY_SERVICE_SID"]) \
    .verification_checks \
    .create(to="+15558675310", cod

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-voice-conversation-relay7.46 KB

View saved version →

---
name: twilio-voice-conversation-relay
description: >
  Build AI-powered voice agents using Twilio ConversationRelay. Handles
  real-time speech recognition (ASR), text-to-speech (TTS), and bidirectional
  audio streaming via WebSocket. Covers TwiML setup, WebSocket message types,
  LLM integration, streaming responses, and voice provider configuration. Use
  this skill to build voice bots, IVR replacements, or real-time AI voice
  assistants on Twilio calls.
---

## Overview

ConversationRelay connects Twilio's telephony layer to your app via a persistent WebSocket. Twilio handles ASR (speech-to-text) and TTS (text-to-speech); your app receives transcripts, calls an LLM, and sends text back for playback.

```
Caller ←→ Twilio (ASR/TTS) ←→ WebSocket ←→ Your App ←→ LLM
```

---

## Prerequisites

- Upgraded Twilio account with ConversationRelay access (requires onboarding)
  — New to Twilio? See `twilio-account-setup`
  — Start onboarding at: [Console > Voice > ConversationRelay](https://console.twilio.com/us1/voice/conversation-relay) — access is **not** instant
- A voice-capable Twilio phone number
- `TWILIO_ACCOUNT_SID` and `TWILIO_AUTH_TOKEN` — see `twilio-iam-auth-setup`
- WebSocket server reachable via `wss://` (TLS required)
- An LLM integration (OpenAI, Anthropic, etc.)
- For placing calls: see `twilio-voice-outbound-calls`

**Onboarding:** Complete via Console > Voice > ConversationRelay > Onboarding. Select TTS/ASR providers:
- **TTS:** Deepgram, Amazon Polly, Google Cloud TTS, ElevenLabs
- **ASR:** Deepgram, Google Cloud STT

---

## Quickstart

**Step 1 — Return TwiML pointing to your WebSocket server**

**Python (Flask)**
```python
from flask import Flask
from twilio.twiml.voice_response import VoiceResponse, Connect, ConversationRelay

app = Flask(__name__)

@app.route("/voice", methods=["POST"])
def voice():
    response = VoiceResponse()
    connect = Connect()
    connect.conversation_relay(
        url="wss://yourapp.com/ws/voice",
        welcome_greeting="Hello! How can I help you today?"
    )
    response.append(connect)
    return str(response)
```

**Node.js (Express)**
```node
const { VoiceResponse } = require("twilio").twiml;

app.post("/voice", (req, res) => {
    const response = new VoiceResponse();
    const connect = response.connect();
    connect.conversationRelay({
        url: "wss://yourapp.com/ws/voice",
        welcomeGreeting: "Hello! How can I help you today?",
    });
    res.type("text/xml").send(response.toString());
});
```

**Step 2 — Handle WebSocket events and respond with text**

**Python (websockets)**
```python
import asyncio, json, websockets

async def handle_call(websocket):
    async for message in websocket:
        event = json.loads(message)
        if event["type"] == "prompt":
            ai_response = await call_llm(event["voicePrompt"])
            await websocket.send(json.dumps({"type": "text", "token": ai_response, "last": True}))

async def main():
    async with websockets.serve(handle_call, "0.0.0.0", 8080):
        await asyncio.Future()

asyncio.run(main())
```

**Node.js (ws)**
```node
const WebSocket = require("ws");
const wss = new WebSocket.Server({ port: 8080 });

wss.on("connection", (ws) => {
    ws.on("message", async (data) => {
        const event = JSON.parse(data);
        if (event.type === "prompt") {
            const aiResponse = await callLLM(event.voicePrompt);
            ws.send(JSON.stringify({ type: "text", token: aiResponse, last: true }));
        }
    });
});
```

> **Security:** The `voicePrompt` field contains ASR-transcribed caller speech — it is untrusted external input. When passing to an LLM, isolate it as user input within a structured system prompt. Implement topic boundaries and output filtering to prevent the LLM from disclosing system instructions or speaking inappropriate content. ConversationRelay is a pure transport layer with no built-in content safety — any LLM output is spoken to the caller verbatim.

---

## Key P

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-voice-outbound-calls10.1 KB

View saved version →

---
name: twilio-voice-outbound-calls
description: >
  Make outbound phone calls via Twilio's Programmable Voice REST API. Covers
  the full voice platform: calls.create(), answering machine detection (AMD),
  conference-based agent bridging, call recording, status tracking, and SIP
  Trunking. Use this skill for outbound calls, sales dialers, or when asking
  what voice APIs are available.
---

## Overview

> **Agent safety:** Before placing an outbound call, always confirm the recipient number and intent with the user. Outbound calls are irreversible and may incur charges. For automated systems, implement TCPA compliance: obtain prior express consent, respect quiet hours (8 AM–9 PM recipient local time), and maintain a Do Not Call list.

Every outbound call requires a `from` Twilio number, a `to` recipient, and TwiML instructions that define what happens when the call is answered — either as a webhook URL or inline.

---

## Voice Platform Capabilities

Outbound calls go beyond basic `calls.create()`. Here's what you can build:

| Capability | How | When to use |
|-----------|-----|-------------|
| **Basic outbound call** | `calls.create()` with TwiML or webhook URL | Any outbound call — see Quickstart below |
| **Answering Machine Detection (AMD)** | `machineDetection` parameter on `calls.create()` | Sales dialers, call campaigns — filter voicemail from humans |
| **Conference-based agent bridging** | `<Dial><Conference>` in TwiML | Connect agents to live prospects with whisper, barge, hold |
| **SIP Trunking** | Elastic SIP Trunking | Bring your own carrier for outbound calls — cost reduction at scale |
| **Call Recording** | `record=True` on `calls.create()` or `<Record>` verb | Compliance, QA, training |
| **Voice Insights** | Automatic per-call metrics | Call quality monitoring — latency, jitter, packet loss, answer rates |
| **AI Voice Agents** | ConversationRelay + LLM | Real-time speech recognition → LLM → TTS for conversational AI |

For TwiML verbs (Say, Gather, Dial, Record, Conference, Pay), see `twilio-voice-twiml`.
For AI voice agents, see `twilio-voice-conversation-relay`.

---

## Prerequisites

- Twilio account with a voice-capable phone number
  — New to Twilio? See `twilio-account-setup` for signup, getting a number, and trial limitations
  — Trial accounts can only call verified numbers
- Environment variables:
  - `TWILIO_ACCOUNT_SID`
  - `TWILIO_AUTH_TOKEN`
  — See `twilio-iam-auth-setup` for credential setup and best practices
- SDK: `pip install twilio` / `npm install twilio`

---

## Quickstart

**Python**
```python
import os
from twilio.rest import Client

client = Client(os.environ["TWILIO_ACCOUNT_SID"], os.environ["TWILIO_AUTH_TOKEN"])

call = client.calls.create(
    from_="+15017122661",    # Your Twilio number (E.164)
    to="+15558675310",       # Recipient (E.164)
    twiml="<Response><Say>Your order has shipped. Goodbye.</Say></Response>"
)

print(call.sid)     # CAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
print(call.status)  # queued | ringing | in-progress | completed | failed
```

**Node.js**
```node
const twilio = require("twilio");
const client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);

const call = await client.calls.create({
    from: "+15017122661",
    to: "+15558675310",
    twiml: "<Response><Say>Your order has shipped. Goodbye.</Say></Response>",
});

console.log(call.sid);
console.log(call.status);
```

---

## Key Patterns

### Use a Webhook URL for Dynamic Call Handling

Pass a `url` instead of inline `twiml` — Twilio POSTs to your server when the call connects and executes the TwiML you return.

**Python**
```python
call = client.calls.create(
    from_="+15017122661",
    to="+15558675310",
    url="https://yourapp.com/twiml/welcome"
)
```

**Node.js**
```node
const call = await client.calls.create({
    from: "+15017122661",
    to: "+15558675310",
    url: "https://yourapp.com/twiml/welcome",
});
```

**Python (Flask) — TwiML webhook handler**
```pyth

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-voice-twiml10.4 KB

View saved version →

---
name: twilio-voice-twiml
description: >
  Build voice call logic using TwiML (Twilio Markup Language). Covers the
  core verbs (Say, Play, Gather, Dial, Record, Conference), generating TwiML
  with Python and Node.js SDKs, and a complete inbound call IVR example. Use
  this skill to define call behavior for inbound or outbound calls.
---

## Overview

TwiML is XML that Twilio executes during a call. Your server returns a TwiML document in response to a Twilio webhook POST, and Twilio executes it.

```
Caller → Twilio → POST to your webhook → Your server returns TwiML → Twilio executes it
```

---

## Prerequisites

- Twilio account with a voice-capable phone number
  — New to Twilio? See `twilio-account-setup`
- Webhook endpoint returning TwiML with `Content-Type: text/xml`
- SDK (for programmatic generation): `pip install twilio` / `npm install twilio`

---

## Quickstart

A minimal inbound call handler that greets the caller and presents a menu:

**Python (Flask)**
```python
from flask import Flask, request
from twilio.twiml.voice_response import VoiceResponse

app = Flask(__name__)

@app.route("/voice", methods=["POST"])
def handle_call():
    response = VoiceResponse()
    gather = response.gather(num_digits=1, action="/menu-choice")
    gather.say("Welcome to Acme. Press 1 for sales, 2 for support.")
    response.redirect("/voice")  # Loop if no input
    return str(response)

@app.route("/menu-choice", methods=["POST"])
def menu_choice():
    digit = request.form.get("Digits")
    response = VoiceResponse()
    if digit == "1":
        response.dial("+15551234567")
    elif digit == "2":
        response.say("Connecting to support.")
        response.dial("+15559876543")
    else:
        response.say("Invalid option.")
        response.redirect("/voice")
    return str(response)
```

**Node.js (Express)**
```node
const { VoiceResponse } = require("twilio").twiml;

app.post("/voice", (req, res) => {
    const response = new VoiceResponse();
    const gather = response.gather({ numDigits: 1, action: "/menu-choice" });
    gather.say("Welcome. Press 1 for sales, 2 for support.");
    response.redirect("/voice");
    res.type("text/xml").send(response.toString());
});

app.post("/menu-choice", (req, res) => {
    const digit = req.body.Digits;
    const response = new VoiceResponse();
    if (digit === "1") response.dial("+15551234567");
    else response.say("Invalid option.").redirect("/voice");
    res.type("text/xml").send(response.toString());
});
```

---

## Core Verbs

### Say — Text-to-speech

**Python**
```python
from twilio.twiml.voice_response import VoiceResponse

response = VoiceResponse()
response.say("Your appointment is confirmed.", voice="alice", language="en-US")
```

**Node.js**
```node
const { VoiceResponse } = require("twilio").twiml;
const response = new VoiceResponse();
response.say({ voice: "alice", language: "en-US" }, "Your appointment is confirmed.");
```

Voices: `alice` (default), `man`, `woman`, or Polly/Google TTS (e.g. `Polly.Joanna`).

### Gather — Collect keypad input or speech

**Python**
```python
response = VoiceResponse()
gather = response.gather(num_digits=1, action="/handle-input", method="POST")
gather.say("Press 1 for sales, press 2 for support.")
response.say("We did not receive your input.")  # Fallback if no input
```

**Node.js**
```node
const gather = response.gather({ numDigits: 1, action: "/handle-input", method: "POST" });
gather.say("Press 1 for sales, press 2 for support.");
response.say("We did not receive your input.");
```

Twilio POSTs collected digits to `action` as `Digits` parameter.

### Play — Play an audio file

**Python**
```python
response = VoiceResponse()
response.play("https://example.com/audio/greeting.mp3")
```

**Node.js**
```node
const response = new VoiceResponse();
response.play("https://example.com/audio/greeting.mp3");
```

Supported formats: MP3, WAV. URL must be publicly accessible.

### Dial — Connect to another number

**Python**
```python
f

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-webhook-architecture14.7 KB

View saved version →

---
name: twilio-webhook-architecture
description: >
  Design, secure, and operate Twilio webhook endpoints. Covers inbound event
  handling, status callbacks, signature validation, connection overrides for
  retry and timeout tuning, local development tunneling, and production
  hardening. Use this skill whenever an agent needs to receive HTTP callbacks
  from Twilio for any product -- messaging, voice, verify, or event streams.
---

## Overview

Twilio delivers events to your application via HTTP callbacks (webhooks). Inbound messages and calls trigger webhooks that expect a TwiML response; status callbacks and event streams push delivery and lifecycle data asynchronously. This skill covers the cross-product patterns that apply to every webhook integration.

---

## Prerequisites

- Twilio account with a phone number or service configured with a webhook URL
  -- New to Twilio? See `twilio-account-setup`
- `TWILIO_ACCOUNT_SID` and `TWILIO_AUTH_TOKEN` -- see `twilio-iam-auth-setup`
- SDK: `pip install twilio flask` / `npm install twilio express`
- Publicly accessible HTTPS endpoint (see Local Development section below)

---

## Quickstart

Receive an inbound SMS and validate the request signature before replying.

**Python (Flask)**
```python
import os
from flask import Flask, request, abort
from twilio.request_validator import RequestValidator
from twilio.twiml.messaging_response import MessagingResponse

app = Flask(__name__)
validator = RequestValidator(os.environ["TWILIO_AUTH_TOKEN"])

@app.route("/sms", methods=["POST"])
def incoming_sms():
    sig = request.headers.get("X-Twilio-Signature", "")
    if not validator.validate(request.url, request.form, sig):
        abort(403)
    resp = MessagingResponse()
    resp.message(f"Got: {request.form.get('Body')}")
    return str(resp), 200, {"Content-Type": "text/xml"}
```

**Node.js (Express)**
```node
const express = require("express");
const twilio = require("twilio");
const app = express();
app.use(express.urlencoded({ extended: false }));

app.post("/sms", (req, res) => {
    const valid = twilio.validateRequest(
        process.env.TWILIO_AUTH_TOKEN,
        req.headers["x-twilio-signature"],
        `https://${req.headers.host}${req.originalUrl}`,
        req.body
    );
    if (!valid) return res.status(403).send("Forbidden");
    const twiml = new twilio.twiml.MessagingResponse();
    twiml.message(`Got: ${req.body.Body}`);
    res.type("text/xml").send(twiml.toString());
});
```

Set your webhook URL in Console: **Phone Numbers > Active Numbers > (your number) > Messaging > "A Message Comes In"**.

---

## Key Patterns

### 1. Webhook Types Across Products

| Webhook type | Trigger | Expected response | Products |
|---|---|---|---|
| Inbound event | Message received / call answered | TwiML (XML) | Messaging, Voice |
| Status callback | Resource state change | `200` or `204` (no body required) | Messaging, Voice, Verify, Video |
| Action URL | TwiML verb completes (`<Gather>`, `<Record>`) | Next TwiML | Voice |
| Recording status | Recording processing completes | `200` or `204` | Voice |
| Debugger event | Error or warning on account | `200` or `204` | All |
| Event Streams | Any subscribed event | `200` or `204` | All (via Sink) |

### 2. Signature Validation

Twilio signs every webhook with an `X-Twilio-Signature` header (HMAC-SHA1 using your Auth Token). Always validate before processing.

**Form-encoded requests (`application/x-www-form-urlencoded`):**

Pass the full URL and POST body parameters to the validator.

**Python**
```python
from twilio.request_validator import RequestValidator

validator = RequestValidator(os.environ["TWILIO_AUTH_TOKEN"])
is_valid = validator.validate(request.url, request.form, request.headers.get("X-Twilio-Signature", ""))
```

**Node.js**
```node
const { validateRequest } = require("twilio");

const isValid = validateRequest(
    process.env.TWILIO_AUTH_TOKEN,
    req.headers["x-twilio-signature"],
    `https://${req.headers.host}${re

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-whatsapp-manage-senders5.9 KB

View saved version →

---
name: twilio-whatsapp-manage-senders
description: >
  Create, configure, and manage WhatsApp Business senders via Twilio's
  Channels Senders API. Covers programmatic sender registration, profile setup,
  webhook configuration, sender lifecycle statuses, and ISV flows. Use this
  skill to register and manage production WhatsApp senders at scale.
---

## Overview

A WhatsApp sender is a phone number registered with WhatsApp Business through Twilio. Registration goes through a lifecycle of statuses before becoming `ONLINE`. Sandbox testing does not require a registered sender — see `twilio-whatsapp-send-message`.

---

## Prerequisites

- Upgraded Twilio account (trial accounts cannot register production senders)
  — See `twilio-account-setup` for signup and upgrade steps
- A phone number capable of receiving SMS or voice verification
- Number must not already be registered with WhatsApp
- Environment variables:
  - `TWILIO_ACCOUNT_SID`
  - `TWILIO_AUTH_TOKEN`
  — See `twilio-iam-auth-setup` for credential setup and best practices
- SDK: `pip install twilio` / `npm install twilio`

---

## Quickstart

**Python**
```python
import os
from twilio.rest import Client

client = Client(os.environ["TWILIO_ACCOUNT_SID"], os.environ["TWILIO_AUTH_TOKEN"])

# Step 1: Initiate registration
sender = client.messaging.v2.channels.senders.create(
    sender_id="whatsapp:+15017122661",
    verification_method="sms"
)
print(sender.sid)     # XExxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
print(sender.status)  # CREATING

# Step 2: Submit the OTP Twilio sends to the number
sender = client.messaging.v2.channels.senders(sender.sid).update(
    verification_code="123456"
)
print(sender.status)  # ONLINE (may pass through TWILIO_REVIEW first)
```

**Node.js**
```node
const twilio = require("twilio");
const client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);

// Step 1: Initiate registration
const sender = await client.messaging.v2.channels.senders.create({
    senderId: "whatsapp:+15017122661",
    verificationMethod: "sms",
});
console.log(sender.sid, sender.status);

// Step 2: Submit the OTP
const verified = await client.messaging.v2.channels.senders(sender.sid).update({
    verificationCode: "123456",
});
console.log(verified.status);
```

---

## Sender Lifecycle Statuses

| Status | Meaning |
|--------|---------|
| `CREATING` | Registration initiated |
| `PENDING_VERIFICATION` | Awaiting OTP submission |
| `VERIFYING` | OTP being validated |
| `TWILIO_REVIEW` | Under Twilio/Meta review |
| `ONLINE` | Active and ready to send |
| `OFFLINE` | Inactive — check `offlineReasons` |
| `DRAFT` | Incomplete registration |

---

## Key Patterns

### Set Business Profile

**Python**
```python
sender = client.messaging.v2.channels.senders(SENDER_SID).update(
    profile_name="Acme Support",
    profile_about="Official support channel for Acme Corp",
    profile_address="123 Main St, San Francisco, CA",
    profile_vertical="PROFESSIONAL_SERVICES",
    profile_logo_url="https://acme.com/logo.png",
    profile_websites=["https://acme.com"]
)
```

**Node.js**
```node
const sender = await client.messaging.v2.channels.senders(SENDER_SID).update({
    profileName: "Acme Support",
    profileAbout: "Official support channel for Acme Corp",
    profileAddress: "123 Main St, San Francisco, CA",
    profileVertical: "PROFESSIONAL_SERVICES",
    profileLogoUrl: "https://acme.com/logo.png",
    profileWebsites: ["https://acme.com"],
});
```

### Configure Webhooks

**Python**
```python
sender = client.messaging.v2.channels.senders(SENDER_SID).update(
    callback_url="https://yourapp.com/whatsapp/inbound",
    callback_method="POST",
    status_callback_url="https://yourapp.com/whatsapp/status"
)
```

**Node.js**
```node
await client.messaging.v2.channels.senders(SENDER_SID).update({
    callbackUrl: "https://yourapp.com/whatsapp/inbound",
    callbackMethod: "POST",
    statusCallbackUrl: "https://yourapp.com/whatsapp/status",
});
```

### Retrieve 

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

twilio-whatsapp-send-message5.62 KB

View saved version →

---
name: twilio-whatsapp-send-message
description: >
  WhatsApp messaging deep-dive reference. Covers the 24-hour service
  window rules (free-form vs template mode), sandbox setup for testing,
  template approval workflow, production sender requirements, and
  WhatsApp-specific error handling. For sending WhatsApp messages, use
  twilio-send-message instead. Use this skill when setting up WhatsApp
  for the first time or debugging WhatsApp-specific delivery behavior.
---

## Overview

**WhatsApp is one channel in Twilio's Messaging platform.** All channels share the same `messages.create()` API — see `twilio-messaging-overview` for the full channel comparison and onboarding sequence.

Twilio routes WhatsApp through the Programmable Messaging API — all numbers use `whatsapp:+E.164` prefix. Two sending modes apply: **free-form** (within 24 hrs of last inbound) and **template** (anytime). Sending free-form outside the window causes silent delivery failure — always check which mode is required.

| Mode | When allowed | Parameters |
|------|-------------|------------|
| Free-form | Within 24 hrs of last inbound from user | `body`, optional `mediaUrl` |
| Template | Anytime | `contentSid` + `contentVariables` |

---

## Prerequisites

- Twilio account with WhatsApp enabled
  — New to Twilio? See `twilio-account-setup`
- Environment variables:
  - `TWILIO_ACCOUNT_SID`
  - `TWILIO_AUTH_TOKEN`
  — See `twilio-iam-auth-setup` for credential setup and best practices
- SDK: `pip install twilio` / `npm install twilio`
- Recipient opted in to receive messages from your WhatsApp Business Account

**Testing (sandbox):** Join by texting `join <your-code>` to `+14155238886`. No registration needed — see [Console > Messaging > Try it out > Send a WhatsApp message](https://console.twilio.com/us1/develop/sms/try-it-out/whatsapp-learn). Sandbox participants must re-join every 3 days.

**Production:** Register a WhatsApp Business sender first — see `twilio-whatsapp-manage-senders`.

---

## Quickstart

**Python**
```python
import os
from twilio.rest import Client

client = Client(os.environ["TWILIO_ACCOUNT_SID"], os.environ["TWILIO_AUTH_TOKEN"])

message = client.messages.create(
    from_="whatsapp:+14155238886",   # Sandbox sender (or your production number)
    to="whatsapp:+15005550006",      # Must have joined the sandbox
    body="Your order has been confirmed."
)

print(message.sid)     # MMxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
print(message.status)  # queued | sent | delivered | failed
```

**Node.js**
```node
const twilio = require("twilio");
const client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);

const message = await client.messages.create({
    from: "whatsapp:+14155238886",
    to: "whatsapp:+15005550006",
    body: "Your order has been confirmed.",
});

console.log(message.sid);
console.log(message.status);
```

---

## Key Patterns

### Send a Template Message (outside service window)

Templates are created in Console > Messaging > Content Template Builder and must be approved by Meta. See `twilio-content-template-builder` for template creation.

**Python**
```python
message = client.messages.create(
    from_="whatsapp:+14155238886",
    to="whatsapp:+15005550006",
    content_sid="HXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    content_variables='{"1": "March 25", "2": "2:00 PM"}'
)
```

**Node.js**
```node
const message = await client.messages.create({
    from: "whatsapp:+14155238886",
    to: "whatsapp:+15005550006",
    contentSid: "HXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    contentVariables: JSON.stringify({ "1": "March 25", "2": "2:00 PM" }),
});
```

### Send Media (free-form only)

Max file size: 16 MB.

**Python**
```python
message = client.messages.create(
    from_="whatsapp:+14155238886",
    to="whatsapp:+15005550006",
    body="Here is your invoice.",
    media_url=["https://example.com/invoice.pdf"]
)
```

**Node.js**
```node
const message = await client.messages.create({
    from: "whatsapp:+141552

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

Package details

Publisher declarations from the archived package. These are separate from our research and the live service's terms.

Package license
MIT
Package author
Twilio
Keywords
See keywords

Declared capabilities

  • Read
  • Write

Package observed Nov 15, 2026.

Technical details
First seen
Sep 30, 2026 · 22:02 UTC
Last seen
Nov 15, 2026 · 06:00 UTC
Collection status
Collected

Plugin_c266c85897248191be15eb07c415f89e

Download plugin data (JSON)

Plugin details: freshly prepared. Prepared . Refreshed when plugin data changes or after 6 hours. Your account and Follow status are live.