Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.waspytech.com/llms.txt

Use this file to discover all available pages before exploring further.

POST /messages

Enviar un mensaje de WhatsApp. Soporta texto, imagen, video, audio, documento, template e interactivos. Scope requerido: messages:write

Body

CampoTipoRequeridoDescripción
phoneNumberIdstring (UUID)ID del canal (de GET /channels)
tostringNúmero del destinatario en formato E.164 (+5491126032641)
typestringtext, image, video, audio, document, template, interactive
textobjectSi type=text{ body: string, preview_url?: boolean }
imageobjectSi type=image{ link?: string, id?: string, caption?: string }
videoobjectSi type=video{ link?: string, id?: string, caption?: string }
audioobjectSi type=audio{ link?: string, id?: string }
documentobjectSi type=document{ link?: string, id?: string, filename?: string, caption?: string }
templateobjectSi type=template{ name: string, language: { code: string }, components?: array }

Enviar texto

curl -X POST https://api.waspytech.com/api/v2/messages \
  -H "Authorization: Bearer wspy_..." \
  -H "Content-Type: application/json" \
  -d '{
    "phoneNumberId": "channel-uuid",
    "to": "+5491126032641",
    "type": "text",
    "text": { "body": "Hola! Tu pedido fue despachado." }
  }'
Los mensajes de texto libre requieren una ventana de servicio activa (24hs desde el último mensaje del contacto). Si la ventana expiró, usá un template. Ver Ventana de servicio.

Enviar template

curl -X POST https://api.waspytech.com/api/v2/messages \
  -H "Authorization: Bearer wspy_..." \
  -H "Content-Type: application/json" \
  -d '{
    "phoneNumberId": "channel-uuid",
    "to": "+5491126032641",
    "type": "template",
    "template": {
      "name": "confirmacion_pedido",
      "language": { "code": "es_AR" },
      "components": [
        {
          "type": "body",
          "parameters": [
            { "type": "text", "text": "María" },
            { "type": "text", "text": "#1847" }
          ]
        }
      ]
    }
  }'

Enviar imagen

curl -X POST https://api.waspytech.com/api/v2/messages \
  -H "Authorization: Bearer wspy_..." \
  -H "Content-Type: application/json" \
  -d '{
    "phoneNumberId": "channel-uuid",
    "to": "+5491126032641",
    "type": "image",
    "image": { "link": "https://ejemplo.com/producto.jpg", "caption": "Vista frontal" }
  }'

Response 201

{
  "data": {
    "id": "msg-uuid",
    "conversationId": "conv-uuid",
    "direction": "outbound",
    "type": "text",
    "status": "queued",
    "waMessageId": null,
    "createdAt": "2026-04-13T15:00:00.000Z"
  },
  "meta": { "requestId": "..." }
}
waMessageId es null en el response inicial. El envío a Meta es asíncrono — status: "queued" significa que aceptamos la request y la encolamos. Para obtener el waMessageId real (el wamid.HBgL... de Meta) tenés dos opciones:
  1. Recomendado: suscribite al webhook message.status_changed. Cuando el status pasa a sent, el payload trae waMessageId poblado. Es la forma confiable.
  2. Polling: GET /messages/{data.id} después de 1-2 segundos.
Para correlacionar tu mensaje con el de Meta inmediatamente, guardá el data.id (UUID interno) que sí está disponible al instante.

Idempotencia

Incluí el header Idempotency-Key para evitar envíos duplicados. Ver Idempotencia.
curl -X POST https://api.waspytech.com/api/v2/messages \
  -H "Authorization: Bearer wspy_..." \
  -H "Idempotency-Key: pedido-1847-confirmacion" \
  -H "Content-Type: application/json" \
  -d '{ ... }'

Errores frecuentes

CódigoDescripción
SERVICE_WINDOW_EXPIREDLa ventana de 24hs expiró, usá un template
INVALID_CHANNELEl canal no existe o no pertenece a tu cuenta
CHANNEL_NOT_CONNECTEDEl canal no está conectado
INVALID_MESSAGE_TYPETipo de mensaje no válido
INVALID_PHONENúmero de teléfono con formato inválido

Comportamiento

  • Si el contacto no existe, se crea automáticamente con el número.
  • Si no hay conversación previa, se crea una nueva.
  • El mensaje se encola y se envía de forma asíncrona. El status inicial es queued.
  • Consultá el estado final con GET /messages/:id.

GET /messages/:id

Consultar un mensaje por ID. Útil para verificar el estado de envío. Scope requerido: messages:read
curl https://api.waspytech.com/api/v2/messages/MSG_ID \
  -H "Authorization: Bearer wspy_..."

Response 200

{
  "data": {
    "id": "msg-uuid",
    "conversationId": "conv-uuid",
    "direction": "outbound",
    "type": "text",
    "content": { "text": "Hola! Tu pedido fue despachado." },
    "status": "delivered",
    "waMessageId": "wamid.HBgLNT...",
    "errorCode": null,
    "errorMessage": null,
    "createdAt": "2026-04-13T15:00:00.000Z"
  },
  "meta": { "requestId": "..." }
}
Para entender los estados posibles, ver Estados de mensajes.

POST /messages/:waMessageId/read

Marcar un mensaje entrante como leído por su waMessageId (el mismo que llega en el webhook message.received). Conveniente cuando tenés a mano el waMessageId en lugar del conversationId. Scope requerido: conversations:write
curl -X POST https://api.waspytech.com/api/v2/messages/wamid.HBgLNT.../read \
  -H "Authorization: Bearer wspy_..."
Equivalente a POST /conversations/:id/read — manda el read receipt a Meta y resetea el unreadCount de la conversación padre.
{
  "data": {
    "conversationId": "conv-uuid",
    "markedMessageId": "wamid.HBgLNT...",
    "deliveredToMeta": true
  },
  "meta": { "requestId": "..." }
}
404 si el waMessageId no existe o no es inbound.