Webhook
Consegne di eventi firmate: eventi disponibili, verifica di X-LinkProfit-Signature in JavaScript e Python, tentativi ripetuti e stato failing.
Aggiornato il 13 agosto 2026
I webhook inviano gli eventi al tuo endpoint come richieste POST in JSON: niente
polling. Registra gli endpoint nella dashboard (Impostazioni → Webhook) o
tramite POST /v1/webhooks; il segreto di firma viene mostrato una sola volta,
al momento della creazione.
Eventi
| Evento | Si attiva quando | Disponibile per |
|---|---|---|
| link.created / link.updated / link.deleted | Un link cambia — dalla dashboard, dall'API o da un'importazione in blocco | endpoint di area di lavoro e partner |
| domain.pending_ssl | Il DNS è verificato, il certificato è in emissione | area di lavoro e partner |
| domain.activated | Il dominio serve traffico | area di lavoro e partner |
| domain.error | Il provisioning non è riuscito; i dettagli sono all'interno | area di lavoro e partner |
| click.threshold | 80% / 100% del limite mensile di clic tracciati | area di lavoro e partner |
| conversion.created | Una conversione è stata registrata: un ordine, una registrazione o un obiettivo personalizzato attribuito a un clic | area di lavoro e partner |
| workspace.subscribed | Un cliente ha pagato la prima fattura di un abbonamento | solo partner |
| workspace.past_due | Il pagamento di un cliente non è andato a buon fine | solo partner |
| workspace.suspended | Un cliente è stato sospeso (dunning o manualmente) | solo partner |
| payment.succeeded | Un pagamento di un cliente è stato incassato, con il dettaglio delle commissioni | solo partner |
| payment.refunded | Un pagamento è stato rimborsato | solo partner |
La consegna
POST /your/endpoint HTTP/1.1
Content-Type: application/json
X-LinkProfit-Event: link.created
X-LinkProfit-Delivery: dlv_8Yq2…
X-LinkProfit-Signature: t=1755081600,v1=5f8a2c…
{
"id": "dlv_8Yq2…",
"type": "link.created",
"created_at": "2026-08-13T10:00:00.000Z",
"data": { "id": "lnk_…", "domain": "go.your-brand.com", "slug": "x7f2q1z", "url": "https://example.com" }
}
Rispondi con un qualsiasi 2xx entro 10 secondi. Qualunque altra cosa — timeout
compreso — conta come errore e programma un nuovo tentativo. Le consegne possono
arrivare fuori ordine e, raramente, due volte: deduplica in base a id.
Verificare la firma
La firma è un HMAC-SHA256 calcolato su `${t}.${rawBody}` con il segreto
del tuo endpoint, codificato in esadecimale. Verificala sempre sul corpo
grezzo della richiesta, prima di qualsiasi parsing JSON, e rifiuta i
timestamp più vecchi di 5 minuti.
import { createHmac, timingSafeEqual } from "node:crypto";
function verifySignature(secret, rawBody, header, toleranceSeconds = 300) {
const parts = Object.fromEntries(
header.split(",").map((piece) => piece.split("=", 2)),
);
if (!parts.t || !parts.v1) return false;
if (Math.abs(Date.now() / 1000 - Number(parts.t)) > toleranceSeconds) return false;
const expected = createHmac("sha256", secret)
.update(`${parts.t}.${rawBody}`)
.digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(parts.v1);
return a.length === b.length && timingSafeEqual(a, b);
}
import hashlib
import hmac
import time
def verify_signature(secret: str, raw_body: bytes, header: str, tolerance: int = 300) -> bool:
parts = dict(piece.split("=", 1) for piece in header.split(",") if "=" in piece)
timestamp, signature = parts.get("t"), parts.get("v1")
if not timestamp or not signature:
return False
if abs(time.time() - int(timestamp)) > tolerance:
return False
expected = hmac.new(
secret.encode(), f"{timestamp}.".encode() + raw_body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
Tentativi ripetuti e stato failing
Il primo tentativo è immediato. In caso di errore, i tentativi seguono una
pianificazione fissa: 1 min → 5 min → 30 min → 2 h → 12 h. Dopo il quinto
tentativo l'endpoint viene contrassegnato come failing, smette di ricevere
nuovi eventi e il proprietario riceve un'email.
Sistema l'endpoint, poi riattivalo dalla dashboard o con
PATCH /v1/webhooks/{id} e {"status": "active"}. Gli eventi persi non vengono
riconsegnati automaticamente: il log delle consegne
(GET /v1/webhooks/{id}/deliveries o la dashboard) mostra ogni payload, così
puoi fare la riconciliazione.
Una consegna riuscita azzera la serie di errori.
Test
Il pulsante Invia test (o POST /v1/webhooks/{id}/test) consegna un evento
reale e firmato, con "data": { "test": true }, attraverso la stessa pipeline
degli eventi di produzione: il log delle consegne mostra la risposta del tuo
endpoint.