Back to site
Syncro

Template with a file header

How to send an official template with a document, image or video header — a different PDF invoice for each customer.

Base URLhttps://app.syncro.chat/api/v1AuthX-API-Key: crm_SUA_CHAVE_AQUI

Prerequisites

Meta's official templates can carry a document, image or video header. The file is not part of the approved template: it travels with each send, and it can be different for every recipient.

This is how you send one PDF invoice per customer, a receipt, a payment slip or a shipping label.

  • The number must be on Meta's Official API (provider: "cloud_api"). Numbers connected via QR Code cannot send templates.
  • The template must be approved (status: "APPROVED") and must have been created with a media header. The header is defined when the template is created, in the dashboard — you cannot attach a file to a text template.
  • The file must sit on a public URL. Meta downloads it from its own servers; a URL behind a login, a VPN or an IP allowlist will not work. Use a long-lived signed link if the file is sensitive.

Size and format limits are Meta's, not ours.

Find out whether a template needs a file

GET /whatsapp/templates returns the template's components exactly as Meta publishes them. Look for the HEADER component and read its format:

curl "https://app.syncro.chat/api/v1/whatsapp/templates?status=APPROVED" \
  -H "X-API-Key: crm_YOUR_KEY_HERE"
{
  "success": true,
  "data": [
    {
      "id": 10,
      "name": "fatura_mensal",
      "language": "pt_BR",
      "category": "UTILITY",
      "status": "APPROVED",
      "variables": ["1", "2"],
      "components": [
        { "type": "HEADER", "format": "DOCUMENT" },
        { "type": "BODY", "text": "Olá {{1}}, sua fatura vence em {{2}}." }
      ]
    }
  ]
}
HEADER format What to send
TEXT or absent nothing — the header is fixed text
DOCUMENT header_media_url pointing at the file (a PDF, for example)
IMAGE header_media_url pointing at the image
VIDEO header_media_url pointing at the video

A template with a media header and no header_media_url is rejected with 422 before anything is sent.

Send

Sending uses the usual endpoint: POST /leads/{id}/send-whatsapp-template, with the whatsapp:write scope. The full parameter table lives there.

A different invoice per customer

curl -X POST https://app.syncro.chat/api/v1/leads/123/send-whatsapp-template \
  -H "X-API-Key: crm_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "template_id": 10,
    "variables": { "1": "João", "2": "30/07" },
    "header_media_url": "https://yourdomain.com/invoices/8842.pdf",
    "header_media_filename": "Invoice-July-2026.pdf"
  }'
{
  "success": true,
  "conversation_id": 99,
  "message_id": 457,
  "provider_msg_id": "wamid.xyz456",
  "template_name": "fatura_mensal"
}

To send in bulk, repeat the call per recipient swapping header_media_url. It is the only route that allows one file per contact — the dashboard's bulk send uses the same media for the whole campaign.

About header_media_filename

Without it, the contact sees whatever name Meta can infer from the URL — usually the file's identifier. With it, they see the name you choose:

Without header_media_filename With
8842.pdf Invoice-July-2026.pdf

On IMAGE and VIDEO headers the field is ignored: Meta does not display a filename for those types.

Variables

The key is the {{N}} number in the template's approved body:

{ "variables": { "1": "João", "2": "30/07" } }

A list in order is also accepted and is equivalent to the map above:

{ "variables": ["João", "30/07"] }

Two of Meta's rules are worth remembering, because it rejects the whole send when they are broken:

  • a variable cannot be empty;
  • a variable cannot contain a line break.

If the template has a text header with a variable ({{1}} inside the HEADER), pass that value under the header_1 key, so it does not compete for position with the body:

{ "variables": { "header_1": "Julho", "1": "João", "2": "30/07" } }

Errors

HTTP Body What to do
422 skip_reason: "header_media_required", with header_format The template needs a file in the header. Send header_media_url
422 Envio de template requer instancia Cloud API. The number is QR Code. Use an Official API number
422 Lead sem telefone cadastrado. The lead must have a phone number
502 Provedor retornou erro: … with raw Meta rejected it. raw carries Meta's original error

Example of the header 422:

{
  "success": false,
  "message": "O template \"fatura_mensal\" tem cabecalho de document e exige `header_media_url` com a URL publica do arquivo.",
  "skip_reason": "header_media_required",
  "header_format": "DOCUMENT"
}

This error comes before the send and before the conversation is created — a looping integration can retry without littering the inbox.

What the API does not do

  • It does not accept file uploads. Public URL only; there is no multipart/form-data and no base64. The file stays hosted on your side.
  • It does not send documents outside a template. POST /leads/{id}/send-whatsapp only accepts type: "text" and type: "image".
  • It does not create templates. Creation — with the media header and the sample file Meta requires for approval — happens in the dashboard.