Mensajes

Envío y consulta de mensajes (texto, media, plantillas, interactivos, location, contactos).

Base path: /organizations/:orgId/messages·10 endpoints·Source: mosend-wb-backend/src/modules/messages/messages.controller.ts
POST/organizations/:orgId/messages
bearer

Envía un mensaje de WhatsApp (texto, media o plantilla) a un contacto.

Path params

  • orgIdstringrequerido

Body (JSON)

  • phoneNumberIdstring · uuidrequerido
  • tostringrequerido

    Número del destinatario en E.164. Aceptamos con o sin `+` para ser tolerantes con integraciones que usen formato internacional clásico (`+573001234567`) — la normalización quita el `+` antes de validar para que toda la app maneje un único formato (`573001234567`). Sin esto, un mismo número enviado a veces con `+` y a veces sin él creaba contactos y conversaciones duplicados (cada uno con `waId` distinto en la BD). El `@Matches` final exige que después de la normalización solo queden dígitos.

  • typestringrequerido
    texttemplateimagevideoaudiodocumentstickerlocationcontactsinteractivereaction
  • payloadobject

    Payload Meta-passthrough. Modo "experto": el cliente arma manualmente la estructura completa según WhatsApp Cloud API (`{ name, language, components: [...] }` para templates, `{ body }` para text, etc). Para `type === 'template'`, ahora es OPCIONAL. Si no se provee, hay que mandar `templateId` o `templateName` + `variables` y Mosend arma el payload internamente. Para los demás `type`, sigue siendo requerido.

  • templateIdstring · uuid

    Modo simplificado para `type === 'template'`. UUID de la plantilla en Mosend (no el `metaTemplateId`). Útil cuando el cliente ya tiene la plantilla creada desde el dashboard y solo quiere enviarla.

  • templateNamestring

    Alternativa a `templateId`: nombre de la plantilla aprobada en Meta. Cuando hay varias plantillas con el mismo nombre en distintos idiomas, Meta resuelve por `templateLanguage`. Para WABAs con múltiples WABAs, se resuelve a partir del `phoneNumberId`.

  • templateLanguagestring

    Código de idioma para `templateName`. Default = idioma de la primera plantilla aprobada con ese nombre en la WABA del phoneNumberId.

  • variablesobject

    Variables que rellenan los `{{N}}` de la plantilla. Dos shapes posibles: - Array: solo body posicional → `["Juan", "12345"]` rellena `{{1}}` con "Juan" y `{{2}}` con "12345". - Objeto: para plantillas con header media o botones URL dinámicos: `{ body: ["Juan"], header: { type: "image", link: "..." }, buttons: [{ index: 0, value: "ord-456" }] }` El backend valida que el conteo de variables coincida con la plantilla.

  • clientIdstring
  • replyToMessageIdstring · uuid

    Si se envía como respuesta a otro mensaje (cita visible en WhatsApp del destinatario), pasar aquí el UUID del Message original. El backend resuelve su `metaMessageId` y lo manda a Meta como `context.message_id`.

Respuestas

  • 201
curl -X POST 'https://api.mosend.dev/organizations/a1b2c3d4-1234-5678-9abc-def012345678/messages' \
  -H 'X-Api-Key: mk_live_<prefix>.<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"phoneNumberId": "00000000-0000-0000-0000-000000000000","to": "<to>","type": "text","payload": {},"templateId": "00000000-0000-0000-0000-000000000000","templateName": "<templateName>","templateLanguage": "<templateLanguage>","variables": {},"clientId": "00000000-0000-0000-0000-000000000000","replyToMessageId": "00000000-0000-0000-0000-000000000000"}'
Response · 200
{
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "phoneNumberId": "00000000-0000-0000-0000-000000000000",
    "to": "+573000000000",
    "type": "text",
    "payload": {
      "body": "Hola desde Mosend"
    }
  },
  "timestamp": "2026-05-01T03:42:18.123Z"
}
POST/organizations/:orgId/messages/product
bearer

Envía un mensaje de producto de WhatsApp Commerce (single / multi / catálogo).

Path params

  • orgIdstringrequerido

Body (JSON)

  • phoneNumberIdstring · uuidrequerido
  • tostringrequerido
  • catalogIdstringrequerido

    ID del catálogo conectado a la WABA.

  • bodyTextstring
  • footerTextstring
  • headerTextstring
  • productRetailerIdstring

    SPM: un solo producto.

  • productsstring[]

    MPM (simple): lista plana de SKUs → una sección.

  • sectionsProductSectionDto[]

    MPM (con secciones): título + SKUs por sección.

  • catalogMessageboolean

    Catalog message: muestra el catálogo completo.

  • thumbnailProductRetailerIdstring
  • replyToMessageIdstring · uuid

    Cita a otro mensaje (context).

Respuestas

  • 201
curl -X POST 'https://api.mosend.dev/organizations/a1b2c3d4-1234-5678-9abc-def012345678/messages/product' \
  -H 'X-Api-Key: mk_live_<prefix>.<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"phoneNumberId": "00000000-0000-0000-0000-000000000000","to": "<to>","catalogId": "00000000-0000-0000-0000-000000000000","bodyText": "<bodyText>","footerText": "<footerText>","headerText": "<headerText>","productRetailerId": "00000000-0000-0000-0000-000000000000","products": [],"sections": [],"catalogMessage": true,"thumbnailProductRetailerId": "00000000-0000-0000-0000-000000000000","replyToMessageId": "00000000-0000-0000-0000-000000000000"}'
Response · 200
{
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "description": "string"
  },
  "timestamp": "2026-05-01T03:42:18.123Z"
}
POST/organizations/:orgId/messages/interactive
bearer

Envía un mensaje de servicio interactivo (lista / botón CTA URL / pedir ubicación).

Path params

  • orgIdstringrequerido

Body (JSON)

  • phoneNumberIdstring · uuidrequerido
  • tostringrequerido
  • kindstringrequerido
    listcta_urllocation_requestrequest_contact_info
  • bodyTextstring
  • headerTextstring
  • footerTextstring
  • buttonTextstring
  • sectionsListSectionDto[]
  • displayTextstring
  • urlstring
  • replyToMessageIdstring · uuid

Respuestas

  • 201
curl -X POST 'https://api.mosend.dev/organizations/a1b2c3d4-1234-5678-9abc-def012345678/messages/interactive' \
  -H 'X-Api-Key: mk_live_<prefix>.<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"phoneNumberId": "00000000-0000-0000-0000-000000000000","to": "<to>","kind": "list","bodyText": "<bodyText>","headerText": "<headerText>","footerText": "<footerText>","buttonText": "<buttonText>","sections": [],"displayText": "<displayText>","url": "https://tu-app.com/endpoint","replyToMessageId": "00000000-0000-0000-0000-000000000000"}'
Response · 200
{
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "description": "string"
  },
  "timestamp": "2026-05-01T03:42:18.123Z"
}
POST/organizations/:orgId/messages/flow
bearer

Envía un mensaje de WhatsApp Flow (formulario nativo).

Path params

  • orgIdstringrequerido

Body (JSON)

  • phoneNumberIdstring · uuidrequerido
  • tostringrequerido
  • flowIdstring · uuidrequerido

    Id local del WhatsAppFlow (nuestra tabla).

  • bodyTextstringrequerido
  • ctaTextstringrequerido
  • headerTextstring
  • footerTextstring
  • screenstring
  • dataobject
  • flowActionstring
    navigatedata_exchange
  • replyToMessageIdstring · uuid

Respuestas

  • 201
curl -X POST 'https://api.mosend.dev/organizations/a1b2c3d4-1234-5678-9abc-def012345678/messages/flow' \
  -H 'X-Api-Key: mk_live_<prefix>.<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"phoneNumberId": "00000000-0000-0000-0000-000000000000","to": "<to>","flowId": "00000000-0000-0000-0000-000000000000","bodyText": "<bodyText>","ctaText": "<ctaText>","headerText": "<headerText>","footerText": "<footerText>","screen": "<screen>","data": {},"flowAction": "navigate","replyToMessageId": "00000000-0000-0000-0000-000000000000"}'
Response · 200
{
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "Onboarding nuevo cliente",
    "steps": []
  },
  "timestamp": "2026-05-01T03:42:18.123Z"
}
POST/organizations/:orgId/messages/carousel
bearer

Envía un carrusel multimedia interactivo (hasta 10 tarjetas).

Path params

  • orgIdstringrequerido

Body (JSON)

  • phoneNumberIdstring · uuidrequerido
  • tostringrequerido
  • bodyTextstringrequerido
  • cardsCarouselCardDto[]requerido
  • replyToMessageIdstring · uuid

Respuestas

  • 201
curl -X POST 'https://api.mosend.dev/organizations/a1b2c3d4-1234-5678-9abc-def012345678/messages/carousel' \
  -H 'X-Api-Key: mk_live_<prefix>.<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"phoneNumberId": "00000000-0000-0000-0000-000000000000","to": "<to>","bodyText": "<bodyText>","cards": [],"replyToMessageId": "00000000-0000-0000-0000-000000000000"}'
Response · 200
{
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "description": "string"
  },
  "timestamp": "2026-05-01T03:42:18.123Z"
}
PATCH/organizations/:orgId/messages/:messageId/edit
bearer

Edita el texto de un mensaje ya enviado.

Path params

  • orgIdstringrequerido
  • messageIdstringrequerido

Body (JSON)

  • bodystringrequerido

Respuestas

  • 200
curl -X PATCH 'https://api.mosend.dev/organizations/a1b2c3d4-1234-5678-9abc-def012345678/messages/00000000-0000-0000-0000-000000000000/edit' \
  -H 'X-Api-Key: mk_live_<prefix>.<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"body": "<body>"}'
Response · 200
{
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "phoneNumberId": "00000000-0000-0000-0000-000000000000",
    "to": "+573000000000",
    "type": "text",
    "payload": {
      "body": "Hola desde Mosend"
    }
  },
  "timestamp": "2026-05-01T03:42:18.123Z"
}
DELETE/organizations/:orgId/messages/:messageId
bearer

Elimina un mensaje (lo oculta del inbox como tombstone).

Path params

  • orgIdstringrequerido
  • messageIdstringrequerido

Respuestas

  • 200
curl -X DELETE 'https://api.mosend.dev/organizations/a1b2c3d4-1234-5678-9abc-def012345678/messages/00000000-0000-0000-0000-000000000000' \
  -H 'X-Api-Key: mk_live_<prefix>.<secret>'
Response · 200
{
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "createdAt": "2026-05-01T03:42:18.123Z"
  },
  "timestamp": "2026-05-01T03:42:18.123Z"
}
POST/organizations/:orgId/messages/:messageId/restore
bearer

Revierte el tombstone de un mensaje y lo vuelve a mostrar en el inbox.

Path params

  • orgIdstringrequerido
  • messageIdstringrequerido

Respuestas

  • 200
curl -X POST 'https://api.mosend.dev/organizations/a1b2c3d4-1234-5678-9abc-def012345678/messages/00000000-0000-0000-0000-000000000000/restore' \
  -H 'X-Api-Key: mk_live_<prefix>.<secret>'
Response · 200
{
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "createdAt": "2026-05-01T03:42:18.123Z"
  },
  "timestamp": "2026-05-01T03:42:18.123Z"
}
POST/organizations/:orgId/messages/upload
bearer

Sube un archivo a Meta como media adjunto y devuelve el mediaId para usar al enviar.

Path params

  • orgIdstringrequerido

Query params

  • phoneNumberIdstringrequerido

Respuestas

  • 201
curl -X POST 'https://api.mosend.dev/organizations/a1b2c3d4-1234-5678-9abc-def012345678/messages/upload' \
  -H 'X-Api-Key: mk_live_<prefix>.<secret>'
Response · 200
{
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "createdAt": "2026-05-01T03:42:18.123Z"
  },
  "timestamp": "2026-05-01T03:42:18.123Z"
}
GET/organizations/:orgId/messages/:messageId/media
bearer

Descarga y proxyea el media de un mensaje (sirve desde caché S3 o desde Meta).

Path params

  • orgIdstringrequerido
  • messageIdstringrequerido

Respuestas

  • 200
curl -X GET 'https://api.mosend.dev/organizations/a1b2c3d4-1234-5678-9abc-def012345678/messages/00000000-0000-0000-0000-000000000000/media' \
  -H 'X-Api-Key: mk_live_<prefix>.<secret>'
Response · 200
{
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "createdAt": "2026-05-01T03:42:18.123Z"
  },
  "timestamp": "2026-05-01T03:42:18.123Z"
}