SMS 6 min de lectura

API SMS: Guía Completa para Enviar Mensajes desde tu Sistema

Aprende a integrar la API de SMS en tu software. Endpoint, autenticación, ejemplos de código y mejores prácticas.

La API de SMS te permite enviar mensajes directamente desde tu software, aplicación o sistema CRM. Es la solución perfecta para automatizar notificaciones, códigos de verificación, alertas y campañas de marketing.

¿Qué es una API de SMS?

Una API (Application Programming Interface) de SMS es un conjunto de protocolos que permiten que tu software se comunique con un servidor de mensajería para enviar y recibir mensajes de texto.

Con una API de SMS puedes automatizar el envío de mensajes desde tu sistema sin necesidad de intervención manual, integrando directamente con tu CRM, ERP, aplicación móvil o sitio web.

Beneficios de Usar API SMS

Automatización Total

Envía SMS automáticamente desde tus procesos sin intervención manual. Perfecto para notificaciones y alertas.

Escalabilidad

Maneja miles de mensajes por segundo. Ideal para campañas masivas y aplicaciones de alto volumen.

Integración Directa

Conecta directamente con tu software existente: CRM, ERP, e-commerce, aplicaciones móviles.

Costo Efectivo

Solo pagas por los mensajes enviados. Sin mensualidades ni costos fijos adicionales.

Endpoint de la API

El endpoint principal para enviar SMS con LETEL es:

POST https://api.letel.cl/v1/sms/send

Autenticación

La API usa autenticación Bearer Token. Incluye tu API Key en el header de Authorization:

Authorization: Bearer TU_API_KEY

Cuerpo de la Solicitud

Ejemplo del cuerpo JSON para enviar un SMS:

{
  "phone": "+56912345678",
  "message": "Tu código de verificación es: 123456",
  "sender": "LETEL"
}

Respuesta de la API

Respuesta exitosa:

{
  "success": true,
  "messageId": "sms_1234567890",
  "status": "sent",
  "timestamp": "2026-03-01T10:00:00Z"
}

Casos de Uso Comunes

Códigos de Verificación

Envía códigos OTP para autenticación de dos factores (2FA) en tu aplicación.

Notificaciones Transaccionales

Confirma pedidos, envíos, pagos y actualizaciones de estado automáticamente.

Alertas y Recordatorios

Programa recordatorios de citas, vencimiento de servicios o pagos pendientes.

Marketing Automatizado

Envía promociones personalizadas basadas en comportamiento del cliente.

Mejores Prácticas

  • Valida el formato del teléfono antes de enviar (solo números, código de país)
  • Implementa reintentos con exponential backoff para fallos temporales
  • Guarda los messageId para hacer seguimiento del estado
  • Usa webhooks para recibir notificaciones de entrega en tiempo real
  • Monitorea tus límites de uso y costos

Manejo de Errores

La API de SMS retorna códigos de estado HTTP estándar. Es importante manejar los errores correctamente para garantizar la confiabilidad de tu sistema.

Los errores más comunes incluyen:

  • 400 Bad Request: Parámetros inválidos en la solicitud (teléfono, mensaje vacío, etc.)
  • 401 Unauthorized: API Key inválida o expirada
  • 429 Too Many Requests: Has excedido tu límite de tasa (rate limit)
  • 500 Internal Server Error: Error del servidor (reintentar después de unos segundos)

Seguridad y Privacidad

Protege tus credenciales y datos de usuarios al usar la API:

  • Nunca hardcodees tu API Key en el código fuente. Usa variables de entorno.
  • Usa HTTPS para todas las solicitudes a la API (se requiere automáticamente).
  • Valida y sanitiza los números de teléfono antes de enviar para evitar inyecciones.
  • Almacena los messageId para auditoría y cumplimiento normativo.

Límites y Quotas

Conocer tus límites ayuda a planificar mejor tu integración:

  • Rate Limit: 100 solicitudes por segundo (ajustable según plan)
  • Longitud máxima: 160 caracteres por SMS (se divide en múltiples si es más largo)
  • Sin límite diario en plans profesionales

Implementación completa con Express.js

A continuación te mostramos cómo implementar una solución completa con Express.js que integre la API SMS de LETEL e incluya validación, reintentos y un manejo robusto de errores.

// smsService.ts
import axios from 'axios';

interface SmsPayload {
  phone: string;
  message: string;
  sender?: string;
}

interface SmsResponse {
  success: boolean;
  messageId: string;
  status: string;
  timestamp: string;
}

export class SmsService {
  private apiKey: string;
  private apiUrl = 'https://api.letel.cl/v1/sms/send';
  private maxRetries = 3;
  private retryDelay = 1000;

  constructor(apiKey: string) {
    this.apiKey = apiKey;
  }

  async sendSms(payload: SmsPayload): Promise<SmsResponse> {
    let lastError: Error | null = null;

    for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
      try {
        const response = await axios.post<SmsResponse>(
          this.apiUrl,
          {
            phone: this.normalizePhone(payload.phone),
            message: payload.message,
            sender: payload.sender || 'LETEL'
          },
          {
            headers: {
              'Authorization': `Bearer ${this.apiKey}`,
              'Content-Type': 'application/json',
              'User-Agent': 'SmsService/1.0'
            },
            timeout: 10000
          }
        );

        return response.data;
      } catch (error) {
        lastError = error as Error;

        if (attempt < this.maxRetries) {
          const delayMs = this.retryDelay * Math.pow(2, attempt - 1);
          console.log(
            `Intento ${attempt} falló. Reintentando en ${delayMs}ms...`
          );
          await this.delay(delayMs);
        }
      }
    }

    throw new Error(
      `Error enviando SMS después de ${this.maxRetries} intentos: ${lastError?.message}`
    );
  }

  private normalizePhone(phone: string): string {
    // Remover espacios y caracteres especiales
    let normalized = phone.replace(/[\s\-\(\)]/g, '');

    // Si comienza con +56, devolver tal cual
    if (normalized.startsWith('+56')) {
      return normalized;
    }

    // Si comienza con 56, agregar +
    if (normalized.startsWith('56')) {
      return '+' + normalized;
    }

    // Si comienza con 9 (número local), agregar +56
    if (normalized.startsWith('9') && normalized.length === 9) {
      return '+56' + normalized;
    }

    throw new Error(`Formato de teléfono inválido: ${phone}`);
  }

  private delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

Uso en un controlador de Express

Integra el servicio en tu controlador para enviar SMS directamente desde tus endpoints.

// smsController.ts
import { Router, Request, Response } from 'express';
import { SmsService } from './smsService';
import { validateRequest } from './middleware/validator';

const router = Router();
const smsService = new SmsService(process.env.LETEL_API_KEY!);

router.post('/send-sms', validateRequest, async (req: Request, res: Response) => {
  try {
    const { phone, message, sender } = req.body;

    // Validar que el mensaje no esté vacío
    if (!message || message.trim().length === 0) {
      return res.status(400).json({
        success: false,
        error: 'El mensaje no puede estar vacío'
      });
    }

    // Validar longitud del mensaje
    if (message.length > 160) {
      return res.status(400).json({
        success: false,
        error: 'El mensaje excede 160 caracteres'
      });
    }

    const result = await smsService.sendSms({
      phone,
      message,
      sender
    });

    res.json({
      success: true,
      data: result
    });
  } catch (error) {
    console.error('Error en envío de SMS:', error);
    res.status(500).json({
      success: false,
      error: error instanceof Error ? error.message : 'Error desconocido'
    });
  }
});

export default router;

Reintentos automáticos y manejo avanzado de errores

Para garantizar que tus SMS se envíen correctamente incluso con conexiones inestables, implementa una estrategia de reintentos con backoff exponencial y un registro (logging) detallado.

// advancedRetryHandler.ts
export interface RetryConfig {
  maxRetries: number;
  initialDelayMs: number;
  maxDelayMs: number;
  backoffMultiplier: number;
  retryableStatusCodes: number[];
}

export class AdvancedRetryHandler {
  private config: RetryConfig;

  constructor(config?: Partial<RetryConfig>) {
    this.config = {
      maxRetries: 3,
      initialDelayMs: 1000,
      maxDelayMs: 30000,
      backoffMultiplier: 2,
      retryableStatusCodes: [408, 429, 500, 502, 503, 504],
      ...config
    };
  }

  async executeWithRetry<T>(
    operation: () => Promise<T>,
    context: string
  ): Promise<T> {
    let lastError: Error | null = null;
    const startTime = Date.now();

    for (let attempt = 1; attempt <= this.config.maxRetries; attempt++) {
      try {
        console.log(`[${context}] Intento ${attempt}/${this.config.maxRetries}`);
        const result = await operation();
        const duration = Date.now() - startTime;
        console.log(
          `[${context}] Éxito en ${duration}ms después de ${attempt} intento(s)`
        );
        return result;
      } catch (error) {
        lastError = error as Error;
        const isRetryable = this.isRetryableError(error);

        console.warn(
          `[${context}] Intento ${attempt} falló: ${lastError.message} (Reintentable: ${isRetryable})`
        );

        if (!isRetryable || attempt === this.config.maxRetries) {
          throw lastError;
        }

        const delay = this.calculateDelay(attempt);
        console.log(
          `[${context}] Esperando ${delay}ms antes de reintentar...`
        );
        await this.sleep(delay);
      }
    }

    throw lastError;
  }

  private isRetryableError(error: any): boolean {
    // No reintentar errores de validación de cliente
    if (error.response?.status === 400 || error.response?.status === 401) {
      return false;
    }

    // Reintentar errores de servidor y timeout
    return (
      error.code === 'ECONNREFUSED' ||
      error.code === 'ECONNRESET' ||
      error.code === 'ETIMEDOUT' ||
      this.config.retryableStatusCodes.includes(error.response?.status)
    );
  }

  private calculateDelay(attempt: number): number {
    const exponentialDelay =
      this.config.initialDelayMs *
      Math.pow(this.config.backoffMultiplier, attempt - 1);

    // Agregar jitter aleatorio (±10%)
    const jitter = exponentialDelay * 0.1 * (Math.random() * 2 - 1);

    // Limitar al máximo configurado
    return Math.min(
      exponentialDelay + jitter,
      this.config.maxDelayMs
    );
  }

  private sleep(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

// Uso:
const retryHandler = new AdvancedRetryHandler({
  maxRetries: 3,
  initialDelayMs: 1000,
  maxDelayMs: 30000
});

const result = await retryHandler.executeWithRetry(
  () => smsService.sendSms(payload),
  'SendSMS'
);

Pruebas (testing) y mocking de la API SMS

Para desarrollar y probar tu integración sin gastar créditos en SMS reales, implementa un mock de la API que simule su comportamiento.

// mockSmsService.ts
export class MockSmsService {
  private messageLog: Array<{
    phone: string;
    message: string;
    timestamp: Date;
    messageId: string;
    status: string;
  }> = [];

  async sendSms(payload: any) {
    // Simular latencia de red
    await this.delay(Math.random() * 500);

    // Simular fallos aleatorios (10% de probabilidad)
    if (Math.random() < 0.1) {
      throw new Error('Network timeout');
    }

    const messageId = `sms_mock_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    const record = {
      phone: payload.phone,
      message: payload.message,
      timestamp: new Date(),
      messageId,
      status: 'sent'
    };

    this.messageLog.push(record);

    return {
      success: true,
      messageId,
      status: 'sent',
      timestamp: new Date().toISOString()
    };
  }

  getMessageLog() {
    return this.messageLog;
  }

  clearLog() {
    this.messageLog = [];
  }

  private delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

// Ejemplo de test con Jest
describe('SmsService', () => {
  it('debería enviar un SMS correctamente', async () => {
    const mockService = new MockSmsService();

    const result = await mockService.sendSms({
      phone: '+56912345678',
      message: 'Hola desde test'
    });

    expect(result.success).toBe(true);
    expect(result.messageId).toBeDefined();
    expect(mockService.getMessageLog()).toHaveLength(1);
  });

  it('debería manejar errores de conexión', async () => {
    const mockService = new MockSmsService();

    // Simular múltiples intentos
    let successCount = 0;
    for (let i = 0; i < 10; i++) {
      try {
        await mockService.sendSms({
          phone: '+56912345678',
          message: 'Test'
        });
        successCount++;
      } catch (error) {
        // Esperado: algunos intentos fallarán
      }
    }

    // Debería tener ~9 éxitos (90% de probabilidad)
    expect(successCount).toBeGreaterThan(7);
  });
});

// Comando curl para probar:
// curl -X POST http://localhost:3000/send-sms \
//   -H "Content-Type: application/json" \
//   -H "Authorization: Bearer test_api_key" \
//   -d '{
//     "phone": "+56912345678",
//     "message": "Mensaje de prueba desde curl",
//     "sender": "LETEL"
//   }'

¿Necesitas implementar SMS API en producción?

Con LETEL obtén una API REST completa y confiable para enviar SMS masivos desde tu aplicación. Incluye webhooks en tiempo real, reintentos automáticos y soporte técnico 24/7.

  • API REST completamente documentada
  • Webhooks en tiempo real para eventos SMS
  • Tasa de entrega de 98%+ en Chile
  • Planes desde $5 CLP por SMS

Conclusión

La API de SMS es esencial para cualquier empresa que busque automatizar su comunicación. Con endpoint REST, autenticación simple y documentación clara, integrar SMS en tu sistema es rápido y sencillo.

Preguntas Frecuentes sobre API SMS

¿Qué es una API de SMS?
Es una interfaz de programación que permite enviar mensajes SMS desde software externo. Usa protocolos REST para comunicación.
¿Necesito conocimientos técnicos para usar la API?
Sí, se requiere conocimiento básico de desarrollo web para integrar la API. Ofrecemos documentación y soporte técnico.
¿Cuánto cuesta usar la API de SMS?
Solo pagas por mensaje enviado. Los precios comienzan desde $5 CLP por SMS, igual que los envíos desde la plataforma web.
¿Puedo enviar SMS masivos con la API?
Sí, la API soporta envíos masivos. Puedes enviar miles de mensajes por segundo.
¿La API incluye reportes?
Sí, la API retorna el estado de cada mensaje. También puedes usar webhooks para recibir actualizaciones en tiempo real.
LE

LETEL

Expertos en telecomunicaciones y automatización empresarial

Compartir:

📚 Próximos Pasos

Después de dominar la API, te recomendamos:

¿Necesitas ayuda con la integración?

Nuestro equipo técnico puede guiarte en la integración de nuestra API.