API de Waspy vs Cloud API directa de Meta: qué cambia para desarrolladores (2026)
Waspy expone REST en /api/v2 (mensajes, plantillas de solo lectura, contactos, bandeja, webhooks, canales y descarga de media). Integrar Graph directo es armar inbox, webhooks y Embedded Signup. Meta factura los mensajes; Waspy no suma markup.
Respuesta corta: integrar la Cloud API directo es hablarle a Graph: webhooks de Meta, tokens, plantillas, inbox y Embedded Signup los armás vos. Con Waspy tu sistema habla con https://api.waspytech.com/api/v2 (Authorization: Bearer wspy_...) y el equipo sigue en la bandeja. Waspy es Tech Provider: Meta le factura los mensajes al negocio y el plan no suma markup. La clave pública está en Scale (US$150 por mes) y Enterprise.
La referencia está en docs.waspytech.com. Lo que la v2 no hace está en limitaciones. El cruce de producto, sin el detalle de endpoints, está en WhatsApp Cloud API.
Quién cobra qué
| API de Waspy | Cloud API directa | |
|---|---|---|
| Plataforma | Plan. La API entra en Scale (US$150) y Enterprise. 10 días sin tarjeta | Sin abono de un proveedor. El costo es el equipo que arma inbox, webhooks y el alta |
| Mensajes de Meta | Los factura Meta, a tu cuenta. Waspy no suma un porcentaje | Los factura Meta si integrás vos. Un BSP puede facturártelos con recargo |
| Inbox del equipo | Incluido. Un POST de tu sistema aparece en la bandeja | Lo construís |
| Coexistencia (app + API) | Alta en el panel: Canales → WhatsApp → Continuar con Facebook | Embedded Signup lo implementás en tu app |
| Tiendanube | Integración nativa: el pedido se ve en el chat | La conectás vos |
Qué llama tu backend
Base https://api.waspytech.com/api/v2. Scope entre paréntesis. Una clave vieja sin lista de scopes entra a todo.
| Para | Método | Scope |
|---|---|---|
| Números conectados | GET /channels | channels:read |
| Mandar texto, media, plantilla, interactivo o reacción | POST /messages | messages:write |
| Ver si Meta aprobó la plantilla | GET /templates | templates:read |
| Contactos | GET /contacts, POST /contacts, PATCH /contacts/:id | contacts:read / contacts:write |
| Bandeja | GET /conversations | conversations:read |
| Eventos a tu URL | POST /webhooks | webhooks:write |
| Bajar un archivo que mandó el cliente | GET /media/:id | media:read |
phoneNumberId del POST es el id (UUID) que devuelve GET /channels. No es el id de Meta. Cómo no mezclarlos está en consultar canales.
curl -sS https://api.waspytech.com/api/v2/channels \
-H "Authorization: Bearer $WASPY_API_KEY"
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-texto" \
-d '{
"phoneNumberId": "CHANNEL_UUID",
"to": "+5491126032641",
"type": "text",
"text": { "body": "Tu pedido 1847 ya está en preparación." }
}'
La respuesta 201 trae status: "queued". El texto libre exige la ventana de 24 horas. Si está cerrada, es 403 SERVICE_WINDOW_EXPIRED: ahí va una plantilla, como en enviar plantilla. El canal que no está active es 403 CHANNEL_NOT_CONNECTED.
Listar solo las aprobadas (el filtro va en minúscula):
curl -sS "https://api.waspytech.com/api/v2/templates?status=approved&pageSize=50" \
-H "Authorization: Bearer $WASPY_API_KEY"
Un archivo que mandó el cliente se baja con el mediaId del mensaje. La URL firmada caduca: se vuelve a pedir.
curl -sS https://api.waspytech.com/api/v2/media/MEDIA_UUID \
-H "Authorization: Bearer $WASPY_API_KEY"
Los eventos a tu servidor son cuatro: message.received, message.status_changed, conversation.created, contact.created. La firma va en X-Waspy-Signature. El alta y los reintentos están en gestionar webhooks.
curl -sS -X POST https://api.waspytech.com/api/v2/webhooks \
-H "Authorization: Bearer $WASPY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://tu-sistema.example.com/waspy",
"events": ["message.received", "message.status_changed"]
}'
El cupo es 120 pedidos por minuto por cuenta, compartido por todas las claves. El middleware usa la cuenta, no la clave. Un 429 trae Retry-After. El detalle está en rate limits.
Lo que la v2 no hace
| Querés | Dónde está |
|---|---|
| Crear, editar o borrar una plantilla | Panel de Waspy o WhatsApp Manager. No hay POST /templates ni PATCH. El MCP sí tiene create_template (templates:write), y eso no escribe al cliente |
| Subir un archivo | No está en la v2. En el mensaje va link (URL pública) o un id de media que ya tenga Meta |
| Disparar una campaña | El panel. No hay endpoints de campañas en la v2 |
Un webhook template.approved | No existe. Se vuelve a consultar GET /templates |
POST /messages acepta type: "reaction" y el worker llama al envío de Meta con message_id y emoji. La referencia de messages es la que manda. Sigue siendo un mensaje de sesión: sin ventana abierta, no sale. Un emoji vacío saca la reacción anterior.
El filtro de contactos que lee la ruta es tags (separados por coma), no tag. La página de contactos todavía muestra tag.
Qué te ahorrás frente a Graph
Directo a Meta, el trabajo que no es “mandar un JSON” es este:
- Verificar el webhook de la app (el challenge) y validar la firma de cada aviso.
- Guardar y rotar el token del número. Si se vence, se corta el envío.
- Dar de alta clientes con Embedded Signup, incluida la coexistencia si el número ya vive en la app. El flujo vigente es el v4. El detalle de producto está en coexistencia.
- Crear y perseguir la aprobación de plantillas en WhatsApp Manager.
- Armar la bandeja para que el equipo no atienda en una tabla.
Eso no desaparece porque uses Waspy: desaparece de tu servicio. Tu código manda el mensaje, lee el estado y, si hace falta, reacciona al webhook de Waspy. La persona del equipo sigue en el inbox. Waspy no contesta esos chats solo. Si conectás un modelo de afuera, es tu integración (API o MCP), y el envío al cliente lo confirma alguien.
Otras fichas de proveedores están en comparativas. Los planes, en Planes. La página de la API, en funcionalidades. La cuenta de prueba, 10 días y sin tarjeta, se abre en el registro.
