# Templates

Draft a WhatsApp template, attach media if needed, and submit it for approval.

## Create and submit

`create_template` saves a draft. `submit_template` sends it for approval — that call is a real submission, not a local flag. Approval is asynchronous. `list_templates` filters by status: `draft`, `submitted`, `pending_meta`, `approved`, `rejected`, `paused`, `archived`.

Call `list_template_variables` before create. Category is `MARKETING`, `UTILITY`, or `AUTHENTICATION`. `parameter_format` is `POSITIONAL` or `NAMED`.

## Positional vs named

Meta-direct lines accept both `POSITIONAL` and `NAMED`. Lines that send through Respond.io accept `POSITIONAL` only. When unsure, use POSITIONAL. A named template on a line that sends through Respond.io fails closed with:

«named_params_unsupported — plantillas con variables con nombre no se pueden enviar por Respond.io todavía; usa formato POSITIONAL o una línea Meta directa»

A positional body sent with too few values:

`missing POSITIONAL parameters (need N, got M)`

Frepi builds the component payload. A `#100 … must be a JSON object` or `#132012 … expected IMAGE, received UNKNOWN` on a Respond.io send points at the payload Frepi built (or a missing header on the template). Report it; changing variable values will not fix it. See `bi_help("delivery-errors")`.

## Variables

`list_template_variables` is the catalog, with per-contact coverage. Pick `config.key` by coverage (for a greeting, `first_name`, not a sparse custom name). `config.example` is the sample used at approval time. `config.fallback` defaults to "Cliente" at send time. `name_coverage.unnamed` on a preview counts contacts that would hit that fallback.

## Media headers

`request_template_image_upload` returns an `upload_url`. The operator drops the file in the browser; the server attaches it to the draft. `header_type` is `IMAGE`, `VIDEO`, or `DOCUMENT`. Then `submit_template`.

A media header needs the connection's App ID. If it is missing, the error code is `fuente_missing_meta_app_id` (reasons `no_link`, `link_not_live`, `link_pending`). The App ID fills in on the daily health check or when the line is reconnected. Text-only templates do not need it.

Legacy drafts that have a media URL but no handle return `template_header_handle_missing`. Re-upload from the form; the server does not rebuild the handle. `media_url_not_allowed` means the URL is not an in-bucket object from `request_template_image_upload`. `template_media_missing` means the file was not stored.

## Provider catalog

Launch refuses a template the provider catalog does not list:

«La plantilla no está disponible en el catálogo del proveedor. Sincroniza las plantillas en el proveedor e inténtalo de nuevo.»

When the line's provider publishes its own remediation, the launch shows that instead, e.g. «La plantilla no está en el catálogo de Respond.io. Sincroniza las plantillas en Respond.io y vuelve a verificar.» followed by numbered steps and a link. At send time the per-recipient reason is `template_not_in_catalog`.

On a Respond.io line that lag is fixed by syncing templates in Respond.io, then creating a new draft. Do not relaunch the failed broadcast.
