Multi-Vertrags-Lead-Erfassung von der Website
Dieses Dokument beschreibt einen einheitlichen API-Vertrag, über den das Website-Backend Lead-Daten, Besucherkontaktdaten und Marketing-UTM-Metriken mit einer einzigen Anfrage an ReactiveCRM sendet.
1. Zweck
Der Website-Integrator muss nicht separat Kontakt, Telefon, E-Mail, Lead und Marketing-Ereignis erstellen. Eine einzige Anfrage soll atomar Folgendes erstellen:
- Kontakt;
- primäre Telefonnummer des Kontakts;
- primäre E-Mail des Kontakts, falls angegeben;
- Lead;
- Verknüpfung zwischen Kontakt und Lead;
- Marketing-Ereignis und UTM-Attribution.
Wenn ein Schritt fehlschlägt, wird die gesamte Anfrage zurückgerollt, und teilweise erstellte Daten werden nicht gespeichert.
2. Endpunkt
POST /api/site/leads
Authorization: Bearer <CRM_ACCESS_TOKEN>
Content-Type: application/json
Das Token darf nur vom Website-Backend oder einer Serverless-Funktion gesendet werden. Platzieren Sie das CRM-Token niemals in JavaScript im Browser.
Der Mandant wird aus dem Autorisierungs-Token abgeleitet. Alle übergebenen UUIDs werden im Rahmen dieses Mandanten geprüft.
3. Vollständiger JSON-Vertrag
{
"externalId": "site-form-01J7K9A2M4Y5T6",
"lead": {
"leadSourceId": "7b33b18f-55bd-48a5-a8f0-e450a56dde47",
"quality": "WARM",
"message": "Ich möchte eine Beratung zur CRM-Einführung"
},
"contact": {
"firstName": "Ivan",
"lastName": "Ivanov",
"phone": "+79991234567",
"email": "ivan@example.com"
},
"marketing": {
"occurredAt": "2026-09-06T18:00:00Z",
"visitorId": "visitor-8b7f",
"sessionId": "session-31ac",
"source": "website",
"channel": "paid",
"utmSource": "google",
"utmMedium": "cpc",
"utmCampaign": "summer-consulting",
"utmContent": "banner-a",
"utmTerm": "crm consultation",
"gclid": "EAIaIQobChMI-example",
"fbclid": null,
"landingUrl": "https://example.com/consultation",
"referrer": "https://www.google.com/"
}
}
4. Anfragefelder
4.1. Stammfelder
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
externalId | string | empfohlen | Stabile eindeutige ID der Formularübermittlung für Idempotenz |
lead | object | ja | Daten des zu erstellenden Leads |
contact | object | ja | Daten der Kontaktperson |
marketing | object | nein | UTM-Metriken und technische Daten des Marketing-Besuchs |
externalId wird vor dem ersten Sendeversuch generiert. Bei Wiederholung der Anfrage nach Timeout oder Netzwerkfehler verwenden Sie denselben Wert.
4.2. Objekt lead
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
leadSourceId | uuid | ja | ID der Lead-Quelle im aktuellen Mandanten |
quality | string | nein | Anfängliche Bewertung: HOT, WARM, COOL oder COLD |
message | string | nein | Nachricht des Besuchers oder Kommentar zur Anfrage |
Wenn die Website keine Vorqualifizierung durchführt, sollte das Feld quality besser nicht gesendet werden.
4.3. Objekt contact
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
firstName | string | ja | Vorname der Kontaktperson |
lastName | string | nein | Nachname der Kontaktperson |
phone | string | ja | Primäre Telefonnummer; empfohlenes Format E.164 |
email | string(email) | nein | Primäre E-Mail der Kontaktperson |
Der minimale Datensatz für die Bearbeitung einer Anfrage ist firstName und phone.
4.4. Objekt marketing
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
occurredAt | date-time | nein | Zeitpunkt der Formularübermittlung; wenn nicht angegeben, wird die CRM-Zeit verwendet |
visitorId | string | nein | Anonyme Besucher-ID |
sessionId | string | nein | ID der Website-Sitzung |
source | string | nein | Ereignisquelle, Standardwert website |
channel | string | nein | Kanal, z.B. paid, organic, social, email, direct |
utmSource | string | nein | Wert von utm_source |
utmMedium | string | nein | Wert von utm_medium |
utmCampaign | string | nein | Wert von utm_campaign |
utmContent | string | nein | Wert von utm_content |
utmTerm | string | nein | Wert von utm_term |
gclid | string | nein | Google Click Identifier |
fbclid | string | nein | Meta/Facebook Click Identifier |
landingUrl | string | nein | URL der Landingpage |
referrer | string | nein | URL der vorherigen Seite |
Personenbezogene Daten dürfen nicht im Marketing-Objekt dupliziert werden. Name, Telefon, E-Mail und Nachrichtentext werden nur in contact und lead übermittelt.
5. Minimale Anfrage
{
"externalId": "site-form-550e8400-e29b-41d4-a716-446655440000",
"lead": {
"leadSourceId": "7b33b18f-55bd-48a5-a8f0-e450a56dde47"
},
"contact": {
"firstName": "Ivan",
"phone": "+79991234567"
}
}
6. Erfolgreiche Antwort
Erste Anfrage — 201 Created
{
"leadId": "22222222-2222-2222-2222-222222222222",
"contactId": "33333333-3333-3333-3333-333333333333",
"phoneId": "44444444-4444-4444-4444-444444444444",
"emailId": "55555555-5555-5555-5555-555555555555",
"marketingEventId": "66666666-6666-6666-6666-666666666666",
"duplicate": false,
"createdAt": "2026-09-06T18:00:01Z"
}
Wenn keine E-Mail oder Marketingdaten übermittelt wurden, werden die entsprechenden IDs als null zurückgegeben.
Wiederholung mit derselben externalId — 200 OK
{
"leadId": "22222222-2222-2222-2222-222222222222",
"contactId": "33333333-3333-3333-3333-333333333333",
"phoneId": "44444444-4444-4444-4444-444444444444",
"emailId": "55555555-5555-5555-5555-555555555555",
"marketingEventId": "66666666-6666-6666-6666-666666666666",
"duplicate": true,
"createdAt": "2026-09-06T18:00:01Z"
}
Eine wiederholte Anfrage darf keinen zweiten Lead oder Kontakt erstellen.
7. cURL-Beispiel
curl -X POST "$CRM_BASE_URL/api/site/leads" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"externalId": "site-form-01J7K9A2M4Y5T6",
"lead": {
"leadSourceId": "7b33b18f-55bd-48a5-a8f0-e450a56dde47",
"quality": "WARM",
"message": "Rufen Sie mich zurück"
},
"contact": {
"firstName": "Ivan",
"lastName": "Ivanov",
"phone": "+79991234567",
"email": "ivan@example.com"
},
"marketing": {
"utmSource": "google",
"utmMedium": "cpc",
"utmCampaign": "crm-demo",
"landingUrl": "https://example.com/demo"
}
}'
8. TypeScript-Schnittstellen
type LeadQuality = 'HOT' | 'WARM' | 'COOL' | 'COLD';
interface SiteLeadRequest {
externalId?: string;
lead: {
leadSourceId: string;
quality?: LeadQuality;
message?: string;
};
contact: {
firstName: string;
lastName?: string;
phone: string;
email?: string;
};
marketing?: {
occurredAt?: string;
visitorId?: string;
sessionId?: string;
source?: string;
channel?: string;
utmSource?: string;
utmMedium?: string;
utmCampaign?: string;
utmContent?: string;
utmTerm?: string;
gclid?: string;
fbclid?: string;
landingUrl?: string;
referrer?: string;
};
}
interface SiteLeadResponse {
leadId: string;
contactId: string;
phoneId: string;
emailId: string | null;
marketingEventId: string | null;
duplicate: boolean;
createdAt: string;
}
9. Serverseitiges Beispiel
export async function sendLeadToCrm(payload: SiteLeadRequest): Promise<SiteLeadResponse> {
const response = await fetch(`${process.env.CRM_BASE_URL}/api/site/leads`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRM_ACCESS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});
if (!response.ok) {
const body = await response.text();
throw new Error(`ReactiveCRM returned ${response.status}: ${body}`);
}
return response.json() as Promise<SiteLeadResponse>;
}
10. Fehler
| HTTP | Ursache | Maßnahme für den Integrator |
|---|---|---|
400 | Formatfehler, Pflichtfeld fehlt, ungültige E-Mail/Telefon/quality | Daten korrigieren; nicht automatisch ohne Änderungen wiederholen |
401 | Token fehlt oder ist ungültig | Integrationstoken aktualisieren |
403 | Kein Zugriff auf Mandanten oder Operation | Benutzer und Integrationsrolle prüfen |
404 | leadSourceId im aktuellen Mandanten nicht gefunden | Quellen-ID in den Website-Einstellungen aktualisieren |
409 | externalId bereits mit inkompatibler Anfrage verknüpft | ID-Generierung und Integrationsprotokoll prüfen |
5xx | Vorübergehender CRM-Fehler | Dieselbe Anfrage mit derselben externalId wiederholen |
Beispiel für einen Validierungsfehler:
{
"status": 400,
"error": "Bad Request",
"message": "contact.phone must not be blank",
"path": "/api/site/leads"
}
11. Idempotenz
externalIdmuss innerhalb des Mandanten und der Quellewebsiteeindeutig sein.- Generieren Sie
externalIdvor der ersten Anfrage und speichern Sie es in der Website-Anfrage. - Bei Timeout wiederholen Sie die Anfrage mit demselben Body und derselben
externalId. - Erstellen Sie bei einer Wiederholung derselben Anfrage keine neue
externalId. - Wenn
duplicate: trueist, wurde die Anfrage bereits verarbeitet und gilt als erfolgreich zugestellt.
12. Kurzanleitung für Website-Entwickler
- Speichern Sie bei der ersten Sitzung UTM-Tags,
gclid,fbclid, URL der Landingpage und Referrer. - Generieren Sie bei der Formularübermittlung eine stabile
externalId. - Senden Sie das Formular an das Website-Backend.
- Das Backend fügt das CRM-Token hinzu und ruft
POST /api/site/leadsauf. - Bei
201oder200mitduplicate: truegilt die Anfrage als zugestellt. - Bei Timeout oder
5xxwiederholen Sie die Anfrage mit derselbenexternalId. - Senden Sie das CRM-Token niemals direkt aus dem Browser.
13. Was der CRM-Manager sieht
Nach einer erfolgreichen Anfrage erscheint im CRM ein Lead, der:
- die angegebene Quelle
leadSourceIdhat; - die Nachricht des Besuchers enthält;
- eine anfängliche Qualitätsbewertung hat, falls die Website sie übermittelt hat;
- mit einem Kontakt verknüpft ist, der Name und primäre Telefonnummer hat;
- mit der primären E-Mail verknüpft ist, falls angegeben;
- UTM-Metriken und Werbe-IDs für die Analyse speichert.
Dieser Datensatz reicht aus, damit der Manager die Anfrage sieht, den Kontakt anruft und den Lead qualifizieren kann.
Reactive CRM