Ir al contenido

Envío de SMS

El servicio de SMS permite enviar mensajes de texto a números chilenos desde tu sistema. Los mensajes se procesan de forma asíncrona con routing inteligente, reintentos automáticos y tracking de estado de entrega.


Antes de usar el endpoint necesitas:

  1. Una API Key con uno de estos roles: ADMIN, SUPER-ADMIN, SMS_OPERADOR, o FULL-API
  2. El tenant debe tener el servicio SMS habilitado

POST /{tenantSlug}/sms/send
Validar teléfono y body
Calcular segmentos (GSM-7 / Unicode)
Crear registro en BD (status: queued)
Encolar en BullMQ (prioridad según routeType)
Respuesta inmediata: { messageId, status: "queued" }
[Async] Worker procesa con circuit breaker
[Async] Proveedor entrega SMS → status: delivered/failed

La respuesta es inmediata — el mensaje se encola y se procesa en background. Usa el messageId para consultar el estado posteriormente.


POST /{tenantSlug}/sms/send
Authorization: Bearer {api_key}
Content-Type: application/json
{
"to": "+56912345678",
"body": "Tu código de verificación es 123456",
"routeType": "transactional",
"metadata": {
"orderId": "ORD-001",
"source": "mi-sistema"
}
}
CampoTipoRequeridoDescripción
tostringTeléfono chileno destino
bodystringTexto del mensaje (máx. 1600 caracteres)
routeTypestringTipo de ruta para priorización
metadataobjectNoObjeto JSON libre para trazabilidad
FormatoEjemploDescripción
+56XXXXXXXXX+56912345678Con prefijo internacional
56XXXXXXXXX56912345678Sin signo +
9XXXXXXXX912345678Solo número móvil

Todos se normalizan internamente a +56XXXXXXXXX.

El routeType determina la prioridad de procesamiento y el proveedor de envío:

TipoDescripciónPrioridad
otpCódigos de verificación y autenticaciónMáxima
premiumMensajes prioritarios de negocioAlta
transactionalNotificaciones de transacciones y eventosMedia
marketingCampañas promocionales (requiere opt-in del destinatario)Baja
wholesaleEnvíos masivos de alto volumenMínima
Ventana de terminal
curl -X POST "https://api.redcumbre.cl/{tenantSlug}/sms/send" \
-H "Authorization: Bearer {api_key}" \
-H "Content-Type: application/json" \
-d '{
"to": "+56912345678",
"body": "Hola, tu pedido #1234 fue despachado.",
"routeType": "transactional"
}'

{
"messageId": "cmovnx2op0001sezxd0srby0g",
"status": "queued",
"segmentCount": 1,
"encoding": "gsm7"
}
CampoTipoDescripción
messageIdstringIdentificador único del mensaje (CUID)
statusstringSiempre "queued" en respuesta inicial
segmentCountnumberCantidad de segmentos SMS
encodingstring"gsm7" o "ucs2" según caracteres usados

Los SMS se dividen en segmentos según la codificación del contenido:

EncodingCaracteres por segmentoCuándo se usa
GSM-7 (gsm7)160Texto ASCII estándar (letras, números, puntuación básica)
UCS-2 (ucs2)70Texto con caracteres especiales, emojis, acentos no-GSM

CódigoDescripciónCausa
400Validación fallidaTeléfono mal formado, body vacío, routeType inválido
401No autorizadoAPI key inválida, expirada o revocada
403ProhibidoServicio SMS no habilitado o rol insuficiente
429Rate limitedOTP rate limit (1 por número cada 5 min)
{
"statusCode": 400,
"message": [
"to must be a valid Chilean phone number (+56XXXXXXXXX, 56XXXXXXXXX, or 9XXXXXXXX)"
],
"error": "Bad Request"
}
{
"statusCode": 403,
"message": "El servicio 'SMS' no está habilitado para este tenant. Contacte al administrador de la plataforma.",
"error": "Forbidden"
}

Después de enviar un SMS, puedes consultar su estado de entrega:

GET /{tenantSlug}/sms/messages
Ventana de terminal
curl "https://api.redcumbre.cl/{tenantSlug}/sms/messages?status=delivered" \
-H "Authorization: Bearer {api_key}"
GET /{tenantSlug}/sms/messages/{messageId}
Ventana de terminal
curl "https://api.redcumbre.cl/{tenantSlug}/sms/messages/cmovnx2op0001sezxd0srby0g" \
-H "Authorization: Bearer {api_key}"
EstadoTerminalDescripción
queuedNoEn cola, pendiente de procesamiento
submittedNoEnviado al proveedor SMS
sentNoConfirmado enviado por el proveedor
deliveredEntregado al destinatario
undeliveredNo se pudo entregar (número inválido, apagado, etc.)
failedError en el envío (proveedor falló)
expiredSin confirmación de entrega después de 1 hora
rejectedRechazado por política de contenido

Consulta estadísticas de envío para un rango de fechas:

GET /{tenantSlug}/sms/stats?dateFrom=2026-01-01&dateTo=2026-01-31
Ventana de terminal
curl "https://api.redcumbre.cl/{tenantSlug}/sms/stats?dateFrom=2026-01-01&dateTo=2026-01-31" \
-H "Authorization: Bearer {api_key}"

Ventana de terminal
curl -X POST "https://api.redcumbre.cl/{tenantSlug}/sms/send" \
-H "Authorization: Bearer {api_key}" \
-H "Content-Type: application/json" \
-d '{
"to": "+56987654321",
"body": "Tu pedido #5678 fue despachado. Seguimiento: https://track.example.com/5678",
"routeType": "transactional",
"metadata": { "orderId": "5678", "type": "dispatch" }
}'
Ventana de terminal
curl -X POST "https://api.redcumbre.cl/{tenantSlug}/sms/send" \
-H "Authorization: Bearer {api_key}" \
-H "Content-Type: application/json" \
-d '{
"to": "+56912345678",
"body": "Tu código de verificación es 482913. Expira en 5 minutos.",
"routeType": "otp"
}'
const response = await fetch(
`https://api.redcumbre.cl/${tenantSlug}/sms/send`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
to: '+56912345678',
body: 'Recordatorio: tu cita es mañana a las 10:00.',
routeType: 'transactional',
metadata: { appointmentId: 'APT-100' },
}),
}
);
const { messageId, segmentCount } = await response.json();
console.log(`SMS encolado: ${messageId} (${segmentCount} segmento/s)`);