Enviar email

Una API para cada email que envías.

Configúralo en:

Transaccional o de marketing, un mensaje o cien, enviados a través de la misma Email API, con idempotencia, supresión y webhooks integrados. Pasa HTML sin procesar o renderiza tus plantillas de React Email.

welcome.tsx
200 · 1.2s
import { BirdClient } from "@messagebird/sdk";
import { render } from "@react-email/render";
import { WelcomeEmail } from "./emails/welcome";

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

const { data, error } = await bird.email.send({
  from:    "Bird <hello@bird.com>",
  to:      ["ada@example.com"],
  subject: "Your invite is ready",
  html:    await render(<WelcomeEmail name="Ada" />),
}).safe();

if (error) throw error;
console.log(data.id);
// → "em_2bX91Yk8h..."

Envía tu primer email en cinco minutos.

Desde el lenguaje que ya usas.

El envío es el núcleo de la Bird Email API. El primer envío puede ir a una dirección de prueba autorizada (delivered@messagebird.dev), de modo que puedes probar toda la plataforma (envíos, webhooks, supresión) antes de verificar un dominio.

1
2
3
4
5
6
7
8
9
10
import { BirdClient } from "@messagebird/sdk";

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

const { data, error } = await bird.email.send({
  from:    "you@yourdomain.com",
  to:      ["delivered@bird.dev"],
  subject: "Hello from Node",
  html:    "<p>It works.</p>",
}).safe();

Cinco cosas que no construyes tú mismo.

El mismo contrato en cada canal de Bird.

  1. 01

    Transaccional y de marketing.

    El mismo endpoint envía un restablecimiento de contraseña o una campaña. Un campo de categoría decide cómo se aplican la supresión y las bajas.

  2. 02

    Plantillas a tu manera.

    Pasa HTML sin procesar, o renderiza plantillas de React Email a HTML en tu aplicación y envía el resultado. Tu cadena de herramientas, sin cambios.

  3. 03

    Lotes de hasta 100.

    Hasta 100 mensajes independientes por llamada, cada uno con su propio destinatario y variables, validados como una unidad para que nunca envíes a medias.

  4. 04

    Idempotente por contrato.

    Cada envío acepta una clave de idempotencia, de modo que una solicitud reintentada tras un tiempo de espera agotado devuelve el resultado original en lugar de enviar por duplicado.

  5. 05

    Un webhook en cada cambio de estado.

    Aceptado, entregado, abierto, con clic, rebotado, marcado como spam. Cada uno firmado con HMAC, protegido contra repetición, idempotente, el mismo envelope en cada canal.

¿Ya envías desde otra plataforma? Cámbiate en una tarde.

La llamada que ya haces apenas cambia: cambia el cliente, conserva tus plantillas, apunta tus webhooks a un solo endpoint. Las guías de migración cubren SendGrid, Amazon SES, Mailgun y Resend.

sendgrid.ts
SendGrid
import sgMail from "@sendgrid/mail";

sgMail.setApiKey(process.env.SENDGRID_API_KEY!);

await sgMail.send({
  from:    "hello@bird.com",
  to:      "ada@example.com",
  subject: "Your invite is ready",
  html:    "<p>Welcome aboard, Ada.</p>",
});
bird.ts
Bird
import { BirdClient } from "@messagebird/sdk";

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

await bird.email.send({
  from:    "hello@bird.com",
  to:      ["ada@example.com"],
  subject: "Your invite is ready",
  html:    "<p>Welcome aboard, Ada.</p>",
});

Un mensaje o cien, en una sola llamada.

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

digest.ts
202 · batch
import { BirdClient } from "@messagebird/sdk";
import { render } from "@react-email/render";
import { Digest } from "./emails/digest";

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

const messages = await Promise.all(
  users.map(async (u) => ({
    from:    "Bird <hello@bird.com>",
    to:      [u.email],
    subject: "Your weekly digest",
    html:    await render(<Digest user={u} />),
  })),
);

const { data: batch, error } = await bird.email
  .sendBatch(messages, { idempotencyKey: `digest-${runId}` })
  .safe();

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

Añade tu propio contexto a cada envío.

Las etiquetas son una dimensión filtrable de primera clase: segmenta la entrega y la interacción por campaña, plantilla o experimento en la API de estadísticas (hasta 20 por mensaje). Los metadatos son JSON arbitrario, hasta 2 KB, que se conserva intacto en cada lectura y webhook, de modo que tus propios IDs viajan junto con el mensaje.

tagged.ts
await bird.email.send({
  from:     "Bird <hello@bird.com>",
  to:       ["ada@example.com"],
  subject:  "Your invite is ready",
  html:     "<p>Welcome aboard, Ada.</p>",
  tags:     [{ name: "campaign", value: "spring-2026" }],
  metadata: { user_id: "u_2bX91", order_id: "ord_5512" },
});

Observa cada mensaje durante toda su vida.

Un envío devuelve 202 de inmediato; el resultado llega como un webhook por destinatario. Verifica una firma, conmuta según el type: el mismo envelope que ya gestionas para SMS, 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 "email.delivered":
      await markDelivered(event.data.email_id);
      break;
    case "email.bounced":
      await flag(event.data.recipient, event.data.bounce_type);
      break;
  }

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

Los rebotes definitivos, las quejas y las bajas también actualizan tu lista de supresión automáticamente, así una dirección incorrecta nunca te cuesta reputación dos veces.

  • email.acceptedAceptado por la API y encolado para su entrega.
  • email.processedGenerado y entregado al pipeline de envío.
  • email.deliveredEl servidor de correo receptor aceptó el mensaje.
  • email.deferredUn fallo transitorio que Bird reintenta automáticamente.
  • email.bouncedFallo permanente: tipo de rebote y código SMTP en el payload.
  • email.openedPíxel de seguimiento cargado (las aperturas precargadas no cuentan).
  • email.clickedSe hizo clic en un enlace con seguimiento.
  • email.complainedEl destinatario marcó el mensaje como spam.
  • email.unsubscribedEl destinatario se dio de baja a través de un enlace con seguimiento en el cuerpo del mensaje.

Prueba cada resultado antes de salir a producción.

En el sandbox, la dirección decide el resultado, no el estado de tu cuenta. Envía a delivered@messagebird.dev para una entrega limpia, o a bounce@, complaint@ y suppressed@ para forzar cada vía de fallo a través del pipeline y los webhooks reales. Ningún dominio que verificar, ningún riesgo para tu reputación. El envío en producción está controlado como debe ser: primero verificas un dominio, y un dominio nuevo o una IP dedicada se va incrementando mediante el warmup de reputación antes de manejar todo el volumen.

Profundiza en la documentación.

Lee la guía de envío, configura los eventos de email y webhooks, o, si vienes de otro proveedor, sigue una guía de migración de SendGrid, SES, Mailgun o Resend.

Preguntas frecuentes sobre el envío

¿Puedo enviar email transaccional y de marketing?+
Sí. Ambos pasan por la misma API de envío; la única diferencia es el campo category, que decide cómo se aplican las supresiones y las bajas. Elige transactional para restablecimientos de contraseña y recibos, y marketing para campañas.
¿Admiten plantillas de React Email?+
Renderiza tus plantillas de React Email a HTML en tu aplicación —la función render de @react-email/render funciona sin cambios— y pasa el resultado como cuerpo html. Nada de tu cadena de herramientas de plantillas cambia.
¿Cuántos emails puedo enviar en una sola solicitud?+
Hasta 100 mensajes independientes por llamada batch, cada uno con su propio destinatario, asunto y variables. El batch se valida como una unidad, así que un único mensaje no válido rechaza toda la llamada con un 422: nunca envías a medias. Un solo mensaje admite de 1 a 50 destinatarios entre to, cc y bcc.
¿Qué ocurre si una solicitud agota el tiempo de espera y la reintento?+
Envía una Idempotency-Key con cada envío lógico. Si la solicitud original tuvo éxito pero se perdió la respuesta, repetirla con la misma clave devuelve el resultado original (marcado con una cabecera Idempotency-Replay) en lugar de volver a enviar.
¿Cuáles son los límites de frecuencia?+
Los envíos individuales y los batches tienen límites independientes: en el plan gratuito, 10 envíos individuales y 5 llamadas batch por minuto (5 × 100 = 500 mensajes/min), que suben a 1,000 envíos y 100 llamadas batch por minuto en Growth. Los límites cuentan solicitudes, no destinatarios, así que agrupar en batch es la palanca del volumen.
¿Cómo pruebo sin enviar email real?+
Envía a una dirección de sandbox como delivered@messagebird.dev: el resultado lo decide la dirección, no el estado de tu cuenta, de modo que puedes probar envíos, webhooks y supresiones antes de verificar un dominio. Direcciones como bounce@ y complaint@ simulan esos resultados a través del pipeline real.

Alrededor del 40% del correo comercial del mundo ya funciona sobre Bird.

Email transaccional y de marketing sobre una infraestructura que operamos desde hace una década. El envío es una de las capacidades de la Bird Email API: capacidad de entrega, IPs dedicadas, supresión y analíticas vienen incluidas.

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: