Volver al blog
Desarrolladores

Limitaciones de la API v2 de Waspy: qué todavía no podés hacer (2026)

La API v2 lista y envía plantillas, pero no las crea por REST. No hay upload de media, ni campañas, ni un sandbox que no entregue el WhatsApp. El cupo del código es 120 requests por minuto por cuenta.

· 13 min
Limitaciones de la API v2 de Waspy: qué todavía no podés hacer (2026)

Respuesta corta: la API pública (https://api.waspytech.com/api/v2) cubre cuenta, canales, contactos, conversaciones, mensajes, lectura de plantillas, descarga de media y webhooks. No crea plantillas por REST, no sube archivos, no tiene campañas y no tiene un modo que acepte el envío y no lo entregue. La lista viva está en limitaciones. Donde esa página y el handler no dicen lo mismo, en esta nota manda el código.

La referencia general está en docs.waspytech.com. La página comercial de la API está en /api-whatsapp y el módulo, en la API. La clave pública entra en Scale y Enterprise: Planes.

Lo que pedís, y lo que existe

QuerésEn la v2 pública
Listar o leer una plantillaGET /templates, GET /templates/:id, GET /templates/by-name/:name
Crear, editar o borrar una plantillaNo. Panel, Meta Business Manager, o la herramienta MCP create_template
Enviar una plantilla ya aprobadaPOST /messages con type: "template"
Subir un archivoNo. En el body va link o id de Meta
Bajar un archivo que entróGET /media/:id (scope media:read)
Lanzar una campañaNo hay rutas. El panel usa la API interna
Reaccionar con un emojiLa página de limitaciones dice que no. El código acepta type: "reaction"
Aviso template.approvedNo. Hay que volver a leer GET /templates
Saber si el texto libre puede salirserviceWindowExpiresAt en el chat. No existe GET /contacts/:id/can-send-text
Probar sin entregarPOST /webhooks/:id/test. Un POST /messages llega al número real

Plantillas: leer y enviar, no administrar

templates.ts registra tres GET. No hay POST, PATCH ni DELETE /templates en /api/v2.

curl -sS "https://api.waspytech.com/api/v2/templates?status=approved" \
  -H "Authorization: Bearer $WASPY_API_KEY"

status va en minúscula: pending, approved, rejected, disabled o paused. El envío es otro pedido, POST /messages, con el nombre que ya está aprobado. El contrato está en enviar una plantilla y el listado, en listar plantillas.

Limitaciones dice que se crean en el panel de Waspy o en Meta Business Manager. Además, el conector MCP tiene la herramienta create_template (scope templates:write): arma una plantilla de texto y la manda a revisión de Meta. No le escribe a ningún cliente y no es POST /api/v2/templates. La guía del conector está en conectar MCP.

No hay POST /media. Una imagen, un video, un audio o un PDF salen en POST /messages con link (URL pública) o id (el media id de Meta):

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: foto-pedido-1847" \
  -d '{
    "phoneNumberId": "UUID-DEL-CANAL",
    "to": "+5491126032641",
    "type": "image",
    "image": { "link": "https://cdn.ejemplo.com/pedido-1847.jpg", "caption": "Así sale el 1847" }
  }'

Si generás el archivo en el momento y no tenés dónde publicarlo, ese hueco sigue abierto: la página de limitaciones lo dice así. Lo que sí está es la bajada de lo que el cliente ya mandó. GET /media/:id (y GET /media/by-key) devuelve una URL firmada, con scope media:read. El paso a paso está en descargar media y en enviar foto, PDF y audio.

Campañas

/api/v2 no monta un router de campañas. Existen en la API interna del panel. Por la pública, muchos avisos juntos son POST /messages/batch (hasta 100, una sola request, prioridad de campaña para no pisar el chat). No es el programador ni el segmento del panel. El lote está en mensajes en lote.

Reacciones: la página dice que no, el worker las manda

Limitaciones escribe que las reacciones salientes no están soportadas por API. El schema de POST /messages acepta type: "reaction" (reaction.message_id es el wamid, reaction.emoji es el emoji, y "" la saca). El worker, en el caso reaction, llama a sendReaction. Si la ventana está cerrada, ese POST no se encola: responde 403 SERVICE_WINDOW_EXPIRED, igual que un texto.

Donde las dos fuentes no coinciden, el envío que existe es el del código. El pedido está en cómo reaccionar. No uses la página de limitaciones para borrar esa ruta.

Webhooks: cuatro eventos, sin el de la plantilla

El catálogo entrega message.received, message.status_changed, conversation.created y contact.created. No hay template.approved ni template.rejected. Mientras Meta revisa, el estado se vuelve a leer:

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

Cada GET cuenta para el cupo de la cuenta. No hagas un loop cerrado. El alta, la firma y POST /webhooks/:id/test están en gestionar webhooks y en webhooks en Node y Python.

Otras dos notas de esa misma página, para no descubrirlas en producción:

  • POST /webhooks/:id/replay/:deliveryId reenvía un evento sintético con el mismo nombre. El payload original no se guarda verbatim (queda el hash). Tu receptor tiene que ser idempotente sobre data.id.
  • No hay WebSocket público. Si necesitás latencia por debajo del segundo, no está en esta API.

La ventana, sin un atajo

No existe GET /contacts/:id/can-send-text. La fecha está en serviceWindowExpiresAt, dentro de GET /conversations/:id y del listado. Limitaciones dice que la leas en GET /conversations/by-phone/:phone. Ese JSON no trae el campo: devuelve conversationId, contactName y contactPhone. resolve tampoco. Cómo decidir texto o plantilla está en serviceWindowExpiresAt.

120 por minuto, y los 80 de Meta

Limitaciones dice 120 req/min por API key, y que para cupos independientes hacen falta keys distintas. El limitador de /api/v2 arma la clave v2: más el id de la cuenta. Todas las keys de esa cuenta comparten los 120. La página que coincide con el handler es rate limits. El 429, el Retry-After y el Idempotency-Key están en rate limits y reintentos y en idempotencia y scopes.

Los 80 mensajes por segundo por número están anotados en la misma página de limitaciones como límite de Meta, no como otro contador de Waspy. No los busques en el 429 de la API.

503 de Cloud Run y 5xx de la app

Un error de la aplicación, desde abril de 2026, sale como JSON: { "error": { "code": "INTERNAL_ERROR", "message": "Internal server error" } }. Un código interno de Postgres no viaja en esa respuesta.

Cuando Cloud Run rota una instancia o hace cold start, el 503 puede venir con Content-Type: text/html, sin ese sobre. Reintentá el HTML. Leé el mensaje del JSON. En POST /messages, el reintento lleva el mismo Idempotency-Key. La página sugiere esperas de 1, 2, 4 y 8 segundos, con jitter, y una alerta después de 4 o 5 intentos.

Qué sí podés armar hoy

Account, channels, contacts, conversations (lectura, typing, marcar leído), messages (incluido origin para el handoff), templates en lectura, media en descarga, y webhooks con alta, deliveries, rotación de secreto, test y replay. El índice está al final de limitaciones.

Si el hueco te frena la integración, el contacto está en waspytech.com. Para probar la clave con tu número, el registro son 10 días sin tarjeta.

Tu equipo atendiendo por WhatsApp en minutos

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