Documentație
Webhook-uri de ieșire: payload și semnătură
Primește alertele și rapoartele AutoPSEO sub formă de JSON semnat la orice endpoint HTTPS: antetele cererii, câmpurile din corp, tipurile de evenimente și modul de verificare a semnăturii.
Un webhook de ieșire trimite alertele, rapoartele programate, mesajele de test și rezumatele de raport din AutoPSEO către un endpoint pe care îl administrezi tu, câte un POST JSON pentru fiecare mesaj, semnat cu HMAC-SHA256. Îl poți folosi pentru Zapier, Make, n8n, un instrument de gestionare a incidentelor sau propriul cod; nu este nevoie de niciun cont Slack sau Teams. Cauți webhook-ul care livrează articole pe site-ul tău? Acela aparține motorului de conținut: vezi livrarea conținutului.
Adaugă un webhook
- În secțiunea Outbound webhooks, fă clic pe New webhook.
- Dă-i un Name și lipește URL-ul endpointului. Trebuie să fie HTTPS public: sunt refuzate
httpsimplu,localhost, numele care se termină în.localsau.internal, gazdele fără punct și adresele IP private sau link-local. - Copiază signing secret-ul afișat după salvare. Este afișat o singură dată.
- Fă clic pe Send test pentru a trimite un eveniment
test, apoi atașează webhook-ului rapoarte programate sau alerte.
Cum arată o cerere webhook
Fiecare mesaj este un POST cu următoarele antete:
| Antet | Valoare |
|---|---|
Content-Type | application/json |
User-Agent | AutoPSEO-Webhook/1.0 |
X-AutoPSEO-Event | Tipul evenimentului, de exemplu traffic_drop |
X-AutoPSEO-Signature | sha256= urmat de 64 de caractere hexazecimale minuscule |
Iată o alertă de scădere a traficului pentru o proprietate de tip domeniu, din rularea de la 06:00 UTC din 12 octombrie 2026, formatată pentru citire (în transmisie este JSON compact, iar valorile id și site_id sunt inventate):
{
"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"
}
Câmpurile de nivel superior sunt aceleași pentru toate evenimentele:
| Câmp | Ce conține |
|---|---|
id | Un șir hexazecimal aleatoriu de 32 de caractere, nou la fiecare cerere |
event_type | Ce s-a întâmplat (vezi secțiunea următoare) |
severity | critical, high, medium sau low pentru alerte; info pentru rapoarte, rezumate și teste |
site_id | ID-ul AutoPSEO al proprietății, sau null pentru teste și proprietatea demo |
site_url | Proprietatea din Search Console, de exemplu sc-domain:example.com sau https://www.example.com/, ori null pentru teste |
occurred_at | Momentul în care a fost construit mesajul, ca marcaj de timp ISO 8601 în UTC |
title, text | Titlul și propoziția-rezumat pe care le afișează Slack și Teams |
url | Raportul din AutoPSEO, sau null pentru teste |
payload.fields | Valorile etichetate pe care Slack le afișează drept câmpuri, iar Teams drept fapte |
payload.table | columns și rows pentru rapoarte și rezumate, altfel null |
source | Întotdeauna autopseo |
Rapoartele sunt exprimate ca fracții: un change de -0.25 înseamnă o scădere de 25%, iar un ctr de 0.034 înseamnă 3,4%.
Tipuri de evenimente
event_type | Se trimite când | Chei suplimentare în payload |
|---|---|---|
traffic_drop, traffic_spike, position_drop, ctr_drop, new_lost_rankings, anomaly, index_flip, rank_drop, audit_regression | Se declanșează o regulă de alertă, conform programului sau prin Test rule | detector, window, range (datele, sau null pentru index_flip, rank_drop și audit_regression), result |
scheduled_report | Se trimite un raport programat, conform programului sau prin Send now | reportType (summary, queries, pages sau rankings), range (datele plus un label), totals, previous |
report_summary | Cineva folosește Send to Slack pe pagina unui raport | Niciuna: cifrele se află în fields și table |
test | Cineva face clic pe Send test la webhook | sample, întotdeauna true |
result reia ce a măsurat detectorul: fired, metric, value, baseline, change (null când nu există nimic cu care să se compare), severity și summary, plus z, scorul z modificat, pentru anomaly. totals și previous conțin clicks, impressions, ctr și position pentru cele două intervale ale unui raport. Ce măsoară fiecare detector este descris la Alerte.
Cum verifici semnătura
Semnătura este un HMAC-SHA256 calculat peste exact octeții trimiși de AutoPSEO, cu signing secret-ul webhook-ului drept cheie, și scrisă ca sha256= urmat de hexazecimal cu litere mici. Pentru a o verifica:
- Citește corpul brut al cererii înainte de orice parsare JSON. Parsarea urmată de o nouă serializare poate modifica octeții.
- Calculează HMAC-SHA256 peste acești octeți, folosind secretul ca text: șirul de 64 de caractere exact așa cum este afișat, nu decodat din hexazecimal.
- Adaugă prefixul
sha256=și compară rezultatul cu antetulX-AutoPSEO-Signatureîn timp constant. - Respinge cererea dacă valorile diferă. Altfel, răspunde imediat cu un status 2xx și efectuează abia după aceea lucrările mai lente.
Un receptor pentru Node.js, fără dependențe:
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);
Verificarea lungimii vine prima, deoarece timingSafeEqual din Node aruncă o eroare când cele două buffere au lungimi diferite.
Reguli de livrare
- Fiecare mesaj primește o singură încercare, cu un timeout de 10 secunde. Orice răspuns diferit de 2xx este considerat eșec și este păstrat în Delivery history, împreună cu codul de status și începutul corpului răspunsului tău.
- Redirecționările nu sunt urmate. Un răspuns 3xx eșuează, cu o notă să folosești URL-ul final.
- Nu se reîncearcă nimic automat. O alertă eșuată nu este marcată ca trimisă, așa că la următoarea verificare este evaluată din nou și se postează dacă se declanșează în continuare: a doua zi dimineață pentru majoritatea detectoarelor, în ora următoare pentru index flips. Un raport programat eșuat nu este retrimis în aceeași perioadă, așa că folosește Send now după ce ai reparat endpointul.
ideste creat pentru fiecare cerere, deci identifică o livrare, nu un eveniment. Pentru a elimina duplicatele de alerte, combinăevent_type,site_urlși data dinoccurred_at: o regulă postează cel mult o dată pe proprietate pe zi UTC, cu excepția cazului în care cineva rulează Test rule.
Signing secret-ul
AutoPSEO afișează signing secret-ul o singură dată, când salvezi webhook-ul, iar lista nu îl mai arată ulterior. Păstrează-l imediat în configurația receptorului tău, alături de endpointul pe care îl protejează.
URL-ul în sine este stocat criptat, iar lista afișează doar gazda și ultimele caractere. Ștergerea unui webhook șterge și toate regulile care postează către el. Dacă vrei un card ușor de citit într-un canal Teams, nu JSON, folosește Microsoft Teams.