Volver al blog
Desarrolladores

Cómo listar plantillas de WhatsApp con la API de Waspy

GET /api/v2/templates lista las plantillas con el scope templates:read. Filtrás por estado y por canal. La API no las crea ni las edita: eso se hace en el panel o en Meta Business Manager.

· 12 min
Cómo listar plantillas de WhatsApp con la API de Waspy

Respuesta corta: para ver las plantillas de la cuenta hacés GET https://api.waspytech.com/api/v2/templates con Authorization: Bearer wspy_... y el scope templates:read. Filtrás con status (approved, pending, rejected, disabled, paused) y con phoneNumberId. La API v2 no crea, no edita y no borra plantillas. Eso se hace en el panel de Waspy o en Meta Business Manager. No hay webhook de aprobación: hay que volver a consultar.

Sirve el domingo antes de un envío: tu script tiene que saber si aviso_despacho ya está approved en es_AR, o si Meta la rechazó. Cómo redactarlas y qué mira Meta está en la guía de plantillas. La referencia de estos tres GET está en templates.

Los tres GET

PedidoCuándo
GET /templatesLa lista, paginada. Filtros status y phoneNumberId
GET /templates/:idUna plantilla, por el UUID interno
GET /templates/by-name/:namePor el nombre que después mandás en POST /messages. Query opcional language y phoneNumberId
Los tres piden templates:read. La base es https://api.waspytech.com/api/v2.
curl -sS "https://api.waspytech.com/api/v2/templates?status=approved&pageSize=50" \
  -H "Authorization: Bearer $WASPY_API_KEY"
{
  "data": [
    {
      "id": "template-uuid",
      "phoneNumberId": "channel-uuid",
      "metaTemplateId": "1234567890",
      "name": "confirmacion_pedido",
      "language": "es_AR",
      "category": "UTILITY",
      "status": "approved",
      "components": [
        { "type": "BODY", "text": "Hola {{1}}, tu pedido {{2}} fue confirmado." }
      ],
      "createdAt": "2026-03-15T10:00:00.000Z"
    }
  ],
  "meta": { "requestId": "...", "page": 1, "pageSize": 50, "total": 12 }
}
CampoPara qué
idUUID de Waspy. Es el de GET /templates/:id
nameEl string de template.name en POST /messages
languageCódigo, por ejemplo es_AR
statusSolo approved se puede enviar
categoryMARKETING, UTILITY o AUTHENTICATION
componentsHEADER, BODY, FOOTER, BUTTONS. Ahí ves las variables {{1}}, {{2}}
metaTemplateIdEl id del lado de Meta, para cruzarlo con Business Manager
phoneNumberIdCanal, o null si la plantilla es global
La lista no documenta un orden. Si el mismo nombre existe dos veces, GET /templates/by-name/:name devuelve la creada más reciente (createdAt descendente).

Filtros que existen, y el que no

QueryDóndeValores
statusSolo en la listapending, approved, rejected, disabled, paused. En minúscula
phoneNumberIdLista y by-nameUUID del canal, el de GET /channels
languageSolo en by-namees_AR, en_US, el código que aprobaste
pageListaDefault 1
pageSizeListaDefault 20, máximo 100
language no filtra GET /templates. Si necesitás “todas las de es_AR”, recorré las páginas y quedate con ese language, o llamá by-name cuando ya sabés el nombre.

Si no pasás phoneNumberId, la lista deja afuera las plantillas de números que no están active. Si pasás el UUID del canal, trae las de ese canal.

curl -sS "https://api.waspytech.com/api/v2/templates/by-name/confirmacion_pedido?language=es_AR" \
  -H "Authorization: Bearer $WASPY_API_KEY"

Si no hay match, 404 TEMPLATE_NOT_FOUND. Lo mismo con un UUID de otra cuenta: no es un 403 que diga “es de otro tenant”.

Qué no hace este recurso

La página de limitaciones lo deja escrito: las plantillas se envían y se consultan, y no se crean, editan ni borran por la API. No hay POST /templates.

El alta es el panel (Templates → Crear template) o Meta Business Manager. Meta revisa el texto. Qué suele rechazar está en por qué rechazan una plantilla.

Tampoco hay template.approved ni template.rejected entre los webhooks. Los eventos públicos son message.received, message.status_changed, conversation.created y contact.created. Para el estado de una plantilla, el camino es este GET.

Cada cuánto consultar

La API v2 permite 120 pedidos por minuto por cuenta. Lo comparten todas las claves de esa cuenta. Cada respuesta trae X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset (segundos hasta que se renueva la ventana). Si te pasás, es 429 RATE_LIMITED y el header Retry-After, en segundos. El detalle está en rate limits.

Una plantilla no cambia de estado cada segundo. Consultar by-name cada varios minutos, o una pasada de la lista antes del envío del día, alcanza. Un loop sin pausa se come el cupo que también usan POST /messages y los webhooks que tu sistema confirma con un GET.

Del nombre aprobado al envío

Cuando status es approved, el envío es otro recurso: POST /messages o el lote, con scope messages:write. El nombre y el idioma tienen que coincidir con lo que devolvió este GET. Las variables del BODY van en components.

curl -sS -X POST https://api.waspytech.com/api/v2/messages \
  -H "Authorization: Bearer $WASPY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pedido-1847-confirmado" \
  -d '{
    "phoneNumberId": "UUID-DEL-CANAL",
    "to": "+5491155554444",
    "type": "template",
    "template": {
      "name": "confirmacion_pedido",
      "language": { "code": "es_AR" },
      "components": [
        {
          "type": "body",
          "parameters": [
            { "type": "text", "text": "Sofía" },
            { "type": "text", "text": "1847" }
          ]
        }
      ]
    }
  }'

El lote de hasta 100 está en mensajes en lote. La clave, el 401 y el 403 están en idempotencia y scopes.

Una plantilla es la vía cuando la ventana de 24 horas está cerrada. Si el cliente escribió hace menos de un día, podés mandar texto libre. La regla está en la ventana de 24 horas.

Qué cobra Meta, según la categoría

El category del JSON es el que factura Meta, por mensaje entregado, al país del destinatario. En Argentina, desde el 1 de octubre de 2026:

categoryDólaresPesos
MARKETINGUS$0,0618ARS 89,56
UTILITYUS$0,026ARS 37,68
AUTHENTICATIONUS$0,026ARS 37,68
Waspy no suma un markup. La rate card es la fuente. El desglose en pesos está en cuánto cuesta la API y las tres categorías, en marketing, utilidad y autenticación.

Un aviso de despacho con un cupón adentro puede dejar de ser UTILITY. Mirá el category que devolvió el GET, no el nombre que le pusiste.

Errores de esta llamada

HTTPerror.codeCuándo
401UNAUTHORIZEDFalta el header, o la clave no existe
403FORBIDDENLa clave tiene scopes y no incluye templates:read
404TEMPLATE_NOT_FOUNDEl id o el nombre no están en tu cuenta
400VALIDATION_ERRORphoneNumberId que no es un UUID, o un status fuera de la lista
429RATE_LIMITEDMás de 120 pedidos por minuto en la cuenta
El mensaje del 403 es API key missing required scope: templates:read.

En resumen

  • Listá con GET /api/v2/templates?status=approved.
  • Resolvé un nombre con GET /templates/by-name/:name?language=es_AR.
  • No hay alta ni baja por REST, ni webhook de aprobación.
  • Mandá solo si status es approved, con POST /messages.

La clave se crea en el panel, en Scale (US$150/mes) y Enterprise. El inbox y las plantillas del equipo están desde el plan de US$70. Si todavía no hay número en la API, abrí la cuenta: 10 días, sin tarjeta. La superficie pública está en la API.

Tu equipo atendiendo por WhatsApp en minutos

CRM facil pero potente. En 10 minutos tenes a tu equipo trabajando — no necesitas hablar con nadie.