Dokumentation
Ausgehende Webhooks: Payload und Signatur
Empfangen Sie AutoPSEO-Alerts und -Berichte als signiertes JSON an einem beliebigen HTTPS-Endpunkt: die Request-Header, Body-Felder, Ereignistypen und die Prüfung der Signatur.
Ein ausgehender Webhook sendet die Alerts, geplanten Berichte, Testnachrichten und Berichtszusammenfassungen von AutoPSEO an einen Endpunkt, den Sie selbst betreiben: pro Nachricht ein JSON-POST, signiert mit HMAC-SHA256. Damit speisen Sie Zapier, Make, n8n, ein Incident-Tool oder Ihren eigenen Code; ein Slack- oder Teams-Konto ist dafür nicht nötig. Suchen Sie den Webhook, der Artikel an Ihre Website ausliefert? Er gehört zur Content-Engine: siehe Content-Auslieferung.
Webhook hinzufügen
- Klicken Sie im Bereich Outbound webhooks auf New webhook.
- Vergeben Sie einen Name und fügen Sie die URL des Endpunkts ein. Sie muss öffentlich per HTTPS erreichbar sein: Einfaches
http,localhost, Namen mit der Endung.localoder.internal, Hosts ohne Punkt sowie private oder Link-Local-IP-Adressen werden abgelehnt. - Kopieren Sie das Signing-Secret, das nach dem Speichern angezeigt wird. Es wird nur dieses eine Mal angezeigt.
- Klicken Sie auf Send test, um ein
test-Ereignis zu senden, und verknüpfen Sie dann geplante Berichte oder Alerts mit dem Webhook.
So sieht ein Webhook-Request aus
Jede Nachricht ist ein POST mit diesen Headern:
| Header | Wert |
|---|---|
Content-Type | application/json |
User-Agent | AutoPSEO-Webhook/1.0 |
X-AutoPSEO-Event | Der Ereignistyp, zum Beispiel traffic_drop |
X-AutoPSEO-Signature | sha256= gefolgt von 64 hexadezimalen Kleinbuchstaben |
Hier ist ein Traffic-Drop-Alert für eine Domain-Property aus dem Lauf von 06:00 UTC am 12. Oktober 2026, lesbar formatiert (über die Leitung geht kompaktes JSON, und die Werte für id und site_id sind erfunden):
{
"id": "9b2e61f04c3a4d7e8f15a0b6c2d39e47",
"event_type": "traffic_drop",
"severity": "high",
"site_id": "4f0c1e9a2b7d4c58",
"site_url": "sc-domain:example.com",
"occurred_at": "2026-10-12T06:00:04.183Z",
"title": "Traffic drop: example.com",
"text": "Clicks 1,500 vs 2,000 in the previous window (-25.0%).",
"url": "https://app.autopseo.com/property/sc-domain%3Aexample.com",
"payload": {
"fields": [
{ "label": "Metric", "value": "clicks" },
{ "label": "Current", "value": "1,500" },
{ "label": "Baseline", "value": "2,000" },
{ "label": "Window", "value": "7 days (2026-10-05 → 2026-10-11 vs 2026-09-28 → 2026-10-04)" },
{ "label": "Change", "value": "-25.0%" }
],
"table": null,
"detector": "traffic_drop",
"window": 7,
"range": { "start": "2026-10-05", "end": "2026-10-11", "compStart": "2026-09-28", "compEnd": "2026-10-04" },
"result": {
"fired": true,
"metric": "clicks",
"value": 1500,
"baseline": 2000,
"change": -0.25,
"severity": "high",
"summary": "Clicks 1,500 vs 2,000 in the previous window (-25.0%)."
}
},
"source": "autopseo"
}
Die Felder der obersten Ebene sind bei jedem Ereignis gleich:
| Feld | Inhalt |
|---|---|
id | Ein zufälliger, 32 Zeichen langer Hex-String, der für jeden Request neu erzeugt wird |
event_type | Was passiert ist (siehe nächster Abschnitt) |
severity | critical, high, medium oder low bei Alerts; info bei Berichten, Zusammenfassungen und Tests |
site_id | Die ID der Property in AutoPSEO, oder null bei Tests und der Demo-Property |
site_url | Die Search Console-Property, etwa sc-domain:example.com oder https://www.example.com/, oder null bei Tests |
occurred_at | Zeitpunkt, zu dem die Nachricht erstellt wurde, als ISO-8601-Zeitstempel in UTC |
title, text | Die Überschrift und der Zusammenfassungssatz, die Slack und Teams anzeigen |
url | Der Bericht in AutoPSEO, oder null bei Tests |
payload.fields | Die beschrifteten Werte, die Slack als Felder und Teams als Fakten anzeigt |
payload.table | columns und rows bei Berichten und Zusammenfassungen, sonst null |
source | Immer autopseo |
Verhältnisse werden als Bruchzahlen angegeben: Ein change von -0.25 bedeutet einen Rückgang um 25 %, und eine ctr von 0.034 entspricht 3,4 %.
Ereignistypen
event_type | Wird gesendet, wenn | Zusätzliche Schlüssel in payload |
|---|---|---|
traffic_drop, traffic_spike, position_drop, ctr_drop, new_lost_rankings, anomaly, index_flip, rank_drop, audit_regression | Eine Alert-Regel auslöst, planmäßig oder über Test rule | detector, window, range (die Daten, oder null bei index_flip, rank_drop und audit_regression), result |
scheduled_report | Ein geplanter Bericht verschickt wird, planmäßig oder über Send now | reportType (summary, queries, pages oder rankings), range (Daten plus ein label), totals, previous |
report_summary | Jemand auf einer Berichtsseite Send to Slack verwendet | Keine: Die Zahlen stehen in fields und table |
test | Jemand beim Webhook auf Send test klickt | sample, immer true |
result gibt wieder, was der Detektor gemessen hat: fired, metric, value, baseline, change (null, wenn es nichts zu vergleichen gibt), severity und summary, bei anomaly zusätzlich z, den modifizierten Z-Score. totals und previous enthalten clicks, impressions, ctr und position für die beiden Zeiträume eines Berichts. Was die einzelnen Detektoren messen, beschreibt der Abschnitt Alerts.
So prüfen Sie die Signatur
Die Signatur ist ein HMAC-SHA256 über genau die Bytes, die AutoPSEO gesendet hat, berechnet mit dem Signing-Secret des Webhooks als Schlüssel und geschrieben als sha256= plus Hex in Kleinbuchstaben. So prüfen Sie sie:
- Lesen Sie den rohen Request-Body, bevor Sie JSON parsen. Erneutes Parsen und Serialisieren kann die Bytes verändern.
- Berechnen Sie den HMAC-SHA256 über diese Bytes und verwenden Sie das Secret als Text: den 64-stelligen String genau so, wie er angezeigt wird, nicht aus Hex dekodiert.
- Stellen Sie
sha256=voran und vergleichen Sie das Ergebnis in konstanter Zeit mit dem HeaderX-AutoPSEO-Signature. - Lehnen Sie den Request ab, wenn beide Werte voneinander abweichen. Andernfalls antworten Sie sofort mit einem 2xx-Status und erledigen die aufwendige Verarbeitung danach.
Ein Empfänger für Node.js ohne Abhängigkeiten:
import { createServer } from 'node:http';
import { createHmac, timingSafeEqual } from 'node:crypto';
const secret = process.env.AUTOPSEO_WEBHOOK_SECRET;
createServer((req, res) => {
const chunks = [];
req.on('data', (chunk) => chunks.push(chunk));
req.on('end', () => {
const raw = Buffer.concat(chunks);
const expected = Buffer.from('sha256=' + createHmac('sha256', secret).update(raw).digest('hex'));
const received = Buffer.from(String(req.headers['x-autopseo-signature'] || ''));
if (received.length !== expected.length || !timingSafeEqual(received, expected)) {
res.writeHead(401).end();
return;
}
res.writeHead(204).end();
const event = JSON.parse(raw.toString('utf8'));
console.log(event.event_type, event.severity, event.site_url);
});
}).listen(8080);
Die Längenprüfung steht an erster Stelle, weil timingSafeEqual in Node einen Fehler wirft, wenn die beiden Buffer unterschiedlich lang sind.
Regeln für die Zustellung
- Jede Nachricht erhält einen Zustellversuch mit einem Timeout von 10 Sekunden. Jede andere Antwort als 2xx gilt als Fehlschlag und wird im Delivery history mit dem Statuscode und dem Anfang Ihres Response-Bodys festgehalten.
- Weiterleitungen werden nicht verfolgt. Eine 3xx-Antwort schlägt fehl und enthält den Hinweis, die endgültige URL zu verwenden.
- Es gibt keine zeitgesteuerten Wiederholungen. Ein fehlgeschlagener Alert wird nicht als gesendet markiert, daher bewertet ihn die nächste Prüfung erneut und sendet ihn, wenn er weiterhin auslöst: bei den meisten Detektoren am nächsten Morgen, bei Index-Flips in der nächsten Stunde. Ein fehlgeschlagener geplanter Bericht wird im selben Zeitraum nicht erneut gesendet; nutzen Sie nach der Reparatur des Endpunkts Send now.
idwird pro Request erzeugt und identifiziert daher eine Zustellung, nicht ein Ereignis. Um Alerts zu deduplizieren, kombinieren Sieevent_type,site_urlund das Datum vonoccurred_at: Eine Regel sendet höchstens einmal pro Property und UTC-Tag, es sei denn, jemand führt Test rule aus.
Das Signing-Secret
AutoPSEO zeigt das Signing-Secret einmalig an, nämlich beim Speichern des Webhooks, und die Liste zeigt es danach nie wieder an. Legen Sie es sofort in der Konfiguration Ihres Empfängers ab, zusammen mit dem Endpunkt, den es schützt.
Die URL selbst wird verschlüsselt gespeichert, und die Liste zeigt nur den Host und die letzten Zeichen. Wenn Sie einen Webhook löschen, werden auch alle Regeln gelöscht, die an ihn senden. Wenn Sie in einem Teams-Kanal statt JSON eine lesbare Karte möchten, nutzen Sie Microsoft Teams.