Custom Forms API
Die Custom Forms API verwaltet konfigurierbare Formulare (CustomForm), die das Anlegen von Tickets mit dynamischen Feldern hinterlegen. Verwendet werden die Formulare beim Anlegen und Bearbeiten von Tickets (Web und Mobile). Ein Formular besteht aus einem JSON formSchema mit Feldern, optionaler Zuweisung (assignedTo) und mehrsprachigen Labels. Basis-Pfad: /api/forms.
🔐 Auth: Nur mit Benutzer-Anmeldung, API-Keys werden nicht akzeptiert. Alle Verwaltungs-Endpoints (Liste, Detail, Anlegen, Ändern) erfordern settings.editGeneral; /available erfordert tickets.create. Siehe RBAC →.
Endpunkte
| Method | Endpoint | Beschreibung | Permission |
|---|---|---|---|
GET | /api/forms | Admin-Liste (Filter, Voll-Felder) | settings.editGeneral |
GET | /api/forms/available | Formulare für die Ticket-Anlage (ohne Verwaltungsdaten, nach assignedTo und Feld-Sichtbarkeit gefiltert) | tickets.create |
GET | /api/forms/:id | Einzelnes Formular | settings.editGeneral |
POST | /api/forms | Erstellen (201) | settings.editGeneral |
PATCH | /api/forms/:id | Aktualisieren (Deaktivieren = isActive:false, Archivieren = isArchived:true) | settings.editGeneral |
Admin-Liste vs. /available
GET /api/forms ist der Admin-Endpoint (settings.editGeneral, alle Felder). GET /api/forms/available ist der Endpoint für die Ticket-Anlage (tickets.create): Der Server filtert nach assignedTo (allRoles/roles/users), liefert die Formulare ohne Verwaltungsdaten und entfernt Felder nach visibleToRoles / hiddenForEndUsers. hiddenForEndUsers greift für User OHNE tickets.viewAll/editAll (Custom-Enduser-Rollen zählen also mit).
Listen-Filter (GET /api/forms)
| Parameter | Werte |
|---|---|
isActive | true | false | all |
isArchived | true | false | all |
includeWorkflowTemplates | true | false (Default false) |
Formular erstellen
POST /api/forms
{
"name": "Hardware Request",
"description": "Form for new hardware tickets",
"isActive": true,
"isDefault": false,
"formSchema": {
"fields": [
{
"id": "subject",
"type": "subject",
"label": "Subject",
"order": 0,
"required": true,
"labels": { "de": "Betreff", "en": "Subject" }
},
{
"id": "device",
"type": "text",
"label": "Device",
"order": 1,
"required": true,
"maxLength": 100,
"visibleToRoles": ["AGENT", "ADMIN"],
"hiddenForEndUsers": false
}
],
"assignedTo": { "allRoles": false, "roles": ["clx-role-enduser"], "users": [] },
"names": { "de": "Hardware-Anfrage", "en": "Hardware Request" }
}
}
Felder: name (3–100, eindeutig), description? (max 500), formSchema (Pflicht), isActive (Default true), isDefault (Default false; es gibt höchstens ein Standard-Formular, ein neues ersetzt das bisherige automatisch). formSchema.fields: 1–50 Einträge; assignedTo = { allRoles, roles (Role-IDs), users (User-IDs) }. Unbekannte Felder werden mit 400 abgelehnt.
Feld-Struktur (formSchema.fields[])
| Feld | Beschreibung |
|---|---|
id, type, label, order | Pflicht. type ist frei (subject, category, description, text, number, email, …) |
required | Pflichtfeld (Default false) — wirkt in den Masken UND in der API; an einem Anhangsfeld nicht setzbar |
placeholder, description, defaultValue | Optionale UI-Hilfen |
minLength, maxLength, validation | Validierungsgrenzen (validation = freies Objekt) |
visibleToRoles | Nur diese Rollen sehen das Feld (leer = alle) |
hiddenForEndUsers | Feld für Enduser ausblenden (Default false) |
labels, placeholders, descriptions, optionLabels | Mehrsprachige Varianten (Record<lang, …>) |
Wo die Pflicht greift: Die Feldregel gilt in den Eingabemasken UND in der Ticket-API: wer mit formId anlegt oder Zusatzfelder ändert, wird serverseitig geprüft — Pflicht, Mindest- und Höchstlänge, E-Mail-, URL- und Telefonformat sowie die Zugehörigkeit zur Optionsliste. Verstöße sind 400 FORM_SUBMISSION_INVALID; details.issues nennt je Feld fieldId, fieldType und einen Code (REQUIRED, MIN_LENGTH, MAX_LENGTH, INVALID_EMAIL, INVALID_URL, INVALID_PHONE, INVALID_OPTION). Geprüft wird nur, was der Aufrufer sehen darf. Werte für unsichtbare Felder und unbekannte Schlüssel werden ohne Fehler verworfen.
Anhangsfelder nehmen an der Prüfung NICHT teil — Dateien werden erst nach dem Anlegen hochgeladen, zum Anlegezeitpunkt ist die Pflicht nicht prüfbar. Deshalb lässt sich ein Anhangsfeld auch nicht als Pflichtfeld speichern (400). Standardwerte gelten, solange nichts eingetragen ist: sie kommen in die Antwort und werden gespeichert; ein Feld mit Standardwert lässt sich nicht auf leer setzen.
Verbindung zu Workflows
Ein CustomForm kann einem oder mehreren Workflow-Templates zugeordnet sein (workflowTemplates-Relation). Das WorkflowTemplate hält das gerenderte FormSchema als triggerSchema; abgesendete Werte landen in der WorkflowInstance unter data.trigger.*. DATA_COLLECTION-Steps nutzen dieselbe Feld-Struktur und schreiben in data.stepOutputs[stepName]. Das Formular liefert also die FELDER — gestartet wird ein Workflow über den Katalog (Benutzer) oder den API-Trigger (API-Key); ein Formular-Versand startet für sich genommen keinen Workflow.
⚙️ Trigger-Typen, Step-Typen und das Instanz-Datenmodell: Workflows API →.
Start-Dialog (triggerSchema), DATA_COLLECTION-Steps
Ticket-Anlage nutzt /forms/available
settings.editGeneral berechtigt die Formular-Verwaltung
Permission-Matrix