GET /conversations permiso: messages
Tu bandeja de entrada.
La caja de búsqueda va en `search` y busca en los CONTACTOS: nombre, correo y teléfono. Se busca ahí y no en la conversación porque la conversación no guarda ni el nombre ni el número, solo a quién pertenece.
Parámetros
search string — Nombre, correo o teléfono del contacto
status string — abierta | cerrada
modo string — ia | humano
canal string — cloud | baileys
funnelId string — Solo las de un embudo
estadoId string — Una etapa concreta: es una columna del tablero
contactId string — La conversación de esta persona, esté donde esté
scope string — sin_asignar: la cola de lo que espera a alguien
expand string — contacto,ultimoMensaje — la bandeja en UNA petición
page number — Página (por defecto 1)
limit number — Máximo 100
curl "https://apis.sds-soft.co:5503/api/public/v1/conversations?search=marta&status=abierta&expand=contacto,ultimoMensaje" \
-H "Authorization: Bearer bpk_live_tu_llave"
GET /conversations/:id/messages permiso: messages
El historial de una conversación.
curl https://apis.sds-soft.co:5503/api/public/v1/conversations/68a1f.../messages \
-H "Authorization: Bearer bpk_live_tu_llave"
POST /conversations/:id/messages permiso: messages
Responder en una conversación abierta.
Solo funciona dentro de la ventana de 24 horas de Meta: si tu cliente no te escribe hace más de un día, WhatsApp no entrega este mensaje y no avisa de nada. Para esos casos está el envío por plantilla. Manda tu propia referencia en `clientRef` y un reintento no duplica: responde 200 con el mensaje de antes en vez de 201 con uno nuevo. Los tipos estructurados (botones, lista, ubicación, contactos) van en `payload`.
Cuerpo
{ "contentType": "texto", "texto": "Tu pedido ya salió", "clientRef": "pedido-8842" }
curl -X POST https://apis.sds-soft.co:5503/api/public/v1/conversations/68a1f.../messages \
-H "Authorization: Bearer bpk_live_tu_llave" \
-H "Content-Type: application/json" \
-d '{"contentType":"texto","texto":"Tu pedido ya salió","clientRef":"pedido-8842"}'
POST /conversations/:id/close permiso: messages
Cerrar una conversación atendida.
curl -X POST https://apis.sds-soft.co:5503/api/public/v1/conversations/68a1f.../close \
-H "Authorization: Bearer bpk_live_tu_llave"
POST /conversations/:id/reopen permiso: messages
Volver a abrir una que se cerró.
Reabrir NO le manda nada al cliente: solo devuelve la conversación a la bandeja. Si la ventana de 24 horas ya se cerró, para escribirle sigue haciendo falta una plantilla.
curl -X POST https://apis.sds-soft.co:5503/api/public/v1/conversations/68a1f.../reopen \
-H "Authorization: Bearer bpk_live_tu_llave"
GET /conversations/:id permiso: messages
Una conversación con su contacto, su etapa y quién la atiende.
curl https://apis.sds-soft.co:5503/api/public/v1/conversations/68a1f... \
-H "Authorization: Bearer bpk_live_tu_llave"
GET /conversations/queue permiso: messages
La cola: lo que espera a que alguien lo atienda.
Son las conversaciones que pidieron una persona y todavía no tienen a nadie asignado. Es la lista que mira quien coordina para repartir, distinta de la bandeja completa.
curl https://apis.sds-soft.co:5503/api/public/v1/conversations/queue \
-H "Authorization: Bearer bpk_live_tu_llave"
POST /conversations/:id/read permiso: messages
Marcar como leída.
Pone a cero el contador de sin leer de ESA conversación. No manda el doble check azul al cliente: eso lo decide la línea, no esta llamada.
curl -X POST https://apis.sds-soft.co:5503/api/public/v1/conversations/68a1f.../read \
-H "Authorization: Bearer bpk_live_tu_llave"
POST /conversations/:id/pedir-numero permiso: messages
Pedirle al cliente su número de teléfono.
WhatsApp ya no siempre entrega el número de quien te escribe. **No hay forma de averiguarlo**: lo único que se puede hacer es pedírselo, y esto le muestra un botón para que lo comparta si quiere. Si acepta, su número queda guardado en el contacto y lo ves en `GET /contacts/:id`. El texto es opcional; el botón lo pone WhatsApp y no se puede cambiar. Solo para líneas de WhatsApp Api Cloud, y devuelve un 400 si ya tienes su número.
Cuerpo
{ "texto": "Para enviarte la cotización, ¿nos compartes tu número?" }
curl -X POST https://apis.sds-soft.co:5503/api/public/v1/conversations/68a1f.../pedir-numero \
-H "Authorization: Bearer bpk_live_tu_llave" \
-H "Content-Type: application/json" \
-d '{"texto":"Para enviarte la cotización, ¿nos compartes tu número?"}'
POST /conversations/:id/notes permiso: messages
Dejar una nota interna.
La nota queda en el historial para tu equipo. «El cliente no la ve nunca.»
Cuerpo
{ "texto": "Pidió factura a nombre de la empresa" }
curl -X POST https://apis.sds-soft.co:5503/api/public/v1/conversations/68a1f.../notes \
-H "Authorization: Bearer bpk_live_tu_llave" \
-H "Content-Type: application/json" \
-d '{"texto":"Pidió factura a nombre de la empresa"}'
PUT /conversations/:id/mode permiso: messages
Pasar la conversación al asistente o a una persona.
Con `humano` el asistente deja de contestar en esa conversación hasta que la devuelvas a `ia`. Es lo mismo que el interruptor del chat en el CRM.
Cuerpo
{ "modo": "humano" }
curl -X PUT https://apis.sds-soft.co:5503/api/public/v1/conversations/68a1f.../mode \
-H "Authorization: Bearer bpk_live_tu_llave" \
-H "Content-Type: application/json" \
-d '{"modo":"humano"}'
PUT /conversations/:id/state permiso: messages
Moverla de etapa en el embudo.
El `stateId` sale de `GET /funnels`: cada embudo trae sus etapas con su identificador. No se mueve por nombre, porque dos embudos pueden tener etapas que se llamen igual.
Cuerpo
{ "stateId": "6a2d733f0e1b4c5a9d8e7f60" }
curl -X PUT https://apis.sds-soft.co:5503/api/public/v1/conversations/68a1f.../state \
-H "Authorization: Bearer bpk_live_tu_llave" \
-H "Content-Type: application/json" \
-d '{"stateId":"6a2d733f0e1b4c5a9d8e7f60"}'
PUT /conversations/:id/group-ia permiso: messages
Encender o apagar el asistente en un GRUPO de WhatsApp.
Solo aplica a conversaciones de grupo. Un grupo con el asistente encendido contesta a todo el mundo que escriba dentro, así que viene apagado salvo que lo enciendas.
Cuerpo
{ "activa": true }
curl -X PUT https://apis.sds-soft.co:5503/api/public/v1/conversations/68a1f.../group-ia \
-H "Authorization: Bearer bpk_live_tu_llave" \
-H "Content-Type: application/json" \
-d '{"activa":true}'
POST /messages permiso: messages
Mandar a un número sin saber si ya existe la conversación.
Si esa persona ya te escribió, entra en su conversación; si no existe, la abre. ⚠️ Fuera de la ventana de 24 horas esto NO entrega: para eso está `POST /outreach` con plantilla. Con `clientRef` un reintento no duplica: la respuesta trae `repetido: true` cuando esa referencia ya se había mandado.
Cuerpo
{ "to": "573001234567", "contentType": "texto", "texto": "Tu pedido ya salió", "clientRef": "pedido-8842" }
curl -X POST https://apis.sds-soft.co:5503/api/public/v1/messages \
-H "Authorization: Bearer bpk_live_tu_llave" \
-H "Content-Type: application/json" \
-d '{"to":"573001234567","contentType":"texto","texto":"Tu pedido ya salió","clientRef":"pedido-8842"}'
POST /media permiso: messages
Subir un archivo y quedarte con su `mediaRef`.
Va en base64 para no obligarte a armar un multipart. El `mediaRef` que devuelve es lo que se manda luego como adjunto de un mensaje, o lo que se indexa en la base de conocimiento.
Cuerpo
{ "contenidoBase64": "JVBERi0xLjQK...", "filename": "catalogo.pdf", "mimetype": "application/pdf" }
curl -X POST https://apis.sds-soft.co:5503/api/public/v1/media \
-H "Authorization: Bearer bpk_live_tu_llave" \
-H "Content-Type: application/json" \
-d '{"contenidoBase64":"JVBERi0xLjQK...","filename":"catalogo.pdf","mimetype":"application/pdf"}'
GET /media/:ref permiso: messages
Una dirección temporal para descargar un adjunto.
Los mensajes con adjunto traen su `mediaRef`, no la dirección: los enlaces caducan y uno guardado en tu base deja de servir. Se pide en el momento de enseñarlo.
curl https://apis.sds-soft.co:5503/api/public/v1/media/6a61f8c2d4e5b6a7c8d9e0f1 \
-H "Authorization: Bearer bpk_live_tu_llave"