Documentation
Sign inGet started

WhatsApp document messages

A document message carries a public URL WhatsApp fetches at send time, with an optional caption and an optional filename. It's the largest media arm, and the only one that carries both a caption and a filename.

Send a document

Set document.url:
const msg = await bird.whatsapp.send({
  to: "+16505551234",
  from: "+13124495648",
  document: { url: "https://cdn.example.com/invoices/a1b2c3.pdf" },
});
console.log(msg.id, msg.status);
The full shape adds caption and filename:
Esempio di codice
{
  "to": "+16505551234",
  "from": "+13124495648",
  "document": {
    "url": "https://cdn.example.com/invoices/a1b2c3.pdf",
    "caption": "Your invoice for order A1B2C3",
    "filename": "invoice-a1b2c3.pdf"
  }
}
from is required on every service message: a number your workspace owns, not a Bird-managed one.

Limits

FieldBoundEnforced by
File size100 MBWhatsApp only, at fetch (async)
File typePDF, Word, Excel, PowerPoint, or plain text render reliably in the WhatsApp client; other types are transmitted but not supportedWhatsApp only, at fetch (async)
captionup to 1024 charactersBird, at accept (422)
filename1 to 100 charactersBird, at accept (422); this cap is Bird's own, since WhatsApp documents no filename limit
urlabsolute, https, has a host, no raw spaceBird, at accept (422)
Bird checks the URL's shape and the caption's and filename's length before anything is enqueued. It does not check the file's actual size or type; only WhatsApp's own fetch at send time can. See the hub's sending media by URL and when media fails.

Reading an inbound document

An inbound document carries the same document object, plus an id and mime_type Bird learned by fetching the file:
Esempio di codice
{
  "id": "wam_01kya19eknftrs2s6p82asmvnh",
  "direction": "inbound",
  "from": { "phone_number": "+14155550100" },
  "to": { "phone_number": "+13124495569" },
  "document": {
    "id": "waf_01kyb2m4xq7whs0d8n3prv6tez",
    "url": "https://platform.bird.com/v1/whatsapp/messages/wam_01kya19eknftrs2s6p82asmvnh/media/waf_01kyb2m4xq7whs0d8n3prv6tez",
    "mime_type": "application/pdf",
    "caption": "Signed contract",
    "filename": "contract.pdf"
  },
  "status": "received"
}
id and mime_type are absent on an outbound read-back, since Bird never fetched the file it sent. To fetch the bytes behind an inbound document, see Receiving WhatsApp messages.

Limits and failure modes

  • The customer service window has to be open. Documents 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, and this is the arm most likely to run into it. At 100 MB, a document is the largest thing you can send, and Bird checks nothing about the actual bytes at accept. See the hub's when media fails for media_rejected and the charge-on-failure fact. Document's own rejection text from WhatsApp hasn't been independently measured the way image's has, so treat the mapping as inferred by symmetry rather than confirmed per cause.
  • Omitting filename doesn't mean the recipient sees no name. WhatsApp derives one from the URL's path instead, which can be an opaque hash or slug rather than something readable. Set filename explicitly to control what actually shows.
  • The 100-character filename cap is Bird's own choice, not a WhatsApp limit. WhatsApp documents no filename length limit at all.
  • 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