Los SMS y MMS son las tecnologías de mensajería móvil más antiguas y universales del mundo. A pesar del auge de WhatsApp, Telegram y otras apps, siguen siendo fundamentales para verificación de usuarios, notificaciónes criticas y marketing. En esta guía te explicamos todo lo que necesitas saber como desarrollador.
Qué es un SMS?
SMS significa Short Message Service (Servicio de Mensajes Cortos). Es un protocolo de comunicación que permite enviar mensajes de texto entre teléfonos móviles a través de la red celular.
Características Principales del SMS
| Característica | Valor |
|---|---|
| Longitud máxima | 160 caracteres (GSM-7) o 70 caracteres (Únicode) |
| Tipo de contenido | Solo texto |
| Requiere internet | No |
| Cobertura | 99% de teléfonos móviles |
| Tasa de apertura | ~98% |
Historia del SMS
- 1984: Primera propuesta del concepto SMS
- 1992: Primer SMS enviado ("Merry Christmas")
- 2000s: Explosion de uso entre consumidores
- 2010s: Transición hacia uso empresarial (A2P)
- 2020s: Fundamental para 2FA y notificaciones
Como Funciona Tecnicamente el SMS
[Tu App] --> [API Zavu] --> [SMSC] --> [Red Celular] --> [Teléfono]Qué es un MMS?
MMS significa Multimedia Messaging Service (Servicio de Mensajería Multimedia). Es una extensión del SMS que permite enviar contenido multimedia.
Características del MMS
| Característica | Valor |
|---|---|
| Tamaño máximo | 300KB - 600KB (varia por operador) |
| Tipos de contenido | Imágenes, videos, audio, vCards |
| Requiere internet | Datos móviles |
| Cobertura | ~95% de smartphones |
| Costo | 3-5x más caro que SMS |
Tipos de contenido MMS
- Imágenes: JPG, PNG, GIF (hasta ~500KB)
- Video: MP4, 3GP (muy limitado, ~15 segundos)
- Audio: MP3, AAC (clips cortos)
- vCard: Tarjetas de contacto
- Texto largo: Mensajes sin límite de 160 caracteres
SMS vs MMS: Diferencias Clave
| Aspecto | SMS | MMS |
|---|---|---|
| Contenido | Solo texto | Multimedia + texto |
| Límite | 160 caracteres | ~600KB |
| Costo por mensaje | $0.01 - $0.03 | $0.03 - $0.10 |
| Requiere datos | No | Si |
| Velocidad entrega | Segundos | Segundos a minutos |
| Compatibilidad | Universal | Casi universal |
| Uso principal | 2FA, notificaciones | Marketing visual |
Cuando Usar SMS
- Verificación de usuarios (OTP/2FA)
- Notificaciones críticas (alertas de seguridad, confirmaciones)
- Recordatorios (citas, pagos, renovaciones)
- Alertas transacciónales (pedidos, envíos)
- Mercados con internet limitado
Cuando Usar MMS
- Campañas de marketing visual
- Promociones con imágenes de productos
- Cupones con código QR
- Confirmaciones con recibos visuales
- Contenido que requiere impacto visual
Limitaciones Técnicas del SMS
1. Límite de Caracteres
El SMS usa codificación GSM-7, que permite 160 caracteres. Pero si usas caracteres especiales (emojis, acentos como a, n, u), cambia a UCS-2/Único y el límite baja a 70 caracteres.
TypeScript// Este mensaje usa 1 SMS (GSM-7) const mensaje1 = "Your verification code is 123456"; // Este mensaje usa 2 SMS (Únicode por el emoji) const mensaje2 = "Tu código es 123456. Valido 5 min";
Tabla de Segmentos SMS
| Codificación | Caracteres por SMS | Concatenados (por segmento) |
|---|---|---|
| GSM-7 | 160 | 153 |
| Únicode | 70 | 67 |
Nota: Los mensajes largos se dividen en "segmentos" y cada uno cuenta como un SMS individual para facturación.
2. Caracteres GSM-7 Permitidos
A-Z, a-z, 0-9
@ ! " # $ % & ' ( ) + , - . / : ; < = > ?
Espacio, salto de línea
Algunos caracteres especiales: [ ] \ ^ _ { | } ~Caracteres que activan Únicode:
- Emojis
- Caracteres acentuados (a, e, i, o, u, n)
- Simbolos especiales
- Caracteres de otros alfabetos
3. Problemas de Entrega
Los SMS pueden fallar por varias razones:
| Código Error | Significado | Solucion |
|---|---|---|
| 30001 | Número inválido | Validar formato E.164 |
| 30002 | Número no alcanzable | Teléfono apagado/sin cobertura |
| 30003 | Número no existe | Verificar el número |
| 30004 | Spam detectado | Revisar contenido del mensaje |
| 30005 | Carrier bloqueo | Registrar 10DLC (USA) |
| 30007 | Mensaje filtrado | Evitar palabras spam |
Regulaciónes Importantes
En Estados Unidos: 10DLC
Desde 2021, todos los mensajes A2P (Application-to-Person) en USA requieren registro 10DLC:
Sin registro: Los mensajes seran bloqueados o tendran muy baja entrega.
En Union Europea: GDPR
- Consentimiento explicito requerido
- Derecho a desuscribirse (STOP)
- Registro de consentimientos
- Protección de datos personales
En Mexico: LFPDPPP
- Aviso de privacidad requerido
- Consentimiento para mensajes promociónales
- Mecanismo de baja (STOP, CANCELAR)
En Chile: Ley 19.628
- Autorizacion del titular de datos
- Finalidad específica del tratamiento
- Derecho a cancelación
Enviando SMS con Zavu
Instalacion
terminalnpm install @zavudev/sdk
Configuración
TypeScriptimport Zavudev from "@zavudev/sdk"; const client = new Zavu({ apiKey: process.env.ZAVU_API_KEY, });
Enviar SMS Simple
TypeScriptconst result = await client.messages.send({ to: "+56912345678", channel: "sms", text: "Tu código de verificación es 847293. Valido por 5 minutos.", }); console.log(); console.log(Mensaje enviado:${result.message.id}Estado:${result.message.status});
Enviar SMS con Metadatos
TypeScriptconst result = await client.messages.send({ to: "+56912345678", channel: "sms", text: "Tu pedido #12345 ha sido enviado. Llegara manana.", metadata: { orderId: "12345", userId: "user_abc", type: "shipping_notification", }, });
Enviar a Múltiples Destinatarios
TypeScriptconst recipients = ["+56912345678", "+56987654321", "+56911223344"]; const results = await Promise.all( recipients.map((to) => client.messages.send({ to, channel: "sms", text: "Recordatorio: Tu cita es manana a las 10:00 AM.", }) ) ); console.log();Enviados:${results.length} mensajes
Casos de Uso Comúnes
1. Verificación de Usuario (OTP)
El caso de uso más común. Tasa de conversión superior al 95%.
TypeScriptimport Zavudev from "@zavudev/sdk"; const client = new Zavu(); async function sendOTP(phoneNumber: string): Promise<string> { const code = Math.floor(100000 + Math.random() 900000).toString(); await client.messages.send({ to: phoneNumber, channel: "sms", text:, }); return code; } // Uso const code = await sendOTP("+56912345678"); // Guardar 'code' en cache (Redis) con TTL de 5 minutosTu código de verificación es${code}. Expira en 5 minutos. No lo compartas con nadie.
2. Confirmación de Pedido
TypeScriptinterface Order { id: string; customerPhone: string; total: number; items: number; } async function sendOrderConfirmation(order: Order) { await client.messages.send({ to: order.customerPhone, channel: "sms", text:, metadata: { orderId: order.id, type: "order_confirmation", }, }); }Pedido #${order.id} confirmado. Total: $${order.total}. ${order.items} artículos. Te avisaremos cuando se envie.
3. Recordatorio de Cita
TypeScriptinterface Appointment { id: string; patientPhone: string; doctorName: string; date: Date; location: string; } async function sendAppointmentReminder(apt: Appointment) { const formattedDate = apt.date.toLocaleDateString("es-CL", { weekday: "long", day: "numeric", month: "long", hour: "2-digit", minute: "2-digit", }); await client.messages.send({ to: apt.patientPhone, channel: "sms", text:, }); }Recordatorio: Cita con Dr.${apt.doctorName} el ${formattedDate} en ${apt.location}. Responde SI para confirmar o NO para cancelar.
4. Alerta de Seguridad
TypeScriptasync function sendSecurityAlert( phoneNumber: string, eventType: "new_login" | "password_change" | "suspicious_activity", details: { ip?: string; location?: string; device?: string } ) { const messages = { new_login:, password_change:Nuevo inicio de sesión detectado desde${details.location || "ubicación desconocida"}. Si no fuiste tu, cambia tu contrasena inmediatamente.Tu contrasena fue cambiada éxitosamente. Si no realizaste este cambio, contacta soporte inmediatamente., suspicious_activity:Detectamos actividad sospechosa en tu cuenta. Por seguridad, verifica tus últimas transacciones., }; await client.messages.send({ to: phoneNumber, channel: "sms", text: messages[eventType], metadata: { type: "security_alert", eventType, ...details, }, }); }
5. Notificación de Envio
TypeScriptinterface Shipment { orderId: string; customerPhone: string; carrier: string; trackingNumber: string; estimatedDelivery: Date; } async function sendShippingNotification(shipment: Shipment) { const deliveryDate = shipment.estimatedDelivery.toLocaleDateString("es-CL", { weekday: "long", day: "numeric", month: "long", }); await client.messages.send({ to: shipment.customerPhone, channel: "sms", text:, }); }Tu pedido #${shipment.orderId} esta en camino! Seguimiento: ${shipment.trackingNumber} (${shipment.carrier}). Llegada estimada: ${deliveryDate}.
Mejores Prácticas
1. Formato de Números
Siempre usa formato E.164 (código de país + número):
TypeScript// Correcto const phoneE164 = "+56912345678"; // Incorrecto const phoneLocal = "912345678"; const phoneWithSpaces = "+56 9 1234 5678";
2. Contenido del Mensaje
TypeScript// BIEN: Conciso, claro, con CTA const good = "Tu código: 847293. Valido 5 min. No lo compartas."; // MAL: Muy largo, spam-like const bad = "FELICIDADES!!! Has GANADO un PREMIO INCREIBLE! Haz clic AHORA en este link para RECLAMAR tu REGALO GRATIS!!!";
3. Incluir Opt-out
Para mensajes de marketing, siempre incluye opcion de baja:
TypeScriptconst marketingMessage =Oferta especial: 20% de descuento en tu próxima compra. Usa código VERANO20. Valido hasta el 31/12. Responde STOP para no recibir más ofertas..trim();
4. Manejar Errores
TypeScriptasync function sendSMSWithRetry( to: string, text: string, maxRetries = 3 ): Promise<boolean> { 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(, error); if (attempt === maxRetries) { throw new Error(Intento${attempt} fallido:SMS fallido después de${maxRetries} intentos); } // Esperar antes de reintentar (backoff exponencial) await new Promise(r => setTimeout(r, 1000 * attempt)); } } return false; }
5. Validar Antes de Enviar
TypeScriptfunction válidateSMS(to: string, text: string): { valid: boolean; errors: string[] } { const errors: string[] = []; // Validar formato E.164 if (!/^\+[1-9]\d{6,14}$/.test(to)) { errors.push("Número debe estar en formato E.164 (+56912345678)"); } // Validar longitud if (text.length === 0) { errors.push("El mensaje no puede estar vacio"); } if (text.length > 1600) { errors.push("El mensaje excede 10 segmentos SMS"); } // Advertencia sobre Únicode const hasÚnicode = /[^\x00-\x7F]/.test(text); if (hasÚnicode && text.length > 70) { errors.push("Mensaje con caracteres especiales: se enviaran múltiples SMS"); } return { valid: errors.length === 0, errors, }; }
Costos y Optimización
Estructura de Costos Típica
| Componente | Costo Apróximado |
|---|---|
| SMS saliente (USA) | $0.0083 - $0.02 |
| SMS saliente (LATAM) | $0.02 - $0.08 |
| SMS saliente (Europa) | $0.03 - $0.10 |
| Número telefónico | $1 - $5/mes |
| MMS saliente | $0.02 - $0.10 |
Consejos para Reducir Costos
SMS vs WhatsApp: Cuando Usar Cada Uno
| Criterio | SMS | |
|---|---|---|
| Cobertura | 99% teléfonos | ~75% smartphones |
| Requiere app | No | Si |
| Requiere internet | No | Si |
| Costo | Por mensaje | Por conversación |
| Contenido rico | No (solo MMS) | Si |
| Verificación | Ideal | Bueno |
| Marketing | Limitado | Excelente |
| Soporte al cliente | Básico | Completo |
Recomendaciones
- Usa SMS para: OTP, alertas criticas, usuarios sin WhatsApp
- Usa WhatsApp para: Soporte, marketing, conversaciones largas
- Usa ambos: Fallback automático si uno falla
TypeScript// Ejemplo: Enviar con fallback automático const result = await client.messages.send({ to: "+56912345678", channel: "auto", // Zavu elige el mejor canal text: "Tu código es 123456", fallbackEnabled: true, // Si WhatsApp falla, usa SMS });
Integración con Webhooks
Recibe actualizaciones de estado en tiempo real:
TypeScript// Tu endpoint de webhook app.post("/webhooks/zavu", (req, res) => { const { event, data } = req.body; switch (event) { case "message.delivered": console.log(); break; case "message.failed": console.error(SMS entregado:${data.messageId}SMS fallido:${data.errorMessage}); // Reintentar o notificar break; case "message.inbound": console.log(SMS recibido de${data.from}: ${data.text}); // Procesar respuesta (ej: STOP, SI, NO) break; } res.sendStatus(200); });
Conclusion
SMS y MMS siguen siendo herramientas fundamentales en 2025:
- SMS: Ideal para verificación, alertas y notificaciónes criticas
- MMS: Util para marketing visual cuando el impacto justifica el costo
Claves para el éxito:
Recursos Adicionales
- SMS para Desarrolladores - Documentación completa
- WhatsApp para Desarrolladores - Alternativa para mensajería rica
Necesitas ayuda con SMS? Nuestro equipo esta disponible para asistirte. Contáctaños o unete a nuestra comúnidad en Discord.