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);msg = client.whatsapp.send(
to="+16505551234",
from_="+13124495648",
text={"body": "Your driver is 2 minutes away."},
)
print(msg.id, msg.status)package main
import (
"context"
"fmt"
"log"
"os"
bird "github.com/messagebird/bird-sdk-go"
"github.com/messagebird/bird-sdk-go/option"
)
func main() {
client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
if err != nil {
log.Fatal(err)
}
msg, err := client.Whatsapp.Send(context.Background(), bird.WhatsappSendParams{
To: "+16505551234",
From: "+13124495648",
Text: &bird.WhatsAppTextSend{Body: "Your driver is 2 minutes away."},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(msg.Id, *msg.Status)
}$text = (new WhatsAppMessageSendRequestText())
->setBody('Your driver is 2 minutes away.');
$message = $bird->whatsapp->send(
to: '+16505551234',
from: '+13124495648',
text: $text,
);
echo $message->getId(), ' ', $message->getStatus();bird whatsapp send \
--from +13124495648 \
--text 'Your driver is 2 minutes away.' \
--to +16505551234{
"name": "whatsapp_send",
"arguments": {
"from": "+13124495648",
"text": {
"body": "Your driver is 2 minutes away."
},
"to": "+16505551234"
}
}curl -X POST "https://us1.platform.bird.com/v1/whatsapp/messages" \
-H "Authorization: Bearer $BIRD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+16505551234",
"from": "+13124495648",
"text": {
"body": "Your driver is 2 minutes away."
}
}'The full shape adds preview_url plus the fields any free-form send can carry:
Ejemplo de código
{
"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
| Field | Bound | Enforced by |
|---|---|---|
| body | 1 to 4096 characters | Bird, at accept (422) |
| preview_url | boolean, defaults to false | N/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:
Ejemplo de código
{
"id": "wam_01kya19eknftrs2s6p82asmvnh",
"direction": "inbound",
"from": { "phone_number": "+14155550100" },
"to": { "phone_number": "+13124495569" },
"text": { "body": "Does it come in another color?" },
"status": "received"
}See Receiving WhatsApp messages for the message list, the API, and the webhook path.
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
- WhatsApp service messages: the customer service window and the model every service message shares
- How sending works: the request envelope, the 202 model, and safe retries
- Interactive messages: when you want a tap instead of a typed reply