Hoppa till innehållet
Dokumentation

Utgående webhooks: payload och signatur

Ta emot AutoPSEO-aviseringar och rapporter som signerad JSON på valfri HTTPS-endpoint: förfrågningshuvuden, fält i bodyn, händelsetyper och hur du verifierar signaturen.

Konto → Slack, Teams och webhooks → Utgående webhooksKräver prenumeration eller provperiod5 min läsning

En utgående webhook skickar AutoPSEO:s aviseringar, schemalagda rapporter, testmeddelanden och rapportsammanfattningar till en endpoint som du driver själv, som en JSON-POST per meddelande signerad med HMAC-SHA256. Använd den för att mata Zapier, Make, n8n, ett incidentverktyg eller din egen kod; inget konto i Slack eller Teams behövs. Letar du efter webhooken som levererar artiklar till din webbplats? Den hör till innehållsmotorn: se innehållsleverans.

Lägg till en webhook

  1. Klicka på New webhook i avsnittet Outbound webhooks.
  2. Ge den ett Name och klistra in endpointens URL. Den måste vara publik HTTPS: vanlig http, localhost, namn som slutar på .local eller .internal, värdnamn utan punkt samt privata eller länklokala IP-adresser avvisas.
  3. Kopiera den signing secret som visas när du har sparat. Den visas bara en enda gång.
  4. Klicka på Send test för att skicka en test-händelse och koppla sedan schemalagda rapporter eller aviseringar till webhooken.

Så ser en webhook-förfrågan ut

Varje meddelande är en POST med dessa huvuden:

HuvudVärde
Content-Typeapplication/json
User-AgentAutoPSEO-Webhook/1.0
X-AutoPSEO-EventHändelsetypen, till exempel traffic_drop
X-AutoPSEO-Signaturesha256= följt av 64 hexadecimala tecken i gemener

Här är en avisering om trafikfall för en domänegendom från körningen 06:00 UTC den 12 oktober 2026, formaterad för läsning (i själva förfrågan är det kompakt JSON, och värdena för id och site_id är påhittade):

{
  "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"
}

Fälten på toppnivå är desamma för alla händelser:

FältInnehåll
idEn slumpmässig hexsträng på 32 tecken, ny för varje förfrågan
event_typeVad som hände (se nästa avsnitt)
severitycritical, high, medium eller low för aviseringar; info för rapporter, sammanfattningar och tester
site_idAutoPSEO:s id för egendomen, eller null för tester och demoegendomen
site_urlSearch Console-egendomen, till exempel sc-domain:example.com eller https://www.example.com/, eller null för tester
occurred_atNär meddelandet byggdes, som en ISO 8601-tidsstämpel i UTC
title, textRubriken och sammanfattningsmeningen som Slack och Teams visar
urlRapporten i AutoPSEO, eller null för tester
payload.fieldsDe namngivna värden som Slack visar som fält och Teams som fakta
payload.tablecolumns och rows för rapporter och sammanfattningar, annars null
sourceAlltid autopseo

Kvoter anges som bråktal: en change på -0.25 är en minskning med 25 %, och en ctr på 0.034 är 3,4 %.

Händelsetyper

event_typeSkickas närExtra nycklar i payload
traffic_drop, traffic_spike, position_drop, ctr_drop, new_lost_rankings, anomaly, index_flip, rank_drop, audit_regressionEn aviseringsregel utlöses, enligt schema eller via Test ruledetector, window, range (datumen, eller null för index_flip, rank_drop och audit_regression), result
scheduled_reportEn schemalagd rapport skickas, enligt schema eller via Send nowreportType (summary, queries, pages eller rankings), range (datum plus en label), totals, previous
report_summaryNågon använder Send to Slack på en rapportsidaInga: siffrorna finns i fields och table
testNågon klickar på Send test på webhookensample, alltid true

result upprepar vad detektorn mätte: fired, metric, value, baseline, change (null när det inte finns något att jämföra med), severity och summary, samt z, det modifierade z-värdet, för anomaly. totals och previous innehåller clicks, impressions, ctr och position för rapportens två perioder. Vad varje detektor mäter beskrivs under Aviseringar.

Så verifierar du signaturen

Signaturen är en HMAC-SHA256 av exakt de bytes som AutoPSEO skickade, nycklad med webhookens signing secret och skriven som sha256= plus hex i gemener. Så här kontrollerar du den:

  1. Läs den råa förfrågningsbodyn innan någon JSON-tolkning sker. Om du tolkar och serialiserar om den kan bytesen ändras.
  2. Beräkna HMAC-SHA256 över dessa bytes med hemligheten som text: strängen på 64 tecken precis som den visas, inte avkodad från hex.
  3. Lägg till prefixet sha256= och jämför resultatet med huvudet X-AutoPSEO-Signature i konstant tid.
  4. Avvisa förfrågan om de skiljer sig åt. Svara annars direkt med en 2xx-status och gör det tidskrävande arbetet efteråt.

En mottagare för Node.js utan beroenden:

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

Längdkontrollen kommer först eftersom Nodes timingSafeEqual kastar ett fel när de två buffertarna har olika längd.

Leveransregler

  • Varje meddelande får ett försök med en timeout på 10 sekunder. Alla svar utom 2xx räknas som ett misslyckande och sparas i Delivery history med statuskoden och början av din svarsbody.
  • Omdirigeringar följs inte. Ett 3xx-svar misslyckas med en uppmaning att använda den slutliga URL:en.
  • Inget skickas om automatiskt på timer. En misslyckad avisering markeras inte som skickad, så nästa kontroll utvärderar den igen och postar om den fortfarande utlöses: nästa morgon för de flesta detektorer, nästa timme för indexförändringar. En misslyckad schemalagd rapport skickas inte om under samma period, så använd Send now när du har lagat endpointen.
  • id skapas per förfrågan, så det identifierar en leverans och inte en händelse. För att avduplicera aviseringar kan du kombinera event_type, site_url och datumet i occurred_at: en regel postar högst en gång per egendom och UTC-dygn, om inte någon kör Test rule.

Signing secret

AutoPSEO visar signing secret en enda gång, när du sparar webhooken, och listan visar den aldrig igen. Spara den direkt i mottagarens konfiguration, tillsammans med den endpoint som den skyddar.

Själva URL:en lagras krypterad, och listan visar bara dess värdnamn och sista tecken. När du tar bort en webhook tas även alla regler som postar till den bort. Vill du ha ett lättläst kort i en Teams-kanal i stället för JSON, använd Microsoft Teams.

Sätt ditt SEO-innehåll på autopilot

Anslut Search Console och din webbplats. AutoPSEO skannar den och planerar de första ämnena direkt. Inget kreditkort krävs.