Saltar al contenido
OmniChannels.ai

Enviar SMS por API: ejemplos en Python, Node.js, PHP y cURL

Envíe SMS por API en Python, Node.js, PHP y cURL: envíos individuales y masivos, Unicode y árabe, conteo de segmentos, webhooks de entrega y errores.

Actualizado 10 min de lectura

Por OmniChannels.ai Editorial Team · Revisado por BroadNet Messaging Solutions Team

Integración

Respuesta breve

Para enviar un SMS con la API de OmniChannels.ai, haga un POST autenticado a https://api.broadnet.me/sms/sendSms con un cuerpo JSON que contenga senderId, destinationNumber, message y messageType. Use TEXT para texto GSM-7 y UNICODE para árabe o emojis. Una respuesta 200 devuelve el ID del mensaje como texto sin formato, y el estado final de entrega llega después a su webhook.

En esta página
  1. ¿Cómo envío un SMS con la API?
  2. ¿Cómo debo dar formato a los números de teléfono?
  3. ¿Cómo envío árabe, emojis u otro texto Unicode?
  4. ¿Cómo cuento los segmentos antes de enviar?
  5. ¿Cómo envío a muchos números?
  6. ¿Cómo recibo el estado de entrega?
  7. ¿Cómo gestiono los errores y evito los duplicados?
  8. Ejemplo práctico: códigos de inicio de sesión para una app regional
  9. ¿Cuáles son los errores habituales?
  10. Cómo le ayuda OmniChannels.ai

Puntos clave

  • POST /sms/sendSms necesita cuatro campos: senderId, destinationNumber, message y messageType; el cuerpo de la respuesta es el ID del mensaje como texto sin formato, no JSON.
  • Establezca messageType en UNICODE para árabe, emojis o cualquier carácter fuera de GSM-7; un solo carácter así convierte todo el mensaje en Unicode y acorta cada segmento.
  • POST /sms/identify cuenta los caracteres y los segmentos antes de enviar, para que pueda prever cuántos segmentos usa un mensaje.
  • La entrega es asíncrona: un 200 significa aceptado, y DELIVERED, FAILED o REJECTED llega después a su webhook.
  • La API no tiene clave de idempotencia, así que registre cada envío antes de hacerlo y compruebe el estado tras un tiempo de espera agotado en lugar de reenviar.

Esta guía está dirigida a los desarrolladores que necesitan enviar SMS desde una aplicación y quieren código funcional en Python, Node.js, PHP o cURL. Abarca un envío individual, Unicode y árabe, el conteo de segmentos, la carga masiva, los webhooks de estado de entrega y la gestión de errores, usando únicamente endpoints y campos de nuestra referencia de la API de SMS y de la especificación OpenAPI.

¿Cómo envío un SMS con la API?

Haga un POST autenticado a /sms/sendSms con un cuerpo JSON. La respuesta es 200 OK con el ID del mensaje como texto sin formato.

Elemento Valor
URL base https://api.broadnet.me (sin prefijo /v1)
Endpoint POST /sms/sendSms
Autenticación Authorization: Bearer $BROADNET_TOKEN
Tipo de contenido application/json
Campos obligatorios senderId, destinationNumber, message, messageType

Las credenciales de prueba se emiten tras una breve solicitud de acceso, y los envíos de prueba van a sus propios números verificados. No hay alta autoservicio instantánea. Consulte el inicio rápido.

curl -X POST https://api.broadnet.me/sms/sendSms \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "senderId": "OmniDemo",
    "destinationNumber": "447700900123",
    "message": "Your OmniDemo code is 482913",
    "messageType": "TEXT"
  }'
// Node.js 18+ (fetch integrado)
const res = await fetch("https://api.broadnet.me/sms/sendSms", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.BROADNET_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    senderId: "OmniDemo",
    destinationNumber: "447700900123",
    message: "Your OmniDemo code is 482913",
    messageType: "TEXT",
  }),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const messageId = await res.text(); // ID del mensaje en texto sin formato
import os
import requests

r = requests.post(
    "https://api.broadnet.me/sms/sendSms",
    headers={"Authorization": f"Bearer {os.environ['BROADNET_TOKEN']}"},
    json={
        "senderId": "OmniDemo",
        "destinationNumber": "447700900123",
        "message": "Your OmniDemo code is 482913",
        "messageType": "TEXT",
    },
    timeout=15,
)
r.raise_for_status()
message_id = r.text  # ID del mensaje en texto sin formato, no JSON
<?php
$payload = json_encode([
    "senderId" => "OmniDemo",
    "destinationNumber" => "447700900123",
    "message" => "Your OmniDemo code is 482913",
    "messageType" => "TEXT",
]);

$ch = curl_init("https://api.broadnet.me/sms/sendSms");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 15,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("BROADNET_TOKEN"),
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => $payload,
]);
$messageId = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $status . " " . $messageId . PHP_EOL;

El cuerpo de una respuesta correcta tiene este aspecto:

2603121407537573731

Guarde ese ID junto a su propio registro, como un pedido o un intento de inicio de sesión. Es lo que le permite relacionar después los estados de entrega.

¿Cómo debo dar formato a los números de teléfono?

Use el prefijo del país más el número nacional, solo dígitos. El formato sigue el plan internacional de numeración de la ITU-T E.164, sin el signo más.

Entrada ¿Válida? Motivo
447700900123 Sí Prefijo de país 44 más número nacional
+44 7700 900123 No Quite el signo más y los espacios
07700900123 No Sustituya el 0 inicial por el prefijo del país

Guarde los números en formato E.164 (+447700900123) en su base de datos y quite el + al construir la petición. Nuestro formateador gratuito de números de teléfono ayuda a hacer una comprobación rápida.

¿Cómo envío árabe, emojis u otro texto Unicode?

Establezca messageType en UNICODE. Cualquier carácter fuera del alfabeto GSM-7, como una letra árabe, un emoji, unas comillas tipográficas o una raya, convierte todo el mensaje en Unicode.

r = requests.post(
    "https://api.broadnet.me/sms/sendSms",
    headers={"Authorization": f"Bearer {os.environ['BROADNET_TOKEN']}"},
    json={
        "senderId": "OmniDemo",
        "destinationNumber": "971500000000",
        "message": "رمز التحقق الخاص بك هو 482913",
        "messageType": "UNICODE",
        "campaignName": "login-otp",
    },
    timeout=15,
)

En PHP, use JSON_UNESCAPED_UNICODE al llamar a json_encode. La codificación determina el tamaño del segmento, tal como se define para el SMS en 3GPP TS 23.040:

messageType SMS único Por segmento al dividir Uso
TEXT 160 caracteres 153 caracteres Texto que usa solo el alfabeto GSM-7
UNICODE 70 caracteres 67 caracteres Árabe, cirílico, chino, emojis

La mayoría de los operadores facturan por segmento, de modo que un mensaje largo en árabe cuesta más que uno de la misma longitud en alfabeto latino. Lea nuestra guía de SMS en Unicode y árabe y pruebe el contador de caracteres SMS.

¿Cómo cuento los segmentos antes de enviar?

Llame a POST /sms/identify con el mensaje. Devuelve la codificación detectada, el número de caracteres, el número de segmentos y el límite por segmento.

curl -X POST https://api.broadnet.me/sms/identify \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "message": "Your OmniDemo code is 482913" }'
{
  "message": "Your OmniDemo code is 482913",
  "messageType": "TEXT",
  "smscount": 1,
  "charCount": 28,
  "charLimit": 160
}

Puede pasar smsParts (a partir de smscount), charCount y charLimit en una petición de envío. El texto GSM-7 puede aparecer etiquetado como GSM-7 en la respuesta; envíelo como TEXT.

¿Cómo envío a muchos números?

Use POST /sms/sendbulk, una petición multipart/form-data con un archivo de destinatarios y una cadena JSON de ajustes.

curl -X POST https://api.broadnet.me/sms/sendbulk \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -F destinationNumberFile=@recipients.csv \
  -F 'bulkRequest={"senderId":"OmniDemo","message":"Your statement is ready in the app.","messageType":"TEXT","campaignName":"oct-statements","allowDuplicate":false}'
import json
import os
import requests

bulk_request = {
    "senderId": "OmniDemo",
    "message": "Your statement is ready in the app.",
    "messageType": "TEXT",
    "campaignName": "oct-statements",
    "allowDuplicate": False,
}

with open("recipients.csv", "rb") as f:
    r = requests.post(
        "https://api.broadnet.me/sms/sendbulk",
        headers={"Authorization": f"Bearer {os.environ['BROADNET_TOKEN']}"},
        files={"destinationNumberFile": ("recipients.csv", f, "text/csv")},
        data={"bulkRequest": json.dumps(bulk_request)},
        timeout=60,
    )
print(r.json())

La respuesta incluye bulkSessionId y un objeto bulkListInfo con total, validCount, invalidCount y duplicate. Guarde bulkSessionId con la campaña. Los trabajos pueden listarse, pausarse, reanudarse y abortarse con los endpoints de la referencia. También puede comprobar los números antes de un envío grande con POST /sms/lookup; consulte nuestra guía de HLR lookup.

¿Cómo recibo el estado de entrega?

Los estados de entrega se envían a la URL del webhook configurada en su cuenta. Un mensaje pasa por SUBMITTED y SENT hasta DELIVERED, o termina como FAILED o REJECTED. Usted facilita a nuestro equipo la URL HTTPS pública, y los revendedores pueden tener un webhook por subcuenta.

Los campos de la carga varían según el canal y la especificación de la API no define un único esquema de webhook, así que registre primero el cuerpo sin procesar y asigne los campos a partir de un evento real de su cuenta. Un receptor mínimo guarda el evento y responde con rapidez:

import express from "express";

const app = express();

app.post("/webhooks/omnichannels", express.json(), async (req, res) => {
  await saveStatusEvent(req.body); // su almacenamiento; procese de forma asíncrona
  res.sendStatus(200);             // responda rápido
});

app.listen(3000);

Haga que el procesamiento sea idempotente, porque el mismo estado puede llegar dos veces, y no deje nunca que un SENT tardío sobrescriba un DELIVERED guardado. Si su endpoint estuvo caído, POST /sms/resendDlr vuelve a enviar los informes de un intervalo de fechas:

curl -X POST https://api.broadnet.me/sms/resendDlr \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "startDate": "2026-10-09",
    "endDate": "2026-10-10",
    "senderId": "OmniDemo",
    "messageStatus": "DELIVERED"
  }'

Encontrará más información en la guía de webhooks y en estados de entrega de mensajes explicados.

¿Cómo gestiono los errores y evito los duplicados?

Gestione primero el estado HTTP y después el cuerpo del error. Reintente solo los errores de red, 429 y 5xx.

Código Significado Acción
200 Aceptado Guarde el ID
400 Error de validación o campo ausente Corrija la petición
401 / 403 Token incorrecto u operación no permitida Corrija; no reintente
429 Límite de frecuencia superado Espere según Retry-After
500, 503, 504 Problema del servidor o del servicio previo Reintente con espera creciente y jitter

Los errores que genera la API usan un cuerpo JSON de cinco campos con status, error, message, errorCode y requestUri. El límite REST documentado por defecto es de 200 peticiones por segundo sostenidas; los límites de su cuenta se confirman junto con sus credenciales.

La API no acepta ninguna clave de idempotencia. Una petición puede tener éxito aunque se pierda su respuesta, y un reintento a ciegas envía entonces el mensaje dos veces. Escriba una fila pendiente con su propio ID de operación antes de llamar, guarde el ID de mensaje devuelto y, tras un tiempo de espera agotado, compruebe si hay un estado por webhook antes de volver a enviar. En los envíos masivos, establezca allowDuplicate en false. Los detalles están en Errores y límites.

Ejemplo práctico: códigos de inicio de sesión para una app regional

"Souq Rafiq" (ficticia), un comercio de los Emiratos Árabes Unidos, envía códigos de inicio de sesión por SMS.

  1. El servicio de autenticación genera un código de seis dígitos, guarda un hash con una caducidad de cinco minutos y escribe una fila de envío pending.
  2. Llama a /sms/sendSms con messageType=UNICODE para los usuarios en árabe y TEXT para los usuarios en inglés.
  3. Con un 200, guarda el ID del mensaje.
  4. El gestor del webhook marca la fila como DELIVERED, FAILED o REJECTED.
  5. Si el estado no es DELIVERED tras una breve espera, la app ofrece un reenvío y, si está configurado, otro canal. Consulte el respaldo entre canales.
  6. Los límites de solicitudes de código por número y por IP protegen contra los abusos; consulte la prevención del SMS pumping.

¿Cuáles son los errores habituales?

  • Llamar a r.json() sobre la respuesta del envío. Es texto sin formato.
  • Nombres de campo incorrectos. Use senderId, destinationNumber y message; campos como to, from o text no forman parte de este endpoint.
  • Signos más y ceros iniciales en los números.
  • Olvidar UNICODE para el árabe, lo que desfigura el texto.
  • Sender ID sin registrar. Algunos países los bloquean o los sustituyen; consulte las normas de sender ID de su destino y pídanos que nos encarguemos del registro.
  • Tratar un 200 como entregado.
  • El token en una app móvil o en un navegador, donde cualquiera puede extraerlo.
  • Límites: esta guía muestra la petición habitual. Los campos opcionales, como los formatos de programación, deben confirmarse con nuestro equipo.

Cómo le ayuda OmniChannels.ai

OmniChannels.ai envía SMS A2P mediante la conectividad directa con operadores de BroadNet, con SMS bidireccional, sender ID, Unicode y árabe, HLR lookup y SMPP 3.4 para grandes volúmenes. La API REST en https://api.broadnet.me usa un token Bearer y abarca también WhatsApp, RCS y otros canales, con los estados de entrega normalizados en un único formato de webhook. Nuestro equipo prepara con usted los registros de sender ID. Consulte la referencia de la API de SMS o el canal SMS.

Preguntas frecuentes

¿Cómo envío un SMS con Python?

Use la librería requests para hacer un POST JSON a https://api.broadnet.me/sms/sendSms con una cabecera Authorization: Bearer y los campos senderId, destinationNumber, message y messageType. Lea el token de una variable de entorno. El cuerpo de una respuesta 200 es el ID del mensaje como texto sin formato, así que use r.text en lugar de r.json().

¿Qué formato de número de teléfono espera la API de SMS?

Prefijo del país más número nacional, solo dígitos, sin signo más, sin prefijo 00, sin espacios ni cero inicial. Por ejemplo, 447700900123 es válido, mientras que +44 7700 900123 y 07700900123 no lo son. Guarde los números en formato E.164 en su propia base de datos y quite el signo más al construir la petición.

¿Cómo envío SMS en árabe por la API?

Establezca messageType en UNICODE y envíe el texto árabe en el campo message en UTF-8. Los mensajes Unicode admiten 70 caracteres en un segmento único y 67 por segmento al dividirse, frente a 160 y 153 en GSM-7. Pruebe en teléfonos reales y llame antes a /sms/identify para ver el número de segmentos.

¿Cómo obtengo los informes de entrega?

Los estados se envían a la URL del webhook configurada en su cuenta. Los mensajes pasan por SUBMITTED y SENT hasta DELIVERED, FAILED o REJECTED. Su endpoint debe guardar el evento sin procesar, responder 2xx con rapidez y procesar de forma asíncrona. Si se perdieron eventos, POST /sms/resendDlr puede volver a enviar los informes de entrega de un intervalo de fechas.

¿Cómo envío SMS a muchos números a la vez?

Use POST /sms/sendbulk, una petición multipart con un destinationNumberFile (CSV o TXT) y una cadena JSON bulkRequest que contenga senderId, message y messageType. La respuesta indica cuántos números eran válidos, no válidos o duplicados, y devuelve un bulkSessionId que puede guardar con su campaña.

¿Necesito registrar un sender ID?

En muchos países, sí. Algunos exigen un sender ID alfanumérico aprobado y otros requieren identificadores del regulador o de plantilla, que la API acepta en campos opcionales como peId y templateId. Los requisitos dependen de cada país, así que consulte la página de sender ID de su destino; nuestro equipo puede encargarse del registro con usted.

Fuentes

  1. 3GPP TS 23.040: Technical realization of the Short Message Service (SMS)
  2. ITU-T E.164: The international public telecommunication numbering plan
  3. RFC 9110: HTTP Semantics