# Delivery errors

How to read `get_broadcast` when recipients failed. `failure_breakdown` items are `{code, title, count, help_topic}` — titles, never the raw reason string.

## Enviado vs Entregado

`recipient_counts.sent` is not delivery.

- Meta-direct: `sent` means the provider accepted the payload. `delivered` and `read` arrive later on the status webhook.
- Respond.io: `sent` means Respond.io accepted the send. A vendor `failed` is applied by status sync. The poll cron is `*/1` (about one minute). The reason prefix is `{provider}: code=<n> msg=…` only when a Meta code parses, otherwise `{provider}: <text>`. The poll window is 48 hours.

On a Meta-direct line the send call returns the wamid, so a missing wamid means the payload never cleared validation. On a line that sends through Respond.io the wamid arrives later from the status poll (about one minute, and it can lag); a missing wamid there is not evidence of a failure until the poll has run.

## 131049

Title: «Límite de frecuencia por usuario (Meta)». Webhook text contains "healthy ecosystem engagement". This is a per-recipient marketing-frequency cap. It is not an account outage and it is not retryable: repeated test sends to the same recipient trip it. Wait, or choose other recipients.

One observed send succeeded after that recipient messaged the line. That is an observation, not a rule, and not the prescribed fix.

UTILITY templates are not subject to the marketing limit (per the provider's marketing-limit documentation).

## Parameter errors

`132000` and `132012` are titled «Parámetros inválidos»; `#100` appears as «Código 100».

Shapes that show up:

- Zero parameters for a template that needs one.
- A plain string where the body parameter must be a JSON object (`{"type":"text","text":…}`) → `#100`.
- A media-header template sent without its header component → `#132012` (expected IMAGE, received UNKNOWN).

Fix the draft (positional values, header component) and create a new broadcast. Do not relaunch.

## Billing

`#200` is a permission error. One observed cause is a client-owned WABA with no payment method. `health_status` can still say AVAILABLE. Discriminator: the same token sends through a sibling WABA. The fix is a payment method on that WABA, outside Frepi.

`131042` means the payment method is invalid. Same place to fix it: the WABA's billing, not a Frepi retry.

## Template could not be found

`template_not_in_catalog`, or the launch text «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`.

Sync templates on the provider, then create a new draft.

## Other codes

Titles from the code catalog:

| Code | Title |
| --- | --- |
| 4, 80004, 130429 | Meta está limitando peticiones |
| 102, 190 | Credenciales rechazadas |
| 132000, 132001, 132012, 132015 | Parámetros inválidos |
| 132005, 132007 | Plantilla no aprobada |
| 131026 | No entregable (sin WhatsApp) |
| 131047 | Ventana de 24h cerrada |
| 131049 | Límite de frecuencia por usuario (Meta) |
| 131051 | Tipo de mensaje no soportado |
| 131053 | Error de medios (formato/MIME) |

Anything else is titled "Código NNN" or "Otros".

## exhausted retries

The worker records «worker exhausted retries» when the send step gave up. Read `failure_breakdown` before deciding; a freeze or a parameter error underneath is a new draft, not another launch.
