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": "data:image/png;base64,iVBORw0KGgo...",
"favicon": "data:image/x-icon;base64,AAABAAEAEBA...",
"theme": "system"
}
// Update UI settings
PUT /api/settings/ui-settings
{
"value": {
"applicationName": "New Helpdesk Name",
"theme": "dark"
}
}
- All four fields are optional; with nothing set the endpoint answers null.
- Logo and favicon are embedded images (data: URI), not references to files — so they need no second request and no public upload folder.
- theme is the appearance for users without a choice of their own: light, dark or system.
- Company name, support address and phone number do not belong here — they live in the general settings.
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/public/ui-settings | Appearance WITHOUT login — so the sign-in page can show name, logo, favicon and default theme; returns exactly those four fields or null |
GET | /api/settings/email | Email settings (SMTP/Graph; secrets only as _has* flag) |
POST | /api/settings/email | Update email settings — known fields only, partial update allowed |
POST | /api/settings/email/test-smtp | Test SMTP connection → { connected: true } |
POST | /api/settings/email/test-graph | Test Microsoft Graph API connection → { connected: true } |
// 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
}
- A failure is an error, not a response with
connected: false: status 400, and the reason of the probe is itself theerrorCode— one of theMAIL_*reasons (see Inbound Mailboxes API).details.messagecarries an English diagnosis for support. - If the email channel is not enabled, both probes answer
400 EMAIL_SYSTEM_DISABLED; if the email service does not answer within 20 seconds,503 EMAIL_WORKER_UNAVAILABLE. - When the send mode is SMTP and SMTP is enabled, saving requires a sender address: otherwise
400 EMAIL_SMTP_FROM_ADDRESS_REQUIRED. What is checked is the state AFTER merging — so a partial update can violate the rule even when it does not touch the address itself. - The probes of an individual mailbox use their own endpoints: Inbound Mailboxes API.
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
- Email System - Receiving and sending in context
- Inbound Mailboxes API - Mailboxes, connection probes, access restriction
- Integrations - Teams, Webex and outgoing webhooks
- Users & Roles - Settings permissions (RBAC)
- Audit System - Settings change audit logging
- Reopen & Lifecycle - reopen reasons + lifecycle config (settings.editGeneral)