twilio-verify-send-otp
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.
What this skill does
## 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", code="123456")
if check.status == "approved":
print("Verified!")
else:
print("Invalid or expired code")
```
**Node.js**
```node
const check = await client.verify.v2
.services(process.env.VERIFY_SERVICE_SID)
.verificationChecks.create({ to: "+15558675310", code: "123456" });
if (check.status === "approved") {
console.log("Verified!");
} else {
console.log("Invalid or expired code");
}
```
---
## Key Patterns
### Supported Channels
| Channel | `channel` value | Notes |
|---------|----------------|-------|
| SMS | `sms` | Default, widest coverage |
| Voice call | `voice` | Reads code aloud |
| Email | `email` | Use email address in `to` |
| WhatsApp | `whatsapp` | Requires own WhatsApp sender (see below) |
| RCS | `rcs` | Rich messaging, Android devices |
> **TOTP (authenticator apps):** Supported via the Verify Factors API — a separate implementation from channel-based OTP. See [Verify TOTP docs](https://www.twilio.com/docs/verify/quickstarts/totp).
### WhatsApp OTP
Change `channel` to `"whatsapp"` — the send/check flow is identical to SMS.
> **Requires:** A registered production WhatsApp sender. As of March 2024, Twilio no longer provides a shared sender for Verify. See `twilio-whatsapp-manage-senders`.
**Python**
```python
verification = client.verify.v2 \
.services(os.environ["VERIFY_SERVICE_SID"]) \
.verifications \
.create(to="+15558675310", channel="whatsapp")
```
**Node.js**
```node
const verification = await client.verify.v2
.services(process.env.VERIFY_SERVICE_SID)
.verifications.create({ to: "+15558675310", channel: "whatsapp" });
```
### WhatsApp with Automatic SMS Fallback
**Python**
```python
verification = client.verify.v2 \
.services(os.environ["VERIFY_SERVICE_SID"]) \
.verifications \
.create(
to="+15558675310",
channel="whatsapp",
channel_configuration={
"whatsapp": {"enabled": True},
"sms": {"enabled": True} # falls back to SMS if WhatsApp undelivered
}
)
```
**Node.js**
```node
const verification = await client.verify.v2
.services(process.env.VERIFY_SERVICE_SID)
.verifications.create({
to: "+15558675310",
channel: "whatsapp",
channelConfiguration: {
whatsapp: { enabled: true },
sms: { enabled: true },
},
});
```
With fallback enabled, your UI can say "a verification code was sent" without specifying the channel.
### Service Configuration
**Python**
```python
service = client.verify.v2.services.create(
friendly_name="My App",
code_length=6, # 4–10 digits (default: 6)
lookup_enabled=True, # Validate number before sending
do_force_check_once=True, # Code can only be checked once
ttl=600, # Code expiry in seconds (default: 600)
)
```
**Node.js**
```node
const service = await client.verify.v2.services.create({
friendlyName: "My App",
codeLength: 6,
lookupEnabled: true,
doForceCheckOnce: true,
ttl: 600,
});
```
### Verification Status Values
| Status | Meaning |
|--------|---------|
| `approved` | Code is correct |
| `pending` | Code is wrong or not yet submitted |
| `expired` | Code has expired (default TTL: 10 minutes) |
| `canceled` | Verification was canceled |
---
## Debugging
**Primary debugging tool:** Console > Verify > Logs (per-Service). Shows every verification attempt, delivery status, channel used, and error codes. Check here first before writing custom monitoring code.
### Common Errors
| Code | Meaning | Fix |
|------|---------|-----|
| 60200 | Invalid parameter | Check `to` format and `channel` value |
| 60202 | Max send attempts reached | Wait before retrying |
| 60203 | Max check attempts reached | Issue a new verification |
| 60212 | Service not found | Verify `VERIFY_SERVICE_SID` is correct |
| 60410 | Geo-permission not enabled | Enable country in Console |
**Built-in protections (no custom code needed):**
- Rate limiting: 5 verifications per phone per service per 10 minutes
- Max check attempts: 5 per verification (6th attempt → error 60203)
- Phone number validation: Verify checks line type before sending (if `lookup_enabled=True`)
- Fraud Guard: geo-permissions, rate anomaly detection, SMS pumping protection
**International OTP traffic warning:** International numbers are high-risk for SMS pumping — fraudsters trigger OTPs to premium-rate destinations to generate revenue. Verify's Related in Image & Video
watch
IncludedWatch a video (URL or local path). Downloads with yt-dlp, extracts auto-scaled frames with ffmpeg, pulls the transcript from captions (or Whisper API fallback), and hands the result to Claude so it can answer questions about what's in the video.
physical-ai-defect-image-generation
IncludedUse when the user wants to orchestrate defect image generation, run associated setup, or handle outputs on OSMO. The Day 0 path handles cold-start with USD-to-ROI, image-edit augmentation, and AnomalyGen to create initial PCBA datasets. The Day 1 path performs inference and labeling on real images. This skill helps with first-time asset setup, creation of finetuning checkpoints, and configuring deployment. Trigger keywords: defect image generation, dig workflow, dig pipeline, defect image detection workflow, aoi pipeline, aoi anomalygen, usd2roi anomalygen, day 0 pcba, day 1 pcba, day 1 real-photo alignment, day 1 manual roi, metal surface anomaly, glass defect, anomalygen finetune, setup_pcb, setup_metal, setup_glass, setup_pretrained, dig setup, dig datasets, dig pretrained checkpoint, dig image-edit endpoint.
accelint-react-best-practices
IncludedReact performance optimization and best practices. ALWAYS use this skill when working with any React code - writing components, hooks, JSX; refactoring; optimizing re-renders, memoization, state management; reviewing for performance; fixing hydration mismatches; debugging infinite re-renders, stale closures, input focus loss, animations restarting; preventing remounting; implementing transitions, lazy initialization, effect dependencies. Even simple React tasks benefit from these patterns. Covers React 19+ (useEffectEvent, Activity, ref props). Triggers - useEffect, useState, useMemo, useCallback, memo, inline components, nested components, components inside components, re-render, performance, hydration, SSR, Next.js, useDeferredValue, combined hooks.
elevenlabs-agents
IncludedBuild conversational AI voice agents with ElevenLabs Platform using React, JavaScript, React Native, or Swift SDKs. Configure agents, tools (client/server/MCP), RAG knowledge bases, multi-voice, and Scribe real-time STT. Use when: building voice chat interfaces, implementing AI phone agents with Twilio, configuring agent workflows or tools, adding RAG knowledge bases, testing with CLI "agents as code", or troubleshooting deprecated @11labs packages, Android audio cutoff, CSP violations, dynamic variables, or WebRTC config. Keywords: ElevenLabs Agents, ElevenLabs voice agents, AI voice agents, conversational AI, @elevenlabs/react, @elevenlabs/client, @elevenlabs/react-native, @elevenlabs/elevenlabs-js, @elevenlabs/agents-cli, elevenlabs SDK, voice AI, TTS, text-to-speech, ASR, speech recognition, turn-taking model, WebRTC voice, WebSocket voice, ElevenLabs conversation, agent system prompt, agent tools, agent knowledge base, RAG voice agents, multi-voice agents, pronunciation dictionary, voice speed control, elevenlabs scribe, @11labs deprecated, Android audio cutoff, CSP violation elevenlabs, dynamic variables elevenlabs, case-sensitive tool names, webhook authentication
humanizer
IncludedHumanize AI-generated text by detecting and removing patterns typical of LLM output. Rewrites text to sound natural, specific, and human. Uses 28 pattern detectors, 560+ AI vocabulary terms across 3 tiers, and statistical analysis (burstiness, type-token ratio, readability) for comprehensive detection. Use when asked to humanize text, de-AI writing, make content sound more natural/human, review writing for AI patterns, score text for AI detection, or improve AI-generated drafts. Covers content, language, style, communication, and filler categories.
generating-mermaid-diagrams
IncludedSalesforce architecture diagrams using Mermaid with ASCII fallback. Use this skill when generating text-based diagrams for Salesforce architecture, OAuth flows, ERDs, integration sequences, or Agentforce structure. TRIGGER when: user says "diagram", "visualize", "ERD", or asks for sequence diagrams, flowcharts, class diagrams, or architecture visualizations in Mermaid. DO NOT TRIGGER when: user wants PNG/SVG image output (use generating-visual-diagrams), or asks about non-Salesforce systems.