Enviar SMS

Una API para cada SMS que envías.

Configúralo en:
Cursor

Envía un mensaje o cien a través de la misma API de SMS. El SDK cuenta los segmentos antes del envío, elige GSM-7 o Unicode por ti, y cada envío es idempotente con un webhook en cada estado de entrega.

send-notification.ts
202 · 0.4s
import { BirdClient } from "@messagebird/sdk";

const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY! });

const { data, error } = await bird.sms.send({
  from:     "Bird",
  to:       "+15005550006",
  text:     "Your order #4821 has shipped. Track it: bird.ly/t/4821x",
  category: "transactional",
}).safe();

if (error) throw error;
console.log(data.id);
// → "sms_4kT01Lq2m..."
Hi Ada, reminder of your appointment tomorrow at 14:30 with Dr. Kowalski.
Your order #4821 has shipped. Track it: bird.ly/t/4821x
Your subscription renews on 3 Sep for €12/mo. Manage it here: bird.ly/account

Envía tu primer SMS en cinco minutos.

Desde el lenguaje que ya usas.

El envío es el núcleo de la API de SMS de Bird. El primer envío va a un destinatario de prueba autorizado (+15005550006), así que puedes desplegar una comprobación de CI y conectar webhooks antes de aprovisionar un número.

1
2
3
4
5
6
7
const msg = await bird.sms.send({
  from: "+15557654321",
  to: "+14155550100",
  text: "Your verification code is 123456.",
  category: "authentication",
});
console.log(msg.id, msg.status);

Cinco cosas que no construyes tú mismo.

El mismo contrato en cada canal de Bird.

  1. 01

    Recuento de segmentos antes del envío.

    El SDK mide la longitud codificada y te dice cuántos segmentos cuesta un mensaje, así que un carácter perdido nunca divide en silencio un SMS en tres.

  2. 02

    GSM-7 y Unicode, decididos por ti.

    El texto plano viaja en GSM-7; un emoji o un alfabeto no latino convierte todo el mensaje a UCS-2. Bird elige la codificación y te avisa cuando un solo carácter cambia el coste.

  3. 03

    Agrupa en una sola llamada.

    Envía muchos mensajes independientes en una petición, cada uno con su propio destinatario y texto, validados como una unidad para que nunca envíes a medias.

  4. 04

    Idempotente por contrato.

    Cada envío acepta una clave de idempotencia, así que una petición reintentada tras un timeout devuelve el resultado original en lugar de mandar un SMS a alguien dos veces.

  5. 05

    Un webhook en cada cambio de estado.

    En cola, enviado, entregado, fallido. Cada uno firmado con HMAC, protegido contra repetición, idempotente, el mismo sobre en cada canal.

¿Ya envías desde otro sitio? Cambia el cliente, conserva la llamada.

La forma apenas cambia: cambia el cliente, conserva tu from, to y text, apunta tus webhooks a un solo endpoint. El mismo modelo de autenticación que tus envíos de email, voz y WhatsApp.

twilio.ts
Twilio
import twilio from "twilio";

const client = twilio(accountSid, authToken);

await client.messages.create({
  from: "+14155550172",
  to:   "+15005550006",
  body: "Your code is 123456.",
});
bird.ts
Bird
import { BirdClient } from "@messagebird/sdk";

const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY! });

await bird.sms.send({
  from:     "Bird",
  to:       "+15005550006",
  text:     "Your code is 123456.",
  category: "authentication",
});

Conoce el coste antes que el operador.

Un mensaje GSM-7 cabe en 160 caracteres por segmento; un solo emoji o carácter no latino convierte todo el mensaje a UCS-2 y lo reduce a 70. El SDK informa de la codificación y el recuento de segmentos en cada envío, así que la facturación nunca es una sorpresa y un mensaje concatenado siempre es una decisión deliberada.

segments.ts
200 · 1 segment
const { data } = await bird.sms.send({
  from:     "Bird",
  to:       "+15005550006",
  text:     "Your code is 123456.",
  category: "authentication",
}).safe();

console.log(data.encoding); // → "GSM-7"
console.log(data.segments); // → 1

Un mensaje o cien, una llamada.

Agrupa mensajes independientes en una petición, cada uno con su propio destinatario y texto. El lote se valida como una unidad: un número incorrecto rechaza la llamada con un 422, así que nunca envías a medias. Una sola clave de idempotencia hace que toda la petición sea segura de reintentar.

reminders.ts
202 · batch
const { data: batch, error } = await bird.sms
  .sendBatch(
    users.map((u) => ({
      from: "Bird",
      to:   u.phone,
      text: `Hi ${u.name}, your appointment is tomorrow at ${u.time}.`,
    })),
    { idempotencyKey: `reminders-${runId}` },
  )
  .safe();

if (error) throw error;
console.log(`queued ${batch.data.length} messages`);

Sigue cada mensaje durante toda su vida.

Un envío devuelve 202 de inmediato; el resultado llega como webhook. Verifica una firma, conmuta según el tipo: el mismo sobre que ya gestionas para email, voz y WhatsApp.

app/api/webhooks/bird/route.ts
signed
import { bird } from "@/lib/bird";

export async function POST(req: Request) {
  const event = bird.webhooks.unwrap(
    await req.text(),
    Object.fromEntries(req.headers),
  );

  switch (event.type) {
    case "sms.delivered":
      await markDelivered(event.data.sms_id);
      break;
    case "sms.failed":
      await flag(event.data.to, event.data.reason);
      break;
  }

  return new Response(null, { status: 204 });
}

Los envíos fallidos y las respuestas STOP actualizan tu lista de supresión automáticamente, así que un número incorrecto nunca te cuesta dos veces.

  • sms.acceptedAceptado por la API y en cola para la entrega al operador.
  • sms.sentEnviado al SMSC del operador de destino.
  • sms.deliveredAcuse de recibo recibido del operador (DLR).
  • sms.failedFallo permanente: rechazo del operador, número inválido o coincidencia con lista de supresión.

Profundiza en la documentación.

Conecta webhooks, haz que cada envío sea seguro de reintentar con claves de idempotencia, y lee la referencia de errores para gestionar cada fallo de la forma correcta.

Alrededor del 40 % del SMS comercial del mundo ya circula por Bird.

El envío es una capacidad de la API de SMS de Bird: los números, la recepción bidireccional, el cumplimiento, el enrutamiento y la analítica vienen con ella, sobre una infraestructura que llevamos una década operando.

Empieza con un canal.
Añade los demás cuando estés listo.

Una clave API de prueba es tuya de inmediato. El acceso a producción se desbloquea cuando añades un método de pago y verificas un remitente.

¿Usas Claude Code, Cursor o Codex? Copia un prompt de configuración y tu agente instalará el Bird CLI y las habilidades por ti. Elige el tuyo:

Cursor