SocialHook
Documentation/API Outbound

API Outbound

Envoyez des messages WhatsApp, Facebook et Instagram depuis votre propre serveur via SocialHook. Un seul point de terminaison signé couvre les trois plateformes — votre code ne change pas quand vous ajoutez une nouvelle plateforme.

Quand utiliser ceci

Vous voulez envoyer des messages à des contacts depuis un CRM, un helpdesk ou un tableau de bord personnalisé.
Vous exécutez une automatisation (n8n, Make, Zapier, votre propre worker) qui doit diffuser des réponses.
Vous construisez un chatbot dont le cerveau vit sur vos serveurs.
Pour les réponses ponctuelles, tapez simplement dans la boîte de réception SocialHook — pas d'API nécessaire. Votre webhook peut également répondre avec { "reply": "..." } pour envoyer automatiquement un message en retour sans appeler ce point de terminaison du tout. Voir Réponse automatique ci-dessous.

1. Obtenez une clé API

Ouvrez clé API dans votre tableau de bord et cliquez sur Générer. Vous verrez la clé complète une seule fois — copiez-la maintenant et stockez-la quelque part de sûr (par ex. votre gestionnaire de secrets). Si vous la perdez, générez-en une nouvelle ; l'ancienne cesse de fonctionner immédiatement.

Les clés commencent par sk_live_ suivi de 64 caractères hexadécimaux. Traitez-la comme un mot de passe : ne la commitez jamais dans git, ne l'exposez jamais dans le code du navigateur.

2. Point de terminaison

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

Votre user_id est affiché dans l'URL de la page de clé API. Le chemin est limité à l'utilisateur intentionnellement afin qu'une clé divulguée ne puisse impacter qu'un seul compte.

3. Authentification

Choisissez la méthode qui convient à votre configuration. Les deux fonctionnent avec le même point de terminaison.

Méthode A — Clé simple (n8n, Make, Zapier, outils no-code)

Ajoutez un seul en-tête. Aucune signature requise.

HTTP
X-Api-Key: <your_api_key>
n8n / Nœud 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éthode B — Requête signée (HMAC-SHA256, serveurs personnalisés)

Construisez la signature en hachant HMAC-SHA256 <timestamp>.<raw_body> avec votre clé API, puis envoyez le digest hexadécimal minuscule dans l'en-tête X-Socialhook-Signature préfixé par sha256=. Les requêtes avec des horodatages datant de plus de 5 minutes de l'heure du serveur sont rejetées.

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"
Important : signez les octets de corps brut exacts que vous envoyez. Re-sérialiser le JSON entre la signature et le POST change les octets et casse la signature.

4. Corps de la requête par plateforme

WhatsApp

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

"to" est le numéro de téléphone du destinataire au format E.164 (sans + initial).

Facebook

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

"to" est l'identifiant utilisateur scopé par page (PSID). "page_id" est requis pour que nous sachions depuis quelle page envoyer.

Instagram

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

"to" est l'identifiant utilisateur scopé par IG. "page_id" est l'identifiant de la page Facebook liée (Instagram utilise l'OAuth FB).

5. Codes de réponse

CodeSignificationQue faire
200EnvoyéMessage accepté par la plateforme ; apparaît dans le fil de discussion.
400Requête invalideChamp manquant ou invalide. Vérifiez platform/to/message_text/page_id.
401Non autoriséX-Api-Key manquant/invalide, ou X-Socialhook-Signature ne correspond pas. Recalculez-le avec le corps brut exact.
403Fenêtre expiréeFenêtre de messagerie de 24 heures fermée (FB / IG / WA). Attendez un message entrant avant de répondre.
408Horodatage trop ancienX-Socialhook-Timestamp est plus de 5 minutes avant l'heure du serveur. Renvoyez avec un nouvel horodatage.
429Limite de taux atteinteTrop de requêtes. Réduisez le débit et réessayez.

Réponse automatique (éviter le point de terminaison)

Si votre seul besoin sortant est de répondre aux messages entrants, vous n'avez pas du tout besoin d'appeler ce point de terminaison. Quand SocialHook vous livre un webhook, votre serveur peut répondre avec l'un de :

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

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

SocialHook envoie chaque réponse sur la bonne plateforme automatiquement et l'enregistre dans le fil de discussion. Les échecs de réponse ne bloquent pas l'accusé de livraison — votre webhook est toujours marqué DELIVERED.

Protection contre le replay (requêtes signées)

Les horodatages plus anciens de 5 minutes sont rejetés (tolérant à la dérive d'horloge).
Les signatures sont comparées en temps constant.
Le chemin est limité à l'utilisateur, donc une clé divulguée ne peut impacter qu'un seul compte.
Révoquer la clé (ou en générer une nouvelle) bloque immédiatement toute autre requête avec l'ancienne clé.

Et ensuite

Générez votre clé API si vous ne l'avez pas encore fait.
Lisez la référence des payloads pour comprendre ce que reçoit votre webhook — utile pour câbler la réponse automatique.
Consultez la vérification de signature pour les livraisons webhook entrantes (schéma de signature différent — même idée).