Settings API
The Settings API manages the general settings (company name, application URL), numbering, the email, Microsoft Teams and Webex connections, the CAPTCHA configuration and the enabled languages. It also reports the status of the notification channels.
Authentication, Permissions & Structure
Each settings key has a read and a write permission. Holding either one allows reading: the write permission includes reading so that the form shows the stored values when editing and saving does not replace them with defaults. PUT /api/settings/:key expects the value as { "value": … } and validates it against the schema of the key (e.g. numbering).
- User-only: All settings endpoints require a logged-in user; API keys are rejected. The exceptions are the public GETs /captcha and /enabled-languages.
- settings.viewGeneral is intended for administrators and is not part of the End User and Agent system roles. general-settings and ui-settings (branding, locale) can be read by any logged-in user.
- Sensitive keys: entra-id-config, webex-settings and teams-settings are only reachable through their own endpoints (see Integration Settings), which never return secrets in plain text.
- Further endpoints:
/api/settings/license(product license) and/api/settings/file-settings(Attachments) are documented on the linked pages.
System currency & price mode: general-settings contains systemCurrency (single currency for all amounts, default EUR, no conversion) and priceTaxMode (net | gross, default net; labels price fields, no tax calculation). Both apply system-wide to assets, contracts, licenses, cost centers and reports. A change takes effect in the backend immediately; the worker containers pick it up within 60 seconds.
Global Search
Cross-entity search (GET /api/search) is its own domain and has its own page: Global Search →.
Numbering Settings
Entity Number Formats
| Entity | Format | Example | Reset Policy |
|---|---|---|---|
| Ticket | PREFIX-NNNNNN | TKT-000001 | Never |
| Problem | PREFIX-NNNNNN | PRB-000001 | Never |
| Change | PREFIX-NNNNNN | CHG-000001 | Never |
| Incident | PREFIX-YYYY-NNNNNN | INC-2026-000001 | Yearly |
Numbering Settings Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET/PUT | /api/settings/:key | Numbering for tickets, problems, changes and incidents (key = ticket-numbering-settings, problem-numbering-settings, change-numbering-settings, incident-numbering-settings). PUT expects { "value": {…} } and validates the value against the schema of the key. |
System & Languages
| Method | Endpoint | Description |
|---|---|---|
GET | /api/settings/captcha | Turnstile CAPTCHA configuration (public) |
GET | /api/settings/enabled-languages | Enabled languages (public) |
PUT | /api/settings/enabled-languages | Configure enabled languages |
GET | /api/settings/channel-status | Notification channel status (email, Teams, Webex) |
GET | /api/settings/system-banner | System banner message |
General Settings: Company name (companyName) and application URL (applicationUrl) are configured via PUT /api/settings/general-settings. Both values are used for QR codes, PDF labels and email templates. The same key carries the system defaults for language (defaultLanguage), timezone (timezone, default Europe/Berlin) and date format (dateTimeFormat, default dd/MM/yyyy HH:mm). They apply to every user without an own preference — in the interface as well as in the texts the server generates (email, push, Webex, Teams). Setting timezone and date format explicitly during setup is recommended so that both sides show the same picture.
Numbering Configuration
// GET Response
GET /api/settings/ticket-numbering-settings
Response:
{
"prefix": "TKT", // 1-10 uppercase letters
"suffixLength": 6, // 1-10 digits (zero-padded)
"lastAssignedNumber": 12345 // read-only: last number handed out (null = none yet)
}
// Generated Ticket Number:
// TKT-012345 (prefix + zero-padded atomic counter)
Update Numbering
// Custom numbering for tickets
const update = await fetch('/api/settings/ticket-numbering-settings', {
method: 'PUT',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
value: {
prefix: "TICKET", // Custom prefix (only prefix + suffixLength are settable)
suffixLength: 4 // Shorter suffix
}
})
});
const result = await update.json();
console.log(result);
// {
// "prefix": "TICKET",
// "suffixLength": 4,
// "lastAssignedNumber": null // read-only; the atomic counter keeps numbers unique
// }
// Next generated ticket number continues from the atomic counter:
// e.g. TICKET-2175, TICKET-2176, ...
⚠️ Warning: Numbering settings should be configured BEFORE production start. Changes after first tickets may lead to confusing numbers.
Year-Based Numbering (Incidents)
// Incidents have year-based counters
// Counter key: "incident-number-{YEAR}"
// 2025:
INC-2025-000001
INC-2025-000002
...
INC-2025-012345
// 2026 (automatic reset):
INC-2026-000001
INC-2026-000002
...
// Advantage: easy filtering by year
Application Settings
Settings Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET | /api/settings | All settings in category general |
GET | /api/settings/:key | Get specific setting |
PUT | /api/settings/:key | Update setting |
DELETE | /api/settings/:key | Delete setting |
UI Settings (Application Branding)
// Get UI settings
GET /api/settings/ui-settings
Response:
{
"applicationName": "ACME IT Helpdesk",
"logo": {
"url": "/uploads/logo.png",
"width": 200,
"height": 60
},
"favicon": {
"url": "/uploads/favicon.ico"
},
"theme": {
"primaryColor": "#3b82f6",
"accentColor": "#8b5cf6"
},
"branding": {
"companyName": "ACME Corporation",
"supportEmail": "support@acme.com",
"supportPhone": "+1 555 1234567"
}
}
// Update UI settings
PUT /api/settings/ui-settings
{
"value": {
"applicationName": "New Helpdesk Name",
"logo": {
"url": "/uploads/new-logo.png"
}
}
}
Language Settings
// Available languages (PUBLIC endpoint)
GET /api/settings/enabled-languages
Response:
{
"languages": ["de", "en"]
}
// Update language settings (Admin)
PUT /api/settings/enabled-languages
{
"languages": ["de", "en", "fr"]
}
// The effective default language must stay in the list —
// otherwise 400 DEFAULT_LANGUAGE_NOT_ENABLED
Integration Settings
Email Settings
| Method | Endpoint | Description |
|---|---|---|
GET | /api/settings/email | Email settings (SMTP/Graph; secrets only as _has* flag) |
POST | /api/settings/email | Update email settings |
POST | /api/settings/email/test-smtp | Test SMTP connection |
POST | /api/settings/email/test-graph | Test Microsoft Graph API connection |
// Update email settings
POST /api/settings/email
{
"isEnabled": true,
"smtp": {
"enabled": true,
"host": "smtp.gmail.com",
"port": 587,
"security": "tls",
"username": "notifications@company.com",
"password": "app-specific-password",
"fromAddress": "notifications@company.com",
"fromName": "IT Helpdesk",
"tlsVerify": true
}
}
// Test SMTP connection
POST /api/settings/email/test-smtp
Response:
{
"connected": true,
"diagnostic": null // optional technical diagnostic from the email worker
}
// Failure: 400 EMAIL_CONNECTION_TEST_FAILED
Teams Settings
| Method | Endpoint | Description |
|---|---|---|
GET | /api/settings/teams | Teams Bot Framework settings |
POST | /api/settings/teams | Update Teams settings |
POST | /api/settings/teams/test | Test Teams Bot connection |
POST | /api/teams/bot | Teams Bot Framework messaging endpoint (called by Microsoft) |
// Teams Bot Framework konfigurieren
POST /api/settings/teams
{
"appId": "00000000-0000-0000-0000-000000000000", // Azure App Registration (GUID)
"appPassword": "your-bot-secret",
"tenantId": "your-tenant-id",
"isEnabled": true
}
// Test senden
POST /api/settings/teams/test
Response:
{
"connected": true,
"connectedUsers": 12,
"connectedChannels": 2,
"testMessageSent": true
}
Webex Settings
| Method | Endpoint | Description |
|---|---|---|
GET | /api/settings/webex | Webex bot settings (token only as _hasToken flag) |
POST | /api/settings/webex | Update Webex settings |
POST | /api/settings/webex/test | Test Webex bot connection |
// Webex Bot konfigurieren
POST /api/settings/webex
{
"botToken": "Bearer_YOUR_BOT_TOKEN_HERE",
"isEnabled": true
}
// Bot-Connection testen
POST /api/settings/webex/test
Response:
{
"connected": true,
"botId": "webex-bot-id",
"botName": "Helpdesk Bot",
"botEmail": "bot@webex.bot"
}
Settings Categories & Permissions
| Category | Settings Keys | Permissions |
|---|---|---|
| /api/settings/email (own endpoint) | settings.viewEmail, settings.editEmail | |
| Integrations | webex-settings, teams-settings, entra-id-config (own endpoints; secrets only as _has* flag) | settings.viewIntegrations, settings.editIntegrations |
| Numbering | ticket/problem/change/incident-numbering-settings | settings.viewNumbering, settings.editNumbering |
| Security | captcha/turnstile-settings | settings.editSecurity |
| SLA | sla-settings | settings.editSLA (read AND write) |
| General | general-settings, ui-settings (readable by any logged-in user) | settings.viewGeneral (for administrators), settings.editGeneral |
SLA thresholds (sla-settings)
PUT /api/settings/sla-settings
{
"value": {
"warningThresholdPercent": 80, // 50–99
"criticalThresholdMinutes": 60 // 5–1440
}
}
When an SLA counts as WARNING and when a breach escalates to CRITICAL. sla-settings belongs to category sla and is therefore not included in GET /api/settings; both reading and writing require settings.editSLA so that the SLA thresholds are not shown to every holder of settings.viewGeneral. Details and cache behavior: SLA Management API.
Security Features
Secret Masking
// GET Response maskiert Secrets
GET /api/settings/webex
Response:
{
"isEnabled": true,
"_hasToken": true // Secret never returned — only this boolean flag
}
// GET response for SMTP
{
"smtp": {
"username": "notifications@company.com",
"_hasPassword": true // Secret never returned — only this boolean flag
}
}
Secrets are never returned on GET — only a _has* flag indicates whether a value is set. In addition, the SMTP password, the MS-Graph and Entra clientSecret, the Webex botToken and the Teams appPassword are stored encrypted with AES-256-GCM. Details on the security page.
RBAC Integration
- Critical settings: every change checks the permission directly in the database, bypassing the cache; a revoked right takes effect immediately
SSRF Protection
Teams bot communication only accepts service URLs on approved Microsoft domains over HTTPS. The list of domains is documented under Integrations →.
Notification Channel Status
Channel Status Endpoint
// Get status of all notification channels
GET /api/settings/channel-status
Response:
{
"EMAIL": { "enabled": true, "configured": true },
"TEAMS": { "enabled": true, "configured": true },
"WEBEX": { "enabled": false, "configured": false },
"IN_APP": { "enabled": true, "configured": true },
"PUSH": { "enabled": true, "configured": true }
}
Best Practices
- Numbering Setup: Configure BEFORE production start, use meaningful prefixes
- Suffix Length: 6 digits for large deployments (up to 999,999), 4 for small
- Email Test: Always run test-smtp/test-graph after settings change
- Channel Status: After changes, use channel-status to check that all channels are enabled and configured
- UI Branding: Logo max. 200x60px, favicon 32x32px for best display
- Secrets: Use strong passwords, rotate tokens regularly
- Language Support: Enable only languages with complete templates
- Permissions: Only ADMIN should have settings.editIntegrations (critical)
Related Documentation
- Tickets API - Ticket numbering, search integration
- Problems API - Problem numbering
- Changes API - Change numbering
- Incidents API - Incident numbering (year-based)
- Global Search - cross-entity search across nine types
- Integrations - Email, Teams, Webex integration details
- Users & Roles - Settings permissions (RBAC)
- Audit System - Settings change audit logging
- Reopen & Lifecycle - reopen reasons + lifecycle config (settings.editGeneral)