Header media

A template with an image, video or document header needs a sample for review and a different reference at send time. Confusing the two is the usual reason a media template fails to send.

A handle is not a media id

header_handlemedia_id
What it is forMeta’s review of the templateThe actual send
Where it goesexample.header_handle at creationA header parameter at send time
How you get itPOST /api/templates/mediaResolved for you when sending
LifetimeCreation only — it cannot sendAbout 30 days

You cannot send with a handle

The handle exists so a reviewer can see what the header will look like. It is write-only and has no meaning after approval. At send time a real media id is needed, which is resolved for you — see below.

What you can upload

kindAccepted typesMaximum size
IMAGEimage/jpeg, image/png5MB
VIDEOvideo/mp4, video/3gpp16MB
DOCUMENTapplication/pdf100MB
Enforced by the API. Anything else is a 400 naming what is allowed.

These are the header limits and are unrelated to the limits on a normal media message, which are larger and allow far more formats.

Uploading a sample

POST/api/templates/media
Auth: API key or sessionPlan feature: campaigns

multipart/form-data. Fields: file, wabaAccountId, kind.

cURL
curl -X POST https://api.wpai.co.in/api/templates/media \
  -H "X-API-Key: $WPAI_KEY" \
  -F "file=@./header-sample.png" \
  -F "wabaAccountId=68a1f3…" \
  -F "kind=IMAGE"
201
{
  "handle": "4::aW1hZ2UvcG5n:ARZ…",
  "mimeType": "image/png",
  "size": 184320,
  "headerMediaFile": { "filename": "3f9a1c…", "mimeType": "image/png", "size": 184320 }
}

Two things come back and you need both. handle goes to Meta; headerMediaFile is our durable copy, because Meta never returns the sample again and without it there is nothing to preview or to fall back on.

Errors

  • 400 file is required — the field must be named file.
  • 400 kind must be IMAGE, VIDEO or DOCUMENT
  • 400 IMAGE must be one of: image/jpeg, image/png
  • 400 VIDEO exceeds 16MB limit
  • 500 Meta App ID is not configured — a platform setting, not yours.

Using the handle

Pass both parts through to the create call:

POST /api/templates
{
  "wabaAccountId": "68a1f3…",
  "name": "monthly_menu",
  "category": "MARKETING",
  "headerMediaFile": {
    "filename": "3f9a1c…",
    "mimeType": "image/png",
    "size": 184320
  },
  "components": [
    {
      "type": "HEADER",
      "format": "IMAGE",
      "example": { "header_handle": ["4::aW1hZ2UvcG5n:ARZ…"] }
    },
    { "type": "BODY", "text": "This month’s menu is out — take a look." }
  ]
}

The format on the header must match the kind you uploaded. Mismatched, Meta rejects the template rather than the request.

Sending the template later

Not through the send endpoint

POST /api/messages/send supplies body parameters only. A media-header template goes out with no header, and Meta rejects it with error 132000. There is no flag that changes this.

Media-header templates are sent from the dashboard, which resolves a real media id for you — from the sample stored above, or from a file you attach at the time. That is why the durable copy exists: without it there would be nothing to send after approval.

If your integration has to send programmatically, keep a second version of the template with a text header. Everything else about it can be identical, and it will send through /api/messages/send without trouble.

Reading the sample back

GET/api/templates/:id/media
Auth: API key or sessionPlan feature: campaigns

Streams the stored sample with its original content type. Immutable, so cache it freely.

  • 404 No stored media for this template — it was imported from Meta rather than created here, so no sample was ever uploaded through us.
  • 404 Stored media file is missing — the record exists but the file has gone from storage. You will have to attach media explicitly when sending it.