Sign inGet started

WhatsApp plain text messages

Plain text is the simplest free-form content arm: a body with no attachment, and an optional preview for the first link inside it.

Send a text message

Set text.body:
const msg = await bird.whatsapp.send({
  to: "+16505551234",
  from: "+13124495648",
  text: { body: "Your driver is 2 minutes away." },
});
console.log(msg.id, msg.status);
The full shape adds preview_url plus the fields any free-form send can carry:
Code example
{
  "to": "+16505551234",
  "from": "+13124495648",
  "text": {
    "body": "Your order shipped: https://example.com/track/A1B2C3",
    "preview_url": true
  },
  "in_reply_to_message_id": "wam_01kya19eknftrs2s6p82asmvnh",
  "tags": [{ "name": "category", "value": "shipping" }],
  "metadata": { "order_id": "A1B2C3" }
}
from is required on every service message: a number your workspace owns, not a Bird-managed one. in_reply_to_message_id quotes an earlier message in the same conversation; see Quoting a message for what it resolves against and what it can miss.

Limits

FieldBoundEnforced by
body1 to 4096 charactersBird, at accept (422)
preview_urlboolean, defaults to falseN/A, informational
A whitespace-only body passes the schema's own minLength: 1, but Bird still catches it: body that is empty after trimming is refused with 422 E15015 WhatsAppContentRequired. A body over 4096 characters is refused with a plain 422 and no dedicated catalog code.

Reading an inbound text message

An inbound text message carries the same text.body field, and nothing else on the arm. See Receiving WhatsApp text messages for the inbound read in full, the whatsapp.received payload, and what to watch for.

Limits and edge cases

  • The customer service window has to be open. Plain text is a service message, deliverable only inside an open window; see the hub's customer service window.
  • preview_url only affects the first link, and only what the recipient's client renders. It defaults to false. Set it to preview the first URL in body; a later URL in the same body never gets one. If the recipient's client can't fetch a preview for that link, it falls back silently to a plain clickable link. Nothing on read tells you whether a preview actually rendered.
  • WhatsApp markdown is the recipient's client rendering body, not part of the API contract. Bird passes body through untouched; it does not validate, strip, or encode *bold*, _italic_, ~strikethrough~, or triple-backtick monospace. Whether those markers render is entirely up to the client that opens the message.
  • An inbound body is not guaranteed to be non-empty, despite what the read schema says. Meta can report an inbound message as "text": {} or with an empty body, and Bird stores it verbatim rather than synthesizing a placeholder. This is a known, open gap: don't write a consumer that trusts the schema's required: body here.

Next steps