Skip to main content

SMS

Envíe SMS por todo el mundo a través de la puerta SMPP de Orbit. Orbit se conecta a operadores de nivel 1 y agregadores en más de 190 países, y maneja concatenación, codificación y seguimiento de entrega automáticamente. Esta página lleva a través del canal de principio a fin: qué remitente adjuntar, dónde se necesita registro antes de que se acepte el tráfico, cómo la codificación decide qué cuesta cada envío, qué le dice el ciclo de vida del estado, y cómo leer fallos cuando vuelven.

Envíe un SMS

Tanto to como from se validan como E.164 — formato internacional completo con el prefijo del país, como +14155552671. Cómo Orbit valida y normaliza números en Ciclo de vida de números. Use una clave sandbox (dv_test_sk_… sobre curl, ORBIT_API_KEY en el código) mientras prototipa — los envíos sandbox son simulados, gratuitos y nunca llegan a un operador. Cambie a la clave en vivo cuando vaya a producción; nada del código arriba cambia. La pestaña Node arriba usa el ayudante genérico orbit.messages.send({ channel: 'sms', ... }); el método tipado por canal orbit.messages.sendSms({ to, body, from }) hace el mismo POST — elija una forma y úsela consistentemente.

Respuesta

El punto responde HTTP 202 Accepted — el mensaje está persisted y en cola para entrega (aún no entregado al operador). El id es un id de mensaje de plataforma de la forma msg_ seguido de 32 caracteres hex en minúsculas (sin infijo de canal); siga su ciclo de vida a través de webhooks de entrega.
Con cualquier pestaña de idioma haya hecho el envío, el sobre es el de arriba — lea data.id para consultar o conciliar después, y bifurque en data.status (comienza en queued):
  • Node.js / fetch (TypeScript) — el SDK o el valor de retorno de res.json() lleva el sobre: message.data.id, message.data.status.
  • Python — send_sms devuelve el cuerpo JSON crudo como dict: message["data"]["id"], message["data"]["status"].
  • Go — SendSMS desmarca el sobre en un struct tipado: msg.Data.ID, msg.Data.Status.
  • Ruby / PHP (vía de escape) — client.request devuelve el cuerpo JSON crudo: send.dig("data", "id") / $send['data']['id'].
Lea segments y encoding en cada envío — son lo que recobtaba la facturación, y la sección Codificación y concatenación abajo muestra cómo predecir ambos antes de enviar.

Patrones comunes

Dos patrones cubren casi toda integración SMS de producción: reintentos seguros al enviar y paginar el historial de mensajes.

Envío idempotente con Idempotency-Key

Puntos POST que crean recursos aceptan un encabezado Idempotency-Key. Un reintento que presenta la misma clave devuelve el sobre original — sin envío duplicado, sin segundo cargo. Los SDKs mintan un UUID por llamada automáticamente; sobre HTTP crudo lo pone explícitamente. De cualquier forma, pase una clave estable a los intentos de un envío lógico en vez de dejar que cada reintento minta la suya.
Node
Python
El contrato completo está en Idempotencia y reintentos seguros.

Paginar GET /messages a través de llamadas de lista SDK

El historial de mensajes está paginado por cursor: cada página lleva meta.pagination.cursor y meta.pagination.has_more; pase el cursor de vuelta hasta que has_more sea false. El SDK Node envía un bucle de cursor y un iterador que se pagin solo; los otros SDKs paginan a través de sus métodos de lista o la vía de escape:
Node
Python
El modelo de paginación completo — familias cursor vs. offset, techos de tamaño de página y por qué los cursores no son marcadores — está en la Guía de paginación.

Ejemplo trabajado: envíe, consulte y maneje fallos

La secuencia abajo es la misma de principio a fin: POST el envío, consulte GET /messages/{id} (o tome el webhook — consulta es el respaldo), y bifurque deterministicamente cuando algo falla. El cuerpo es intencionalmente un envío UCS-2 para que vea el veredicto de codificación volver en vez de asumir precio GSM-7.

1. Envíe el mensaje

Envíos API directos deben declarar un remitente — from, sender_pool_id, messaging_service_id o from_extension — de otra forma el punto devuelve HTTP 422 con SENDER_REQUIRED (p.ej. cuando un paste como "from": null entra a su solicitud). Para lo que significa cada selector, vea Elija un tipo de remitente.

2. Lea la respuesta de envío

status: queued es el estado inicial — todavía nada entregado, y ningún external_id (referencia del operador) ha vuelto. Los campos segments y encoding son exactamente contra lo que multiplica el precio por segmento; trátelos como la factura, no una sugerencia.

3. Consulte la fila

Cuando no puede (o no quiere) suscribirse a webhooks, consulte GET /messages/{id} en el id que devolvió el envío. La fila avanza por sending → sent → delivered / un fallo terminal. Cada respuesta muestra también metadata.classified_error_code para fallos terminales y metadata.no_dlr_channel para filas Meta-DM, entonces bifurque en el status legible por máquina, nunca en strings de etiqueta.
Consulta sin webhooks usualmente también recoge estados intermedios — sending (el proveedor la ganó) o sent (el proveedor la aceptó) antes de delivered. Añada ?include=webhook_deliveries cuando quiere la historia de fan-out en el mismo viaje.

4. Bifurque en fallos

Bifurque en el status de la consulta, el data.status del webhook, o metadata.classified_error_code — todos cuentan la misma historia. Las familias de fallo abajo son las que tiene que manejar realísticamente: En cualquier webhook message.failed, data.status es el campo a bifurcar — submitted_no_receipt y expired montan el mismo evento, y un webhook posterior message.delivered puede aterrizar incluso después de uno de esos.

Fundamentos de entrega SMS

La entrega SMS depende de tres cosas, en este orden: de quién envía, de dónde, y qué rápido. Tengálas bien, y la codificación se convierte en la única variable de costo que queda.

Elija un tipo de remitente

Los remitentes existen por un razón cada uno: entrega. Necesita un ID de remitente aprobado para las reglas del país destino, o el operador filtra el tráfico antes de que le cueste un segmento — vea Requisitos de cumplimiento de países.

Onboarding a través del dashboard

La recorrido del dashboard dura menos de cinco minutos y capta los dos modos de fallo abajo antes de que escriba una línea de código.
  1. Abra Channels → SMS en el dashboard.
  2. Haga clic en Attach Sender y elija un tipo de remitente arriba. Orbit valida el formato (número E.164, ID alfanumérico de 3–11, o referencia de grupo) y verifica si el destino que define como default necesita registro.
  3. Envíe un mensaje de prueba a un número que posea. El compositor muestra segments y encoding inline, así que ve el costo por segmento estimado antes de enviar.
  4. Si su puerta de destino rechaza el adjuntar (US sin campaña 10DLC, un país gated sin aprobación de remitente ID), el asistente lo dirige al flujo de registro — vea las próximas dos secciones.
Una vez que un remitente es adjuntado aquí, el mismo remitente es seleccionable del SenderIdSelect en el compositor y pasa por el camino de envío registrado. Así también es cómo revisa qué devuelve GET /api/v1/messaging/senders sobre API.

Registro de 10DLC & tipos de campañas (US)

Si envía a destinos US sobre códigos largos numéricos, los operadores necesitan registro; el tráfico no registrado es filtrado, sobrecargado, o ambos. Orbit someter registro a través de The Campaign Registry en su nombre — la recorrido completa (marca → campaña → aprobación → niveles de volumen) está en la Guía de registro de 10DLC. El punto US-específico a tener en cuenta: el volumen después del registro se conquenta como un techo de segmento de por-día, por-número basado en su puntuación de vetting de marca — no una tasa por-segundo. Si necesita más capacidad diaria, alza su puntuación de vetting (datos de marca completos, EIN, website) o asigne más números a la campaña. Para destinos no-US que gerten IDs de remitente alfanuméricos (mayoría de Europa, Brasil, Bangladesh, partes de APAC), el flujo paralelo de registro es Registro de ID de remitente, que registra su aprobación por país y adjunta los documentos KYC soportantes. La puerta en tiempo de envío rechaza tráfico a países gated hasta que la entrada del país coincidente sea approved — sin filtración silenciosa, el fallo regresa como un rejected visible. India es la excepción: sus IDs de remitente (“Headers”) registran a través de DLT/TRAI en vez del flujo genérico — vea Onboarding de DLT-India.

Codificación y concatenación

La codificación es la única variable de costo que sobrevive un remitente debidamente registrado. SMS recaba por segmentos, y el contador de segmentos depende totalmente de en qué alfabeto caba el cuerpo.

GSM-7 vs. UCS-2

  • GSM-7 — alfabeto GSM de 7-bit (ASCII más unos pocos extras: @, £, €, algo de griego). Un cuerpo que caba obtiene hasta 160 caracteres por segmento, o 153 caracteres en envío de múltiples partes (7 por segmento van al encabezado UDH de concatenación).
  • UCS-2 — cualquier carácter fuera de GSM-7 (emoji, CJK, comillas inteligentes, la mayoría de scripts no-Latin) flipa todo el mensaje a codificación 16-bit. Un cuerpo obtiene hasta 70 caracteres por segmento, o 67 en múltiples partes.
Un solo carácter no-GSM-7 reclassifica todo el mensaje. Orbit normaliza los intrusos accidentales — comillas inteligentes pegadas, guiones largos, apóstrofos rizados, caracteres de ancho-cero invisibles — a equivalentes seguros-GSM-7 antes de contar, así que errores de paste-resolve no duplican su factura de segmentos. El modelo completo de codificación y segmentación — tablas de capacidad, el techo de 10 segmentos y por qué el compositor empareja facturación — está en Concepto de segmentos y codificación SMS. Una fórmula de habilito que puede aplicar a mano:

Ejemplo trabajado

Su pedido se envió — responda YES — 30 caracteres, todos GSM-7 → 1 segmento, GSM-7. Adjuntar un solo emoji flipa el alfabeto: 54 caracteres en UCS-2 → todavía 1 segmento, pero un boletín ASCII de 160 caracteres se vuelve 2 segmentos UCS-2 tan pronto como entra un emoji. A escala, ese es el número que conduce costo. La plataforma cuenta los segmentos antes de despachar; la respuesta de envío lleva el veredicto:
Techo duro: 10 segmentos (1.530 caracteres GSM-7 o 670 caracteres UCS-2). Los cuerpos más allá de eso se truncan y el envío sigue; el contador de segmentos marca wasTruncated: true para que lo ve, en vez de preguntarse dónde fue el rabo. Eso es lo que la lista de features llama “mensajes concatenados hasta 10 segmentos”. Lea segments en cada envío y bifurque sus estimaciones de facturación en él — es exactamente contra lo que multiplica el precio por segmento.

Límites de velocidad, volumen y grupos de remitentes

Dos límites independientes sobre el volumen SMS, y tiene que despejar ambos:
  1. Límite de solicitud del lado API. 100 solicitudes/minuto por inquilino por default en POST /messages/sms, keyed por organización. Encima obtiene 429 RATE_LIMITED; vea la Guía de límites de velocidad para encabezados y manejo de reintentos. La tabla completa por canal abajo.
  2. Volumen del lado remitente. US 10DLC: un techo de segmento por-día, por-número fijado por su nivel de vetting. En otros lugares: lo que la ruta del destino admite por remitente.
Cuando cualquiera de los techos ata, un grupo de remitentes es el palanca: añada más remitentes registrados al grupo, espacie el volumen en estrategia sticky, round_robin, random o geomatch, y el volumen por remitente multiplica por tamaño del grupo. Los grupos también dejan que un remitente degradado rote fuera sin que su código de envío cambie — el punto de salud del grupo le dice qué miembro está degradando antes de que se convierta en un problema de entrega.

Ciclo de vida del estado de mensajes

Cada SMS saliente lleva un status que avanza cuando el mensaje se mueve de su llamada API hacia el handset — o hacia un fallo terminal: queued → sending → sent → delivered (o failed / undelivered / rejected / expired) Suscríbase a transiciones de estado vía webhooks usando los eventos message.sent, message.delivered y message.failed — un webhook por transición, cada uno llevando el id del mensaje y el nuevo valor status. Las nuancias que captan operadores:
  • submitted_no_receipt — el proveedor aceptó el envío, ninguna DLR volvió dentro de la ventana de 30 minutos SMPP. Etiquetado intermedio (is_terminal: false) porque una delivered tardía o fallo DLR puede todavía aterrizar y sobreescribir. Trátelo como resultado desconocido, no una entrega y no un fallo.
  • expired — una DLR llegó después de que se cerró la ventana de llegada tardía. Fila cerrada, resultado no conocible; fan-out en message.failed.
  • cancelled — solo alcanzable por usted; ningún webhook nunca dispara por él.
La recorrido de nivel de concepto de esta máquina de estado, las ventanas de gracia por canal y lo que significa is_terminal vive en Ciclo de vida de entrega; las semánticas por estado y la tabla de transición completa están en la referencia del ciclo de vida del estado de mensajes.

Solución de problemas

Cuando llega message.failed, bifurque en el status del payload, no el tipo de evento — submitted_no_receipt y expired fan-out en ese evento también. Lea metadata.classified_error_code para manejo por máquina, y error_code / error_message para la palabras del operador cuando abre un ticket. El paquete de escalación que consigue que un ticket de soporte sea contestado en la primera pasada: su ID de inquilino, un ID de mensaje, y la classified_error_code de la fila — además Referencia del proveedor del Registro de entrega para filas de síntoma DLR. La guía del registro de entrega muestra cómo filtrar el estado; Busca de números es cómo distingue un número muerto de uno vivo antes de repetir.

Precios

El precio SMS es por segmento y varía por país de destino. Consulte la página de precios o consulte el punto GET /api/v1/pricing/messaging?country=<ISO> para tarifas en tiempo real (el array devuelto channels incluye sms). El número de planificación viene de las secciones anteriores: multiplique la tarifa por segmento que devuelve el punto de precios por el valor segments que lleva la respuesta de envío. Dos envíos de lo contrario idénticos se recaban de forma diferente el momento en que uno cambia a UCS-2 — vea Codificación y concatenación para cuándo sucede eso y cómo normalizarlo de nuevo.

Features

  • Mensajes A2P y P2P — soporte aplicación-a-persona y persona-a-persona
  • Alcance global — 190+ países a través de la red de agregadores de Devotel
  • Informes de entrega — webhooks de estado en tiempo real para cada mensaje
  • Mensajes concatenados — SMS multi-parte manejado transparentemente (hasta 10 segmentos)
  • Validación E.164 — validación automática del formato del número de teléfono
  • Soporte Unicode — codificación GSM-7 y UCS-2 completa con detección automática y normalización de comillas inteligentes
  • ID de remitente — IDs de remitente alfanuméricos donde soportan las regulaciones locales, gateados por registro donde se necesita

Límites de Velocidad

Envíos SMS están limitados a 100 solicitudes/minuto por inquilino por default en el punto /messages/sms. El límite es keyed por inquilino (por organización), no por IP ni por plan, así que llamadores concurrentes dentro del mismo inquilino comparten una piscina mientras inquilinos separados nunca se afectan entre sí. ¿Necesita un techo más alto? El techo por inquilino es sobrecrucible a través de la configuración de mensajería de su organización (channel_rate_overrides.sms) — contacte a soporte o póngalo desde el dashboard. Exceder el límite devuelve 429 Too Many Requests con el código de error RATE_LIMITED; vea la Guía de límites de velocidad para encabezados y manejo de retry. El mismo modelo por-canal, por-minuto, por-inquilino aplica a través de canales de mensajería (cada uno independientemente sobrecrucible):