--- title: What are SMS and MMS: Complete Guide for Developers description: Everything you need to know about SMS and MMS: how they work, key differences, use cases, costs, technical limitations, and how to implement them in date: 2025-12-26 author: Jennifer Villalobos locale: en source: https://www.zavu.dev/en/blog/what-is-sms-mms tags: SMS, MMS, Messaging, API --- # What are SMS and MMS: Complete Guide for Developers SMS and MMS are the oldest and most universal mobile messaging technologies in the world. Despite the rise of WhatsApp, Telegram, and other apps, they remain fundamental for user verification, critical notifications, and marketing. In this guide, we explain everything you need to know as a developer. ## What is SMS? **SMS** stands for **Short Message Service**. It's a communication protocol that allows sending text messages between mobile phones through the cellular network. ### Main SMS Characteristics | Characteristic | Value | |----------------|-------| | Maximum length | 160 characters (GSM-7) or 70 characters (Unicode) | | Content type | Text only | | Requires internet | No | | Coverage | 99% of mobile phones | | Open rate | ~98% | ### History of SMS - **1984**: First SMS concept proposal - **1992**: First SMS sent ("Merry Christmas") - **2000s**: Consumer usage explosion - **2010s**: Transition to business use (A2P) - **2020s**: Fundamental for 2FA and notifications ### How SMS Works Technically 1. **Your application** sends the message to an SMS provider (like Zavu) 2. **The provider** connects to an **SMSC** (Short Message Service Center) 3. **The SMSC** locates the recipient's network 4. **The cell tower** delivers the message to the phone 5. **The phone** receives the message without needing internet ``` [Your App] --> [Zavu API] --> [SMSC] --> [Cellular Network] --> [Phone] ``` ## What is MMS? **MMS** stands for **Multimedia Messaging Service**. It's an extension of SMS that allows sending multimedia content. ### MMS Characteristics | Characteristic | Value | |----------------|-------| | Maximum size | 300KB - 600KB (varies by carrier) | | Content types | Images, videos, audio, vCards | | Requires internet | Mobile data | | Coverage | ~95% of smartphones | | Cost | 3-5x more expensive than SMS | ### MMS Content Types - **Images**: JPG, PNG, GIF (up to ~500KB) - **Video**: MP4, 3GP (very limited, ~15 seconds) - **Audio**: MP3, AAC (short clips) - **vCard**: Contact cards - **Long text**: Messages without 160 character limit ## SMS vs MMS: Key Differences | Aspect | SMS | MMS | |--------|-----|-----| | Content | Text only | Multimedia + text | | Limit | 160 characters | ~600KB | | Cost per message | $0.01 - $0.03 | $0.03 - $0.10 | | Requires data | No | Yes | | Delivery speed | Seconds | Seconds to minutes | | Compatibility | Universal | Nearly universal | | Main use | 2FA, notifications | Visual marketing | ### When to Use SMS - **User verification (OTP/2FA)** - **Critical notifications** (security alerts, confirmations) - **Reminders** (appointments, payments, renewals) - **Transactional alerts** (orders, shipments) - **Markets with limited internet** ### When to Use MMS - **Visual marketing campaigns** - **Promotions with product images** - **Coupons with QR codes** - **Confirmations with visual receipts** - **Content requiring visual impact** ## Technical Limitations of SMS ### 1. Character Limit SMS uses GSM-7 encoding, which allows 160 characters. But if you use special characters (emojis, accents), it switches to UCS-2/Unicode and the limit drops to 70 characters. ```typescript // This message uses 1 SMS (GSM-7) const message1 = "Your verification code is 123456"; // This message uses 2 SMS (Unicode due to emoji) const message2 = "Your code is 123456. Valid 5 min"; ``` ### SMS Segment Table | Encoding | Characters per SMS | Concatenated (per segment) | |----------|-------------------|----------------------------| | GSM-7 | 160 | 153 | | Unicode | 70 | 67 | **Note**: Long messages are divided into "segments" and each one counts as an individual SMS for billing. ### 2. Allowed GSM-7 Characters ``` A-Z, a-z, 0-9 @ ! " # $ % & ' ( ) * + , - . / : ; < = > ? Space, line break Some special characters: [ ] \ ^ _ { | } ~ ``` **Characters that trigger Unicode:** - Emojis - Accented characters - Special symbols - Characters from other alphabets ### 3. Delivery Issues SMS can fail for various reasons: | Error Code | Meaning | Solution | |------------|---------|----------| | 30001 | Invalid number | Validate E.164 format | | 30002 | Number unreachable | Phone off/no coverage | | 30003 | Number doesn't exist | Verify the number | | 30004 | Spam detected | Review message content | | 30005 | Carrier blocked | Register 10DLC (USA) | | 30007 | Message filtered | Avoid spam words | ## Important Regulations ### In the United States: 10DLC Since 2021, all A2P (Application-to-Person) messages in the USA require 10DLC registration: 1. **Brand registration** - Your company in The Campaign Registry 2. **Campaign registration** - Usage description 3. **Number assignment** - Link numbers to campaigns **Without registration**: Messages will be blocked or have very low delivery. ### In the European Union: GDPR - **Explicit consent** required - **Right to unsubscribe** (STOP) - **Consent records** - **Personal data protection** ### In Mexico: LFPDPPP - **Privacy notice** required - **Consent** for promotional messages - **Opt-out mechanism** (STOP, CANCEL) ### In Chile: Law 19.628 - **Authorization** from data owner - **Specific purpose** of processing - **Right to cancellation** ## Sending SMS with Zavu ### Installation ```bash npm install @zavudev/sdk ``` ### Configuration ```typescript import Zavudev from "@zavudev/sdk"; const client = new Zavu({ apiKey: process.env.ZAVU_API_KEY, }); ``` ### Send Simple SMS ```typescript const result = await client.messages.send({ to: "+14155551234", channel: "sms", text: "Your verification code is 847293. Valid for 5 minutes.", }); console.log(`Message sent: ${result.message.id}`); console.log(`Status: ${result.message.status}`); ``` ### Send SMS with Metadata ```typescript const result = await client.messages.send({ to: "+14155551234", channel: "sms", text: "Your order #12345 has shipped. Arriving tomorrow.", metadata: { orderId: "12345", userId: "user_abc", type: "shipping_notification", }, }); ``` ### Send to Multiple Recipients ```typescript const recipients = ["+14155551234", "+14155555678", "+14155559012"]; const results = await Promise.all( recipients.map((to) => client.messages.send({ to, channel: "sms", text: "Reminder: Your appointment is tomorrow at 10:00 AM.", }) ) ); console.log(`Sent: ${results.length} messages`); ``` ## Common Use Cases ### 1. User Verification (OTP) The most common use case. Conversion rate above 95%. ```typescript import Zavudev from "@zavudev/sdk"; const client = new Zavu(); async function sendOTP(phoneNumber: string): Promise { const code = Math.floor(100000 + Math.random() * 900000).toString(); await client.messages.send({ to: phoneNumber, channel: "sms", text: `Your verification code is ${code}. Expires in 5 minutes. Don't share it with anyone.`, }); return code; } // Usage const code = await sendOTP("+14155551234"); // Store 'code' in cache (Redis) with 5 minute TTL ``` ### 2. Order Confirmation ```typescript interface Order { id: string; customerPhone: string; total: number; items: number; } async function sendOrderConfirmation(order: Order) { await client.messages.send({ to: order.customerPhone, channel: "sms", text: `Order #${order.id} confirmed. Total: $${order.total}. ${order.items} items. We'll notify you when it ships.`, metadata: { orderId: order.id, type: "order_confirmation", }, }); } ``` ### 3. Appointment Reminder ```typescript interface Appointment { id: string; patientPhone: string; doctorName: string; date: Date; location: string; } async function sendAppointmentReminder(apt: Appointment) { const formattedDate = apt.date.toLocaleDateString("en-US", { weekday: "long", day: "numeric", month: "long", hour: "2-digit", minute: "2-digit", }); await client.messages.send({ to: apt.patientPhone, channel: "sms", text: `Reminder: Appointment with Dr. ${apt.doctorName} on ${formattedDate} at ${apt.location}. Reply YES to confirm or NO to cancel.`, }); } ``` ### 4. Security Alert ```typescript async function sendSecurityAlert( phoneNumber: string, eventType: "new_login" | "password_change" | "suspicious_activity", details: { ip?: string; location?: string; device?: string } ) { const messages = { new_login: `New login detected from ${details.location || "unknown location"}. If this wasn't you, change your password immediately.`, password_change: `Your password was changed successfully. If you didn't make this change, contact support immediately.`, suspicious_activity: `We detected suspicious activity on your account. For security, please verify your recent transactions.`, }; await client.messages.send({ to: phoneNumber, channel: "sms", text: messages[eventType], metadata: { type: "security_alert", eventType, ...details, }, }); } ``` ### 5. Shipping Notification ```typescript interface Shipment { orderId: string; customerPhone: string; carrier: string; trackingNumber: string; estimatedDelivery: Date; } async function sendShippingNotification(shipment: Shipment) { const deliveryDate = shipment.estimatedDelivery.toLocaleDateString("en-US", { weekday: "long", day: "numeric", month: "long", }); await client.messages.send({ to: shipment.customerPhone, channel: "sms", text: `Your order #${shipment.orderId} is on its way! Tracking: ${shipment.trackingNumber} (${shipment.carrier}). Estimated delivery: ${deliveryDate}.`, }); } ``` ## Best Practices ### 1. Number Format Always use E.164 format (country code + number): ```typescript // Correct const phoneE164 = "+14155551234"; // Incorrect const phoneLocal = "4155551234"; const phoneWithSpaces = "+1 415 555 1234"; ``` ### 2. Message Content ```typescript // GOOD: Concise, clear, with CTA const good = "Your code: 847293. Valid 5 min. Don't share it."; // BAD: Too long, spam-like const bad = "CONGRATULATIONS!!! You WON an INCREDIBLE PRIZE! Click NOW on this link to CLAIM your FREE GIFT!!!"; ``` ### 3. Include Opt-out For marketing messages, always include opt-out option: ```typescript const marketingMessage = ` Special offer: 20% off your next purchase. Use code SUMMER20. Valid until 12/31. Reply STOP to stop receiving offers. `.trim(); ``` ### 4. Handle Errors ```typescript async function sendSMSWithRetry( to: string, text: string, maxRetries = 3 ): Promise { for (let attempt = 1; attempt <= maxRetries; attempt++) { try { const result = await client.messages.send({ to, channel: "sms", text, }); if (result.message.status === "queued") { return true; } } catch (error) { console.error(`Attempt ${attempt} failed:`, error); if (attempt === maxRetries) { throw new Error(`SMS failed after ${maxRetries} attempts`); } // Wait before retrying (exponential backoff) await new Promise(r => setTimeout(r, 1000 * attempt)); } } return false; } ``` ### 5. Validate Before Sending ```typescript function validateSMS(to: string, text: string): { valid: boolean; errors: string[] } { const errors: string[] = []; // Validate E.164 format if (!/^\+[1-9]\d{6,14}$/.test(to)) { errors.push("Number must be in E.164 format (+14155551234)"); } // Validate length if (text.length === 0) { errors.push("Message cannot be empty"); } if (text.length > 1600) { errors.push("Message exceeds 10 SMS segments"); } // Unicode warning const hasUnicode = /[^\x00-\x7F]/.test(text); if (hasUnicode && text.length > 70) { errors.push("Message with special characters: multiple SMS will be sent"); } return { valid: errors.length === 0, errors, }; } ``` ## Costs and Optimization ### Typical Cost Structure | Component | Approximate Cost | |-----------|------------------| | Outbound SMS (USA) | $0.0083 - $0.02 | | Outbound SMS (LATAM) | $0.02 - $0.08 | | Outbound SMS (Europe) | $0.03 - $0.10 | | Phone number | $1 - $5/month | | Outbound MMS | $0.02 - $0.10 | ### Tips to Reduce Costs 1. **Use GSM-7 when possible** - Avoid emojis and accents in critical messages - A 161 character message = 2 SMS 2. **Concatenate messages intelligently** - If you need >160 chars, make sure it's worth it 3. **Validate numbers before sending** - Avoid costs for invalid numbers - Use Zavu for number introspection 4. **Consider alternatives for long content** - WhatsApp for long messages (no per-character cost) - Email for extensive content 5. **Check what the per-message price actually includes** - Zavu's SMS starts at $0.004 with US carrier fees already included - Providers quoting $0.0083 usually add $0.0035 to $0.0045 in carrier fees on top ## SMS vs WhatsApp: When to Use Each | Criteria | SMS | WhatsApp | |----------|-----|----------| | Coverage | 99% phones | ~75% smartphones | | Requires app | No | Yes | | Requires internet | No | Yes | | Cost | Per message | Per conversation | | Rich content | No (MMS only) | Yes | | Verification | Ideal | Good | | Marketing | Limited | Excellent | | Customer support | Basic | Complete | ### Recommendations - **Use SMS for**: OTP, critical alerts, users without WhatsApp - **Use WhatsApp for**: Support, marketing, long conversations - **Use both**: Automatic fallback if one fails ```typescript // Example: Send with automatic fallback const result = await client.messages.send({ to: "+14155551234", channel: "auto", // Zavu chooses the best channel text: "Your code is 123456", fallbackEnabled: true, // If WhatsApp fails, use SMS }); ``` ## Webhook Integration Receive real-time status updates: ```typescript // Your webhook endpoint app.post("/webhooks/zavu", (req, res) => { const { event, data } = req.body; switch (event) { case "message.delivered": console.log(`SMS delivered: ${data.messageId}`); break; case "message.failed": console.error(`SMS failed: ${data.errorMessage}`); // Retry or notify break; case "message.inbound": console.log(`SMS received from ${data.from}: ${data.text}`); // Process response (e.g.: STOP, YES, NO) break; } res.sendStatus(200); }); ``` ## Conclusion SMS and MMS remain fundamental tools in 2025: - **SMS**: Ideal for verification, alerts, and critical notifications - **MMS**: Useful for visual marketing when impact justifies the cost **Keys to success:** 1. Comply with local regulations (10DLC, GDPR, etc.) 2. Optimize content to minimize segments 3. Always include opt-out option 4. Validate numbers before sending 5. Implement robust error handling 6. Consider WhatsApp as a complement, not a replacement ## Additional Resources - [SMS for Developers](/en/sms-for-developers) - Complete documentation - [WhatsApp for Developers](/en/whatsapp-for-developers) - Alternative for rich messaging **Need help with SMS?** Our team is available to assist you. [Contact us](/en/contact-us) or join our [Discord community](https://discord.gg/ZxE8DYkveh).