Users, Roles & Agent Groups API
Diese API umfasst User-Management, dynamisches Role-Based Access Control (RBAC), die Manager-Hierarchie (Organigramm), Agents inkl. Agent-Groups mit Assignment-Strategien sowie Specialties (Skill-Routing). Das Auth-/Permission-Modell selbst ist zentral beschrieben unter Permissions & RBAC.
Abwesenheiten/Vertretung (mit Manager-Genehmigung) sind eine eigene Domain: Absences API. Rechte-Auflösung, Cache & kritische Aktionen: Permissions & RBAC.
Vorinstallierte Rollen
Neben den System-Rollen lassen sich beliebig viele Custom-Rollen anlegen, jede mit eigenem Permission-Set und einer Priorität (Reihenfolge/Vorrang). System-Rollen (isSystem) lassen sich weder deaktivieren noch löschen noch verschieben. Vorinstalliert sind die vier System-Rollen und die Rolle DATA_PROTECTION_OFFICER, die als Custom-Rolle angelegt ist:
| Role | Zweck |
|---|---|
END_USER | Kunde/Requester — eigene Tickets |
AGENT | Support-Agent — alle Tickets/Problems verwalten |
ADMIN | Administrator — voller Zugriff |
APPROVER | Change-Approver |
DATA_PROTECTION_OFFICER | Datenschutzbeauftragter (DSGVO: Breach-Details, Incident-Einsicht, Audit); Custom-Rolle, isSystem = false |
User-Endpoints /api/users
| Method | Endpoint | Beschreibung |
|---|---|---|
GET | / | Liste (Filter/Suche); anonymisierte User default ausgeblendet — includeAnonymized=true nur für die Verwaltung |
GET | /stats | Counts pro Rolle |
GET | /assignable?entityType= | Zuweisbare Kandidaten je Entity-Art (TICKET, PROBLEM, CHANGE, INCIDENT, WORKFLOW) — mit ?groupId, ?search, ?take/skip |
GET | /approvers?entityType= | Users mit Approve-Recht (CHANGE, CHANGE_TEMPLATE, INCIDENT) |
GET | /checkout-recipients | Empfänger für Asset-Checkout |
GET | /check-email | E-Mail-Verfügbarkeit prüfen |
GET | /:id | Einzelner User |
POST | / | User erstellen (mit Einladung); eine Einladung verlangt ein aktives Konto — sonst 400 INVITATION_ACCOUNT_NOT_ACTIVE |
PATCH | /:id | User aktualisieren (inkl. roleId) |
PATCH | /:id/profile | Profil/Status (isActive …) |
POST | /:id/promote | E-Mail-Kontakt zum Nutzer befördern (Portal-Zugang, optional neue Rolle); verlangt ein aktives Konto — sonst 400 PROMOTE_ACCOUNT_NOT_ACTIVE |
POST | /:id/resend-invitation | Einladung erneut senden; verlangt ein aktives Konto — sonst 400 INVITATION_ACCOUNT_NOT_ACTIVE |
GET / PUT | /:id/language | Sprache (de, en, es, fr, it) |
GET | /:id/archival-check | Prüft, ob archivierbar |
POST | /:id/archive-with-transfer | Archivieren + Items übertragen |
Anzeige-Einstellungen des Benutzers: Sprache, Zeitzone und Datumsform gehören dem Benutzer selbst — die Sprache über /:id/language, Zeitzone und Datumsform über das eigene Profil (PUT /api/auth/profile). Sie wirken in der Oberfläche und ebenso in den Texten, die der Server erzeugt: E-Mail, Push, Teams und Webex. Eine Nachricht erreicht den Empfänger damit in seiner Sprache, mit seinen Uhrzeiten und in seiner Datumsform, unabhängig davon, wer sie ausgelöst hat. Welche Stufe greift, wenn nichts gesetzt ist.
Hinweis: Für Benutzer gibt es keinen DELETE-Endpoint. Sie werden über /:id/profile deaktiviert (isActive=false) oder über /:id/archive-with-transfer archiviert (Items gehen an einen Nachfolger).
Drei Kontozustände: Ein Konto ist aktiv, gesperrt oder archiviert — archiviert heißt IMMER gesperrt. Wer nur isArchived: true sendet, bekommt isActive: false still dazu; wer isActive: true an einem archivierten Konto verlangt, bekommt 400 ARCHIVED_USER_CANNOT_BE_ACTIVE. Reaktiviert wird mit beiden Feldern in EINEM Request (isArchived: false, isActive: true). So fällt ein archiviertes Konto überall heraus, wo nur aktive Konten zählen: bei Benachrichtigungen, in Workflows und beim Verzeichnis-Sync. Gesperrte und archivierte Konten können sich auf keinem Weg anmelden (403 ACCOUNT_DEACTIVATED); ein Login ändert den Status nie, Ent-archivieren geht nur über PATCH /:id/profile mit users.archive.
Ein gesperrtes oder archiviertes Konto kann nicht Kunde eines neuen Tickets werden und auch nicht Nachfolger beim Archivieren (400 SUCCESSOR_NOT_ACTIVE). Eine eingehende E-Mail an ein archiviertes Konto ändert seinen Status NICHT — sie verschiebt nur die Löschfrist, denn ein Statuswechsel ist eine Verwaltungsentscheidung: Er erfordert eine Berechtigung, wird auditiert und kann Vorgesetzten-Beziehungen übertragen.
Ein gesperrtes Konto nennt die Herkunft seiner Sperre: managedProfile.lockSource ist ADMIN (Verwaltung), ENTRA_SYNC (Verzeichnis-Sync) oder SYSTEM. Bei einem aktiven Konto ist das Feld null. Es beantwortet die Frage, wer die Sperre wieder aufheben kann — der Verzeichnis-Sync hebt nur seine eigenen Sperren auf.
Eine Statusänderung wirkt sofort: Mit der Sperre enden alle Zugänge des Kontos — laufende Sitzungen, Refresh-Token, Push-Abos und offene Echtzeit-Verbindungen; der Rechte-Cache wird geleert. Das gilt für jeden Weg, der den Status schreibt: Anlegen, Bearbeiten, Profil, Archivieren mit Nachfolger, Verzeichnis-Sync und Anonymisierung. Einladung und Beförderung verlangen deshalb ein aktives Konto (400 INVITATION_ACCOUNT_NOT_ACTIVE bzw. PROMOTE_ACCOUNT_NOT_ACTIVE) — ein Einrichtungs-Link an ein gesperrtes Konto würde ins Leere laufen.
Geschützte Konten: Zwei Konten hält die Plattform für sich selbst: das interne System-Konto, unter dem automatisierte Vorgänge laufen, und den lokalen Notzugang, über den die Verwaltung auch bei einem Ausfall der Microsoft-Anmeldung hereinkommt. Beide lassen sich nicht sperren, nicht archivieren, nicht anonymisieren und nicht mit einer Lösch-Sperre versehen; ihre Rolle ist fest. Solche Eingriffe antworten 403 PROTECTED_ACCOUNT, und details.operation nennt den abgelehnten Eingriff (status, archive, role oder erase). Der Verzeichnis-Sync verknüpft beide Konten nie (Konfliktcode PROTECTED_ACCOUNT), und das System-Konto meldet sich auf keinem Weg an. Die Oberfläche kennzeichnet diese Konten und bietet die gesperrten Aktionen gar nicht erst an. Profildaten, Passwort und Zwei-Faktor-Anmeldung des Notzugangs bleiben änderbar.
Rollen-Zuweisung am Konto: Eine roleId setzen POST /, PATCH /:id und /:id/promote — dabei gelten drei Grenzen. Die Rolle eines synchronisierten Kontos gehört dem Verzeichnis: Ein Rollenwechsel wird mit 403 ROLE_MANAGED_BY_ENTRA_ID abgewiesen, solange das Konto in einer zugeordneten Rollen-Gruppe steht (bei entraIDConflict = true bleibt sie manuell setzbar, weil der Sync sie dort nicht überschreibt). Eine Rolle ohne nutzbare Rechte — deaktiviert oder mit ungültiger Rechte-Matrix — lässt sich nicht zuweisen: 400 ROLE_NOT_ASSIGNABLE mit details.roleName, denn das Konto wäre danach an jeder Stelle abgewiesen, ohne dass es gesperrt wäre. Und niemand vergibt eine Rolle mit höheren Privilegien als der eigenen (403).
Sichtbarkeit vor Handlungsrecht: Jede Route auf einen bestimmten Benutzer (PATCH /:id, /:id/profile, /:id/language, /:id/promote, /:id/resend-invitation, /:id/archival-check, /:id/archive-with-transfer, Manager-Routen, Hierarchie-Reads) prüft zuerst, ob der Aufrufer diesen Benutzer überhaupt sehen darf — das eigene Konto oder users.viewAll. Eine Rolle mit users.edit oder users.archive, aber ohne users.viewAll, wirkt damit ausschließlich auf das eigene Profil; alles andere ist 403.
Archivieren verlangt users.archive; nur wenn dabei wirklich Manager-Beziehungen übertragen werden, kommt users.manageManagers hinzu. users.archive und agents.manageGroups sind kritische Aktionen: Ihre Rechte werden frisch aus der Datenbank geprüft und Erfolge wie abgelehnte Versuche auditiert.
Kandidaten-Listen erfordern ein Recht an der Ziel-Domäne: /assignable verlangt ein Recht an der ZIEL-Domäne — viewAll, editAll oder assign der jeweiligen Entity-Art (bei WORKFLOW: editTemplates, createTemplates oder reassignSteps). editOwn genügt bewusst NICHT, sonst könnte jeder Endanwender die Agenten-Liste abfragen. /approvers verlangt das Genehmigungsrecht der Entity-Art (z.B. changes.approve, incidents.approveClosure) oder editAll/editOwn. Rollen ohne diese Rechte erhalten 403.
Manager-Hierarchie
| Method | Endpoint | Beschreibung |
|---|---|---|
GET | /:id/managers | Manager eines Users |
POST | /:id/managers | Manager zuweisen |
PATCH | /:id/managers/:managerId | Beziehung aktualisieren |
DELETE | /:id/managers/:managerId | Manager entfernen |
GET | /:id/subordinates | Direkte Untergebene |
GET | /:id/hierarchy | Vollständiges Organigramm (rekursiv) |
Die Manager-Hierarchie ist Basis für Eskalationen (Assignee→Lead→Manager) und die Genehmigung von Abwesenheiten.
User erstellen
POST /api/users
{
"email": "agent@company.com",
"name": "John Support",
"roleId": "clx-role-agent",
"managedProfile": { "firstName": "John", "lastName": "Support", "department": "IT", "location": "Munich" }
// without password → invitation flow (password setup via link); see Authentication
}
E-Mail-only-Kontakte (autoCreatedFromEmail/emailOnlyContact) entstehen automatisch beim E-Mail-Eingang (Sender-Policy AUTO_CREATE) und haben kein Portal-Login — siehe Integrations.
Rollen (RBAC) /api/roles
| Method | Endpoint | Beschreibung |
|---|---|---|
GET | / | Alle Rollen (mit Permission-Matrix; settings.manageRoles). page/limit werden geprüft: limit höchstens 200, unbrauchbare Werte sind 400 |
GET | /assignable | Schlanke Zuweisungs-Liste für den User-Editor (id/name/displayName/color); erfordert users.manageRoles; enthält nur aktive Rollen, die der Aufrufer vergeben darf (Privileg-Decke) |
GET | /:id | Rolle (mit Permission-Matrix) |
POST | / | Custom-Rolle erstellen |
PATCH | /:id | Permissions aktualisieren |
DELETE | /:id | Custom-Rolle löschen → 204. Nicht möglich bei System-Rollen, bei Rollen mit Nutzern und bei Rollen, an denen ein AKTIVER API-Key hängt (der Key würde sonst ohne Rolle mit 403 API_KEY_NO_ROLE abgewiesen). |
GET | /permissions/schema | Permission-Schema (für UI) |
POST | /:id/move | Rolle in der Prioritäts-Reihenfolge verschieben — GENAU eine Seite angeben (afterRoleId ODER beforeRoleId); beides oder nichts ist 400 |
Fehlercodes der Rollen-Verwaltung
| errorCode | HTTP | Bedeutung |
|---|---|---|
ROLE_NOT_FOUND | 404 | Keine Rolle mit dieser ID |
ROLE_NAME_EXISTS | 409 | Der Name ist bereits vergeben |
ROLE_IN_USE | 409 | Die Rolle hängt noch an Nutzern oder an aktiven API-Keys — details.users und details.activeApiKeys nennen die Zahlen |
SYSTEM_ROLE_PROTECTED | 400 | System-Rollen lassen sich weder deaktivieren noch löschen noch verschieben |
ROLE_PERMISSIONS_INVALID | 400 | Die Matrix enthält unbekannte Module oder Aktionen bzw. Nicht-Boolesche Werte |
ROLE_LOCKOUT | 403 | settings.manageRoles darf nicht aus einer System-Rolle, der eigenen Rolle oder der LETZTEN Rolle entfernt werden, die es trägt — sonst wäre die Rollenverwaltung dauerhaft ausgesperrt. details.reason nennt den Fall. |
ROLE_NOT_ASSIGNABLE | 403 | Privileg-Decke: niemand vergibt eine Rolle mit Rechten, die er selbst nicht hat. details.reason unterscheidet ROLE_NOT_FOUND und PERMISSION_NOT_HELD (mit details.permission). |
Eine Rolle deaktivieren beendet den Zugang ihrer Nutzer: Mit dem Umschalten auf isActive: false verlieren alle Konten dieser Rolle sofort ihre laufenden Sitzungen, Refresh-Token, Push-Abos und offenen Echtzeit-Verbindungen; eine erneute Anmeldung antwortet 403 NO_USABLE_ROLE. Die Konten selbst bleiben aktiv — die Ursache liegt an der Rolle, und die Meldung sagt das auch so. Die Oberfläche verlangt deshalb eine Bestätigung, sobald die Rolle noch Nutzer trägt; sie nennt deren Anzahl und weist darauf hin, dass die Betroffenen keine Benachrichtigung darüber erhalten.
Eine Rolle trägt eine Permission-Matrix über 29 Module (tickets, problems, changes, incidents, assets, inventory, contracts, licenses, costCenters, knowledgeBase, elibrary, workflows, cronjobs, settings, users, agents, notifications, audit, analytics, absences, customReports, savedViews, …). Wie Rechte aufgelöst, gecacht (pro Rolle) und bei kritischen Aktionen frisch validiert werden, steht zentral unter Permissions & RBAC.
POST /api/roles
{
"name": "level2-agent",
"displayName": "Level 2 Agent",
"description": "Agent with change approval",
"priority": 45000,
"permissions": {
"tickets": { "viewAll": true, "create": true, "editAll": true, "assign": true },
"changes": { "viewAll": true, "approve": true, "reject": true }
// more modules …
}
}
Agents /api/agents
Das Agent-Profil ergänzt einen User um Support-spezifische Daten (Workload, isActive, Specialties).
| Method | Endpoint | Beschreibung |
|---|---|---|
GET | /api/agents | Agents auflisten ({data, pagination}); ?forEntityType=TICKET|PROBLEM|CHANGE|INCIDENT|WORKFLOW filtert auf die zuweisbaren |
POST | /api/agents | Agent-Profil anlegen ({userId, isActive}) |
PATCH | /api/agents/:userId | Agent aktualisieren: isActive und/oder maxWorkload |
DELETE | /api/agents/:userId | Agent-Profil entfernen |
Agents werden überall über die userId adressiert: in Pfaden, Eingaben und Responses. Eingaben werden strikt geprüft; unbekannte Felder und unbekannte Query-Werte (z.B. ein falscher forEntityType) ergeben 400.
Agent Groups
Gruppen routen Arbeit an Agents. applicableEntityTypes (Array) legt fest, für welche Entity-Arten die Gruppe als Queue dient, assignmentStrategy bestimmt die Auswahl. Mit Group-Access lässt sich pro Gruppe einschränken, wer sie sieht/zugewiesen bekommt.
| Aspekt | Werte |
|---|---|
applicableEntityTypes (String[]) | TICKET, PROBLEM, CHANGE, INCIDENT, WORKFLOW (Default: alle fünf) |
assignmentStrategy | FIRST_AVAILABLE, ROUND_ROBIN, LEAST_LOADED, SKILL_BASED |
| Method | Endpoint |
|---|---|
GET | /api/agents/groups · /groups/:id |
POST / PATCH | /api/agents/groups · /groups/:id |
POST | /api/agents/groups/:id/archive · /restore |
GET | /api/agents/groups/:id/potential-members (Server-Suche: ?search=, ?take/skip, ?excludeAbsent, ?excludeInactive) |
POST / DELETE / PATCH | /api/agents/groups/:groupId/members/:userId (PATCH: isTeamLead und/oder isActive → 204) |
GET / POST | /api/agents/groups/:id/access (Zugriffsregeln) |
DELETE | /api/agents/groups/:id/access/:accessId |
PUT | /api/agents/groups/:id/restriction (Zugriff ein/aus) |
- Die Gruppen-Liste liefert per Default nur aktive, nicht archivierte Gruppen (für Auswahllisten). Die Verwaltung setzt ?includeInactive=true und bekommt inaktive und archivierte dazu; der Einzel-Lookup /groups/:id löst auch inaktive Gruppen auf, damit bestehende Zuweisungen sichtbar bleiben. Weitere Query-Params: ?forEntityType=, ?search=.
- Berechtigungen: Gruppen lesen = users.viewAgents · Gruppen/Mitglieder/Specialties verwalten = agents.manageGroups · Zugriffsregeln = agents.manageGroupAccess. Jede Gruppe trägt in der Antwort canManageMembers für den anfragenden Benutzer (agents.manageGroups oder aktiver TeamLead dieser Gruppe) — die Mitglieder-Aktionen der UI hängen daran.
- Ein Zugriffs-Eintrag gehört zu genau einer Gruppe: ein zweiter Grant für denselben Benutzer bzw. dieselbe Rolle ist 409 ACCESS_ALREADY_GRANTED, und ein DELETE über eine fremde Gruppen-URL ist 404.
Specialties /api/agents/specialties
Skills/Fachgebiete für SKILL_BASED-Routing. CRUD + Zuordnung zu Agents:
| Method | Endpoint |
|---|---|
GET | / (?includeInactive=true für die Verwaltung) · /:id · /agent/:userId |
POST / PATCH / DELETE | / · /:id |
POST / DELETE | /:id/agents/:userId (Skill zuordnen/entfernen, proficiency 1–5) |
Abwesenheit & Verfügbarkeit
Zuweisbarkeit berücksichtigt Abwesenheiten: Die Kandidaten-Listen markieren abwesende Agents (isAbsent; der Abwesenheitsgrund wird nicht ausgegeben, da er Gesundheitsdaten enthalten kann), und ist ein Ziel-Agent abwesend, greift die Vertreter-Umleitung (Substitute) zum Zuweisungszeitpunkt (override per ignoreSubstitution). Deaktivierte und archivierte Konten sind nie Kandidaten. Verwaltung der Abwesenheiten (inkl. Manager-Genehmigung) auf der eigenen Seite: Absences API.
- ✓ Frei definierbare Rollen mit Priorität
- ✓ Manager-Hierarchie & Organigramm
- ✓ Agent-Groups: Queue, Zuweisungsstrategie, Zugriffsregeln
- ✓ Archivieren mit Übertragung an einen Nachfolger
users.viewAll/create/edit/manageRolessettings.manageRoles– Rollen/Permissionsagents.*– Agents & Groups
Auth-/Rollenmodell: Permissions & RBAC
- Permissions & RBAC – Auflösung, Cache (pro Rolle), kritische Aktionen
- Absences API – Abwesenheit, Vertretung, Manager-Genehmigung
- Authentication – Login, SSO/EntraID, Einladung
- Privacy & DSGVO – Anonymisierung, Lösch-Sperre, Datenexport und Aufbewahrungsfristen eines Kontos
- User Management (Architektur)