SocialHook
Dokumentation/Outbound API

Outbound API

Sende WhatsApp-, Facebook- und Instagram-Nachrichten von deinem eigenen Server über SocialHook. Ein signierter Endpunkt deckt alle drei Plattformen ab — dein Code ändert sich nicht, wenn du eine neue Plattform hinzufügst.

Wann du dies verwendest

Du möchtest Kontakte aus einem CRM, Helpdesk oder benutzerdefinierten Dashboard anschreiben.
Du führst eine Automatisierung (n8n, Make, Zapier, dein eigener Worker) aus, die Antworten verteilen muss.
Du baust einen Chatbot, dessen Logik auf deinen Servern lebt.
Für einmalige Antworten tippe einfach in der SocialHook-Inbox — keine API erforderlich. Dein Webhook kann auch mit { "reply": "..." } antworten, um automatisch eine Nachricht zurückzusenden, ohne diesen Endpunkt überhaupt aufzurufen. Siehe Auto-Antwort unten.

1. API-Schlüssel holen

Öffne API-Schlüssel in deinem Dashboard und klicke auf Generieren. Du siehst den vollständigen Schlüssel einmal — kopiere ihn jetzt und speichere ihn sicher (z.B. in deinem Secrets Manager). Wenn du ihn verlierst, generiere einen neuen; der alte hört sofort auf zu funktionieren.

Schlüssel beginnen mit sk_live_ gefolgt von 64 Hex-Zeichen. Behandle ihn wie ein Passwort: nie in git committen, nie in Browser-Code preisgeben.

2. Endpunkt

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

Deine user_id wird in der URL auf der API-Schlüssel-Seite angezeigt. Der Pfad ist absichtlich benutzerbezogen, sodass ein geleakter Schlüssel nur ein Konto betreffen kann.

3. Authentifizierung

Wähle die Methode, die zu deinem Setup passt. Beide funktionieren mit demselben Endpunkt.

Methode A — Einfacher Schlüssel (n8n, Make, Zapier, No-Code-Tools)

Füge einen einzigen Header hinzu. Keine Signierung erforderlich.

HTTP
X-Api-Key: <your_api_key>
n8n / HTTP Request Node
# 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!"
}

Methode B — Signierte Anfrage (HMAC-SHA256, benutzerdefinierte Server)

Erstelle die Signatur durch HMAC-SHA256-Hashing von <timestamp>.<raw_body> mit deinem API-Schlüssel, dann sende den kleingeschriebenen Hex-Digest im X-Socialhook-Signature Header mit dem Präfix sha256=. Anfragen mit Zeitstempeln, die mehr als 5 Minuten von der Serverzeit abweichen, werden abgelehnt.

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"
Wichtig: signiere die exakten rohen Body-Bytes, die du sendest. Das Neu-Serialisieren von JSON zwischen dem Signieren und dem POST ändert die Bytes und bricht die Signatur.

4. Request-Body pro Plattform

WhatsApp

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

"to" ist die Empfänger-Telefonnummer im E.164-Format (ohne führendes +).

Facebook

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

"to" ist die seitenspezifische Benutzer-ID (PSID). "page_id" ist erforderlich, damit wir wissen, von welcher Seite aus gesendet werden soll.

Instagram

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

"to" ist die IG-spezifische Benutzer-ID. "page_id" ist die verknüpfte Facebook-Seiten-ID (Instagram nutzt den FB OAuth).

5. Antwort-Codes

CodeBedeutungWas zu tun ist
200GesendetNachricht von der Plattform akzeptiert; erscheint im Chat-Thread.
400Ungültige AnfrageFehlendes oder ungültiges Feld. Überprüfe platform/to/message_text/page_id.
401Nicht autorisiertX-Api-Key fehlt/ungültig, oder X-Socialhook-Signature stimmte nicht überein. Mit dem exakten rohen Body neu berechnen.
403Fenster abgelaufen24-Stunden-Messaging-Fenster geschlossen (FB / IG / WA). Auf eine eingehende Nachricht warten, bevor geantwortet wird.
408Zeitstempel zu altX-Socialhook-Timestamp ist mehr als 5 Minuten von der Serverzeit entfernt. Mit einem frischen Zeitstempel erneut senden.
429Rate-Limit erreichtZu viele Anfragen. Warten und erneut versuchen.

Auto-Antwort (Endpunkt überspringen)

Wenn dein einziger ausgehender Bedarf das Antworten auf eingehende Nachrichten ist, musst du diesen Endpunkt gar nicht aufrufen. Wenn SocialHook einen Webhook an dich liefert, kann dein Server mit einem der folgenden antworten:

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

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

SocialHook sendet jede Antwort automatisch auf der richtigen Plattform und zeichnet sie im Chat-Thread auf. Antwortfehler blockieren die Zustellungsbestätigung nicht — dein Webhook wird trotzdem als DELIVERED markiert.

Wiederholungsschutz (signierte Anfragen)

Zeitstempel älter als 5 Minuten werden abgelehnt (tolerant gegenüber Uhrabweichungen).
Signaturen werden in konstanter Zeit verglichen.
Pfad ist benutzerbezogen, sodass ein geleakter Schlüssel nur ein Konto betreffen kann.
Das Widerrufen des Schlüssels (oder das Generieren eines neuen) blockiert sofort alle weiteren Anfragen mit dem alten Schlüssel.

Was als nächstes

API-Schlüssel generieren, falls noch nicht geschehen.
Lies die Payload-Referenz, um zu verstehen, was dein Webhook empfängt — nützlich beim Verdrahten der Auto-Antwort.
Überprüfe die Signaturverifizierung für eingehende Webhook-Zustellungen (anderes Signierungsschema — gleiche Idee).