Kostenlos testen
Handbuch

Rezept: n8n ↔ TaskMonkey per Webhook

n8n-Workflows starten, sobald in TaskMonkey etwas passiert — und TaskMonkey-Tools aus n8n auslösen. Beide Richtungen signiert, ohne Polling.

n8n ↔ TaskMonkey per Webhook

Zwei Richtungen, beide ohne Polling:

  • A — TaskMonkey → n8n: Eine neue Kundennachricht in der Inbox startet einen n8n-Workflow (Ticket im CRM anlegen, Slack-Nachricht, Google Sheet).
  • B — n8n → TaskMonkey: Ein n8n-Workflow löst ein TaskMonkey-Tool aus (Lead anlegen, Bestand prüfen, Assistant eine Mail beantworten lassen).

Voraussetzungen: n8n (Cloud oder selbst gehostet, von außen per https:// erreichbar) und die Rolle Manager/Admin im Workspace. Hintergrund zu Signatur, Events und Retries: Webhooks.

A — TaskMonkey meldet sich bei n8n

1. Webhook-Node in n8n

Neuer Workflow → Node Webhook:

Feld Wert
HTTP Method POST
Path z. B. taskmonkey-inbox
Authentication None (die Signatur prüfen wir selbst, Schritt 3)
Respond Immediately
Options → Raw Body an (für die Signaturprüfung)

Die Production URL kopieren (https://n8n.example.de/webhook/taskmonkey-inbox) und den Workflow aktivieren — die Test-URL funktioniert nur, solange der Editor lauscht.

2. Endpoint in TaskMonkey

Verwaltung → Webhooks → + Ausgehend:

  • URL: die Production URL aus n8n
  • Events: inbox.message.received (und bei Bedarf inbox.thread.created)
  • Anlegen → das Signatur-Secret (whsec_…) kopieren, es wird nur einmal angezeigt

In n8n unter Settings → Variables (oder als Credential) TASKMONKEY_WEBHOOK_SECRET anlegen.

3. Signatur prüfen (Code-Node)

Direkt hinter den Webhook-Node einen Code-Node (JavaScript, „Run Once for All Items“):

const crypto = require('crypto');
const out = [];

for (const [i, item] of $input.all().entries()) {
  const headers = item.json.headers;
  const raw = (await this.helpers.getBinaryDataBuffer(i, 'data')).toString('utf8'); // Raw Body
  const parts = Object.fromEntries((headers['x-taskmonkey-signature'] || '').split(',').map(p => p.split('=')));
  const t = parseInt(parts.t, 10);
  if (!t || Math.abs(Date.now() / 1000 - t) > 300) throw new Error('Zeitstempel ungueltig');

  const expected = crypto.createHmac('sha256', $vars.TASKMONKEY_WEBHOOK_SECRET).update(`${t}.${raw}`).digest('hex');
  if (expected.length !== (parts.v1 || '').length ||
      !crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1))) {
    throw new Error('Signatur ungueltig');
  }

  out.push({ json: { delivery: headers['x-taskmonkey-delivery'], ...JSON.parse(raw) } });
}
return out;

Self-hosted n8n: crypto muss erlaubt sein (NODE_FUNCTION_ALLOW_BUILTIN=crypto). Ohne Raw Body (ältere n8n-Versionen) funktioniert die Prüfung nicht zuverlässig, weil n8n das JSON neu serialisiert.

4. Weiterverarbeiten

Danach normal weiter, z. B. IF auf {{$json.type}} = inbox.message.received, dann HubSpot/Slack/Sheets mit

  • {{$json.data.message.from.address}} — Absender
  • {{$json.data.message.subject}} — Betreff (E-Mail)
  • {{$json.data.message.text}} — Text
  • {{$json.data.thread.chat_id}} — Thread-ID in TaskMonkey

Doppelte Zustellungen (Retry nach Timeout) erkennst du an delivery — z. B. mit dem Node Remove Duplicates („Remove Items Processed in Previous Executions“, Feld delivery).

5. Testen

Verwaltung → Webhooks → Endpoint → Test-Event senden. In n8n erscheint eine Execution mit type: "webhook.test", in TaskMonkey steht im Zustell-Log succeeded mit Antwort 200. Schlägt es fehl, steht dort der Grund (z. B. HTTP 404 = Workflow nicht aktiv).

B — n8n löst TaskMonkey aus

1. Tool freigeben

Im Tool, das n8n auslösen soll (Builder-Chat: „gib createLead für eingehende Webhooks frei“ — der Builder fragt vorher nach):

'createLead' => [
    'description' => 'Legt einen Lead an.',
    'inbound_hook' => true,
    'inbound_hook_write' => true,   // schreibt in die Lead-Tabelle
    'parameters' => [
        'type' => 'object',
        'properties' => [
            'email'  => ['type' => 'string', 'pattern' => '^[^@\s]+@[^@\s]+$'],
            'name'   => ['type' => 'string', 'maxLength' => 100],
            'quelle' => ['type' => 'string', 'enum' => ['messe', 'website', 'telefon']],
        ],
        'required' => ['email'],
    ],
    'handler' => /* … */,
],

2. Hook in TaskMonkey

Verwaltung → Webhooks → + Eingehend:

  • Name: n8n Leads
  • Auth-Format: TaskMonkey-Signatur (oder Bearer, wenn es schnell gehen soll)
  • Ziel: createLead
  • Mapping leer lassen, wenn n8n die Felder direkt als email, name, quelle schickt

URL (https://app.taskmonkey.de/api/v1/hooks/hk_…) und Secret kopieren, in n8n als Variable TM_HOOK_SECRET ablegen.

3. Signieren und senden (n8n)

Variante Bearer — ein HTTP Request-Node reicht:

Feld Wert
Method POST
URL die Hook-URL
Authentication Generic → Header Auth: Authorization = Bearer {{$vars.TM_HOOK_SECRET}}
Send Body JSON: {"email": "{{$json.email}}", "name": "{{$json.name}}", "quelle": "messe"}
Header Idempotency-Key = {{$json.id}} (verhindert Doppelanlage bei Retries)

Variante TaskMonkey-Signatur — erst ein Code-Node, der Body und Signatur baut:

const crypto = require('crypto');
const body = JSON.stringify({ email: $json.email, name: $json.name, quelle: 'messe' });
const t = Math.floor(Date.now() / 1000);
const v1 = crypto.createHmac('sha256', $vars.TM_HOOK_SECRET).update(`${t}.${body}`).digest('hex');
return { json: { body, signature: `t=${t},v1=${v1}`, delivery: `n8n-${$execution.id}-${$itemIndex}` } };

dann HTTP Request:

Feld Wert
Method POST
URL die Hook-URL
Headers Content-Type: application/json, X-TaskMonkey-Signature: {{$json.signature}}, X-TaskMonkey-Delivery: {{$json.delivery}}
Body Raw → {{$json.body}} (genau der signierte String)

Startet der Workflow selbst durch einen TaskMonkey-Webhook (Richtung A), reiche X-TaskMonkey-Hop als Header unverändert weiter ({{$('Webhook').item.json.headers['x-taskmonkey-hop']}}) — dann erkennt TaskMonkey Schleifen auch über n8n hinweg.

Antwort: 202 {"accepted":true,"delivery_id":"…"}. Das Tool läuft Sekunden später; Ergebnis und Fehler stehen im Log des Hooks in TaskMonkey. Eine zweite Anfrage mit derselben X-TaskMonkey-Delivery bzw. Idempotency-Key wird mit 200 {"duplicate":true} quittiert und nicht erneut ausgeführt.

Assistant statt Tool

Soll ein Assistant entscheiden (z. B. „beantworte diese Anfrage aus dem Formular“), in dessen Definition 'inbound_hook' => true setzen und ihn als Ziel wählen. Er bekommt die Daten als Nachricht und arbeitet mit seinen eigenen Tools; die Antwort steht im Hook-Log. Will n8n das Ergebnis zurück, gib dem Assistant emitWebhookEvent und lass ihn am Ende z. B. custom.anfrage.beantwortet senden — das holt Richtung A wieder ab.

Stolpersteine

Symptom Ursache
Zustell-Log: HTTP 404 n8n-Workflow nicht aktiviert oder Test-URL statt Production URL eingetragen
Zustell-Log: Redirect (301) URL leitet um (http→https, Slash am Ende) — endgültige URL eintragen
Zustell-Log: Ziel blockiert n8n läuft im internen Netz (192.168.…, localhost) — TaskMonkey sendet nur an öffentliche Adressen. n8n per Tunnel/Reverse-Proxy öffentlich machen
n8n: „Signatur ungueltig“ Raw Body nicht aktiviert, oder falsches Secret (nach „Secret rotieren“ neu eintragen)
Hook: 401 Body nach dem Signieren verändert (n8n-JSON-Body statt Raw), Uhr des n8n-Servers falsch (> 5 min), falsches Secret
Hook-Log: „Ungueltige Parameter“ Feld fehlt oder heißt anders — Mapping setzen ({"email": "/kontakt/mail"}) oder Tool-Schema prüfen
Hook: 508 Schleife erkannt: der Workflow wurde von einem TaskMonkey-Webhook gestartet, der selbst aus einem eingehenden Hook stammt (X-TaskMonkey-Hop: 2). Workflow so bauen, dass er nicht auf seinen eigenen Auslöser zurückspielt
Hook-Log: „nicht (mehr) freigegeben“ inbound_hook am Tool fehlt oder ist nicht genau true
Endpoint „automatisch deaktiviert“ 5 Zustellungen in Folge gescheitert — Ursache beheben, Endpoint wieder aktivieren, fehlgeschlagene Zustellungen im Log „Erneut senden“
Zuletzt aktualisiert: 2026-09-25