> ## Documentation Index
> Fetch the complete documentation index at: https://developer.omni.z-api.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Upload media

> Get the header_handle for templates with an image, video or document HEADER

## Concepts

Meta **does not accept the file directly** when creating the template. It requires a `header_handle` produced by the Resumable Upload API, which depends on the application token — that is why the upload goes through here and not through your frontend.

This endpoint takes the file and returns the handle, ready to use.

## When you need this

Only when the template has a `HEADER` component of type `IMAGE`, `VIDEO` or `DOCUMENT`. Templates with a text header, or with no header, need no upload.

## Flow

<Steps>
  <Step title="Upload the file">
    `POST /whatsapp/businesses/{wabaId}/templates/media` with `multipart/form-data`, fields `file` and `type`.
  </Step>

  <Step title="Keep the handle">
    The response returns the handle in the `h` field.
  </Step>

  <Step title="Use it on the HEADER component">
    Pass the handle as the HEADER `example` in [Create template](/en/templates/create-template):

    ```json theme={null}
    {
      "type": "HEADER",
      "format": "IMAGE",
      "example": { "header_handle": ["4::aW1hZ2UvanBlZw==:ARZ..."] }
    }
    ```
  </Step>
</Steps>

<Warning>
  The handle expires. Upload the file and create the template in the same session — do not store the handle to use days later.
</Warning>

<Note>
  Besides `h`, the API accepts the handle under the keys `handle`, `header_handle`, `headerHandle` and `mediaHandle`. Use `h`, which is the canonical form.
</Note>

## Configuration prerequisite

The upload depends on the Meta **App ID** and **App Secret** registered on the account. Without them the call returns `422` with `MISSING_APP_CREDENTIALS`.

This is configured in the dashboard, under **Security** — there is no public endpoint to register the app credentials. See also [SDK origins](/en/channels/sdk-info), which covers the other prerequisite of the SDK flow.

## Limits

| Item            | Value          |
| --------------- | -------------- |
| Maximum size    | 100 MB         |
| Required fields | `file`, `type` |


## OpenAPI

````yaml en/templates/openapi.json POST /whatsapp/businesses/{wabaId}/templates/media
openapi: 3.1.0
info:
  title: Omni Z-API - Templates API
  description: API for managing WhatsApp Business message templates
  version: 1.0.0
servers:
  - url: https://api.omni.z-api.io
security:
  - bearerAuth: []
paths:
  /whatsapp/businesses/{wabaId}/templates/media:
    post:
      tags:
        - Templates
      summary: Upload template media
      description: >-
        Uploads the media HEADER file and returns the `header_handle` Meta
        requires.


        Meta does not accept the file directly when creating the template: it
        requires the handle from the Resumable Upload API, which depends on the
        application token. This endpoint bridges that.
      operationId: uploadTemplateMedia
      parameters:
        - name: wabaId
          in: path
          required: true
          description: WABA ID (obtained via List WABAs)
          schema:
            type: string
            example: '428083093730937'
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - file
                - type
              properties:
                file:
                  type: string
                  format: binary
                  description: Header file (image, video or document). 100 MB limit
                type:
                  type: string
                  description: >-
                    File MIME type (e.g. `image/jpeg`, `video/mp4`,
                    `application/pdf`)
                  example: image/jpeg
      responses:
        '200':
          description: Upload completed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TemplateMediaResponse'
              example:
                h: 4::aW1hZ2UvanBlZw==:ARZ...:e:1770000000:...
        '400':
          description: Invalid request — empty file or missing `type`
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Invalid or missing token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '413':
          description: File larger than 100 MB
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: >-
            The account has no Meta App ID and App Secret configured
            (`MISSING_APP_CREDENTIALS`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '502':
          description: >-
            Meta refused the upload (`META_REFUSED`) or the app configuration
            could not be read (`CONFIG_UNREACHABLE`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    TemplateMediaResponse:
      type: object
      properties:
        h:
          type: string
          description: >-
            Handle to use as the HEADER component `example` when creating the
            template
    Error:
      type: object
      properties:
        error:
          type: integer
          description: Error code
        message:
          type: string
          description: Error description
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: Secret Key generated in the Omni Z-API Security panel

````