Saltar al contenido principal

SDK Node.js — socialdesk-node

El SDK oficial de Socialdesk para Node.js simplifica la integración con la API. Incluye tipado completo en TypeScript y helpers para parsear eventos webhook.

Instalación

npm install socialdesk-node

Inicio rápido

import { WebhookHelper, EventType } from 'socialdesk-node';

// Tu handler de webhook (Express, Lambda, etc.)
async function handleWebhook(body: any) {
const webhook = new WebhookHelper(body);
const client = webhook.createClient();

if (webhook.isEventType(EventType.DirectMessage)) {
// Enviar un hint message al agente
await client.sendHintMessage({
text: 'El cliente preguntó por precios',
message_id: webhook.getMessageId(),
conversation_id: webhook.getConversationId(),
callbacks: [
{ id: 'cb_1', label: 'Enviar cotización', value: 'send_quote' },
],
quick_replies: [
{ text: 'El Plan Básico cuesta $79/mes + IVA.' },
],
});
}
}

WebhookHelper

Clase para parsear y extraer datos de los eventos webhook. Recibe el body completo del evento y expone métodos para acceder a los datos de forma segura sin importar el tipo de evento.

import { WebhookHelper } from 'socialdesk-node';

const webhook = new WebhookHelper(eventBody);

Métodos

MétodoRetornaDescripción
getEventType()EventTypeTipo de evento recibido
getPayload()WebhookPayloadPayload crudo del evento
getAccessToken()stringToken para llamar la API (válido 2 horas)
getChannelInstance()stringID del canal donde ocurrió el evento
getInstanceId()stringID de tu app instance
getSettings<T>()TConfiguración de tu app (parsea el JSON de instance.settings automáticamente)
getConversationId()stringID de la conversación (funciona con cualquier tipo de evento)
getMessageId()stringID del mensaje (funciona con cualquier tipo de evento)
getMessageText()stringTexto del mensaje (funciona con cualquier tipo de evento)
getConversationContext<T>()TContexto completo de la conversación
getApplicationContext<T>()TContexto específico de tu app (context.assistants.{appInstanceId})
isEventType(type)booleanVerifica si el evento es de un tipo específico
createClient(baseURL?)SocialdeskClientCrea un cliente pre-autenticado con el token del evento

SocialdeskClient

Cliente HTTP para llamar los endpoints de la API. La forma recomendada es crearlo desde el WebhookHelper, que lo pre-autentica con el token del evento.

import { SocialdeskClient } from 'socialdesk-node';

// Opción 1: desde el webhook (recomendado)
const client = webhook.createClient();

// Opción 2: manual
const client = new SocialdeskClient('tu_access_token');

sendHintMessage

Envía un hint message visible solo para el agente. Útil para mostrar información contextual, sugerencias de respuesta y acciones rápidas.

await client.sendHintMessage({
text: 'El cliente quiere información de precios',
message_id: webhook.getMessageId(),
conversation_id: webhook.getConversationId(),
callbacks: [
{ id: 'cb_quote', label: 'Enviar cotización', value: 'send_quote' },
],
quick_replies: [
{ text: 'Nuestro plan básico cuesta $79/mes.' },
],
application_context: { intent: 'pricing', step: 1 },
});
ParámetroTipoRequeridoDescripción
textstringNoTexto del hint message
message_idstringID del mensaje al que se responde
conversation_idstringID de la conversación
attachmentsAttachment[]NoArchivos adjuntos
interactionsInteraction[]NoInteracciones (botones, listas)
callbacksCallback[]NoBotones de acción para el agente
quick_repliesQuickReply[]NoRespuestas sugeridas para el agente
application_contextobjectNoDatos que se persisten en el contexto de la conversación

sendDirectMessage

Envía un mensaje directo al participante (requiere permiso de respuestas automáticas).

await client.sendDirectMessage({
text: '¡Hola! Un asesor te atenderá en breve.',
message_id: webhook.getMessageId(),
conversation_id: webhook.getConversationId(),
interactions: [
{
label: 'whatsapp',
config: {
type: 'button',
action: {
buttons: [
{ type: 'reply', reply: { id: 'si', title: 'Sí, por favor' } },
{ type: 'reply', reply: { id: 'no', title: 'No, gracias' } },
],
},
},
},
],
});
ParámetroTipoRequeridoDescripción
textstringNoTexto del mensaje
message_idstringID del mensaje al que se responde
conversation_idstringID de la conversación
attachmentsAttachment[]NoArchivos adjuntos
interactionsInteraction[]NoInteracciones nativas del canal (botones de WhatsApp, etc.)
application_contextobjectNoDatos que se persisten en el contexto de la conversación

sendHSMMessage

Envía un mensaje con plantilla (HSM). Puedes identificar al destinatario con account_contact_id (contacto existente) o contact (contacto nuevo), no ambos.

// Con contacto existente
await client.sendHSMMessage({
channel_id: webhook.getChannelInstance(),
account_contact_id: 'ac_123',
raw_text: 'Hola {{1}}, tu cita es el {{2}}',
parameters: ['María', '25 de marzo'],
external_template_id: 'appointment_v1',
});

// Con contacto nuevo
await client.sendHSMMessage({
channel_id: webhook.getChannelInstance(),
contact: {
account_id: 'acc_001',
first_name: 'María',
phone: '+50688881234',
},
raw_text: 'Hola {{1}}, bienvenida a nuestro servicio.',
parameters: ['María'],
external_template_id: 'welcome_v1',
});

// Envío programado
await client.sendHSMMessage({
channel_id: webhook.getChannelInstance(),
account_contact_id: 'ac_123',
raw_text: 'Recordatorio: tu cita es mañana a las {{1}}',
parameters: ['3:00 PM'],
external_template_id: 'reminder_v1',
send_at: '2026-03-25T08:00:00Z',
});
ParámetroTipoRequeridoDescripción
channel_idstringID del canal de WhatsApp
account_contact_idstringCondicionalID del contacto existente (no usar junto con contact)
contactobjectCondicionalDatos del contacto nuevo (no usar junto con account_contact_id)
contact.account_idstringID de la cuenta
contact.phonestringTeléfono con código de país
contact.first_namestringNoNombre
contact.last_namestringNoApellido
contact.emailstringNoEmail
contact.image_urlstringNoURL de imagen de perfil
raw_textstringTexto de la plantilla con placeholders {{N}}
parametersany[]NoValores para los placeholders
external_template_idstringNoID de la plantilla en el proveedor
assign_entity'USER' | 'TEAM'NoTipo de entidad a asignar
assign_entity_idstringNoID de la entidad a asignar
conversation_idstringNoID de conversación existente
send_atstringNoFecha de envío programado (ISO 8601)

assignConversation

Asigna una conversación a un agente o equipo.

await client.assignConversation({
conversation_id: webhook.getConversationId(),
entity: 'TEAM',
entity_id: 'team_sales',
});
ParámetroTipoRequeridoDescripción
conversation_idstringID de la conversación
account_idstringNoID de la cuenta
entity'USER' | 'TEAM'Tipo de entidad: agente (USER) o equipo (TEAM)
entity_idstringID del agente o equipo
force_assignbooleanNoForzar asignación aunque ya esté asignada (default: false)

addLabel

Agrega una etiqueta a una conversación para segmentarla.

await client.addLabel({
conversation_id: webhook.getConversationId(),
labelKey: 'lead_calificado',
});
ParámetroTipoRequeridoDescripción
conversation_idstringID de la conversación
account_idstringNoID de la cuenta
labelKeystringClave de la etiqueta

Ejemplo completo: Bot con Express

import express from 'express';
import { WebhookHelper, EventType } from 'socialdesk-node';

const app = express();
app.use(express.json());

app.post('/webhook', async (req, res) => {
const webhook = new WebhookHelper(req.body);
const client = webhook.createClient();

if (webhook.isEventType(EventType.DirectMessage)) {
const text = webhook.getMessageText();

if (text.toLowerCase().includes('precio')) {
await client.sendHintMessage({
text: 'El cliente preguntó por precios',
message_id: webhook.getMessageId(),
conversation_id: webhook.getConversationId(),
quick_replies: [
{ text: 'El Plan Básico cuesta $79/mes + IVA e incluye 8 usuarios.' },
],
application_context: { step: 1, intent: 'pricing' },
});

await client.addLabel({
conversation_id: webhook.getConversationId(),
labelKey: 'consulta_precios',
});
}
}

if (webhook.isEventType(EventType.ConversationFinalized)) {
console.log('Conversación finalizada:', webhook.getConversationId());
}

res.json({ ok: true });
});

app.listen(3000);
Proyecto de ejemplo completo

Tenemos un proyecto listo para clonar con un ejemplo más completo que incluye manejo de todos los eventos, callbacks, direct messages, asignación y etiquetado de conversaciones:

github.com/godel-git/socialdesk-demo-app

git clone https://github.com/godel-git/socialdesk-demo-app.git
cd socialdesk-demo-app
npm install
npm run dev

Ejemplo: AWS Lambda

import { WebhookHelper, EventType } from 'socialdesk-node';

export const handler = async (event: any) => {
const body = JSON.parse(event.body);
const webhook = new WebhookHelper(body);
const client = webhook.createClient();

if (webhook.isEventType(EventType.DirectMessage)) {
await client.sendDirectMessage({
text: '¡Gracias por escribirnos! Un asesor te atenderá pronto.',
message_id: webhook.getMessageId(),
conversation_id: webhook.getConversationId(),
});

await client.assignConversation({
conversation_id: webhook.getConversationId(),
entity: 'TEAM',
entity_id: 'team_soporte',
});
}

return { statusCode: 200, body: JSON.stringify({ ok: true }) };
};

Tipos exportados

El SDK exporta todos los tipos necesarios para TypeScript:

import {
// Enums
EventType,
MessageDirection,
SenderType,
AttachmentType,
// Webhook
WebhookEvent,
WebhookPayload,
DirectMessagePayload,
ReplyMessagePayload,
ReplyMessageCallbackPayload,
HSMMessagePayload,
ConversationFinalizedPayload,
// Shared
MessageSender,
Participant,
Agent,
Attachment,
Interaction,
QuickReply,
Callback,
// API options
HintMessageOptions,
DirectMessageOptions,
HSMMessageOptions,
AssignConversationOptions,
AddLabelOptions,
} from 'socialdesk-node';