WhatsApp sticker messages
A sticker message carries a public WebP URL WhatsApp fetches at send time. It's the plainest media arm: no caption, no other optional field on send.
Send a sticker
Set sticker.url; there is nothing else to add:
const msg = await bird.whatsapp.send({
to: "+16505551234",
from: "+13124495648",
sticker: { url: "https://cdn.example.com/stickers/thumbs-up.webp" },
});
console.log(msg.id, msg.status);msg = client.whatsapp.send(
to="+16505551234",
from_="+13124495648",
sticker={"url": "https://cdn.example.com/stickers/thumbs-up.webp"},
)
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",
Sticker: &bird.WhatsAppStickerSend{Url: "https://cdn.example.com/stickers/thumbs-up.webp"},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(msg.Id, *msg.Status)
}$sticker = (new WhatsAppMessageSendRequestSticker())
->setUrl('https://cdn.example.com/stickers/thumbs-up.webp');
$message = $bird->whatsapp->send(
to: '+16505551234',
from: '+13124495648',
sticker: $sticker,
);
echo $message->getId(), ' ', $message->getStatus();bird whatsapp send \
--to +16505551234 \
--from +13124495648 \
--sticker https://cdn.example.com/stickers/thumbs-up.webpcurl -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",
"sticker": {
"url": "https://cdn.example.com/stickers/thumbs-up.webp"
}
}'sticker has no caption field, and animated is not something you set on send; Bird only reports it back on an inbound sticker. from is required on every service message: a number your workspace owns, not a Bird-managed one.
Limits
| Field | Bound | Enforced by |
|---|---|---|
| File size, static | 100 KB | WhatsApp only, at fetch (async) |
| File size, animated | 500 KB | WhatsApp only, at fetch (async) |
| File type | WebP only | WhatsApp only, at fetch (async) |
| caption | not a valid field | Bird, at accept (422, schema rejection) |
| url | absolute, https, has a host, no raw space | Bird, at accept (422) |
Bird checks the URL's shape before anything is enqueued; it does not check the file's actual size, format, or whether it's static or animated. Only WhatsApp's own fetch at send time can. Sending a caption is not a length error; the field doesn't exist on this arm's schema, so it fails as an unrecognized property. See the hub's sending media by URL and when media fails.
Reading an inbound sticker
An inbound sticker carries an id, mime_type, and animated Bird learned by fetching the file:
Exemple de code
{
"id": "wam_01kya2d1isuwt4w7e1n6s9zolh",
"direction": "inbound",
"from": { "phone_number": "+14155550100" },
"to": { "phone_number": "+13124495569" },
"sticker": {
"id": "waf_01kyb2m4xq7whs0d8n3prv6tez",
"url": "https://platform.bird.com/v1/whatsapp/messages/wam_01kya2d1isuwt4w7e1n6s9zolh/media/waf_01kyb2m4xq7whs0d8n3prv6tez",
"mime_type": "image/webp",
"animated": true
},
"status": "received"
}id, mime_type, and animated are all absent on an outbound read-back, since Bird never fetched or inspected the file it sent. To fetch the bytes behind an inbound sticker, see Receiving WhatsApp messages.
Limits and failure modes
- The customer service window has to be open. Stickers are service messages, deliverable only inside an open window; see the hub's customer service window.
- Bird rejects http; WhatsApp itself would fetch it. See the hub's sending media by URL for the full shape check.
- A rejected fetch still gets charged. See the hub's when media fails. Sticker's own rejection text from WhatsApp hasn't been independently measured, so treat the mapping as inferred by symmetry rather than confirmed per cause.
- animated is read-only, and only ever present on an inbound or fetched sticker. It's WhatsApp's own verdict on the file, not something you can declare. Whether a sticker is static or animated changes only its size ceiling; WebP is required either way.
- WhatsApp caches a fetched URL for about 10 minutes. Resending the identical URL inside that window re-serves the first fetch; vary the URL to force a fresh one.
Next steps
- WhatsApp service messages: the customer service window and the model every service message shares
- Audio: another media arm with no caption field
- Images: for a photo or graphic with a caption
- How sending works: the request envelope, the 202 model, and safe retries