addProject-API. V2 befindet sich aktuell in Beta hinter dem Feature-Flag showAddProjectV2. V1 (/addProject bzw. /v1/projects) bleibt parallel ohne Einschränkung verfügbar. Eine Übersicht der Unterschiede findest du am Ende dieses Dokuments im Abschnitt Unterschiede zu V1. Die v2 wird in naher Zukunft die v1 ablösen.Die addProject Funktion ermöglicht es externen Systemen, neue Projekte über eine HTTP-Schnittstelle anzulegen. Sie wird typischerweise verwendet, um Projektdaten von externen Quellen (z. B. Website-Formularen, Partner-Systemen, CRM/ERP) automatisiert zu übernehmen.
Die Funktion ermöglicht:
Das Erstellen neuer Projekte mit Gebäude- und Kontaktdaten über eine REST-API
Die sichere Authentifizierung mittels widerrufbarem JWT-Token (JTI-basierte Revokation)
Eine intelligente Kontaktauflösung (Verknüpfen statt immer neu Anlegen)
Detaillierte Eingabe-Validierung mit feldgenauen Fehlermeldungen
Die Verwendung von Projektvorlagen (Templates)
Die automatische E-Mail-Benachrichtigung bei Fehlern
showAddProjectV2 abgesichert. Ohne aktives Flag liefert der Endpunkt HTTP 403 zurück. Das Flag kannst du dir selbst freischalten unter Einstellungen → Im-/Export & Vorschau („Vorschau auf kommende Funktionen" → addProject Public API)Die Funktion verwendet JWT (JSON Web Token) zur Authentifizierung. Das Token wird als Query-Parameter token übergeben.
Wichtig: Die Freischaltung eines Tokens kann über den Support ermöglicht werden.
Nach Freischaltung kannst du das Token unter Einstellungen → Im-/Export & Vorschau generieren.
Tokens können in den Einstellungen jederzeit widerrufen werden. Nach einem Widerruf sind sowohl der widerrufene JTI-Token als auch alle Legacy-Tokens (ohne JTI) dauerhaft ungültig — auch dann, wenn das APP_SECRET weiterhin korrekt ist.
POST https://eba-api.azurewebsites.net/v2/projects?token=MEIN_TOKEN
POST
token (erforderlich): JWT-Token zur Authentifizierung
Der Request Body muss ein JSON-Objekt mit dem Feld data enthalten.
data (oberste Ebene)Parameter
Typ
Pflicht
Standard
Beschreibung
| Objekt | ja | – | Kontaktdaten des Kunden (siehe |
| Objekt | ja | – | Gebäudedaten (siehe |
| string | nein | automatisch | Freie Referenz für das Projekt. 🆕 V2: Wird kein Wert übergeben, generiert das System automatisch die nächste Nummer (basierend auf der zuletzt angelegten Projektreferenz, Fallback |
| string | nein |
| Interne Notiz zum Projekt |
| enum | nein |
| Status des Projekts (siehe Enum |
| string | nein |
| Projekttyp; überschreibt den Template-Typ, wenn |
| string | nein | – | UUID einer Projektvorlage, deren Struktur und Einstellungen übernommen werden |
client (Kontaktdaten)Parameter
Typ
Pflicht
Beschreibung
| string | nein (🆕 V2) | UUID eines bereits existierenden Kontakts. Wenn gesetzt, wird das Projekt direkt mit diesem Kontakt verknüpft (muss zur gleichen Organisation gehören, sonst HTTP 404). |
| string | nein (🆕 V2) | Kontaktnummer für neu angelegte Kontakte. Wird kein Wert übergeben, generiert das System automatisch die nächste Nummer (Fallback |
| string | nein | Vorname des Kunden |
| string | ja | Nachname des Kunden |
| string | nein | E-Mail-Adresse |
| string | nein | Telefonnummer |
| string | nein (🆕 V2) | Mobilnummer; wird zusätzlich zum Field-Matching herangezogen |
| enum | nein | Kontakttyp (siehe Enum |
| string | nein | Firmenname (relevant bei |
| string | nein | Vertreten durch |
| string | nein | Akademischer Titel, z. B. |
| string | nein | Anrede, z. B. |
| string | nein | Straße |
| string | nein | Hausnummer |
| string | nein | Postleitzahl |
| string | nein | Stadt |
building (Gebäudedaten)Parameter
Typ
Pflicht
Beschreibung
| string | ja | Straße des Gebäudes |
| string | ja | Hausnummer des Gebäudes |
| string | ja | Postleitzahl des Gebäudes |
| string | ja | Stadt des Gebäudes |
| number | nein | Baujahr des Gebäudes (z. B. |
| number | nein | Anzahl der Wohneinheiten im Gebäude |
| number | nein | Anzahl der Stockwerke |
| enum | nein | Primärer Gebäudetyp (siehe Enum |
| enum | nein | Nutzungsart des Gebäudes (siehe Enum |
| string | nein | Breitengrad (z. B. |
| string | nein | Längengrad (z. B. |
ProjectState (Feld: state)Wert
Bedeutung
Frontend-Label (sichtbar)
| Aktives Projekt (Standard) |
|
| Archiviert |
|
| Storniert |
|
| Lead |
|
🆕 V2-Unterschied:
TEMPLATEundSYSTEM_TEMPLATEsind über die API nicht erlaubt (HTTP 400 mitfield: "state"). Templates müssen ausschließlich innerhalb der App angelegt werden.
ContactType (Feld: client.type)Wert
Bedeutung
Frontend-Label (sichtbar)
| Natürliche Person |
|
| Unternehmen / juristische Person |
|
| Wohnungseigentümergemeinschaft |
|
BuildingType (Feld: building.usageType)Wert
Bedeutung
Frontend-Label (sichtbar)
| Wohngebäude |
|
| Nichtwohngebäude |
|
| Mischgebäude (Wohn- und Nichtwohnnutzung) |
|
UsageKindType (Feld: building.usageKind)Wert
Bedeutung
Frontend-Label (sichtbar)
| Vermietung |
|
| Eigennutzung |
|
| Gemischte Nutzung (Eigennutzung und Vermietung) |
|
Die folgenden Felder sind zwingend erforderlich:
client.lastName
building.address.street
building.address.houseNumber
building.address.zip
building.address.city
UUID-Format-Prüfung (HTTP 400 bei Verletzung):
data.templateId
data.client.contactId
{
"data": {
"client": {
"firstName": "Max",
"lastName": "Mustermann",
"email": "[email protected]",
"phone": "+49 123 456789",
"mobile": "+49 170 1234567",
"type": "PERSON",
"salutation": "Sehr geehrter"
},
"building": {
"address": {
"street": "Musterstraße",
"houseNumber": "42",
"zip": "12345",
"city": "Berlin"
},
"yearOfCompletion": 1990,
"numberOfFloors": 3,
"usageType": "RESIDENTIAL",
"usageKind": "OWNER_OCCUPIED_BUILDING",
"latitude": "52.520008",
"longitude": "13.404954"
},
"reference": "WEB-2026-001",
"note": "Importiert via Website",
"state": "ACTIVE",
"templateId": "123e4567-e89b-12d3-a456-426614174000"
}
}
{
"message": "Project created successfully",
"projectId": "8f3a…",
"contactId": "1c4b…",
"buildingId": "2d9e…",
"contactAction": "linked",
"buildingAction": "created"
}
Feld
Bedeutung
| UUID des neu erstellten Projekts |
| UUID des verknüpften oder neu angelegten Kontakts |
| UUID des verknüpften oder neu angelegten Gebäudes |
|
|
|
|
{ "error": "Unauthorized" }
{
"error": {
"message": "Die addProject API ist für diese Organisation noch nicht freigeschaltet. Bitte aktiviere die Beta-Funktion unter Einstellungen → Im-/Export & Vorschau."
}
}
V2 liefert eine Liste aller Validierungsfehler gleichzeitig zurück, jeweils mit field und message:
{
"error": {
"message": "Missing or invalid fields",
"fields": [
{ "field": "client.lastName", "message": "Pflichtfeld fehlt" },
{
"field": "building.usageType",
"message": "Ungültiger Wert. Erlaubt: RESIDENTIAL, NONRESIDENTIAL, MIXED"
}
]
}
}
Wird gesendet, wenn client.contactId angegeben ist, aber kein Kontakt mit dieser ID in der Organisation existiert:
{
"error": {
"message": "Kontakt mit der ID \"<id>\" wurde in dieser Organisation nicht gefunden."
}
}
Wird gesendet, wenn das Field-Matching mehr als einen Kontakt findet. Der Aufrufer muss client.contactId setzen, um den gewünschten Kontakt eindeutig zu identifizieren:
{
"error": "conflict",
"message": "Es wurden 3 Kontakte mit den übermittelten Daten gefunden. Übergib client.contactId um den gewünschten Kontakt eindeutig zu identifizieren. Die gefundenen Kandidaten stehen im Feld candidates.",
"candidates": [
{ "contactId": "8f3a…" },
{ "contactId": "1c4b…" },
{ "contactId": "2d9e…" }
]
}
{ "error": "<Fehlermeldung>" }
Token-Validierung – decodeJwt() prüft Signatur und JTI-Hash. Bei ungültigem oder widerrufenem Token: HTTP 401.
Feature-Flag-Guard – hasFeatureFlagForOrg('showAddProjectV2', organizationId). Ohne Flag: HTTP 403.
Eingabe-Validierung – validateInput() sammelt alle Fehler und gibt sie als Liste zurück (HTTP 400).
Projekttyp-Bestimmung – resolveProjectType(): explizites data.type → templateId.type → Standard "Anfrage/Angebot".
Kontaktauflösung – resolveContact() (siehe nächster Abschnitt).
Gebäudeauflösung – resolveBuilding() legt entweder ein neues Gebäude an oder verknüpft ein vorhandenes mit identischer Adresse.
Projekt-Erstellung – createProject() ruft createProjectInOrga auf und setzt anschließend note. Eine fehlende Vorlage mit Referenz "Anfrage/Angebot" (oder dem angegebenen Typ) führt zu einem 500-Fehler mit klarer Anleitung.
Aktivitäts-Log – queuelogActivity schreibt einen Erfolgs-Eintrag und benachrichtigt den Token-Owner.
Fehlerbehandlung – Bei Ausnahmen wird zusätzlich eine E-Mail an den Token-Owner mit Fehlermeldung und übermittelten Daten gesendet.
resolveContact) 🆕 V2Die V2-Logik verknüpft existierende Kontakte automatisch, statt bei jedem Import einen neuen Kontakt anzulegen:
Explizite contactId → Kontakt wird direkt verknüpft (contactAction: "linked"). Existiert die ID nicht in der Organisation, wird HTTP 404 zurückgegeben.
Field-Matching (greift, sobald mindestens eines der Felder firstName, email, phone, mobile oder companyName übergeben wurde):
Genau 1 Treffer → contactAction: "linked"
Mehrere Treffer → HTTP 409 (Conflict) mit Kandidatenliste
Kein Treffer → neuen Kontakt anlegen (contactAction: "created")
Nur lastName (kein weiteres Match-Feld) → Matching wird übersprungen, es wird immer ein neuer Kontakt angelegt.
Wenn data.reference bzw. client.reference leer sind:
Projekt-Referenz: getNextProjectReference(organizationId) – inkrementiert die Nummer der zuletzt nach createdAt angelegten Projekt-Referenz; Fallback 0001.
Kontakt-Referenz (nur bei Neuanlage): getNextContactReference(organizationId) – analog, basierend auf der zuletzt angelegten Kontakt-Referenz; Fallback 0001.
Bei parallelen Anfragen kann es kurzzeitig zu doppelten Referenzen kommen, da die Zähler nicht datenbankseitig gesperrt werden. Die Eindeutigkeit ist also keine harte Garantie – das gleiche Verhalten gilt auch für die Auto-Vervollständigung im Frontend.
curl -X POST "https://eba-api.azurewebsites.net/v2/projects?token=eyJhbGc..." \
-H "Content-Type: application/json" \
-d '{
"data": {
"client": {
"firstName": "Max",
"lastName": "Mustermann",
"email": "[email protected]",
"phone": "+49 123 456789",
"type": "PERSON",
"salutation": "Sehr geehrter"
},
"building": {
"address": {
"street": "Musterstraße",
"houseNumber": "42",
"zip": "12345",
"city": "Berlin"
},
"yearOfCompletion": 1990,
"numberOfFloors": 3,
"usageType": "RESIDENTIAL",
"usageKind": "OWNER_OCCUPIED_BUILDING",
"latitude": "52.520008",
"longitude": "13.404954"
},
"note": "Import von Website-Formular",
"reference": "WEB-2026-001",
"state": "ACTIVE"
}
}'
Ungültiges oder widerrufenes Token – Überprüfe, ob das Token korrekt generiert und nicht widerrufen wurde (Einstellungen → Im-/Export & Vorschau).
Feature-Flag inaktiv – Bei HTTP 403 das Beta-Flag addProject Public API selbst aktivieren unter Einstellungen → Im-/Export & Vorschau.
Validierungsfehler – HTTP 400 mit Feldliste; alle Verstöße werden auf einmal zurückgegeben.
Mehrdeutige Kontakte – HTTP 409 mit Kandidaten; aufrufendes System sollte client.contactId setzen.
Kontakt nicht gefunden – HTTP 404, wenn die übergebene client.contactId nicht zur Organisation gehört.
Fehlende Anfrage/Angebot-Vorlage – HTTP 500 mit Hinweis, dass eine Template-Vorlage mit Referenz "Anfrage/Angebot" benötigt wird oder ein expliziter type / templateId übergeben werden muss.
Bei serverseitigen Importfehlern (HTTP 500) wird automatisch eine E-Mail an den Token-Owner gesendet. Diese E-Mail enthält:
Eine benutzerfreundliche Fehlerbeschreibung
Die vollständigen übermittelten Daten zur Fehleranalyse
Kontaktinformationen für den Support
Bereich
V1 (/v1/projects)
V2 (/v2/projects, Beta)
Pfad |
|
|
Status | Stabil, parallel verfügbar | Beta hinter |
Feature-Flag | – (immer aktiv, sofern Token freigeschaltet) |
|
Token-Widerruf | Schwächere Garantien | Widerrufene Tokens sind sofort und dauerhaft ungültig und können nicht reaktiviert werden |
Kontaktauflösung | Immer neuer Kontakt | Smart: |
| Nicht unterstützt | Optional, UUID; verknüpft direkt mit existierendem Kontakt |
| Nicht unterstützt | Unterstützt (auch für Field-Matching) |
| Nicht unterstützt | Optional; bei Neuanlage; Auto-Generierung wenn leer |
| Pflicht/Default | Optional; Auto-Generierung ( |
| Beliebiger | Eingeschränkt auf |
Validierung | Erste Verletzung → 400 mit Sammeltext | Alle Verletzungen gleichzeitig als strukturierte Liste |
Validierungsformat |
|
|
Erfolgs-Response |
|
|
Gebäude-Auflösung | Adressbasiert, ohne Rückmeldung | Adressbasiert, mit |
Aktivitäts-Log | Vorhanden | Vorhanden – inkl. Benachrichtigung an den Token-Owner |
Bei Fragen zur Integration oder Problemen mit der API-Funktion erreichst du uns über den Support-Chat in der Anwendung. Das Beta-Feature-Flag addProject Public API kannst du selbst aktivieren unter Einstellungen → Im-/Export & Vorschau. Für die Freischaltung eines neuen Tokens wende dich bitte ebenfalls an den Support-Chat.