Sign inGet Started

Enviar SMS

Esta guía cubre el endpoint de envío individual, POST /v1/sms/messages. Construye un payload JSON con un destinatario, remitente, cuerpo y categoría. Bird devuelve 202 Accepted con un ID de mensaje y entrega de forma asíncrona. Cada solicitud envía un mensaje a un destinatario. Para enviar muchos mensajes a la vez, usa el envío por lote. Para enviar una plantilla en lugar de tu propio texto, incluye un objeto template en lugar de text, category y from.

Antes de enviar: habilita el país de destino

Tu espacio de trabajo tiene una lista de destinos permitidos que deniega por defecto y que empieza solo con el país de origen de tu organización habilitado. Bird rechaza un envío a cualquier otro país con 422 SMSDestinationNotEnabled antes de resolver un remitente. Habilita los países a los que envías en SMS > Destinations en el dashboard.

Un envío mínimo

El payload de texto libre válido más pequeño es un destinatario to, un remitente from, un cuerpo text y una categoría category.
const msg = await bird.sms.send({
  from: "+15557654321",
  to: "+14155550100",
  text: "Your verification code is 123456.",
  category: "authentication",
});
console.log(msg.id, msg.status);
Usa tu host regional (https://us1.platform.bird.com o https://eu1.platform.bird.com) con una clave bk_{region}_... correspondiente. La respuesta es el mensaje aceptado:
Ejemplo de código
{
  "id": "sms_01ky7qmwgpfkybj9ecrnwjx714",
  "direction": "outbound",
  "status": "accepted",
  "to": "+31612345678",
  "from": "Bird",
  "text": "Your Bird verification code is 481920. It expires in 10 minutes.",
  "category": "authentication",
  "segments": { "count": 1, "encoding": "GSM_7BIT", "characters": 64 },
  "cost": null,
  "carrier": null,
  "mcc_mnc": null,
  "sent_at": null,
  "delivered_at": null,
  "created_at": "2026-07-23T14:56:34.326Z"
}
status: accepted significa que Bird tiene el mensaje y lo está procesando; cost es null porque el precio se calcula durante el procesamiento. Lo que sucede después se explica en el modelo asíncrono.

Construir el payload

Destinatario

to es un destinatario en formato E.164: un + inicial, código de país y número de abonado, por ejemplo +31612345678. Un mensaje va a un solo destinatario, sin cc, bcc ni array de destinatarios. Para llegar a muchas personas, envía un lote.

Remitente

from es obligatorio en un envío de texto libre y es el remitente que ve el destinatario. Acepta una de dos formas, y cuáles funcionan depende del país de destino:
  • Un identificador de remitente alfanumérico: de 3 a 11 letras, dígitos, espacios, guiones, guiones bajos o puntos, con al menos una letra y sin separador en ningún extremo, como Bird o Acme-Co. Debe contener una letra, por lo que una cadena de dígitos con puntuación como 555 555 se rechaza. Algunos países exigen registro y otros, incluido EE. UU., no admiten remitentes alfanuméricos. Los destinatarios no pueden responder a ellos.
  • Un número que tu espacio de trabajo posee, en E.164 o como dígitos sin formato. Cualquier from compuesto solo de dígitos se interpreta como numérico y se busca entre tus remitentes, así que un número arbitrario que no posees se rechaza. Que actúe como código largo, número gratuito o código corto depende del propio número, no de cuántos dígitos escribas. Un from de 6 dígitos no es un código corto porque tenga 6 dígitos; es un código corto si el número que posees lo es.
Un remitente que no es válido para el destino se rechaza con un 422 que indica el motivo (por ejemplo, SMSAlphaNotSupported donde los remitentes alfanuméricos no están disponibles). En un envío con plantilla, from no se acepta: Bird selecciona un remitente para el destino y la categoría.
Reclamar un sender ID, consultar lo que cada país exige y registrarlo por país se cubren en sender IDs de SMS.

Cuerpo y categoría

text es el cuerpo del mensaje, de al menos un carácter. Se factura y entrega en segmentos; un envío está limitado a 12 segmentos (aproximadamente 1836 caracteres GSM-7, o 804 si el cuerpo usa la codificación extendida UCS-2). Un cuerpo que supere el límite se rechaza con un 422 en lugar de truncarse.
category es obligatorio en un envío de texto libre y clasifica el mensaje como transactional, marketing, authentication o service. Indica a Bird y a los operadores por qué estás enviando. Un código de verificación de un solo uso utiliza authentication; una promoción utiliza marketing. Elige la categoría que corresponda al propósito del mensaje.

Etiquetas y metadatos

Ambos adjuntan datos propios a un envío, pero cumplen funciones distintas:
  • tags son pares {name, value} estructurados (máx. 20 por envío; nombre de 1 a 32 caracteres, valor de 1 a 64, solo ASCII [A-Za-z0-9_-], distingue mayúsculas y minúsculas, nombres únicos dentro de un envío). Son dimensiones de filtrado de primera clase: filtra la lista de mensajes por etiqueta. Úsalas para etiquetas de baja cardinalidad como campaign o experiment_variant.
  • metadata es un objeto JSON arbitrario (máx. 2 KB serializado). Se almacena, se devuelve en lecturas de API y se replica en cada evento de webhook, pero no es una dimensión de filtrado. Úsalo para contexto de ida y vuelta: IDs internos, claves foráneas, cualquier dato que quieras recibir de vuelta con cada evento.
Ejemplo de código
{
  "tags": [{ "name": "campaign", "value": "spring-2026" }],
  "metadata": { "user_id": "usr_12345", "order_id": "ord_98765" }
}

Referencia de campos

CampoTipoObligatorioLímites / notas
tostring (E.164)síUn destinatario por mensaje
fromstringsí*Número E.164 propio, sender ID alfanumérico (3–11 caracteres, mínimo una letra) o código corto (5–6 dígitos)
textstringsí*Al menos 1 carácter; limitado a 12 segmentos
categorystringsí*transactional, marketing, authentication o service
tags{name, value}[]noMáx. 20; nombre 1–32 caracteres, valor 1–64 caracteres; solo [A-Za-z0-9_-]
metadataobjectnoJSON arbitrario, máx. 2 KB serializado
optionsobjectnoConfiguración de procesamiento por mensaje. smart_encoding es la única disponible; consulta segmentos y codificación
* Obligatorio en un envío de texto libre. Un envío con plantilla proporciona el cuerpo, la categoría y el remitente desde la plantilla, y rechaza estos tres campos.

Enviar con una plantilla

En lugar de componer text, configura el objeto template del envío para que haga referencia a una de las plantillas integradas de Bird. La plantilla proporciona el cuerpo, la categoría y el remitente, así que text, category, from y media_urls no se aceptan junto a ella. El catálogo, las variables de cada plantilla y el contrato completo de envío con plantilla están en plantillas de SMS.

Segmentos y codificación

SMS se factura por segmento. Un mensaje que cabe en la codificación GSM-7 obtiene 160 caracteres por segmento individual; UCS-2 (activada por emoji, CJK u otros caracteres fuera de GSM) baja a 70. Los mensajes más largos se dividen en segmentos multiparte con límites por segmento ligeramente menores. Cada respuesta informa el segments resuelto: los count facturables, la encoding y el conteo de caracteres. Los segmentos son la unidad que se te factura; consulta costo.
Cuando los caracteres tipográficos son la única razón por la que un cuerpo queda fuera de GSM-7, la codificación inteligente puede reducir su conteo de segmentos. Configura options.smart_encoding como true y Bird reemplaza comillas curvas, guiones, puntos suspensivos y caracteres similares por equivalentes GSM-7 antes de enviar. Está desactivada por defecto porque modifica el cuerpo que compusiste.
Para el conjunto completo de caracteres, los caracteres de tabla extendida que ocupan dos posiciones, el tamaño de los emoji, lo que la codificación inteligente reemplaza y la aritmética de segmentos, consulta Límites de caracteres.

Envío por lote

POST /v1/sms/batches envía hasta 100 mensajes independientes en una sola solicitud. Las solicitudes por lotes usan la política de limitación de solicitudes sms_batch, distinta de la política sms_send para envíos individuales. El cuerpo es un objeto JSON cuyo array messages contiene los objetos de mensaje de Construir el payload:
const result = await bird.sms.sendBatch({
  messages: [
    {
      from: "+15557654321",
      to: "+15551111111",
      text: "Hi Alice!",
      category: "marketing",
    },
    {
      from: "+15557654321",
      to: "+15552222222",
      text: "Hi Bob!",
      category: "marketing",
    },
  ],
});
La validación es todo o nada: si algún mensaje del lote no es válido, toda la solicitud se rechaza con un 422 y no se envía nada, de modo que un lote nunca se aplica parcialmente. Si tiene éxito, la respuesta 202 incluye cada mensaje aceptado en orden de envío dentro de data, más un summary con el accepted_count. A partir de ahí cada mensaje es independiente: el fallo de un destinatario no afecta a los demás.

El modelo asíncrono: qué significa 202

Un envío exitoso devuelve 202 Accepted con un ID de mensaje y status: accepted. Los errores de solicitud se devuelven de inmediato: un campo no válido, un cuerpo que supera el límite de segmentos, un país de destino que no has habilitado o un remitente no válido devuelven un 422. Un espacio de trabajo sin saldo en la billetera recibe un 402.
La entrega ocurre de forma asíncrona. El mensaje pasa a sent cuando Bird lo entrega al operador. Un acuse de recibo establece entonces delivered, undelivered, failed o expired a través de eventos y webhooks y los endpoints de lectura. Este diseño tiene tres consecuencias:
  • El coste se calcula después de la aceptación. El cost de un mensaje es null en el momento de la aceptación y se completa cuando Bird tarifica el envío durante el procesamiento. Vuelve a leer el mensaje, o espera al evento de entrega, para ver el cargo calculado hasta ese momento; coste y facturación cubre los componentes y cuándo alguno permanece sin tarificar.
  • Un mensaje puede rechazarse después del 202. Si el cargo falla durante el procesamiento, el mensaje termina en rejected con un webhook sms.rejected y no se te factura; una billetera agotada aparece como last_error.code: insufficient_balance.
  • Las lecturas pueden retrasarse brevemente respecto al 202. El mensaje se vuelve visible en los endpoints de lectura poco después del 202, así que un 404 inmediatamente después de un envío se resuelve en instantes.

Campos reservados

Bird rechaza actualmente los siguientes campos de solicitud con 422 SMSUnsupportedFeature:
scheduled_at, validity_period, media_urls, messaging_profile_id, broadcast_id, campaign_id, audience_id, contact_id, topic_id, personalization, options.max_price_per_segment, options.track_clicks
No incluyas estos campos en un envío.

Reintentar de forma segura

Envía el encabezado Idempotency-Key con un valor único por cada envío lógico. Si una solicitud tiene éxito sin devolver una respuesta, repite la misma solicitud y clave. Bird devuelve el resultado original en lugar de enviar un mensaje duplicado. Consulta idempotencia para el formato de clave y la retención.

Coste y facturación

Los SMS salientes se facturan por segmento. Lo que pagas depende del país y el operador de destino; algunas rutas añaden un recargo de terceros, como las tarifas de operador 10DLC en EE. UU.
El cost de un mensaje desglosa el cargo en componentes con nombre. transaction_amount es lo que Bird cobró por transportar el mensaje, passthrough_amount es cualquier tarifa de terceros repercutida, y amount es la suma de los componentes ya tarificados, denominada en currency_code. Un componente que aún no se ha tarificado es null en lugar de "0.00000", de modo que un mensaje cuyo recargo no se resolvió reporta amount solo como el cargo de transporte. La referencia de mensaje documenta cada campo.
El recargo se calcula con base en el mejor esfuerzo. Bird lo resuelve al registrar el acuse de recibo de entrega, dentro de una ventana acotada. Si no se resuelve en esa ventana, passthrough_amount permanece null de forma permanente: Bird no lo reintenta, y amount sigue siendo el cargo de transporte.
Los SMS entrantes se facturan en dos líneas: la tarifa entrante por segmento y un recargo de operador entrante donde corresponda. Ambos se reportan en el cost del mensaje recibido: la tarifa como transaction_amount y el recargo como passthrough_amount. A diferencia de su equivalente saliente, el recargo entrante se tarifica cuando el mensaje se acepta y no en la entrega, por lo que nunca se completa después.
Revisa el coste y los segmentos por mensaje en el registro de SMS.

Próximos pasos

  • Plantillas de SMS: envía una plantilla integrada y deja que Bird elija el remitente.
  • Registro de SMS: busca un mensaje e inspecciona su ciclo de vida, segmentos y coste.
  • Eventos: recibe eventos de entrega en tus sistemas.
  • Métricas de SMS: supervisa la tasa de entrega, la tasa de fallos y el volumen aceptado.
  • Idempotencia: reintenta de forma segura con el encabezado Idempotency-Key.
  • Envía tu primer SMS: un video que recorre la misma configuración en el panel de control