Guides
Template Media Headers
How to send approved Cloud templates that carry a native WhatsApp document (PDF), image, or video — including per-customer files from your ERP or storage — without putting a download URL in the message text.
1. Choose the right pattern
| Customer should receive | Template header | API field at send time | Typical use |
|---|---|---|---|
| Native PDF / document bubble | DOCUMENT |
header_media_url or header_media_file |
Invoices, contracts, statements, tickets |
| Native image | IMAGE |
header_media_url or header_media_file |
Receipts, banners, product shots |
| Native video | VIDEO |
header_media_url or header_media_file |
Short explainers, demos |
| Clickable URL in the text | None / text header | body_variables containing the URL |
Hosted download pages — see Dynamic Invoice Link |
| Same sample media every time | DOCUMENT / IMAGE / VIDEO |
Omit media fields (uses template sample) | Static announcements only |
2. How DOCUMENT delivery works
- Create and approve a UTILITY (or other allowed) template in the dashboard with header format DOCUMENT. Upload any valid sample PDF for Meta review.
- At send time, pass a public HTTPS URL to the customer-specific file via
header_media_url, or upload the bytes via multipartheader_media_file. - Washeej forwards the template to Meta with a document header parameter.
- Meta downloads the file from that URL (server-to-server) and delivers a WhatsApp document. The end user sees a file, not the raw URL.
header_media_url is a fetch address for Meta's servers. Do not confuse it with putting a link inside body_variables.
3. Media URL requirements
- Must be HTTPS and reachable from the public internet (not
localhost, not private VPC-only hosts). - Must return HTTP 200 on
GETwith the binary body (query-string download endpoints are fine if they return the file). - Preferred
Content-Type:application/pdffor documents, matching image/video MIME for other headers. - Meta document size limit: 100 MB (images 5 MB, videos 16 MB).
- Prefer a path or
Content-Dispositionfilename ending in.pdfso WhatsApp shows a clear file name. - Signed / short-lived URLs are OK if they remain valid long enough for Meta to fetch at send time.
- Auth walls, HTML login pages, or HTML error bodies will fail Meta media download (often surfaced as media upload errors).
4. Scenario A — Dynamic PDF via public URL (JSON)
Best when your system already stores each document behind a stable or signed HTTPS link.
curl -X POST "https://staging-mobile.washeej.com/v1/templates/send" \
-H "client-id: YOUR_CLIENT_ID" \
-H "client-secret: YOUR_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"template_id": "YOUR_TEMPLATE_ID",
"mobile_code": "966",
"mobile": "500000000",
"whatsapp_account_id": YOUR_CLOUD_ACCOUNT_ID,
"header_media_url": "https://files.example.com/docs/INV-1001.pdf",
"body_variables": ["Ahmed", "INV-1001"]
}'
body_variables only if the approved template body contains {{1}}, {{2}}, … Placeholders. A fully static body needs no body variables.
5. Scenario B — Upload the PDF at send time (multipart)
Best when the file lives only on your app server and you do not want a public URL.
curl -X POST "https://staging-mobile.washeej.com/v1/templates/send" \
-H "client-id: YOUR_CLIENT_ID" \
-H "client-secret: YOUR_CLIENT_SECRET" \
-F "template_id=YOUR_TEMPLATE_ID" \
-F "mobile_code=966" \
-F "mobile=500000000" \
-F "whatsapp_account_id=YOUR_CLOUD_ACCOUNT_ID" \
-F "header_media_file=@/path/to/invoice.pdf;type=application/pdf" \
-F "body_variables[]=Ahmed" \
-F "body_variables[]=INV-1001"
Accepted file fields: header_media_file or media_file. Washeej stores the upload temporarily and passes a public fetch URL to Meta.
6. Scenario C — DOCUMENT header + dynamic body text
Use when the customer should get both a PDF bubble and personalized text (name, invoice number, amount, …).
- Header format: DOCUMENT (sample PDF for Meta review).
- Body example:
Hello {{1}}, invoice {{2}} is attached. Amount due: {{3}} {{4}}. - Send with
header_media_url(or file upload) and orderedbody_variables.
7. Scenario D — IMAGE or VIDEO headers
Same API fields as documents. Only the approved template header_format changes.
{
"template_id": "YOUR_TEMPLATE_ID",
"mobile_code": "966",
"mobile": "500000000",
"whatsapp_account_id": YOUR_CLOUD_ACCOUNT_ID,
"header_media_url": "https://cdn.example.com/receipts/1001.jpg",
"body_variables": ["Order 1001"]
}
- IMAGE — JPEG/PNG, max 5 MB.
- VIDEO — MP4, max 16 MB.
- DOCUMENT — PDF preferred, max 100 MB.
8. Scenario E — URL in the message text (not a file)
If the product requirement is a link inside the chat text, do not use a DOCUMENT header.
Create a text template and pass the URL in body_variables.
Full walkthrough:
Dynamic Invoice Link.
9. Scenario F — Free-form document inside the 24-hour window
Within 24 hours of the customer’s last inbound message you may send a regular document with
POST /messages
(session message). Outside that window, WhatsApp requires an approved template —
use this guide’s DOCUMENT header pattern.
10. Discover template IDs and header format
- Call
GET /templates(scopetemplates:read). - Use either the Washeej numeric
idor Metawhatsapp_template_idastemplate_idwhen sending. - Confirm
header_formatisDOCUMENT,IMAGE, orVIDEObefore relying onheader_media_url. - Send only from a Cloud API channel (
whatsapp_account_id). Device/QR channels do not support Meta templates.
11. Legacy Cloud API
The same fields work on the legacy path (existing integrations):
curl -X POST "https://staging-mobile.washeej.com/external-api/inbox/send-template-message" \
-H "client-id: YOUR_CLIENT_ID" \
-H "client-secret: YOUR_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"template_id": "YOUR_TEMPLATE_ID",
"mobile_code": "966",
"mobile": "500000000",
"whatsapp_account_id": YOUR_CLOUD_ACCOUNT_ID,
"header_media_url": "https://files.example.com/docs/INV-1001.pdf"
}'
New integrations should prefer POST /v1/templates/send.
12. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Customer sees a URL in text, not a file | URL was put in body_variables on a text template |
Use a DOCUMENT-header template + header_media_url |
| Media / upload errors from Meta | URL not publicly downloadable, HTML error page, wrong MIME, or oversized file | Verify public GET returns binary PDF/image/video under Meta limits |
| Same sample PDF every time | header_media_url / file omitted |
Pass the customer-specific media on every send |
capability_error |
Sending from Device/QR channel | Use a Cloud account whatsapp_account_id |
not_found for template |
Wrong id / not approved / wrong account | Re-check GET /templates for that Cloud number |
Validation error on header_media_url |
Not a valid absolute URL | Use full https://… value |