Skip to main content
A WhatsApp message carries a PDF as its attachment when its template opens with a document. The file can be anything a customer should keep: an invoice after a payment, a contract to sign, a month’s attendance sheet, a booking’s ticket, an account statement. The template is made once and approved by Meta; each message then carries its own PDF, from a link your server gives at send time. The customer sees the document at the top of the message, with its file name, and the text below it. A file tied to something the customer did or holds, such as a payment, a contract or a booking, is a utility template. A brochure or a catalogue that promotes is marketing, which Meta delivers only to customers who opted in.

1. Make the template

On the application’s Notifications → Templates page, press New template, choose the category, and under Header type choose Document. Upload a sample PDF: Meta reviews the template with it, and it is never sent to a customer. Write the body, for example:
Meta refuses a body that starts or ends with a placeholder, so keep words before the first one and after the last.

2. Wait for Meta’s approval

Meta reviews the template; until it approves, a send answers 422 template_not_approved. The list shows the status, and your code reads it with GET /v1/whatsapp/templates/{template_id} until it is APPROVED. A REJECTED template carries Meta’s reason in rejected_reason. See Templates.

3. Send it when the file is ready

When your system has the file, a payment’s invoice, a signed contract or the month’s attendance sheet, make the PDF reachable at a link and send the template with that link in header.document.link and the file’s own name in header.document.filename. Use one Idempotency-Key per file, so a retry never sends it twice.
The answer is 202 Accepted, like any send, and the status follows in message.* webhooks (see Sending messages). The message is charged and logged like any other template message, and its record keeps the link and the file name it was sent with.

Tips

  • Give a short-lived signed link. Meta downloads the file from the link when it sends the message, so the link must open without a sign-in at that moment. An invoice, a contract or an attendance sheet holds personal data: a signed link that lives a few minutes is enough, and nobody can open it afterwards.
  • One link per file. Meta may keep a copy of the file it downloaded and reuse it for a later message to the same link, by the link’s Cache-Control, Last-Modified and ETag headers or by its own rules when there are none. Never put a new file behind a link you already sent; a signed link per file is new every time.
  • Serve it as a PDF. Answer Meta’s download with Content-Type: application/pdf, straight from the link: a sign-in page or an HTML page in its place makes the message fail.
  • Name the file. Without filename, WhatsApp shows a generic name. Pass the file’s own name, ending in .pdf, such as Contract-1042.pdf: WhatsApp picks the file’s icon from the extension.
  • One PDF per message. Each message carries one document, its own. The sample you gave with the template is only for Meta’s review.
  • Meta’s limit for a document is 100 MB. A link Meta cannot download from makes the message fail, with Meta’s reason in error.
  • One template for many files. A placeholder in the body, such as {{document}}, names what is attached, so one approved template carries an invoice today and a contract tomorrow. A connected app makes utility templates only.

Errors to expect

Every code, with what to do, is on Errors.
Last modified on October 15, 2026