SocialHook
Documentación/API de envío

API de envío

Envía mensajes de WhatsApp, Facebook e Instagram desde tu propio servidor a través de SocialHook. Un único endpoint firmado cubre las tres plataformas: tu código no cambia cuando agregas una nueva plataforma.

Cuándo usarlo

→
Quieres enviar mensajes a contactos desde un CRM, un servicio de soporte o un panel personalizado.
→
Ejecutas una automatización (n8n, Make, Zapier o tu propio worker) que necesita distribuir respuestas.
→
Estás construyendo un chatbot cuya lógica vive en tus servidores.
Para respuestas puntuales, basta con escribir desde la bandeja de entrada de SocialHook: no se necesita API. Tu webhook también puede responder con { "reply": "..." } para enviar automáticamente un mensaje de vuelta sin llamar a este endpoint. Consulta Respuesta automática más abajo.

1. Obtén una clave API

Abre Clave API en tu panel y haz clic en Generar. Verás la clave completa una sola vez: cópiala ahora y guárdala en un lugar seguro (por ejemplo, tu gestor de secretos). Si la pierdes, genera una nueva; la anterior deja de funcionar de inmediato.

Las claves comienzan con sk_live_ seguido de 64 caracteres hexadecimales. Trátala como una contraseña: nunca la subas a git, nunca la expongas en código del navegador.

2. Endpoint

HTTP
POST https://api.socialhook.io/api/v1/outbound/<your_user_id>/send
Content-Type: application/json

Tu user_id se muestra en la URL de la página de la clave API. La ruta es de alcance por usuario a propósito, de modo que una clave filtrada solo puede afectar a una cuenta.

3. Autenticación

Elige el método que mejor se adapte a tu configuración. Ambos funcionan con el mismo endpoint.

Método A — Clave simple (n8n, Make, Zapier, herramientas no-code)

Agrega una única cabecera. No se requiere firma.

HTTP
X-Api-Key: <your_api_key>
n8n / nodo HTTP Request
# Method: POST
# URL:    https://api.socialhook.io/api/v1/outbound/<your_user_id>/send
# Header: X-Api-Key  →  sk_live_…
# Body (JSON):
{
  "platform": "whatsapp",
  "to": "447911123456",
  "message_text": "Hello from n8n!"
}

Método B — Solicitud firmada (HMAC-SHA256, servidores propios)

Construye la firma aplicando HMAC-SHA256 a <timestamp>.<raw_body> con tu clave API y luego envía el digest hexadecimal en minúsculas en la cabecera X-Socialhook-Signature con el prefijo sha256=. Se rechazan las solicitudes con marcas de tiempo que difieran más de 5 minutos respecto a la hora del servidor.

HTTP
X-Socialhook-Timestamp: <unix_seconds>
X-Socialhook-Signature: sha256=<hmac_hex>
Node.js
const crypto = require('crypto');

const API_KEY = process.env.SOCIALHOOK_API_KEY;     // sk_live_…
const USER_ID = process.env.SOCIALHOOK_USER_ID;     // shown on the API key page

const body = JSON.stringify({
  platform: 'whatsapp',
  to: '447911123456',
  message_text: 'Hello from your SocialHook integration!',
});
const ts  = Math.floor(Date.now() / 1000).toString();
const sig = crypto
  .createHmac('sha256', API_KEY)
  .update(`${ts}.${body}`)
  .digest('hex');

const res = await fetch(
  `https://api.socialhook.io/api/v1/outbound/${USER_ID}/send`,
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Socialhook-Timestamp': ts,
      'X-Socialhook-Signature': `sha256=${sig}`,
    },
    body,
  }
);

if (!res.ok) throw new Error(await res.text());
cURL
# Drop your real API_KEY and USER_ID in here
TS=$(date +%s)
BODY='{"platform":"whatsapp","to":"447911123456","message_text":"Hello!"}'
SIG=$(printf "%s.%s" "$TS" "$BODY" | openssl dgst -sha256 -hmac "$API_KEY" | awk '{print $2}')

curl -X POST https://api.socialhook.io/api/v1/outbound/$USER_ID/send \
  -H "Content-Type: application/json" \
  -H "X-Socialhook-Timestamp: $TS" \
  -H "X-Socialhook-Signature: sha256=$SIG" \
  -d "$BODY"
Importante: firma los bytes exactos del cuerpo crudo que envías. Volver a serializar el JSON entre la firma y el POST cambia los bytes y rompe la firma.

4. Cuerpo de la solicitud por plataforma

WhatsApp

JSON
{
  "platform": "whatsapp",
  "to": "447911123456",
  "message_text": "Hello from your integration!"
}

"to" es el número de teléfono del destinatario en formato E.164 (sin el signo + inicial).

Facebook

JSON
{
  "platform": "facebook",
  "to": "<recipient_psid>",
  "page_id": "<your_facebook_page_id>",
  "message_text": "Hi from SocialHook"
}

"to" es el id de usuario por página (PSID). "page_id" es obligatorio para saber desde qué página enviar.

Instagram

JSON
{
  "platform": "instagram",
  "to": "<recipient_psid>",
  "page_id": "<your_facebook_page_id>",
  "message_text": "Hey from SocialHook"
}

"to" es el id de usuario por cuenta de IG. "page_id" es el id de la página de Facebook vinculada (Instagram se apoya en el OAuth de FB).

5. Códigos de respuesta

CódigoSignificadoQué hacer
200EnviadoMensaje aceptado por la plataforma; aparece en el hilo de la conversación.
400Solicitud incorrectaCampo faltante o inválido. Revisa platform/to/message_text/page_id.
401No autorizadoX-Api-Key falta o es inválida, o X-Socialhook-Signature no coincide. Recalcúlala con el cuerpo crudo exacto.
403Ventana expiradaVentana de mensajería de 24 horas cerrada (FB / IG / WA). Espera un mensaje entrante antes de responder.
408Marca de tiempo demasiado antiguaX-Socialhook-Timestamp difiere más de 5 minutos respecto a la hora del servidor. Reenvía con una marca de tiempo fresca.
429Límite de velocidadDemasiadas solicitudes. Espera y vuelve a intentarlo.

Respuesta automática (sin llamar al endpoint)

Si tu única necesidad de envío es responder a los mensajes entrantes, no necesitas llamar a este endpoint en absoluto. Cuando SocialHook te entrega un webhook, tu servidor puede responder con una de estas opciones:

JSON
// Single reply
{ "reply": "Thanks — got your message!" }

// Or multiple in order
{ "replies": ["Thanks!", "We'll get back to you within an hour."] }

SocialHook envía cada respuesta en la plataforma correcta automáticamente y la registra en el hilo de la conversación. Los fallos en las respuestas no bloquean la confirmación de entrega: tu webhook sigue marcándose como DELIVERED.

Protección contra reenvíos (solicitudes firmadas)

→
Las marcas de tiempo de más de 5 minutos se rechazan (tolerante a desfases de reloj).
→
Las firmas se comparan en tiempo constante.
→
La ruta es de alcance por usuario, de modo que una clave filtrada solo puede afectar a una cuenta.
→
Revocar la clave (o generar una nueva) bloquea de inmediato cualquier solicitud posterior con la clave anterior.

Qué sigue

→
Genera tu clave API si aún no lo has hecho.
→
Lee la referencia del payload para entender qué recibe tu webhook: útil al configurar la respuesta automática.
→
Revisa la verificación de firma para las entregas de webhooks entrantes (esquema de firma distinto, misma idea).