company logo

Hilfe Center

Anmelden
Zur WebsiteZur AppImpressumDatenschutzAGBs
Alle SammlungenProjekteVor dem ProjektAPI-Funktion Projekterstellung V2 (Beta)

API-Funktion Projekterstellung V2 (Beta)

Diese Funktion stellt die Projekterstellung (addProject) via Schnittstelle (API) bereit. Hierbei handelt es sich um die v2, die in naher Zukunft die v1 ablösen wird.

info icon
Dies ist die Dokumentation der V2 der 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.

Übersicht

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.

Zweck

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

Voraussetzungen

info icon
Beta-Feature-Flag
V2 ist hinter dem Beta-Feature-Flag 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)

Authentifizierung

JWT-Token

Die Funktion verwendet JWT (JSON Web Token) zur Authentifizierung. Das Token wird als Query-Parameter token übergeben.

Token-Freischaltung

Wichtig: Die Freischaltung eines Tokens kann über den Support ermöglicht werden.

Nach Freischaltung kannst du das Token unter Einstellungen → Im-/Export & Vorschau generieren.

Widerruf (Revoke)

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.

API-Endpunkt

POST https://eba-api.azurewebsites.net/v2/projects?token=MEIN_TOKEN

HTTP-Methode

POST

URL-Parameter

  • token (erforderlich): JWT-Token zur Authentifizierung

Request Body

Der Request Body muss ein JSON-Objekt mit dem Feld data enthalten.

Parameter-Übersicht

data (oberste Ebene)

Parameter

Typ

Pflicht

Standard

Beschreibung

client

Objekt

ja

–

Kontaktdaten des Kunden (siehe client-Parameter). client.lastName ist Pflicht. Über client.contactId kannst du das Projekt direkt mit einem existierenden Kontakt verknüpfen, andernfalls greift die Kontaktauflösung.

building

Objekt

ja

–

Gebäudedaten (siehe building-Parameter)

reference

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 0001).

note

string

nein

"Importiert via addProject API"

Interne Notiz zum Projekt

state

enum

nein

"ACTIVE"

Status des Projekts (siehe Enum ProjectState). 🆕 V2: TEMPLATE und SYSTEM_TEMPLATE sind explizit verboten.

type

string

nein

"Anfrage/Angebot"

Projekttyp; überschreibt den Template-Typ, wenn templateId angegeben ist. Ohne type und templateId wird "Anfrage/Angebot" verwendet.

templateId

string

nein

–

UUID einer Projektvorlage, deren Struktur und Einstellungen übernommen werden

client (Kontaktdaten)

Parameter

Typ

Pflicht

Beschreibung

contactId

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).

reference

string

nein (🆕 V2)

Kontaktnummer für neu angelegte Kontakte. Wird kein Wert übergeben, generiert das System automatisch die nächste Nummer (Fallback 0001).

firstName

string

nein

Vorname des Kunden

lastName

string

ja

Nachname des Kunden

email

string

nein

E-Mail-Adresse

phone

string

nein

Telefonnummer

mobile

string

nein (🆕 V2)

Mobilnummer; wird zusätzlich zum Field-Matching herangezogen

type

enum

nein

Kontakttyp (siehe Enum ContactType)

companyName

string

nein

Firmenname (relevant bei type: "COMPANY")

representedBy

string

nein

Vertreten durch

title

string

nein

Akademischer Titel, z. B. "Dr.", "Prof.", "Prof. Dr."

salutation

string

nein

Anrede, z. B. "Hallo", "Sehr geehrte", "Sehr geehrter", "Guten Tag"

address.street

string

nein

Straße

address.houseNumber

string

nein

Hausnummer

address.zip

string

nein

Postleitzahl

address.city

string

nein

Stadt

building (Gebäudedaten)

Parameter

Typ

Pflicht

Beschreibung

address.street

string

ja

Straße des Gebäudes

address.houseNumber

string

ja

Hausnummer des Gebäudes

address.zip

string

ja

Postleitzahl des Gebäudes

address.city

string

ja

Stadt des Gebäudes

yearOfCompletion

number

nein

Baujahr des Gebäudes (z. B. 1990)

numberOfPartiesInBuilding

number

nein

Anzahl der Wohneinheiten im Gebäude

numberOfFloors

number

nein

Anzahl der Stockwerke

livingArea

number

nein (🆕 V2)

Wohnfläche des Gebäudes in m², als ganze Zahl (z. B. 145). Wird ohne eigene Validierung übernommen - Dezimalwerte führen zu einem Fehler.

usageType

enum

nein

Primärer Gebäudetyp (siehe Enum BuildingType)

usageKind

enum

nein

Nutzungsart des Gebäudes (siehe Enum UsageKindType)

latitude

string

nein

Breitengrad (z. B. "52.520008")

longitude

string

nein

Längengrad (z. B. "13.404954")

Enum-Werte

Enum ProjectState (Feld: state)

Wert

Bedeutung

Frontend-Label (sichtbar)

ACTIVE

Aktives Projekt (Standard)

Aktiv (wartend und in Arbeit)

ARCHIVED

Archiviert

Abgeschlossen (teilweise auch Archiviert je nach Ansicht)

CANCELED

Storniert

Abgebrochen

LEAD

Lead

Lead

🆕 V2-Unterschied: TEMPLATE und SYSTEM_TEMPLATE sind über die API nicht erlaubt (HTTP 400 mit field: "state"). Templates müssen ausschließlich innerhalb der App angelegt werden.

Enum ContactType (Feld: client.type)

Wert

Bedeutung

Frontend-Label (sichtbar)

PERSON

Natürliche Person

Privatperson

COMPANY

Unternehmen / juristische Person

Unternehmen

WEG

Wohnungseigentümergemeinschaft

WEG

Enum BuildingType (Feld: building.usageType)

Wert

Bedeutung

Frontend-Label (sichtbar)

RESIDENTIAL

Wohngebäude

Wohngebäude

NONRESIDENTIAL

Nichtwohngebäude

Nicht-Wohngebäude

MIXED

Mischgebäude (Wohn- und Nichtwohnnutzung)

Mischgebäude

Enum UsageKindType (Feld: building.usageKind)

Wert

Bedeutung

Frontend-Label (sichtbar)

LEASED_BUILDING

Vermietung

Vermietung (ausschließlich)

OWNER_OCCUPIED_BUILDING

Eigennutzung

Eigennutzung (ausschließlich)

MIXED_SELFUSE_LEASED

Gemischte Nutzung (Eigennutzung und Vermietung)

Eigennutzung und Vermietung

Pflichtfelder

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

Beispiel-Request-Body

{
  "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,
      "livingArea": 145,
      "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"
  }
}

Response

Erfolgreiche Antwort (HTTP 200) 🆕 erweitert in V2

{
  "message": "Project created successfully",
  "projectId": "8f3a…",
  "contactId": "1c4b…",
  "buildingId": "2d9e…",
  "contactAction": "linked",
  "buildingAction": "created"
}

Feld

Bedeutung

projectId

UUID des neu erstellten Projekts

contactId

UUID des verknüpften oder neu angelegten Kontakts

buildingId

UUID des verknüpften oder neu angelegten Gebäudes

contactAction

"created" (neu angelegt) oder "linked" (existierender Kontakt verknüpft)

buildingAction

"created" (neu angelegt) oder "linked" (existierendes Gebäude verknüpft, gleiche Adresse vorhanden)

Fehlerhafte Authentifizierung (HTTP 401)

{ "error": "Unauthorized" }

Feature-Flag fehlt (HTTP 403) 🆕 V2

{
  "error": {
    "message": "Die addProject API ist für diese Organisation noch nicht freigeschaltet. Bitte aktiviere die Beta-Funktion unter Einstellungen → Im-/Export & Vorschau."
  }
}

Validierungsfehler (HTTP 400) 🆕 strukturierter in V2

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

Kontakt nicht gefunden (HTTP 404) 🆕 V2

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

Mehrdeutige Kontaktauflösung (HTTP 409) 🆕 V2

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…" }
  ]
}

Fehler beim Import (HTTP 500)

{ "error": "<Fehlermeldung>" }

Technische Details

Funktionsablauf (V2)

  1. Token-Validierung – decodeJwt() prüft Signatur und JTI-Hash. Bei ungültigem oder widerrufenem Token: HTTP 401.

  2. Feature-Flag-Guard – hasFeatureFlagForOrg('showAddProjectV2', organizationId). Ohne Flag: HTTP 403.

  3. Eingabe-Validierung – validateInput() sammelt alle Fehler und gibt sie als Liste zurück (HTTP 400).

  4. Projekttyp-Bestimmung – resolveProjectType(): explizites data.type → templateId.type → Standard "Anfrage/Angebot".

  5. Kontaktauflösung – resolveContact() (siehe nächster Abschnitt).

  6. Gebäudeauflösung – resolveBuilding() legt entweder ein neues Gebäude an oder verknüpft ein vorhandenes mit identischer Adresse.

  7. 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.

  8. Aktivitäts-Log – queuelogActivity schreibt einen Erfolgs-Eintrag und benachrichtigt den Token-Owner.

  9. Fehlerbehandlung – Bei Ausnahmen wird zusätzlich eine E-Mail an den Token-Owner mit Fehlermeldung und übermittelten Daten gesendet.

Kontaktauflösung (resolveContact) 🆕 V2

Die V2-Logik verknüpft existierende Kontakte automatisch, statt bei jedem Import einen neuen Kontakt anzulegen:

  1. Explizite contactId → Kontakt wird direkt verknüpft (contactAction: "linked"). Existiert die ID nicht in der Organisation, wird HTTP 404 zurückgegeben.

  2. 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")

  3. Nur lastName (kein weiteres Match-Feld) → Matching wird übersprungen, es wird immer ein neuer Kontakt angelegt.

Auto-Referenz-Generierung 🆕 V2

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.

Beispiel-Aufruf

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,
        "livingArea": 145,
        "usageType": "RESIDENTIAL",
        "usageKind": "OWNER_OCCUPIED_BUILDING",
        "latitude": "52.520008",
        "longitude": "13.404954"
      },
      "note": "Import von Website-Formular",
      "reference": "WEB-2026-001",
      "state": "ACTIVE"
    }
  }'

Fehlerbehandlung

Häufige Fehlerszenarien

  1. Ungültiges oder widerrufenes Token – Überprüfe, ob das Token korrekt generiert und nicht widerrufen wurde (Einstellungen → Im-/Export & Vorschau).

  2. Feature-Flag inaktiv – Bei HTTP 403 das Beta-Flag addProject Public API selbst aktivieren unter Einstellungen → Im-/Export & Vorschau.

  3. Validierungsfehler – HTTP 400 mit Feldliste; alle Verstöße werden auf einmal zurückgegeben.

  4. Mehrdeutige Kontakte – HTTP 409 mit Kandidaten; aufrufendes System sollte client.contactId setzen.

  5. Kontakt nicht gefunden – HTTP 404, wenn die übergebene client.contactId nicht zur Organisation gehört.

  6. 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.

E-Mail-Benachrichtigung bei Fehlern

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

Unterschiede zu V1

Bereich

V1 (/v1/projects)

V2 (/v2/projects, Beta)

Pfad

/addProject bzw. /v1/projects

/v2/projects

Status

Stabil, parallel verfügbar

Beta hinter showAddProjectV2

Feature-Flag

– (immer aktiv, sofern Token freigeschaltet)

showAddProjectV2 (Beta) – ohne Flag HTTP 403

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: contactId → Field-Matching → Neu-Anlage; Konflikte werden mit HTTP 409 + Kandidatenliste zurückgegeben

client.contactId

Nicht unterstützt

Optional, UUID; verknüpft direkt mit existierendem Kontakt

client.mobile

Nicht unterstützt

Unterstützt (auch für Field-Matching)

client.reference

Nicht unterstützt

Optional; bei Neuanlage; Auto-Generierung wenn leer

building.livingArea

Nicht unterstützt

Optional; Wohnfläche in m² (ganze Zahl)

data.reference

Pflicht/Default "WEBSITE"

Optional; Auto-Generierung (getNextProjectReference) wenn leer

data.state

Beliebiger ProjectState-Wert

Eingeschränkt auf ACTIVE, ARCHIVED, CANCELED, LEAD – TEMPLATE/SYSTEM_TEMPLATE sind verboten

Validierung

Erste Verletzung → 400 mit Sammeltext

Alle Verletzungen gleichzeitig als strukturierte Liste [{ field, message }]

Validierungsformat

{ "error": { "message": "Missing or invalid mandatory fields: ..." } }

{ "error": { "message": "Missing or invalid fields", "fields": [{ "field": "...", "message": "..." }] } }

Erfolgs-Response

{ "message": "Project added successfully" }

{ "message": "Project created successfully", "projectId": "...", "contactId": "...", "buildingId": "...", "contactAction": "...", "buildingAction": "..." }

Gebäude-Auflösung

Adressbasiert, ohne Rückmeldung

Adressbasiert, mit buildingAction ("created" oder "linked") in der Response

Aktivitäts-Log

Vorhanden

Vorhanden – inkl. Benachrichtigung an den Token-Owner

Wartung und Support

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.

War diese Antwort hilfreich für dich?
😞
😐
😁