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