Documentazione
Webhook in uscita: payload e firma
Ricevi gli avvisi e i report di AutoPSEO come JSON firmato su qualsiasi endpoint HTTPS: gli header della richiesta, i campi del body, i tipi di evento e come verificare la firma.
Un webhook in uscita invia gli avvisi, i report programmati, i messaggi di test e i riepiloghi dei report di AutoPSEO a un endpoint che gestisci tu, come una POST JSON per ogni messaggio, firmata con HMAC-SHA256. Usalo per alimentare Zapier, Make, n8n, uno strumento di gestione degli incidenti o il tuo codice; non serve alcun account Slack o Teams. Cerchi il webhook che consegna gli articoli al tuo sito? Appartiene al content engine: vedi consegna dei contenuti.
Aggiungere un webhook
- Nella sezione Webhook in uscita, fai clic su Nuovo webhook.
- Assegna un Nome e incolla l'URL dell'endpoint. Deve essere HTTPS pubblico: sono rifiutati
httpsemplice,localhost, i nomi che terminano con.localo.internal, gli host senza punto e gli indirizzi IP privati o link-local. - Copia il segreto di firma mostrato dopo il salvataggio. Viene visualizzato una sola volta.
- Fai clic su Invia test per inviare un evento
test, quindi collega al webhook i report programmati o gli avvisi.
Come appare una richiesta webhook
Ogni messaggio è una POST con questi header:
| Header | Valore |
|---|---|
Content-Type | application/json |
User-Agent | AutoPSEO-Webhook/1.0 |
X-AutoPSEO-Event | Il tipo di evento, ad esempio traffic_drop |
X-AutoPSEO-Signature | sha256= seguito da 64 caratteri esadecimali minuscoli |
Ecco un avviso di calo del traffico per una proprietà di dominio, relativo all'esecuzione delle 06:00 UTC del 12 ottobre 2026, formattato per la lettura (in transito è JSON compatto, e i valori di id e site_id sono inventati):
{
"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"
}
I campi di primo livello sono gli stessi per ogni evento:
| Campo | Cosa contiene |
|---|---|
id | Una stringa esadecimale casuale di 32 caratteri, nuova a ogni richiesta |
event_type | Cosa è successo (vedi la sezione successiva) |
severity | critical, high, medium o low per gli avvisi; info per report, riepiloghi e test |
site_id | L'id che AutoPSEO assegna alla proprietà, oppure null per i test e la proprietà demo |
site_url | La proprietà di Search Console, ad esempio sc-domain:example.com o https://www.example.com/, oppure null per i test |
occurred_at | Il momento in cui il messaggio è stato costruito, come timestamp ISO 8601 in UTC |
title, text | Il titolo e la frase di riepilogo che Slack e Teams mostrano |
url | Il report in AutoPSEO, oppure null per i test |
payload.fields | I valori con etichetta che Slack mostra come campi e Teams come fatti |
payload.table | columns e rows per report e riepiloghi, altrimenti null |
source | Sempre autopseo |
I rapporti sono frazioni: un change di -0.25 indica un calo del 25% e un ctr di 0.034 indica il 3,4%.
Tipi di evento
event_type | Inviato quando | Chiavi aggiuntive in payload |
|---|---|---|
traffic_drop, traffic_spike, position_drop, ctr_drop, new_lost_rankings, anomaly, index_flip, rank_drop, audit_regression | Scatta una regola di avviso, a pianificazione o tramite Testa regola | detector, window, range (le date, oppure null per index_flip, rank_drop e audit_regression), result |
scheduled_report | Parte un report programmato, a pianificazione o tramite Invia ora | reportType (summary, queries, pages o rankings), range (date più un label), totals, previous |
report_summary | Qualcuno usa Invia a Slack nella pagina di un report | Nessuna: i valori sono in fields e table |
test | Qualcuno fa clic su Invia test sul webhook | sample, sempre true |
result riporta ciò che il rilevatore ha misurato: fired, metric, value, baseline, change (null quando non c'è nulla con cui confrontare), severity e summary, più z, lo z-score modificato, per anomaly. totals e previous contengono clicks, impressions, ctr e position per le due finestre di un report. Ciò che misura ciascun rilevatore è descritto in Avvisi.
Come verificare la firma
La firma è un HMAC-SHA256 dei byte esatti inviati da AutoPSEO, calcolato con il segreto di firma del webhook come chiave e scritto come sha256= più esadecimale minuscolo. Per verificarla:
- Leggi il body grezzo della richiesta prima di qualsiasi parsing JSON. Analizzarlo e serializzarlo di nuovo può modificare i byte.
- Calcola l'HMAC-SHA256 su quei byte, usando il segreto come testo: la stringa di 64 caratteri esattamente come mostrata, non decodificata da esadecimale.
- Anteponi
sha256=e confronta il risultato con l'headerX-AutoPSEO-Signaturein tempo costante. - Rifiuta la richiesta se non corrispondono. Altrimenti rispondi subito con uno stato 2xx ed esegui in seguito le operazioni più lente.
Un ricevitore per Node.js senza dipendenze:
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);
Il controllo della lunghezza viene per primo perché timingSafeEqual di Node genera un errore quando i due buffer hanno lunghezze diverse.
Regole di consegna
- Ogni messaggio ha un solo tentativo con un timeout di 10 secondi. Qualsiasi risposta diversa da 2xx conta come errore e viene conservata nella Cronologia consegne con il codice di stato e l'inizio del body della risposta.
- I reindirizzamenti non vengono seguiti. Una risposta 3xx fallisce con l'indicazione di usare l'URL finale.
- Nulla viene ritentato in automatico. Un avviso non riuscito non viene contrassegnato come inviato, quindi al controllo successivo viene valutato di nuovo e pubblicato se scatta ancora: la mattina seguente per la maggior parte dei rilevatori, l'ora successiva per gli index flip. Un report programmato non riuscito non viene rinviato nello stesso periodo, quindi usa Invia ora dopo aver sistemato l'endpoint.
idviene creato per ogni richiesta, quindi identifica una consegna e non un evento. Per deduplicare gli avvisi, combinaevent_type,site_urle la data dioccurred_at: una regola pubblica al massimo una volta per proprietà per giorno UTC, a meno che qualcuno non esegua Testa regola.
Il segreto di firma
AutoPSEO mostra il segreto di firma una sola volta, quando salvi il webhook, e l'elenco non lo mostra più. Conservalo subito nella configurazione del tuo ricevitore, insieme all'endpoint che protegge.
L'URL stesso è memorizzato in forma cifrata, e l'elenco ne mostra solo l'host e gli ultimi caratteri. Eliminare un webhook elimina anche tutte le regole che pubblicano su di esso. Per una scheda leggibile in un canale Teams invece del JSON, usa Microsoft Teams.