Leads mit Webhooks senden
Dies ist eine automatisch aus dem Englischen übersetzte Version. Originalartikel anzeigen
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
Ü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: trueim selben flachen Lead-Objekt - Behandle
is_test: trueals 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
Danke!