Session-basierte Authentifizierung. Nach erfolgreichen Login wird ein session Cookie gesetzt. Alle weiteren Requests benoetigen diesen Cookie. Alle Endpoints ausser POST /auth/login und GET /health liefern 401 wenn nicht angemeldet. Response-Format: {"ok": true/false, "data": ..., "error": "..."}

Authentifizierung

3 Endpoints
POST /auth/login Anmelden und Session starten

Request Body (JSON)

FeldTypPflichtBeschreibung
usernamestringJaBenutzername
passwordstringJaPasswort
rememberbooleanNeinSession dauerhaft merken (default: false)

Response 200

{ "ok": true, "data": { "id": 1, "username": "admin", "email": "...", "company_name": "..." } }

Response 401 - Ungueltige Anmeldedaten

{ "ok": false, "error": "Ungueltige Anmeldedaten" }

Try it

POST /auth/logout Session beenden

Request

Kein Body erforderlich. Benoetigt aktive Session.

Response 200

{ "ok": true, "data": { "message": "Abgemeldet" } }

Try it

GET /auth/me Aktuellen Benutzer abfragen

Response 200

{ "ok": true, "data": { "id": 1, "username": "admin", "email": "admin@example.com", "company_name": "VBWork", "created_at": "2026-01-01T00:00:00" } }

Try it

Projekte

5 Endpoints
GET /projects Alle Projekte des Benutzers

Response 200

[{ "id": 1, "user_id": 1, "name": "Maschinensteuerung", "description": "...", "page_count": 3, "created_at": "...", "updated_at": "...", "is_favorite": false }]

Try it

POST /projects Neues Projekt erstellen

Request Body (JSON)

FeldTypPflichtBeschreibung
namestringJaProjektname
descriptionstringNeinBeschreibung
page_formatstringNeinA4 (default), A3, A2
orientationstringNeinquer (default), hoch

Response 201

{ "ok": true, "data": { "id": 42, "name": "Mein Projekt", "page_count": 1, ... } }

Try it

GET /projects/{project_id} Projekt mit allen Seiten laden

URL Parameter

ParameterTypPflichtBeschreibung
project_idintegerJaProjekt-ID

Response 200

{ "ok": true, "data": { "id": 1, "name": "...", "pages": [{ "id": 1, "page_number": 1, "title": "Seite 1", "canvas_data": {...} }] } }

Try it

PUT /projects/{project_id} Projekt umbenennen / beschreiben

Request Body (JSON)

FeldTypPflichtBeschreibung
namestringNeinNeuer Name
descriptionstringNeinNeue Beschreibung

Response 200

{ "ok": true, "data": { "id": 1, "name": "Neuer Name", ... } }
DELETE /projects/{project_id} Projekt und alle Seiten loeschen

Response 200

{ "ok": true, "data": { "deleted": 1 } }

Hinweis

Loescht unwiderruflich alle Seiten, Elemente und Revisionen des Projekts.

Seiten (SchaltplanPages)

7 Endpoints
GET /projects/{project_id}/pages Alle Seiten eines Projekts

Response 200

[{ "id": 1, "project_id": 1, "page_number": 1, "title": "Seite 1", "page_format": "A4", "orientation": "quer", "canvas_data": { "elements": [], "wires": [] } }]
POST /projects/{project_id}/pages Neue Seite hinzufuegen

Request Body (JSON)

FeldTypPflichtBeschreibung
titlestringNeinSeitentitel (default: "Seite N")
page_formatstringNeinA4, A3, A2 (default: A4)
orientationstringNeinquer, hoch (default: quer)
canvas_dataobjectNeinInitiale Canvas-Daten: {elements:[], wires:[]}

canvas_data Struktur

{
  "elements": [
    { "id": "el_1", "symbolId": "ls3", "x": 200, "y": 300, "width": 60, "height": 60,
      "bmk": "-Q1", "label": "Leitungsschutzschalter", "voltage": "400V", "rotation": 0 }
  ],
  "wires": [
    { "id": "w_1", "segments": [{"x1":200,"y1":80,"x2":200,"y2":300}],
      "color": "#a0522d", "potential": "L1", "crossSection": "1.5", "number": "1" }
  ]
}
PUT /pages/{page_id} Seite speichern (Canvas-Daten, Titel, Format)

Request Body (JSON)

FeldTypPflichtBeschreibung
canvas_dataobjectNeinGesamter Canvas-Inhalt
titlestringNeinNeuer Seitentitel
page_formatstringNeinA4, A3, A2
orientationstringNeinquer, hoch

Revisions-System

Jede Speicherung erstellt automatisch einen Revisions-Snapshot in canvas_data._versions[]. Max. 20 Revisionen werden gespeichert.

GET /pages/{page_id}/versions Versions-History einer Seite

Response 200

[{ "timestamp": "2026-03-23T12:00:00", "elements": [...], "wires": [...] }]
POST /pages/{page_id}/versions/{version_idx}/restore Version wiederherstellen

Response 200

{ "ok": true, "data": { "restored": true, "timestamp": "2026-03-23T12:00:00" } }
DELETE /pages/{page_id} Seite loeschen (mind. 1 Seite bleibt)

Response 200

{ "ok": true, "data": { "deleted": 5 } }

Response 400 - Letzte Seite

{ "ok": false, "error": "Mindestens eine Seite muss vorhanden sein" }
PUT /pages/{page_id}/reorder Seite an neue Position verschieben

Request Body (JSON)

FeldTypPflichtBeschreibung
page_numberintegerJaNeue Seitennummer

Symbole

4 Endpoints
GET /symbols Symbole suchen und filtern

Query Parameter

ParameterTypPflichtBeschreibung
categorystringNeinKategorie-Filter (z.B. "Schuetze")
searchstringNeinSuche in Name, Beschreibung, IEC-Nummer

Response 200

[{ "id": 1, "name": "Schuetz 3-polig", "category": "Schuetze", "subcategory": "", "description": "...", "iec_number": "IEC 60617", "tags": ["motor", "3ph"], "is_custom": false }]

Try it

GET /symbols/categories Alle Kategorien mit Symbolanzahl

Response 200

{ "ok": true, "data": { "categories": [{ "name": "Schuetze", "symbols": [...], "count": 12 }] } }

Try it

GET /symbols/{symbol_id}/svg SVG-Rohdaten eines Symbols

Response

Content-Type: image/svg+xml. Gibt das SVG direkt zurueck (kein JSON-Wrapper).

POST /symbols Eigenes Symbol erstellen

Request Body (JSON)

FeldTypPflichtBeschreibung
namestringJaSymbolname
categorystringJaKategorie
svg_datastringJaSVG-Quellcode (wird sanitized)
descriptionstringNeinBeschreibung
iec_numberstringNeinIEC 60617 Nummer
tagsarrayNeinTags fuer Suche

Sicherheitshinweis

SVG-Daten werden vor dem Speichern automatisch sanitized: <script>, <foreignObject> und javascript: URLs werden entfernt.

Export & Dokumentation

10 Endpoints
POST /projects/{project_id}/export/pdf Schaltplan als PDF exportieren

Request Body (JSON)

FeldTypPflichtBeschreibung
pagesarray[int]NeinSeiten-IDs zum Export. Leer = alle Seiten
companyobjectNeinFirmendaten fuer Schriftfeld
with_schriftfeldbooleanNeinDIN-Schriftfeld einblenden (default: true)

Response

Content-Type: application/pdf. Direkt als Datei-Download.

POST /projects/{project_id}/export/complete Komplette Dokumentation (Deckblatt + alle Seiten + BOM + Klemm + Kabel + Pruefprotokoll)

Inhalt des generierten PDFs

1. Deckblatt (A3 quer, DIN EN 61082) • 2. Inhaltsverzeichnis • 3. Alle Schaltplan-Seiten • 4. Stueckliste (BOM) • 5. Klemmplan • 6. Kabelplan • 7. Pruefprotokoll-Vorlage nach VDE 0100-600

Response

Content-Type: application/pdf

GET /projects/{project_id}/bom Stueckliste (Bill of Materials) generieren

Response 200

{ "ok": true, "data": { "items": [{ "Pos": 1, "BMK": "-Q1", "Bezeichnung": "Leitungsschutzschalter", "Hersteller": "", "Bestellnummer": "", "Symbol": "ls3", "Seite": "Seite 1", "Menge": 1 }], "total": 5 } }

Try it

GET /projects/{project_id}/bom/csv Stueckliste als CSV (Excel-kompatibel)

Response

Content-Type: text/csv; charset=utf-8. Semikolon-separiert, UTF-8 BOM fuer Excel.

GET /projects/{project_id}/klemmplan Klemmplan-Daten abrufen

Response 200

{ "ok": true, "data": { "terminals": [...], "groups": { "X1": [...] }, "total": 12, "project": "Mein Projekt" } }
POST /projects/{project_id}/klemmplan/pdf Klemmplan als PDF (grafische Klemmen-Darstellung nach DIN EN 61082)

Response

Content-Type: application/pdf

GET /projects/{project_id}/kabelplan Kabelplan / Verdrahtungsplan

Response 200

{ "ok": true, "data": { "cables": [{ "number": "1", "potential": "L1", "cable": "", "cross_section": "1.5", "color": "#a0522d", "page": "Seite 1", "length_approx": 250, "from_bmk": "-Q1", "to_bmk": "-K1" }], "total": 8, "total_length_mm": 2400 } }
GET /projects/{project_id}/querverweise Querverweisliste: BMK-Vorkommen ueber alle Seiten

Response 200

{ "ok": true, "data": { "references": [{ "bmk": "-K1", "label": "Hauptschuetz", "symbol": "main_contactor", "occurrences": [{"page": "Seite 1", "page_number": 1, "x": 200, "y": 340}] }], "total": 5, "multi_page": [...] } }
GET /projects/{project_id}/kontaktspiegel/{bmk} Kontaktspiegel fuer ein Geraet

URL Parameter

ParameterTypBeschreibung
bmkstringBMK-Bezeichner (z.B. "-K1")

Response 200

{ "ok": true, "data": { "bmk": "-K1", "contacts": [{ "contact_nr": "13", "type": "NO", "page": "Seite 2", "connected_to": "-F1" }] } }
POST /pruefprotokoll/export Pruefprotokoll nach VDE 0100-600 als PDF

Request Body (JSON)

FeldTypBeschreibung
anlagestringAnlagenbezeichnung
standortstringStandort der Anlage
auftraggeberstringAuftraggeber
prueferstringName des Pruefers
datumstringPruef-Datum (DD.MM.YYYY)
normstringPruefnorm (default: "VDE 0100-600")
messungenarrayMessergebnisse

KI / DeepSeek Integration

4 Endpoints
POST /ki/generate Schaltplan-Elemente aus Textbeschreibung generieren

Request Body (JSON)

FeldTypPflichtBeschreibung
promptstringJaNatuerlichsprachliche Beschreibung (z.B. "Erstelle einen Direktstarter fuer einen 4kW Motor")

Response 200

{ "ok": true, "data": { "elements": [
  { "type": "busline", "y": 80, "label": "L1", "color": "#a0522d" },
  { "type": "symbol", "symbolFile": "schuetze/contactor-3p.svg", "x": 200, "y": 340, "bmk": "-K1" },
  { "type": "wire", "segments": [{"x1":200,"y1":80,"x2":200,"y2":340}] }
] } }

Modell

DeepSeek Chat API (deepseek-chat), temperature=0.3, max_tokens=4000. Timeout: 60s.

Try it

POST /ki/edit Bestehenden Schaltplan per Textbefehl aendern

Request Body (JSON)

FeldTypPflichtBeschreibung
promptstringJaAenderungsbefehl (z.B. "Fuege eine zweite Sicherung hinzu")
elementsarrayJaAktuelle Canvas-Elemente

Response 200

{ "ok": true, "data": { "add": [...], "remove": [...], "modify": [...] } }
POST /ki/vde-check VDE-Konformitaetspruefung per KI

Request Body (JSON)

FeldTypBeschreibung
elementsarrayCanvas-Elemente
wiresarrayLeitungen

Response 200

{ "ok": true, "data": { "issues": [{ "type": "warning", "message": "...", "rule": "VDE 0100" }], "score": 85 } }
POST /projects/{project_id}/bmk/check BMK-Eindeutigkeit pruefen

Request Body

{ "bmk": "-K1" }

Response 200

{ "ok": true, "data": { "unique": false, "existing_pages": [1, 3] } }

Makros, Templates & Sonstiges

7 Endpoints
GET /health Service-Health pruefen (kein Login noetig)

Response 200

{ "ok": true, "data": { "status": "ok", "service": "benning-ecad", "version": "1.0.0" } }

Try it

GET /macros Alle verfuegbaren Makros (vordefinierte Schaltungsgruppen)

Verfuegbare Makros

IDNameKategorieElemente
direktstarterDirektstarterMotorsteuerung4
stern_dreieckStern-Dreieck-AnlaufMotorsteuerung7
wendeschaltungWendeschaltungMotorsteuerung5
steckdosenabzweigSteckdosenabzweigNiederspannung5
beleuchtungsabzweigBeleuchtungsabzweigNiederspannung4

Try it

GET /macros/{macro_id} Einzelnes Makro mit allen Elementen

Response 200

{ "ok": true, "data": { "id": "direktstarter", "name": "Direktstarter", "elements": [{ "symId": "ls3", "dx": 0, "dy": 0, "w": 60, "h": 60, "label": "LS", "bmk_prefix": "-Q" }], "wires": [] } }
GET /project-templates Projekt-Templates abrufen

Response 200

[{ "id": "empty", "name": "Leeres Projekt", "description": "...", "pages_count": 1 }]
POST /projects/from-template Projekt aus Template erstellen

Request Body (JSON)

FeldTypPflichtBeschreibung
namestringJaProjektname
template_idstringNeinTemplate-ID (default: "empty")
descriptionstringNeinProjektbeschreibung
GET /templates Schriftfeld-Templates abrufen

Response 200

[{ "id": 1, "name": "Standard A4", "format": "A4", "company_data": {}, "logo_path": "" }]
GET /projects/{project_id}/potential-arrows Potentialpfeile / Seitenverknuepfungen

Response 200

{ "ok": true, "data": { "potentials": { "L1": [{ "page": "Seite 1", "direction": "out" }] } } }