Skip to main content

Config API

Base path: /api/config
All endpoints use POST. Authentication required unless otherwise noted.

For the overall architecture, see Configuration System Architecture.

Current consumers of catalog keys

KeysConsumerResolved scope
auth.registration.enabledAuthController.Register() — returns 503 when "false"global
auth.captcha.enabledAuthController.Register() — requires captchaId/captchaProof when "true"global
auth.password.min_length, auth.password.require_uppercase, auth.password.require_digit, auth.password.require_specialIPasswordGenerator — used by POST /api/cloud/tenant/create and POST /api/auth/registerglobal-only
forms.{dataArea}.field_configICustomFieldValidationService + frontend useDataAreaConfig — per-field overrides (hidden, required, label) for each DataAreatenant
forms.{dataArea}.custom_fieldsICustomFieldValidationService + frontend useDataAreaConfig — array of tenant-defined additional fields; values stored in colcustom JSONBtenant
permissions.section_visibilityFrontend PermissionGate — map {section: number[]} of allowed userIds per sectiontenant, group
ui.theme, ui.density, ui.sidebar_collapsed, ui.dashboard_layoutFrontend useConfig / useAppConfigtenant, group, user
branding.app_name, branding.primary_colorFrontend useConfigtenant, group
system.group_conflict_strategyConfigMergeService — strategy for resolving conflicts between group overridesglobal, tenant

The IConfigMergeService.ResolveGlobalAsync method is used when no tenant/user context exists yet (e.g. tenant creation, registration).

auth.registration.enabled

PropertyValue
Categoryauth
Value typebool
Default"true"
Allowed levels1 (global only)

Controls whether the self-registration endpoint (POST /api/auth/register) is open to new users. Set to "false" to close registration without disabling existing accounts.

auth.captcha.enabled

PropertyValue
Categoryauth
Value typebool
Default"false"
Allowed levels1 (global only)

When "true", POST /api/auth/register requires the caller to first obtain a POW challenge from POST /api/auth/captcha/challenge, solve it client-side, and submit captchaId + captchaProof with the registration request. See Authentication — POW CAPTCHA for the full flow.

ICustomFieldValidationService

HrStudio2.Api.Services.Forms.CustomFieldValidationService is registered as a scoped service in Program.cs.

Expected usage: called by form endpoints (e.g. POST /api/hr/employee/create) to validate values in the colcustom payload before saving.

var errors = await customFieldValidationService.ValidateAsync(
dataAreaName: "employee_registry",
tenantId: currentTenantId,
values: request.Custom,
ct);

if (errors.Count > 0)
return UnprocessableEntity(new { errors });

Reads forms.{dataAreaName}.custom_fields from the tenant-level resolved config (ResolveForTenantAsync) and validates type, required, and select options.


Catalog management

SuperAdmin only.

POST /api/config/catalog/list

Returns all catalog entries, optionally filtered by category.

Request:

{ "category": "auth" }

Response:

[
{
"keyId": 1,
"code": "auth.password.min_length",
"category": "auth",
"label": "Minimum password length",
"valueType": "int",
"defaultValue": "8",
"allowedValues": "{\"min\":6,\"max\":128}",
"allowedLevels": 3,
"isSensitive": false,
"isActive": true
}
]

POST /api/config/catalog/get

Returns a single catalog entry by code.

Request:

{ "code": "auth.password.min_length" }

POST /api/config/catalog/create

Creates a new catalog key.

Request:

{
"code": "features.module.training",
"category": "features",
"label": "Training module",
"valueType": "bool",
"defaultValue": "false",
"allowedLevels": 3
}

POST /api/config/catalog/update

Updates metadata of an existing catalog key. Does not change override values.

Request:

{
"code": "features.module.training",
"label": "Training & Development module",
"isActive": true
}

POST /api/config/catalog/delete

Permanently deletes a catalog key and all its overrides (cascade).

Request:

{ "code": "test.demo_key" }

Error 404 if the key does not exist.


Global overrides

SuperAdmin only.

POST /api/config/global/list

Returns all global override rows.

POST /api/config/global/set

Creates or updates a global override (upsert).

Request:

{ "code": "auth.registration.enabled", "value": "false" }

POST /api/config/global/unset

Removes a global override, reverting the key to the catalog default.

Request:

{ "code": "auth.registration.enabled" }

Tenant overrides

SuperAdmin (any tenant) or TenantAdmin (own tenant only).

POST /api/config/tenant/list

Returns all tenant overrides for the caller's tenant (or the specified tenant for SuperAdmin).

Request (SuperAdmin):

{ "tenantId": 42 }

POST /api/config/tenant/set

Upserts a tenant override. Validates that the value does not violate global policy constraints.

Request:

{ "code": "branding.app_name", "value": "My Company HR" }

Error 422 if the key has cck_allowed_levels & 2 = 0 (tenant level not permitted) or if the value violates a global policy constraint.

POST /api/config/tenant/unset

Removes a tenant override, reverting to the global/catalog value.

Request:

{ "code": "branding.app_name" }

Tenant GUID variants (SuperAdmin only)

The three endpoints above identify the tenant by its internal integer ID (ten_internal_id). When calling from an external system that only knows the tenant public UUID (ten_uuid), use the GUID variants instead. They behave identically but resolve the tenant by UUID first.

POST /api/config/tenantguid/list

Lists all overrides for the tenant identified by its public UUID.

Auth: SuperAdmin only.

Request:

{ "tenantId": "3fa85f64-5717-4562-b3fc-2c963f66afa6" }

Response: same shape as POST /api/config/tenant/list.

POST /api/config/tenant/guid/set

Upserts a tenant override, identifying the tenant by public UUID.

Auth: SuperAdmin only.

Request:

{
"tenantId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "branding.app_name",
"value": "My Company HR"
}

Error 422 — same policy checks as POST /api/config/tenant/set.

POST /api/config/tenant/guid/unset

Removes a tenant override, identifying the tenant by public UUID.

Auth: SuperAdmin only.

Request:

{
"tenantId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"code": "branding.app_name"
}

Group overrides

TenantAdmin only.

POST /api/config/group/list

Lists group overrides for the caller's tenant, optionally filtered by group type.

Request:

{ "groupType": "mansione" }

Response:

[
{
"code": "ui.density",
"groupType": "mansione",
"groupCode": "DEV",
"value": "compact"
}
]

POST /api/config/group/set

Creates or updates a group override.

Request:

{
"code": "ui.density",
"groupType": "mansione",
"groupCode": "DEV",
"value": "compact"
}

Supported groupType values: mansione, qualifica, sede_op, tipo_tempo, gruppo_tipo, static_list, dynamic_list.

Error 422 if cck_allowed_levels & 4 = 0.


POST /api/config/group/unset

Removes a group override.

Request:

{
"code": "ui.density",
"groupType": "mansione",
"groupCode": "DEV"
}

User overrides

TenantAdmin (any user in their tenant) or authenticated user (own preferences only).

POST /api/config/user/values/list

Lists overrides for a specific user. TenantAdmin may pass any userId; regular users only see their own.

Request:

{ "userId": "uuid-of-user" }

POST /api/config/user/values/set

Creates or updates a user-level override.

Request:

{ "code": "ui.sidebar_collapsed", "value": "true" }

Error 422 if cck_allowed_levels & 8 = 0.


POST /api/config/user/values/unset

Removes a user-level override.

Request:

{ "code": "ui.sidebar_collapsed" }

POST /api/config/user/resolve

Re-fetches and returns the fully resolved config map for the authenticated user. Use this after a TenantAdmin changes settings that should take effect without requiring a re-login.

Request: empty body.

Response:

{
"config": {
"auth.password.min_length": "8",
"ui.theme": "dark",
"features.ai_assistant": "true"
}
}

Error responses

StatusMeaning
401Not authenticated
403Authenticated but not authorized for this level (e.g. TenantAdmin trying global endpoint)
404Config key code not found in catalog
422Level not permitted for this key, or value violates policy constraint