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)
  1. Salva la configurazione
  2. 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!