Eviworx
Docs

Cost Centers API

Die Cost-Centers-API verwaltet Kostenstellen als zentrale Stammdaten — mit Code/Name, Lifecycle (DRAFT/ACTIVE/CLOSED), Gültigkeitszeitraum, Budget, Hierarchie (Kostenstellengruppen/Rollups), Verantwortlichem und ERP-Sync. Kostenstellen werden Assets, Verträgen und Lizenzen per costCenterId zugewiesen und bilden die Grundlage der Kostenberichte.

🏷️
Funktionen
✓ Lifecycle DRAFT → ACTIVE → CLOSED
✓ Gültigkeitszeitraum (validFrom/validUntil)
✓ Hierarchie (parentId, Rollups)
✓ Budget & Owner
✓ ERP-Sync (idempotenter Import)
✓ Merge (Kostenstellen zusammenführen)
✓ Soft-Delete (CLOSED)
✓ Zuweisung an Asset/Contract/License

Authentifizierung & Permissions

Jede Aktion hat ein eigenes Recht unter costCenters.*, das für alle Kostenstellen gleichermaßen gilt. Einschränkungen auf einzelne Kostenstellen oder deren Verantwortliche gibt es nicht. Details siehe User Management & RBAC.

Aktion Permission
Anzeigen / Liste / SuchecostCenters.view
Budget-Beträge sehen und setzencostCenters.viewBudget
ErstellencostCenters.create
AktualisierencostCenters.update
Löschen (Soft-Delete)costCenters.delete
ZusammenführencostCenters.merge (Default: Admin)
Import / ERP-SynccostCenters.import

Benutzer und API-Keys: Alle Lesezugriffe (Liste, Suche, Detail, Aktivitätsverlauf) stehen angemeldeten Benutzern und API-Keys mit costCenters.view gleichermaßen offen — der ERP-Key, der importieren darf, kann also auch die Liste zum Abgleich lesen. Anlegen, Ändern, Löschen und Zusammenführen erfordern einen angemeldeten Benutzer; ein X-API-Key wird dort mit 403 abgelehnt ("This operation requires a logged-in user account, not an API key"). POST /api/cost-centers/import akzeptiert beides. So bleibt die manuelle Pflege einer Person zugeordnet (Audit), während Lesen und ERP-Sync per Key laufen.

Budget-Beträge sind gesondert geschützt: Ohne costCenters.viewBudget enthält jede Antwort budget: null — Liste, Detail und auch die Antwort auf Anlegen/Ändern. Das Feld ist immer vorhanden, nur der Wert fehlt. Mit 403 COST_CENTER_BUDGET_FORBIDDEN abgelehnt werden: Sortieren nach Budget (?sort=budget:…, die Reihenfolge würde die Beträge verraten) und budget im Anlege-/Änderungs-Body. Im Import wird die betroffene Zeile als fehlerhaft gemeldet, der Import läuft weiter. Wer das Budget nicht sehen darf, darf es auch nicht setzen. Im Kostenbericht steuert reports.viewBudget die Sichtbarkeit derselben Beträge.

Endpoints Übersicht

Method Endpoint Beschreibung Permission
GET/api/cost-centersPaginierte, filter-spec-getriebene ListecostCenters.view
GET/api/cost-centers/search?q=&per=Suche für Auswahlfelder: nur zuweisbare (ACTIVE und gültige) Kostenstellen. Erlaubt sind nur q und per; andere Parameter (z. B. limit) → 400costCenters.view
GET/api/cost-centers/:idEinzelne KostenstellecostCenters.view
GET/api/cost-centers/:id/activitiesActivity-Trail der KostenstellecostCenters.view
POST/api/cost-centersKostenstelle erstellen (source=MANUAL)costCenters.create
PATCH/api/cost-centers/:idKostenstelle aktualisierencostCenters.update
DELETE/api/cost-centers/:idSoft-Delete (Status → CLOSED) → 204; mit aktiven Unterkostenstellen: 400 COST_CENTER_HAS_CHILDREN (+ details.children)costCenters.delete
POST/api/cost-centers/:id/mergeReferenzen (Assets/Verträge/Lizenzen) UND Kinder auf targetId umhängen, Quelle schließen — alles in einem Schritt. Das Ziel muss zuweisbar sein und darf keine Unterkostenstelle der Quelle sein. Bei zwei gleichzeitigen, gegenläufigen Merges verliert einer mit 409 COST_CENTER_MERGE_CONFLICTcostCenters.merge
POST/api/cost-centers/importIdempotenter Upsert (ERP-Sync, source=SYNCED) — User ODER API-KeycostCenters.import

Felder

Feld Typ Beschreibung
codeString (1–50)Kostenstellen-Nr./-Kürzel — eindeutig, Pflicht
nameString (1–200)Anzeigename — Pflicht
descriptionString? (≤2000)Beschreibung
colorString (#rrggbb)Badge-Farbe (Default #3b82f6)
sortOrderIntSortierreihenfolge (nur via Import setzbar, kein Create/Update-Input)
statusenumDRAFT, ACTIVE, CLOSED
validFrom / validUntilDateTime?Gültigkeitszeitraum (steuert Zuweisbarkeit); validFrom ≤ validUntil erzwungen (400 COST_CENTER_VALIDITY_INVALID)
ownerIdString?Verantwortlicher User — muss existieren und darf nicht archiviert sein (400 COST_CENTER_OWNER_NOT_FOUND)
budgetDecimal? (14,2)Budget (in Systemwährung — siehe unten)
parentIdString?Übergeordnete Kostenstelle (Hierarchie/Rollups). Löschen räumt die Hierarchie NICHT auf — Kinder hängt nur der Merge um, damit ein Umbau eine bewusste Entscheidung bleibt
externalIdString? (≤100)Stabiler ERP-Schlüssel (SAP/DATEV) — eindeutig
sourceenumMANUAL, SYNCED (read-only, vom System gesetzt)

Währung: Kostenstellen haben kein eigenes Währungsfeld — budget wird in der globalen Systemwährung (general settings: systemCurrency) interpretiert. Es findet keine Umrechnung statt. Siehe Settings & Global Search API.

Kostenstelle erstellen

POST /api/cost-centers
{
  "code": "CC-1000",
  "name": "IT Operations",
  "description": "Betrieb & Infrastruktur",
  "color": "#3b82f6",
  "status": "ACTIVE",
  "validFrom": "2026-01-01T00:00:00Z",
  "ownerId": "clx-user-id",
  "budget": 250000.00,
  "parentId": "clx-parent-cost-center-id"
}

Response (201 Created)

{
  "id": "clx...",
  "code": "CC-1000",
  "name": "IT Operations",
  "status": "ACTIVE",
  "color": "#3b82f6",
  "source": "MANUAL",
  "createdAt": "2026-06-18T08:00:00.000Z"
}

Über diese Route ist source immer MANUAL. SYNCED-Datensätze entstehen ausschließlich über den Import-/ERP-Sync-Endpoint.

ERP-Import (Sync)

Idempotenter Upsert, gekeyt auf externalId (falls vorhanden), sonst code. Importierte Datensätze werden mit source=SYNCED markiert. Ein zuvor soft-gelöschter Code wird beim erneuten Import wiederhergestellt. Bis zu 1000 Einträge pro Request. Dieser Endpoint akzeptiert sowohl User- als auch API-Key-Aktoren.

POST /api/cost-centers/import
X-API-Key: <your-api-key>
{
  "items": [
    {
      "code": "CC-1000",
      "name": "IT Operations",
      "externalId": "SAP-1000",
      "status": "ACTIVE",
      "budget": 250000.00
    },
    {
      "code": "CC-2000",
      "name": "Facility Management",
      "externalId": "SAP-2000",
      "status": "ACTIVE"
    }
  ]
}

Hinweis: parentId (cuid) ist optional; eine Hierarchie-Verknüpfung per Parent-Code wird hier bewusst NICHT unterstützt (dafür Update/UI nutzen).

Lifecycle & Zuweisbarkeit

Status Beschreibung
DRAFTEntwurf — noch nicht zuweisbar
ACTIVEAktiv — innerhalb des Gültigkeitszeitraums zuweisbar
CLOSEDGeschlossen (Soft-Delete) — nicht mehr zuweisbar

Kostenstellen werden Assets, Verträgen und Lizenzen über das Feld costCenterId zugewiesen. Die Zuweisbarkeit prüft der Server: nur ACTIVE-Kostenstellen innerhalb ihres Gültigkeitszeitraums sind zuweisbar — eine CLOSED oder abgelaufene Kostenstelle führt zu 400 Bad Request. Die Zuweisung ist ein einfaches Feld am jeweiligen Objekt, keine Verknüpfung über die Linking-API.

Assets API →
costCenterId an Assets
Contracts & Licenses API →
costCenterId an Verträgen/Lizenzen
Reports API →
Kostenberichte je Kostenstelle