Ga naar inhoud
Documentatie

Uitgaande webhooks: payload en handtekening

Ontvang AutoPSEO-meldingen en -rapporten als ondertekende JSON op elk HTTPS-eindpunt: de request headers, de velden in de body, de eventtypen en hoe je de handtekening controleert.

Account → Slack, Teams & Webhooks → Uitgaande webhooksVereist een abonnement of proefperiode5 min leestijd

Een uitgaande webhook stuurt de meldingen, geplande rapporten, testberichten en rapportsamenvattingen van AutoPSEO naar een eindpunt dat jij beheert, als één JSON-POST per bericht, ondertekend met HMAC-SHA256. Gebruik hem om Zapier, Make, n8n, een incidenttool of je eigen code te voeden; er is geen Slack- of Teams-account nodig. Zoek je de webhook die artikelen op je site aflevert? Die hoort bij de contentengine: zie contentlevering.

Een webhook toevoegen

  1. Klik in het onderdeel Outbound webhooks op New webhook.
  2. Geef de webhook een Name en plak de URL van het eindpunt. Die moet openbaar HTTPS zijn: gewone http, localhost, namen die eindigen op .local of .internal, hosts zonder punt en privé- of link-local-IP-adressen worden geweigerd.
  3. Kopieer het signing secret dat na het opslaan verschijnt. Het wordt maar één keer getoond.
  4. Klik op Send test om een test-event te versturen en koppel daarna geplande rapporten of meldingen aan de webhook.

Hoe een webhookverzoek eruitziet

Elk bericht is een POST met deze headers:

HeaderWaarde
Content-Typeapplication/json
User-AgentAutoPSEO-Webhook/1.0
X-AutoPSEO-EventHet eventtype, bijvoorbeeld traffic_drop
X-AutoPSEO-Signaturesha256= gevolgd door 64 hexadecimale tekens in kleine letters

Hieronder staat een verkeersdalingsmelding voor een domeinproperty uit de run van 06:00 UTC op 12 oktober 2026, opgemaakt om te lezen (over de lijn is het compacte JSON, en de waarden van id en site_id zijn verzonnen):

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

De velden op het hoogste niveau zijn voor elk event hetzelfde:

VeldWat het bevat
idEen willekeurige hexadecimale string van 32 tekens, nieuw bij elk verzoek
event_typeWat er is gebeurd (zie de volgende sectie)
severitycritical, high, medium of low voor meldingen; info voor rapporten, samenvattingen en tests
site_idDe id van AutoPSEO voor de property, of null voor tests en de demo-property
site_urlDe Search Console-property, zoals sc-domain:example.com of https://www.example.com/, of null voor tests
occurred_atHet moment waarop het bericht is opgebouwd, als ISO 8601-tijdstempel in UTC
title, textDe kop en de samenvattende zin die Slack en Teams tonen
urlHet rapport in AutoPSEO, of null voor tests
payload.fieldsDe gelabelde waarden die Slack als velden en Teams als feiten toont
payload.tablecolumns en rows voor rapporten en samenvattingen, anders null
sourceAltijd autopseo

Verhoudingen zijn breuken: een change van -0.25 is een daling van 25% en een ctr van 0.034 is 3,4%.

Eventtypen

event_typeVerzonden wanneerExtra sleutels in payload
traffic_drop, traffic_spike, position_drop, ctr_drop, new_lost_rankings, anomaly, index_flip, rank_drop, audit_regressionEen meldingsregel wordt geactiveerd, volgens schema of via Test ruledetector, window, range (de datums, of null voor index_flip, rank_drop en audit_regression), result
scheduled_reportEen gepland rapport wordt verstuurd, volgens schema of via Send nowreportType (summary, queries, pages of rankings), range (datums plus een label), totals, previous
report_summaryIemand gebruikt Send to Slack op een rapportpaginaGeen: de cijfers staan in fields en table
testIemand klikt op Send test bij de webhooksample, altijd true

result herhaalt wat de detector heeft gemeten: fired, metric, value, baseline, change (null als er niets is om mee te vergelijken), severity en summary, plus z, de gemodificeerde z-score, voor anomaly. totals en previous bevatten clicks, impressions, ctr en position voor de twee periodes van een rapport. Wat elke detector meet, staat beschreven onder Alerts.

De handtekening controleren

De handtekening is een HMAC-SHA256 van exact de bytes die AutoPSEO heeft verstuurd, met het signing secret van de webhook als sleutel, geschreven als sha256= plus hexadecimale tekens in kleine letters. Zo controleer je haar:

  1. Lees de ruwe request body voordat je JSON parset. Opnieuw parsen en serialiseren kan de bytes veranderen.
  2. Bereken HMAC-SHA256 over die bytes en gebruik het secret als tekst: de string van 64 tekens precies zoals getoond, niet gedecodeerd uit hex.
  3. Zet sha256= ervoor en vergelijk het resultaat in constante tijd met de header X-AutoPSEO-Signature.
  4. Weiger het verzoek als ze verschillen. Antwoord anders meteen met een 2xx-status en doe het trage werk daarna.

Een ontvanger voor Node.js zonder afhankelijkheden:

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

De lengtecontrole komt eerst, omdat timingSafeEqual in Node een fout geeft wanneer de twee buffers in lengte verschillen.

Afleverregels

  • Elk bericht krijgt één poging met een timeout van 10 seconden. Elk antwoord anders dan 2xx geldt als mislukt en wordt bewaard in Delivery history, met de statuscode en het begin van je response body.
  • Redirects worden niet gevolgd. Een 3xx-antwoord mislukt met de melding om de definitieve URL te gebruiken.
  • Er wordt niets op een timer opnieuw geprobeerd. Een mislukte melding wordt niet als verzonden gemarkeerd, dus bij de volgende controle wordt ze opnieuw beoordeeld en geplaatst als ze nog steeds afgaat: de volgende ochtend voor de meeste detectors, het volgende uur voor indexflips. Een mislukt gepland rapport wordt in dezelfde periode niet opnieuw verstuurd, gebruik dus Send now nadat je het eindpunt hebt hersteld.
  • id wordt per verzoek aangemaakt en identificeert dus een aflevering, niet een event. Om meldingen te ontdubbelen combineer je event_type, site_url en de datum van occurred_at: een regel plaatst maximaal één bericht per property per UTC-dag, tenzij iemand Test rule uitvoert.

Het signing secret

AutoPSEO toont het signing secret één keer, bij het opslaan van de webhook, en de lijst toont het daarna nooit meer. Bewaar het meteen bij de configuratie van je ontvanger, naast het eindpunt dat het beschermt.

De URL zelf wordt versleuteld opgeslagen en de lijst toont alleen de host en de laatste tekens. Als je een webhook verwijdert, verwijder je ook alle regels die erop posten. Wil je een leesbare kaart in een Teams-kanaal in plaats van JSON, gebruik dan Microsoft Teams.

Zet je SEO-content op de automatische piloot

Koppel Search Console en je site. AutoPSEO scant de site en plant meteen de eerste onderwerpen. Geen creditcard nodig.