Envie email

Uma API para cada email que você envia.

Configure em:

Transacional ou de marketing, uma mensagem ou cem, enviadas pela mesma Email API, com idempotência, supressão e webhooks integrados. Passe HTML bruto ou renderize seus templates 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..."

Envie o seu primeiro email em cinco minutos.

A partir da linguagem que você já usa.

O envio é o núcleo da Bird Email API. O primeiro envio pode ir para um endereço de teste autorizado (delivered@messagebird.dev), para você testar toda a plataforma (envios, webhooks, supressão) antes de verificar um domínio.

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 coisas que você não constrói sozinho.

O mesmo contrato em todos os canais da Bird.

  1. 01

    Transacional + marketing.

    O mesmo endpoint envia uma redefinição de senha ou uma campanha. Um campo category decide como a supressão e os cancelamentos de inscrição se aplicam.

  2. 02

    Templates do seu jeito.

    Passe HTML bruto, ou renderize templates React Email para HTML no seu app e envie o resultado. Seu toolchain, sem alterações.

  3. 03

    Lote de até 100.

    Até 100 mensagens independentes por chamada, cada uma com seu próprio destinatário e variáveis, validadas como uma única unidade para que você nunca envie pela metade.

  4. 04

    Idempotente por contrato.

    Todo envio aceita uma chave de idempotência, então uma requisição repetida após um timeout retorna o resultado original em vez de enviar em duplicidade.

  5. 05

    Um webhook a cada mudança de estado.

    Aceito, entregue, aberto, clicado, devolvido, marcado como spam. Cada um assinado com HMAC, protegido contra replay, idempotente, o mesmo envelope em todos os canais.

Já envia em outro lugar? Mude em uma tarde.

A chamada que você já faz quase não muda: troque o cliente, mantenha seus templates, aponte seus webhooks para um único endpoint. Os guias de migração cobrem SendGrid, Amazon SES, Mailgun e 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>",
});

Uma mensagem ou cem, uma chamada.

Agrupe até 100 mensagens independentes em uma requisição, cada uma com seu próprio destinatário e variáveis. O lote é validado como uma unidade: uma mensagem inválida rejeita a chamada com um 422, então você nunca envia pela metade. Uma única chave de idempotência torna a requisição inteira segura para repetir.

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`);

Anexe seu próprio contexto a cada envio.

As tags são uma dimensão filtrável de primeira classe: segmente entrega e engajamento por campanha, template ou experimento na API de stats (até 20 por mensagem). Metadata é JSON arbitrário, até 2 KB, que circula intacto em cada leitura e webhook, então seus próprios IDs acompanham a mensagem.

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" },
});

Acompanhe cada mensagem por toda a sua vida útil.

Um envio retorna 202 imediatamente; o resultado chega como um webhook por destinatário. Verifique uma assinatura, faça switch no type: o mesmo envelope que você já trata para SMS, voz e 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 });
}

Hard bounces, reclamações e cancelamentos de inscrição também atualizam sua lista de supressão automaticamente, então um endereço inválido nunca custa sua reputação duas vezes.

  • email.acceptedAceito pela API e enfileirado para entrega.
  • email.processedGerado e entregue ao pipeline de envio.
  • email.deliveredO servidor de e-mail destinatário aceitou a mensagem.
  • email.deferredUma falha transitória que o Bird repete automaticamente.
  • email.bouncedFalha permanente: tipo de bounce e código SMTP no payload.
  • email.openedPixel de rastreamento carregado (aberturas pré-carregadas não contam).
  • email.clickedUm link rastreado foi clicado.
  • email.complainedO destinatário denunciou a mensagem como spam.
  • email.unsubscribedO destinatário cancelou a inscrição por um link rastreado no corpo da mensagem.

Teste cada resultado antes de entrar no ar.

No sandbox, o endereço decide o resultado, não o estado da sua conta. Envie para delivered@messagebird.dev para uma entrega limpa, ou para bounce@, complaint@ e suppressed@ para acionar cada caminho de falha pelo pipeline e webhooks reais. Sem domínio para verificar, sem risco para sua reputação. O envio em produção é controlado como deveria ser: você verifica um domínio primeiro, e um novo domínio ou IP dedicado passa por um aquecimento de reputação antes de carregar o volume total.

Aprofunde-se na documentação.

Leia o guia de envio, conecte eventos de e-mail e webhooks, ou, se você está vindo de outro provedor, siga um guia de migração do SendGrid, SES, Mailgun ou Resend.

Perguntas frequentes sobre envio

Posso enviar email transacional e de marketing?+
Sim. Ambos passam pela mesma API de envio; a única diferença é o campo category, que decide como as supressões e os cancelamentos de inscrição são aplicados. Escolha transactional para redefinições de senha e recibos, e marketing para campanhas.
Vocês oferecem suporte a templates React Email?+
Renderize seus templates do React Email para HTML na sua aplicação — a função render do @react-email/render funciona sem alterações — e passe o resultado como o corpo html. Nada na sua toolchain de templates muda.
Quantos emails posso enviar em uma requisição?+
Até 100 mensagens independentes por chamada em lote, cada uma com seu próprio destinatário, assunto e variáveis. O lote é validado como uma unidade, então uma única mensagem inválida rejeita a chamada inteira com um 422 — você nunca envia pela metade. Uma única mensagem aceita de 1 a 50 destinatários entre to, cc e bcc.
O que acontece se uma requisição expirar por timeout e eu tentar novamente?+
Envie um Idempotency-Key a cada envio lógico. Se a requisição original teve sucesso mas a resposta foi perdida, repeti-la com a mesma chave retorna o resultado original (marcado com um cabeçalho Idempotency-Replay) em vez de enviar de novo.
Quais são os limites de taxa?+
Envios únicos e lotes têm limites separados — no plano gratuito, 10 envios únicos e 5 chamadas em lote por minuto (5 × 100 = 500 mensagens/min), subindo para 1,000 envios e 100 chamadas em lote por minuto no Growth. Os limites contam requisições, não destinatários, então o lote é a alavanca para volume.
Como faço testes sem enviar email de verdade?+
Envie para um endereço de sandbox como delivered@messagebird.dev — o resultado é decidido pelo endereço, não pelo estado da sua conta — para que você exercite envios, webhooks e supressões antes de verificar um domínio. Endereços como bounce@ e complaint@ simulam esses resultados através do pipeline real.

Cerca de 40% do e-mail comercial do mundo já roda na Bird.

E-mail transacional e de marketing em uma infraestrutura que operamos há uma década. O envio é uma das capacidades da Bird Email API: entregabilidade, IPs dedicados, supressão e analytics vêm junto.

Comece com um canal.
Adicione os outros quando estiver pronto.

Uma chave API de teste é sua imediatamente. A produção é desbloqueada quando você adiciona um método de pagamento e verifica um remetente.

Usa Claude Code, Cursor ou Codex? Copie um prompt de configuração e o seu agente instala o Bird CLI e as skills por si. Escolha o seu: