Artikel über: Lead Erfassung

Leads mit Webhooks senden

Dies ist eine automatisch aus dem Englischen übersetzte Version. Originalartikel anzeigen


Voraussetzung: Ein öffentlich erreichbarer Endpunkt, der JSON-POST-Anfragen akzeptiert.


Spreadly sendet eine HTTP-POST-Anfrage mit einem JSON-Body, der ein einzelnes Lead-Objekt enthält, sobald ein Lead erstellt oder aktualisiert wird. Die Authentifizierung erfolgt über eine HMAC-SHA-256-Signatur des rohen Anfrage-Bodys.


Typische Ziele:

  • Automatisierungsplattformen (Zapier, Make, n8n)
  • Serverless (AWS Lambda, Vercel, Cloudflare)
  • Benutzerdefinierte APIs/Middleware



Einrichtung


1) Gehe in deinem Spreadly-Dashboard zu: Leads → CRM-Integrationen → Webhook

2) Konfiguriere:

  • Webhook-URL: Dein öffentlich zugänglicher Endpunkt
  • Geheimschlüssel: Kopiere und speichere ihn sicher (z. B. als SPREADLY_WEBHOOK_SECRET)

3) Speichere deine Konfiguration

4) Test senden: Nutze die Schaltfläche „Webhook testen“, um deinen Endpunkt zu überprüfen


Sobald aktiviert, sendet Spreadly das Lead-Objekt bei Erstellung und Aktualisierung per POST.



Authentifizierung


Signaturbasiert (HMAC SHA-256, erforderlich):

  • Header: X-Spreadly-Signature
  • Inhalt: HMAC-SHA-256-Signatur des rohen Anfrage-Bodys, berechnet mit deinem Webhook-Geheimschlüssel


Hinweis: Verifiziere die Signatur immer mit dem unveränderten, rohen Anfrage-Body


Überprüfungsregeln:

  • Berechne HMAC SHA-256 mit SPREADLY_WEBHOOK_SECRET
  • Verwende die rohen Bytes des Anfrage-Bodys (vor dem Parsen von JSON)
  • Vergleiche exakt mit dem X-Spreadly-Signature-Header



Überprüfungsbeispiel (Next.js/Node)


// /pages/api/spreadly-webhook.js
import crypto from 'crypto';

export const config = {
api: { bodyParser: false }, // wichtig: roher Body für 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' });
}

// Body ist ein einzelnes Lead-Objekt
const webhook = JSON.parse(rawBody);

// Optional: Test-Payloads behandeln (falls aktiviert)
if (webhook.data.is_test === true) {
return res.status(200).json({ message: 'Test-Webhook erfolgreich empfangen' });
}

// Upsert über lead.id
// await upsertLead(lead);

return res.status(200).json({ message: 'Webhook erfolgreich empfangen' });
}

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);
});
}



Payload-Struktur: Lead (flaches Objekt)


Beispiel-Anfrage-Body:

{
"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"
}
}


Hinweise zu den Feldern:

  • id: interne Lead-ID (bleibt bei Aktualisierungen stabil; für Upsert verwenden)
  • given_name, family_name, job_title, department, company: Profildaten
  • note: optionaler Freitext
  • emails[], phones[], websites[], addresses[]: Arrays mit zugehörigen Einträgen
  • custom_fields[]: Erweiterbarkeit für dein Schema
  • event_id: optionale Ereignis-/Erfassungsreferenz
  • latitude, longitude: optionale Geolokalisierung
  • locale: Sprach-/Regionalcode
  • source: Ursprung (z. B. spreadly_card, scanner_app)
  • Anreicherungsfelder: enriched_at, is_ai_enrichment_completed
  • external_*: Verknüpfungen zu externen Systemen (falls zutreffend)
  • created_at, updated_at: Zeitstempel im ISO-8601-Format


Optionale Flags (falls in deinem Arbeitsbereich aktiviert):

  • is_test: true kann auf Root-Ebene enthalten sein, um Test-Payloads zu kennzeichnen



Testen


  • Gehe zu Leads → CRM-Integrationen → Webhook und klicke auf „Webhook testen“
  • Erwarte HTTP 200, wenn die Verarbeitung erfolgreich war
  • Falls aktiviert, enthalten Test-Payloads is_test: true im selben flachen Lead-Objekt
  • Behandle is_test: true als nicht persistent und gib einfach 200 zurück



Fehlerbehebung


Webhook wird nicht ausgelöst:

  • Stelle sicher, dass der Endpunkt öffentlich zugänglich ist
  • Gib HTTP 200 bei Erfolg zurück
  • Überprüfe, ob der Webhook unter Leads → CRM-Integrationen → Webhook aktiviert ist
  • Nutze „Webhook testen“, um die Konfiguration zu validieren


Verbindungstest fehlgeschlagen:

  • Akzeptiere POST-Anfragen
  • Überprüfe URL und Verfügbarkeit
  • Bestätige, dass Server/Funktion läuft
  • Prüfe die Server-Logs

Aktualisiert am: 18/06/2026

War dieser Beitrag hilfreich?

Teilen Sie Ihr Feedback mit

Stornieren

Danke!