Bidirecional

Os textos voltam. Então trate-os.

Configure em:
Cursor

Cada mensagem que alguém envia para o seu número aprovisionado chega como webhook assinado com HMAC. Leia o texto, responda a partir do mesmo número, e deixe a Bird tratar do STOP e do HELP por si. Construa fluxos conversacionais e respostas automáticas na API com que já envia.

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

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

const code = generateOtp();

const { data, error } = await bird.sms.send({
  from: "Bird",
  to:   "+15005550006",
  text: `Your Bird verification code is ${code}. Reply STOP to opt out.`,
}).safe();

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

Today at 2:14 PM

Hey Ada — your Bird sign-in code is 482917. It'll expire in 10 minutes. Don't share it with anyone.
482917
Delivered

A receção é apenas mais um webhook.

O bidirecional faz parte da API de SMS da Bird. Quando alguém envia para o seu número, recebe um evento sms.received no mesmo endpoint assinado e protegido contra repetição que já transporta os seus recibos de entrega. Não há uma segunda integração nem polling — verifique a assinatura uma vez e ramifique conforme o tipo.

Esteja atento ao que volta.

Uma mensagem recebida e um opt-out são eventos, tal como um recibo de entrega. Verifique uma assinatura, ramifique conforme o tipo, e trate cada um no handler que já escreveu.

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.received":
      await handleInbound(event.data.from, event.data.text);
      break;
    case "sms.opted_out":
      await removeFromCampaigns(event.data.from);
      break;
  }

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

O payload é o mesmo envelope em cada canal da Bird: um id evt_, uma assinatura HMAC e um timestamp protegido contra repetição.

  • sms.receivedUma mensagem recebida aterrou no seu número — transporta o remetente, o seu número e o texto.
  • sms.deliveredUma resposta que enviou chegou ao telemóvel (DLR do operador).
  • sms.opted_outO remetente enviou STOP — a Bird suprimiu-o e bloqueia envios futuros.

Uma mensagem recebida assinada, na íntegra.

Eis o aspeto de um evento sms.received na rede. O from é quem lhe enviou, o to é o seu número aprovisionado, e os segmentos e a codificação são reportados da mesma forma que num envio, por isso uma resposta recebida longa nunca é uma surpresa.

sms.received
evt_
{
  "id": "evt_7nQ9xLp2aR...",
  "type": "sms.received",
  "created_at": "2026-06-26T14:03:11Z",
  "data": {
    "id": "sms_5hV02Mr3n...",
    "from": "+15005550006",
    "to": "+14155550172",
    "text": "YES book me in for Thursday",
    "encoding": "GSM-7",
    "segments": 1
  }
}

Responda a partir do mesmo número.

Uma resposta é um envio com o from e o to trocados. Defina o from para o seu número e o to para o remetente original, e a conversa fica num só número, por isso o destinatário vê uma conversa em vez de um novo remetente de cada vez. Construa respostas automáticas, confirmações ou um fluxo conversacional completo por cima.

reply.ts
200 · reply
async function handleInbound(from: string, text: string) {
  if (/^yes\b/i.test(text)) {
    const { error } = await bird.sms.send({
      from: "+14155550172", // your two-way number
      to:   from,           // reply to the sender
      text: "Booked. See you Thursday at 10am.",
    }).safe();

    if (error) throw error;
  }
}

STOP, HELP e START tratamos por si.

A Bird reconhece as palavras-chave reservadas antes de chegarem ao seu handler: STOP adiciona o remetente à sua lista de supressão e dispara sms.opted_out, HELP devolve uma resposta de ajuda automática e START volta a subscrevê-lo. Os envios posteriores para um número suprimido são bloqueados automaticamente. Pode manter as suas próprias palavras-chave para YES, BOOK ou o que o seu fluxo precisar. As regras completas de palavras-chave e de exclusão estão em gestão de exclusão.

Duas coisas que vai querer a seguir.

A receção precisa de um número com capacidade bidirecional — long codes, short codes e toll-free podem receber, os sender IDs alfanuméricos não. Para uma troca mais rica no mesmo telemóvel (indicadores de escrita, confirmações de leitura, carrosséis), o RCS melhora a conversa onde o dispositivo o suporta.

Aprofunde na documentação.

Ligue os webhooks para eventos de entrada, leia a referência de erros para as falhas que vai tratar, e consulte abuso e conformidade para as regras de palavras-chave e consentimento.

Perguntas frequentes sobre SMS bidirecional

Como é que um SMS recebido chega à minha aplicação?+
Cada mensagem enviada para o seu número aprovisionado chega como webhook sms.received assinado com HMAC. Verifica uma assinatura, lê o from, o to e o text, e encaminha-a para a sua própria lógica — o mesmo envelope que já trata para os recibos de entrega.
Posso responder a uma mensagem recebida?+
Sim. Responda enviando a partir do mesmo número em que a mensagem chegou. Defina o from para o seu número e o to para o remetente original, e a conversa fica num só número de ponta a ponta.
O que acontece quando alguém envia STOP?+
A Bird adiciona o remetente à sua lista de supressão, dispara sms.opted_out e bloqueia automaticamente os envios posteriores para esse número. HELP devolve uma resposta de ajuda e START volta a subscrevê-lo — tudo tratado antes de chegar ao seu código, para que se mantenha em conformidade sem escrever a lógica de palavras-chave.
Preciso de um número especial para bidirecional?+
Precisa de um número com capacidade bidirecional. Long codes, short codes e números toll-free suportam receção; os sender IDs alfanuméricos são apenas de envio e não podem receber respostas.

Envie e receba num só número, uma só API.

A receção bidirecional é uma das capacidades da API de SMS da Bird: envio, números, conformidade, encaminhamento e analítica vêm incluídos, sobre infraestrutura que operamos há uma década.

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:

Cursor