Configura i webhook nella dashboard, ricevi le consegne e verifica la firma HMAC, con esempi per curl, Node.js e PHP.
Un webhook invia una richiesta HTTP al tuo server appena succede qualcosa nel tuo workspace – per esempio quando viene pubblicata una pagina. Così non devi chiedere di continuo se è cambiato qualcosa. Ogni consegna è firmata, in modo che il tuo server possa distinguere i messaggi autentici da quelli falsificati.
Requisiti
- Proprietario o admin del workspace – la voce di menu «Webhooks» compare solo per questi ruoli
- Da Creator Pro; in Creator Free compare «I webhook sono disponibili a partire da Creator Pro.»
- Fino a 5 webhook in Creator Pro, 25 in Creator Agency, 100 in Enterprise (modificabile)
- Un server raggiungibile a un indirizzo https pubblico
I webhook si gestiscono solo nella dashboard. Non si possono creare né modificare con le chiavi API.
Creare un webhook
- Apri «Webhooks» nella navigazione
- Clicca su «+ Nuovo webhook»
- Inserisci l’URL di destinazione e scegli gli eventi
- Facoltativo: inserisci una descrizione e scegli lo stato
- Clicca su «Crea webhook»
- Nel passaggio «Fatto» copia il secret di firma («Secret di firma – visibile solo ora») e salvalo sul tuo server – viene mostrato solo adesso
- Prova il webhook con «Testa». Il risultato resta sulla scheda fino al test successivo: «Consegnato correttamente» o «Non consegnato» con il codice HTTP (o «nessuna risposta»), la durata e l’inizio della risposta
- «URL di destinazione (https://…)»
- Fino a 2048 caratteri. Solo https, nessuna credenziale nell’URL, nessun indirizzo localhost e nessun nome interno come .local, .internal o .lan. Il nome deve puntare a indirizzi IP pubblici; LinkHarbor lo verifica di nuovo prima di ogni consegna.
- «Eventi»
- Almeno un evento. Ogni gruppo ha «Seleziona tutto» e «Deseleziona tutto».
- «Descrizione»
- Facoltativa, fino a 255 caratteri – per esempio a cosa serve il webhook.
- «Stato»
- «Attivo» o «Disattivato». I webhook disattivati non ricevono consegne.
Eventi
| Evento | Nella dashboard | Quando | Contenuto di data |
|---|---|---|---|
| page.published | Pagina pubblicata | È stata pubblicata una pagina – nella dashboard, tramite l’API o da un assistente AI | page_id, version, checksum, published_by_user_id (null per chiavi API e assistenti AI) |
| form.submitted | Modulo inviato | Un visitatore ha inviato un modulo su una delle tue pagine | form_id, form_name, submission_id, page_id, block_id, submitted_at, values (chiave del campo → valore), consent (chiave del consenso → true/false) |
| domain.verified | Dominio verificato | Un dominio personalizzato è stato verificato correttamente | domain_id, hostname, verification_method, status |
| domain.disabled | Dominio disattivato | Un dominio personalizzato è stato disattivato nella dashboard (non in caso di downgrade) | domain_id, hostname, status |
| webhook.test | – (pulsante «Testa») | Clicchi su «Testa» | message (una nota nella lingua dell’account di chi avvia il test; non basarti su di essa) |
form.submitted contiene i valori esattamente come li ha inviati il visitatore, ma mai il suo indirizzo IP o il browser. La consegna avviene in background: il visitatore non la aspetta e una consegna fallita non impedisce l’invio.
Struttura di una consegna
LinkHarbor invia ogni consegna come POST con un corpo JSON e questi header:
| Header | Contenuto |
|---|---|
| Content-Type | application/json |
| X-LinkHarbor-Event | Nome dell’evento, per esempio page.published |
| X-LinkHarbor-Delivery-Id | ID univoco di questa consegna (UUID), identico a id nel corpo |
| X-LinkHarbor-Timestamp | Momento dell’invio in secondi Unix |
| X-LinkHarbor-Signature | sha256= seguito dalla firma HMAC-SHA256 in esadecimale |
| X-LinkHarbor-Signature-Version | v1 |
{
"id": "3f1c2a9e-8d4b-4a51-9f0e-6b7c1d2e3f40",
"event": "page.published",
"created_at": "2026-11-01T09:30:12+00:00",
"data": {
"page_id": 42,
"version": 8,
"checksum": "9b1e5c…",
"published_by_user_id": 7
}
} I reinvii ricevono un nuovo id più i campi redelivery_of (l’ID della consegna ripetuta) e delivery_root (l’ID della prima consegna di questa catena).
Verificare la firma
Ogni webhook ha il proprio secret di firma (32 caratteri esadecimali). Lo vedi una sola volta: nell’ultimo passaggio della creazione del webhook e subito dopo «Secret ↺». Copialo subito sul tuo server – LinkHarbor non lo mostra più in seguito. LinkHarbor lo usa per calcolare la firma così:
- Componi il messaggio: timestamp, punto, ID della consegna, punto, corpo grezzo – cioè timestamp.delivery_id.body
- Calcola l’HMAC-SHA256 su questo messaggio usando il secret di firma come chiave
- Invia il risultato come stringa esadecimale con il prefisso sha256=
Il tuo server dovrebbe verificare la firma con un confronto a tempo costante, rifiutare le consegne con un timestamp più vecchio di 300 secondi e conservare gli ID delle consegne almeno per lo stesso tempo, per riconoscere le ripetizioni. Importante: viene firmato il corpo grezzo, esattamente come arriva – non un JSON che hai ricodificato.
import crypto from 'node:crypto';
import express from 'express';
const app = express();
const SECRET = process.env.LH_WEBHOOK_SECRET;
const seen = new Set(); // in produzione: un database o Redis con scadenza
app.post('/webhooks/linkharbor', express.raw({ type: 'application/json' }), (req, res) => {
const ts = req.get('X-LinkHarbor-Timestamp') || '';
const id = req.get('X-LinkHarbor-Delivery-Id') || '';
const sig = req.get('X-LinkHarbor-Signature') || '';
if (!/^\d+$/.test(ts) || Math.abs(Date.now() / 1000 - Number(ts)) > 300) {
return res.status(400).send('timestamp');
}
const expected = 'sha256=' + crypto
.createHmac('sha256', SECRET)
.update(ts + '.' + id + '.')
.update(req.body) // corpo grezzo come Buffer
.digest('hex');
const a = Buffer.from(expected);
const b = Buffer.from(sig);
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
return res.status(401).send('signature');
}
const event = JSON.parse(req.body.toString('utf8'));
const key = event.delivery_root || event.id; // riconosce i reinvii della stessa catena
if (!seen.has(key)) {
seen.add(key);
// elabora qui, idealmente in modo asincrono in una coda
}
res.sendStatus(200);
});
app.listen(3000); <?php
$secret = getenv('LH_WEBHOOK_SECRET');
$body = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_LINKHARBOR_TIMESTAMP'] ?? '';
$id = $_SERVER['HTTP_X_LINKHARBOR_DELIVERY_ID'] ?? '';
$sig = $_SERVER['HTTP_X_LINKHARBOR_SIGNATURE'] ?? '';
if (!ctype_digit($ts) || abs(time() - (int)$ts) > 300) {
http_response_code(400);
exit('timestamp');
}
$expected = 'sha256=' . hash_hmac('sha256', $ts . '.' . $id . '.' . $body, $secret);
if (!hash_equals($expected, $sig)) {
http_response_code(401);
exit('signature');
}
$event = json_decode($body, true);
// Riconosci le consegne duplicate da $event['delivery_root'] ?? $event['id'],
// poi elabora.
http_response_code(200); Testare il tuo endpoint con curl
Questo script invia al tuo server una consegna di test firmata correttamente – comodo prima di creare il webhook in LinkHarbor:
SECRET="your-signing-secret"
URL="https://example.com/webhooks/linkharbor"
TS=$(date +%s)
ID=$(uuidgen | tr 'A-Z' 'a-z')
BODY='{"id":"'"$ID"'","event":"webhook.test","created_at":"2026-11-01T09:30:12+00:00","data":{"message":"Questo è un evento di test per questo webhook."}}'
SIG="sha256=$(printf '%s' "$TS.$ID.$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | sed 's/^.* //')"
curl -X POST "$URL" \
-H "Content-Type: application/json" \
-H "X-LinkHarbor-Event: webhook.test" \
-H "X-LinkHarbor-Delivery-Id: $ID" \
-H "X-LinkHarbor-Timestamp: $TS" \
-H "X-LinkHarbor-Signature: $SIG" \
-H "X-LinkHarbor-Signature-Version: v1" \
-d "$BODY" Risposta, timeout e reinvio
- Qualsiasi risposta con stato 2xx vale come successo; i reindirizzamenti (3xx) non vengono seguiti
- Il tuo server ha 10 secondi per rispondere e al massimo 5 secondi per stabilire la connessione
- Tutti i webhook di un evento condividono in totale 25 secondi; quelli che non sono stati serviti entro quel tempo vengono segnati come falliti e possono essere reinviati
- LinkHarbor non ripete automaticamente le consegne fallite
- Puoi reinviare a mano le consegne fallite, ma non una che nel frattempo è andata a buon fine. Il reinvio ha un nuovo id e un nuovo created_at
- Per ogni evento sono consentiti al massimo 3 tentativi, compresa la prima consegna; dopo finisce in «Messaggi non recapitati» e non può più essere reinviato
Consegne nella dashboard
«Consegne» apre il registro di un webhook. Ha tre schede:
- «Tutte le consegne»
- Tutte le consegne, con filtri per evento, stato («Successo (2xx)», «Errore client (4xx)», «Errore server (5xx)», «Falliti») e «Limite». «↺ Riprova» consegna di nuovo una consegna fallita, purché non ce ne sia una successiva andata a buon fine. Cliccando su una riga vedi richiesta, risposta, corpo e JSON grezzo.
- «Ripetizioni»
- Catene di reinvii con il risultato «Ripristinato» o «Ancora in errore» e il numero di tentativi.
- «Messaggi non recapitati»
- Consegne in cui tutti i tentativi consentiti sono falliti – la prima consegna e i reinvii insieme. La scheda è di sola consultazione: non possono più essere reinviate. Controlla il tuo endpoint; dopo, i nuovi eventi vengono consegnati normalmente. Se ti servono i dati, recuperali tramite l’API.
Se un reinvio non va a buon fine, la dashboard ne indica il motivo:
- «Non reinviato: questo evento è già fallito … volte, non sono possibili altri tentativi. Lo trovi in “Messaggi non recapitati”.»
- Tutti e 3 i tentativi sono stati esauriti.
- «Non reinviato: nel frattempo questo evento è stato consegnato correttamente.»
- Una consegna successiva della stessa catena è già andata a buon fine.
Verifica nella dashboard
In «Verifica» trovi due strumenti:
- «Kit di verifica»
- «Carica kit» mostra l’algoritmo, i nomi degli header, il formato del messaggio firmato e la tolleranza consigliata di 300 secondi. Il secret stesso non è incluso.
- «Verifica firma»
- Inserisci ID della consegna, timestamp, firma e corpo grezzo della richiesta di una consegna che hai ricevuto. LinkHarbor ti dice allora «Firma valida» o «Firma non valida». Copia timestamp e firma dagli header X-LinkHarbor-Timestamp e X-LinkHarbor-Signature. Il controllo funziona solo per le consegne degli ultimi 5 minuti; per quelle più vecchie segnala «Firma non valida» anche se la firma è corretta.
Rigenerare il secret, disattivare, eliminare
- «Secret ↺» genera un nuovo secret di firma e lo mostra una volta; quello vecchio smette subito di funzionare e il tuo server deve usare quello nuovo
- In «Modifica» imposta lo stato su «Disattivato» per sospendere le consegne
- L’icona del cestino elimina il webhook; finché non chiudi il messaggio, puoi annullare con «Annulla»
Quando passi a un piano più piccolo, i webhook oltre il nuovo limite vengono disattivati, e in Creator Free tutti. Restano conservati; dopo un aggiornamento del piano, LinkHarbor riattiva automaticamente i webhook disattivati fino al limite del nuovo piano – compresi quelli che hai disattivato tu.
Potrebbe esserti utile anche
Non hai trovato nulla?
Dicci di cosa hai bisogno e il nostro team di assistenza ti aiuterà personalmente.