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).