Invia Lead tramite Webhook
Questo articolo è stato tradotto automaticamente dall'inglese. Visualizza l'articolo originale
Spreadly invia una richiesta HTTP POST con un body JSON contenente un singolo oggetto lead ogni volta che un lead viene creato o aggiornato. L'autenticazione utilizza una firma HMAC SHA-256 sul body grezzo della richiesta.
Destinazioni tipiche:
- Piattaforme di automazione (Zapier, Make, n8n)
- Serverless (AWS Lambda, Vercel, Cloudflare)
- API personalizzate/middleware
Configurazione
1) Nel tuo pannello di controllo Spreadly, vai su: Lead → Integrazioni CRM → Webhook
2) Configura:
- URL Webhook: Il tuo endpoint accessibile pubblicamente
- Chiave Segreta: Copia e conserva in modo sicuro (es.
SPREADLY_WEBHOOK_SECRET)
3) Salva la configurazione
4) Invia Test: Usa il pulsante "Testa webhook" per verificare il tuo endpoint
Una volta attivato, Spreadly invierà l'oggetto lead tramite POST alla creazione e all'aggiornamento.
Autenticazione
Basata su firma (HMAC SHA-256, obbligatoria):
- Intestazione:
X-Spreadly-Signature - Contenuto: Firma HMAC SHA-256 del body grezzo della richiesta, calcolata con la tua Chiave Segreta del Webhook
Regole di verifica:
- Calcola HMAC SHA-256 con
SPREADLY_WEBHOOK_SECRET - Usa i byte del body grezzo della richiesta (prima di qualsiasi parsing JSON)
- Confronta esattamente con l'intestazione
X-Spreadly-Signature
Esempio di Verifica (Next.js/Node)
/// /pages/api/spreadly-webhook.js
import crypto from 'crypto';
export const config = {
api: { bodyParser: false }, /// importante: usa il body grezzo per HMAC
};
export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ message: 'Method Not Allowed' });
}
const rawBody = await getRawBody(req);
const secret = process.env.SPREADLY_WEBHOOK_SECRET;
const signature = req.headers['x-spreadly-signature'];
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
if (!signature || signature !== expectedSignature) {
return res.status(401).json({ message: 'Invalid signature' });
}
/// Il body è un singolo oggetto lead
const webhook = JSON.parse(rawBody);
/// Opzionale: gestisci payload di test (se abilitati)
if (webhook.data.is_test === true) {
return res.status(200).json({ message: 'Test webhook ricevuto correttamente' });
}
/// Upsert per lead.id
/// await upsertLead(lead);
return res.status(200).json({ message: 'Webhook ricevuto correttamente' });
}
function getRawBody(req) {
return new Promise((resolve, reject) => {
const chunks = [];
req.on('data', chunk => chunks.push(chunk));
req.on('end', () => resolve(Buffer.concat(chunks)));
req.on('error', reject);
});
}
Struttura del Payload: Lead (Oggetto Piatto)
Esempio di body della richiesta:
{
"type": "lead.created",
"timestamp": "2025-10-22T19:51:54.000000Z",
"data": {
"id": 0,
"avatar_url": "https://localhost/img/assets/default_avatar.jpg",
"given_name": "John",
"family_name": "Doe",
"job_title": "Sales Manager",
"department": null,
"company": "Acme, Inc.",
"note": "This is a test note",
"emails": [
{ "id": 0, "email": "j.smith@acme.com" }
],
"phones": [
{ "id": 0, "number": "+39 58273 83572", "type": "mobile" }
],
"websites": [
{ "id": 0, "url": "https://acme.com" }
],
"addresses": [
{
"id": 0,
"line1": "Via Roma 12",
"line2": null,
"line3": null,
"city": "Roma",
"state": null,
"postal_code": null,
"country": "Italy"
}
],
"custom_fields": [],
"event_id": null,
"latitude": null,
"longitude": null,
"locale": "en",
"source": null,
"enriched_at": null,
"is_ai_enrichment_completed": true,
"external_id": null,
"external_system": null,
"external_url": null,
"created_at": "2025-10-22T19:51:54.000000Z",
"updated_at": "2025-10-22T19:51:54.000000Z"
}
}
Note sui campi:
- id: ID interno del lead (stabile tra gli aggiornamenti; usa per upsert)
- given_name, family_name, job_title, department, company: campi del profilo
- note: testo libero opzionale
- emails[], phones[], websites[], addresses[]: array di elementi correlati
- custom_fields[]: estendibilità per il tuo schema
- event_id: riferimento opzionale all'evento/cattura
- latitude, longitude: geolocalizzazione opzionale
- locale: codice lingua/regione
- source: origine (es. spreadly_card, scanner_app)
- campi di arricchimento: enriched_at, is_ai_enrichment_completed
- external_*: collegamenti a sistemi esterni, se applicabile
- created_at, updated_at: timestamp ISO 8601
Flag opzionali (se abilitati nel tuo spazio di lavoro):
- is_test: true può essere incluso alla radice per contrassegnare i payload di test
Test
- Vai su Lead → Integrazioni CRM → Webhook e clicca su "Testa Webhook"
- Aspetta HTTP 200 se gestito correttamente
- Se abilitati, i payload di test includono
is_test: truesullo stesso oggetto lead piatto - Tratta
is_test: truecome non persistente e restituisci semplicemente 200
Risoluzione dei Problemi
Webhook non attivato:
- Assicurati che l'endpoint sia accessibile pubblicamente
- Restituisci HTTP 200 in caso di successo
- Verifica che il webhook sia abilitato in Lead → Integrazioni CRM → Webhook
- Usa "Testa Webhook" per validare
Test di connessione fallito:
- Accetta POST
- Verifica URL e disponibilità
- Conferma che il server/funzione sia in esecuzione
- Controlla i log del server
Aggiornato il: 18/06/2026
Grazie!