Crear y rotar una API key de Waspy: scopes, wspy_ y lastUsedAt
La API key de Waspy se crea en Configuración → Claves de API, empieza con wspy_ y se muestra una sola vez. Se usa como Bearer en /api/v2. Crear y revocar keys no está en /api/v2.
Respuesta corta: la API key se crea en el panel, Configuración → Integraciones → Claves de API (la guía lo llama Configuración → API Keys: es la misma pantalla). El secreto empieza con wspy_ y se muestra una sola vez. Para llamar a la API va en Authorization: Bearer wspy_... contra https://api.waspytech.com/api/v2. No hay alta, edición ni revocación de keys en /api/v2. Eso lo hace un humano owner, admin o super admin. Una key no puede crear otra.
El formato del header está en autenticación y la tabla de permisos en scopes. Qué ruta pide cada scope está en idempotencia y scopes. La clave entra en Scale y Enterprise: la API y Planes.
Dónde se crea, y quién puede
En el panel: Configuración → Integraciones → Claves de API → Crear clave. El nombre es obligatorio (hasta 100 caracteres). La descripción y la fecha de expiración son opcionales. El selector dice “dejar vacío = acceso completo”. Al confirmar, la pantalla avisa que esa clave no se va a volver a mostrar.
Por debajo, el panel pega a /api/v1/api-keys con la sesión de la persona, no con wspy_. El hook assertCanManageApiKeys corta dos casos:
| Quién llama | Respuesta |
|---|---|
Authorization: Bearer wspy_... | 403 FORBIDDEN. Mensaje: API keys cannot manage API keys — use the Waspy panel |
| Sesión de un rol que no es owner, admin ni super admin | 403 FORBIDDEN. Mensaje: Only admins can manage API keys, current role: y el rol |
| Owner, admin o super admin | Sigue |
api_key está tratado como admin en otras rutas, y por eso esta queda aparte: una key con scopes chicos no puede fabricarse otra sin restricciones.
Qué rutas existen (y cuáles no)
Estas son las de la sesión humana. Ninguna está bajo /api/v2.
| Método | Ruta | Qué hace |
|---|---|---|
GET | /api/v1/api-keys | Lista las de la cuenta. No devuelve el secreto |
POST | /api/v1/api-keys | Crea. El 201 trae data.key (una vez) y data.apiKey |
PATCH | /api/v1/api-keys/:id | Cambia nombre, descripción, permissions o expiresAt. No cambia el secreto |
POST | /api/v1/api-keys/:id/revoke | Revoca (baja lógica) |
DELETE | /api/v1/api-keys/:id | Lo mismo que revocar. Responde { data: { id } }. No borra la fila |
PATCH o un DELETE de keys en /api/v2 no existe. Rotar no es un PATCH del mismo id: es crear otra key, cambiar el secreto en el servidor y revocar la anterior.
El POST acepta name, description, permissions, expiresAt (fecha futura), expiresInDays (entero de 1 a 365, si no mandás expiresAt) y allowedPhoneNumberIds. El diálogo del panel manda nombre, descripción, permisos y expiresAt. No manda la lista de números: desde esa pantalla la key queda para todos los números de la cuenta. Si un cliente de la ruta manda UUIDs, cada uno tiene que ser un número de esa cuenta. Si falta uno, 400 y el texto One or more allowedPhoneNumberIds do not belong to this tenant.
Un permiso que no está en la lista es 400: Invalid permission: y la lista válida. Una key ya revocada no se edita: 400 Cannot update a revoked API key. Revocar dos veces: 400 API key is already revoked.
Cómo se ve en la lista
Cada ítem trae id, name, description, keyPrefix, permissions, allowedPhoneNumberIds, createdBy, isActive, expiresAt, lastUsedAt, revokedAt, createdAt y status.
| Campo | Qué significa |
|---|---|
keyPrefix | Los primeros 12 caracteres de wspy_ más el azar. El panel lo muestra seguido de asteriscos |
permissions | Los scopes marcados. Array vacío = acceso completo |
allowedPhoneNumberIds | Vacío = todos los números. Con UUIDs, solo esos |
expiresAt | null si no vence. Si la fecha ya pasó, el estado pasa a expirada |
lastUsedAt | Última autenticación con esa key, o null si nunca se usó |
status | active, expired o revoked |
isActive es falso o hay revokedAt, es revoked. Si no, y expiresAt ya pasó, es expired. El resto es active. En el panel, las que no están activas quedan en “Claves inactivas”.
lastUsedAt se actualiza cuando el Bearer wspy_ autentica un pedido de la API o del conector MCP. Es fire-and-forget: la respuesta no espera a que la fecha quede escrita. Sirve para ver una key olvidada. No es un contador de mensajes.
Cómo se usa
El secreto es wspy_ más 32 bytes en hexadecimal. Waspy guarda el hash, no el texto. La página de autenticación muestra un código INVALID_API_KEY. El servidor, hoy, responde 401 UNAUTHORIZED con uno de estos mensajes: Invalid API key, API key has been revoked o API key expired.
curl -sS https://api.waspytech.com/api/v2/account \
-H "Authorization: Bearer $WASPY_API_KEY"
Ese GET pide account:read. La base del resto es https://api.waspytech.com/api/v2. No pegues la key en el frontend ni en el repo.
Scopes reales
Si no marcás ninguno, la key puede lo que la API permite. Si marcás una lista, solo esas rutas. templates:write no está: crear una plantilla y mandarla a Meta es el conector MCP, en crear plantilla por MCP.
| Scope | Para qué |
|---|---|
messages:read / messages:write | Leer un mensaje / POST /messages y el lote |
contacts:read / contacts:write | Leer contactos / crear y editar |
conversations:read / conversations:write | Leer chats / actualizar, leído, typing |
templates:read | GET /templates, por id y por nombre. No crea |
channels:read | GET /channels |
account:read | GET /account |
media:read / media:write | Bajar media / media:write figura, y subir por POST /media no está expuesto |
webhooks:read / webhooks:write | Leer suscripciones y entregas / crear, probar, reenviar |
social:read | GET /api/v2/social (posts, comentarios, cuenta de IG/FB) |
social:read está en el servidor y en el selector del panel. La página de scopes todavía no lo lista. El detalle de cada ruta está en la nota de scopes.
Cómo rotar sin downtime de más
No hay un “rotar” que conserve el id y cambie el secreto.
- Creá una key nueva, con el mismo nombre claro (“ERP despachos”) y los mismos scopes mínimos. No la dejes vacía “para que ande”.
- Poné el secreto nuevo en el servidor (variable de entorno o secrets manager). Un pedido de prueba a
GET /api/v2/account. - Revocá la vieja en el panel (el botón llama a
POST /api/v1/api-keys/:id/revoke). Desde ese momento el Bearer viejo responde 401. - Mirá
lastUsedAtde la nueva. Si sigue en null, la integración todavía no la tomó.
Una key por integración. Si se filtra la del ERP, revocás esa y no la de los reportes. La de reportes puede ser solo conversations:read, messages:read, contacts:read y templates:read. La de avisos, messages:write y templates:read. El webhook que escucha estados es otra, con webhooks:write, y está en gestionar webhooks.
Plan y precio de los mensajes
La clave no es el precio de Meta. Waspy arranca en US$70 por mes y la API pública se habilita en Scale (US$150) y Enterprise. Diez días sin tarjeta, en el registro. Meta factura aparte, sin markup: en Argentina, desde el 1 de octubre de 2026, marketing ARS 89,56 (~US$0,0618) y utilidad o servicio (después de 1.000 por número y por mes) ARS 37,68 (~US$0,026). Fuentes: rate card y precios de la plataforma. El desglose está en precios de la API.
La ayuda corta del panel está en crear una API key.
