Articoli su: Cattura dei lead

Invia Lead tramite Webhook

Questo articolo è stato tradotto automaticamente dall'inglese. Visualizza l'articolo originale


Requisito: Un endpoint accessibile pubblicamente che accetta richieste POST JSON.


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


Nota: Verifica sempre la firma utilizzando il body grezzo della richiesta non modificato


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: true sullo stesso oggetto lead piatto
  • Tratta is_test: true come 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

È stato utile questo articolo?

Condividi il tuo feedback

Annulla

Grazie!