{
  "components": {
    "schemas": {
      "AcceptRequest": {
        "properties": {
          "password": {
            "description": "Current or new password, at most 72 UTF-8 bytes",
            "format": "password",
            "maxLength": 72,
            "minLength": 0,
            "type": "string",
            "writeOnly": true
          },
          "token": {
            "description": "Raw one-time invitation token",
            "maxLength": 512,
            "minLength": 0,
            "type": "string",
            "writeOnly": true
          }
        },
        "required": [
          "password",
          "token"
        ],
        "type": "object"
      },
      "AccessView": {
        "properties": {
          "membershipId": {
            "format": "uuid",
            "type": "string"
          },
          "permissions": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "roles": {
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "type": "object"
      },
      "AccountConfigure": {
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "expectedVersion": {
            "description": "Version last read; stale writes return 409",
            "example": 0,
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          },
          "name": {
            "maxLength": 200,
            "minLength": 0,
            "type": "string"
          }
        },
        "required": [
          "enabled",
          "expectedVersion",
          "name"
        ],
        "type": "object"
      },
      "AccountCreate": {
        "properties": {
          "code": {
            "example": "9901",
            "minLength": 1,
            "pattern": "^[0-9]{4}$",
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "name": {
            "maxLength": 200,
            "minLength": 0,
            "type": "string"
          },
          "type": {
            "enum": [
              "ASSET",
              "CONTRA_ASSET",
              "LIABILITY",
              "EQUITY",
              "INCOME",
              "EXPENSE"
            ],
            "type": "string"
          }
        },
        "required": [
          "code",
          "enabled",
          "name",
          "type"
        ],
        "type": "object"
      },
      "AccountingOptions": {
        "properties": {
          "accountTypes": {
            "items": {
              "enum": [
                "ASSET",
                "CONTRA_ASSET",
                "LIABILITY",
                "EQUITY",
                "INCOME",
                "EXPENSE"
              ],
              "type": "string"
            },
            "type": "array"
          },
          "depreciationMethods": {
            "items": {
              "enum": [
                "STRAIGHT_LINE"
              ],
              "type": "string"
            },
            "type": "array"
          },
          "inventoryValuationMethods": {
            "items": {
              "enum": [
                "FIFO"
              ],
              "type": "string"
            },
            "type": "array"
          },
          "taxRegimes": {
            "items": {
              "enum": [
                "GENERAL",
                "SIMPLIFIED"
              ],
              "type": "string"
            },
            "type": "array"
          }
        },
        "type": "object"
      },
      "AccountingSettingsSave": {
        "properties": {
          "depreciationMethod": {
            "enum": [
              "STRAIGHT_LINE"
            ],
            "type": "string"
          },
          "expectedVersion": {
            "format": "int64",
            "minimum": 0,
            "type": "integer"
          },
          "inventoryValuationMethod": {
            "enum": [
              "FIFO"
            ],
            "type": "string"
          },
          "taxRegime": {
            "enum": [
              "GENERAL",
              "SIMPLIFIED"
            ],
            "type": "string"
          },
          "vatRate": {
            "description": "Percentage, not fraction; configured by user, not a statutory tax rate",
            "example": 12,
            "maximum": 100,
            "minimum": 0,
            "type": "number"
          }
        },
        "required": [
          "depreciationMethod",
          "expectedVersion",
          "inventoryValuationMethod",
          "taxRegime",
          "vatRate"
        ],
        "type": "object"
      },
      "AuditActionOption": {
        "properties": {
          "category": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "label": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "AuditActor": {
        "properties": {
          "displayName": {
            "type": "string"
          },
          "membershipId": {
            "format": "uuid",
            "type": "string"
          }
        },
        "type": "object"
      },
      "AuditActorPage": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/AuditActor"
            },
            "type": "array"
          },
          "page": {
            "format": "int32",
            "type": "integer"
          },
          "size": {
            "format": "int32",
            "type": "integer"
          },
          "totalElements": {
            "format": "int64",
            "type": "integer"
          },
          "totalPages": {
            "format": "int64",
            "type": "integer"
          }
        },
        "type": "object"
      },
      "AuditEvent": {
        "properties": {
          "action": {
            "type": "string"
          },
          "actionLabel": {
            "type": "string"
          },
          "actorDisplayName": {
            "type": "string"
          },
          "actorMembershipId": {
            "format": "uuid",
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "correlationId": {
            "format": "uuid",
            "type": "string"
          },
          "deliveryState": {
            "type": "string"
          },
          "details": {
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "ipAddress": {
            "type": "string"
          },
          "occurredAt": {
            "format": "date-time",
            "type": "string"
          },
          "subjectId": {
            "format": "uuid",
            "type": "string"
          },
          "subjectType": {
            "type": "string"
          },
          "systemActor": {
            "type": "boolean"
          }
        },
        "type": "object"
      },
      "AuditEventPage": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/AuditEvent"
            },
            "type": "array"
          },
          "page": {
            "format": "int32",
            "type": "integer"
          },
          "size": {
            "format": "int32",
            "type": "integer"
          },
          "totalElements": {
            "format": "int64",
            "type": "integer"
          },
          "totalPages": {
            "format": "int64",
            "type": "integer"
          }
        },
        "type": "object"
      },
      "AuditStatistics": {
        "properties": {
          "createdRecords": {
            "format": "int64",
            "type": "integer"
          },
          "date": {
            "format": "date",
            "type": "string"
          },
          "deletedRecords": {
            "format": "int64",
            "type": "integer"
          },
          "otherActions": {
            "format": "int64",
            "type": "integer"
          },
          "timezone": {
            "type": "string"
          },
          "totalActions": {
            "format": "int64",
            "type": "integer"
          },
          "updatedRecords": {
            "format": "int64",
            "type": "integer"
          }
        },
        "type": "object"
      },
      "Company": {
        "properties": {
          "name": {
            "maxLength": 200,
            "minLength": 1,
            "pattern": ".*\\S.*",
            "type": "string"
          },
          "taxId": {
            "pattern": "[0-9]{9}",
            "type": "string"
          }
        },
        "type": "object"
      },
      "CompanyAccount": {
        "properties": {
          "balanceType": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "custom": {
            "type": "boolean"
          },
          "enabled": {
            "type": "boolean"
          },
          "name": {
            "type": "string"
          },
          "normalSide": {
            "type": "string"
          },
          "subaccountCount": {
            "format": "int64",
            "type": "integer"
          },
          "type": {
            "enum": [
              "ASSET",
              "CONTRA_ASSET",
              "LIABILITY",
              "EQUITY",
              "INCOME",
              "EXPENSE"
            ],
            "type": "string"
          },
          "version": {
            "description": "0 for an unconfigured global account; send as expectedVersion when configuring",
            "format": "int64",
            "type": "integer"
          }
        },
        "type": "object"
      },
      "CompanyAccountPage": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/CompanyAccount"
            },
            "type": "array"
          },
          "page": {
            "format": "int32",
            "type": "integer"
          },
          "size": {
            "format": "int32",
            "type": "integer"
          },
          "totalElements": {
            "format": "int64",
            "type": "integer"
          },
          "totalPages": {
            "format": "int64",
            "type": "integer"
          }
        },
        "type": "object"
      },
      "CompanyAccountingSettings": {
        "description": "UI configuration, not an effective-dated tax/policy record. No statutory rate is inferred.",
        "properties": {
          "depreciationMethod": {
            "enum": [
              "STRAIGHT_LINE"
            ],
            "type": "string"
          },
          "inventoryValuationMethod": {
            "enum": [
              "FIFO"
            ],
            "type": "string"
          },
          "legalEntityId": {
            "format": "uuid",
            "type": "string"
          },
          "taxRegime": {
            "enum": [
              "GENERAL",
              "SIMPLIFIED"
            ],
            "type": "string"
          },
          "vatRate": {
            "type": "number"
          },
          "version": {
            "description": "0 and null tax fields until first save",
            "format": "int64",
            "type": "integer"
          }
        },
        "type": "object"
      },
      "CompanySubaccount": {
        "properties": {
          "code": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "parentCode": {
            "type": "string"
          },
          "version": {
            "format": "int64",
            "type": "integer"
          }
        },
        "type": "object"
      },
      "CompanySubaccountPage": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/CompanySubaccount"
            },
            "type": "array"
          },
          "page": {
            "format": "int32",
            "type": "integer"
          },
          "size": {
            "format": "int32",
            "type": "integer"
          },
          "totalElements": {
            "format": "int64",
            "type": "integer"
          },
          "totalPages": {
            "format": "int64",
            "type": "integer"
          }
        },
        "type": "object"
      },
      "CompanyWorkspace": {
        "properties": {
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "onboardingComplete": {
            "type": "boolean"
          },
          "taxId": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "ConfirmRequest": {
        "properties": {
          "code": {
            "minLength": 1,
            "pattern": "[0-9]{6}",
            "type": "string",
            "writeOnly": true
          },
          "currentPassword": {
            "format": "password",
            "maxLength": 72,
            "minLength": 0,
            "type": "string",
            "writeOnly": true
          },
          "enrollmentId": {
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "code",
          "currentPassword",
          "enrollmentId"
        ],
        "type": "object"
      },
      "CreateRequest": {
        "properties": {
          "email": {
            "format": "email",
            "maxLength": 320,
            "minLength": 0,
            "type": "string"
          },
          "roles": {
            "items": {
              "minLength": 1,
              "pattern": "ADMIN|ACCOUNTANT|MANAGER|EMPLOYEE|VIEWER",
              "type": "string"
            },
            "maxItems": 5,
            "minItems": 1,
            "type": "array"
          }
        },
        "required": [
          "email",
          "roles"
        ],
        "type": "object"
      },
      "CreateResponse": {
        "properties": {
          "expiresAt": {
            "format": "date-time",
            "type": "string"
          },
          "invitationId": {
            "format": "uuid",
            "type": "string"
          },
          "token": {
            "description": "Raw one-time token only for legacy manual delivery; null when email dispatch is selected",
            "readOnly": true,
            "type": "string"
          }
        },
        "type": "object"
      },
      "CurrencyView": {
        "properties": {
          "base": {
            "type": "boolean"
          },
          "buyRate": {
            "description": "Bank purchase price in UZS per one unit; null for CBU",
            "type": "number"
          },
          "code": {
            "type": "string"
          },
          "effectiveDate": {
            "format": "date",
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "rate": {
            "description": "UZS per one unit; null for foreign Kapitalbank currencies",
            "type": "number"
          },
          "sellRate": {
            "description": "Bank sale price in UZS per one unit; null for CBU",
            "type": "number"
          },
          "sourceUpdatedAt": {
            "format": "date-time",
            "type": "string"
          },
          "symbol": {
            "type": "string"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "type": "object"
      },
      "CurrentUser": {
        "properties": {
          "company": {
            "$ref": "#/components/schemas/CompanyWorkspace"
          },
          "globalUserId": {
            "type": "string"
          },
          "membershipId": {
            "type": "string"
          },
          "roles": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "tenantId": {
            "type": "string"
          },
          "userId": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "DeviceRequest": {
        "properties": {
          "token": {
            "maxLength": 4096,
            "minLength": 20,
            "pattern": "[A-Za-z0-9_:.-]+",
            "type": "string"
          }
        },
        "required": [
          "token"
        ],
        "type": "object"
      },
      "DeviceResponse": {
        "properties": {
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "platform": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "DisableRequest": {
        "properties": {
          "code": {
            "pattern": "[0-9]{6}",
            "type": "string",
            "writeOnly": true
          },
          "currentPassword": {
            "format": "password",
            "maxLength": 72,
            "minLength": 0,
            "type": "string",
            "writeOnly": true
          },
          "recoveryCode": {
            "pattern": "(?i)[a-z2-7]{4}(?:-?[a-z2-7]{4}){3}",
            "type": "string",
            "writeOnly": true
          }
        },
        "required": [
          "currentPassword"
        ],
        "type": "object"
      },
      "EmailChallengeResponse": {
        "description": "Second-factor challenge without tokens. EMAIL returns a challengeId and expiry; TOTP returns null for both and sends no email.",
        "properties": {
          "challengeId": {
            "description": "EMAIL challenge UUID; null when channel is TOTP.",
            "format": "uuid",
            "type": [
              "string",
              "null"
            ]
          },
          "channel": {
            "description": "Required second factor. TOTP accepts totpCode or one unused recoveryCode.",
            "enum": [
              "EMAIL",
              "TOTP"
            ],
            "type": "string"
          },
          "expiresAt": {
            "description": "EMAIL code expiry; null when channel is TOTP. Authenticator codes use a 30-second time step.",
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "type": "object"
      },
      "EmailRequest": {
        "properties": {
          "email": {
            "example": "accountant@example.uz",
            "format": "email",
            "maxLength": 320,
            "minLength": 0,
            "type": "string"
          }
        },
        "required": [
          "email"
        ],
        "type": "object"
      },
      "EmailValidationReport": {
        "description": "Syntax/domain check only; mailbox remains unverified, independent of account existence",
        "properties": {
          "code": {
            "type": "string"
          },
          "domain": {
            "type": "string"
          },
          "format": {
            "type": "string"
          },
          "mailbox": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "Enqueued": {
        "properties": {
          "devices": {
            "format": "int32",
            "type": "integer"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          }
        },
        "type": "object"
      },
      "LoginRequest": {
        "description": "Start with email/password only. For a second factor, repeat email/password with paired challengeId/code OR totpCode OR recoveryCode. Factors are optional at the first step and mutually exclusive thereafter; mixed factors return 400.",
        "properties": {
          "challengeId": {
            "description": "EMAIL only: challengeId from the 202 response; must be paired with code. Omit for TOTP/recovery.",
            "format": "uuid",
            "type": "string"
          },
          "code": {
            "description": "EMAIL only: eight-digit email code, paired with challengeId; expires in five minutes.",
            "example": "12345678",
            "pattern": "[0-9]{8}",
            "type": "string",
            "writeOnly": true
          },
          "email": {
            "example": "accountant@example.uz",
            "format": "email",
            "minLength": 1,
            "type": "string"
          },
          "password": {
            "format": "password",
            "maxLength": 72,
            "minLength": 0,
            "type": "string",
            "writeOnly": true
          },
          "recoveryCode": {
            "description": "TOTP only: one unused recovery code instead of totpCode; omit email factors.",
            "example": "ABCD-EFGH-JKLM-NPQR",
            "pattern": "(?i)[a-z2-7]{4}(?:-?[a-z2-7]{4}){3}",
            "type": "string",
            "writeOnly": true
          },
          "totpCode": {
            "description": "TOTP only: fresh Google Authenticator six-digit code; omit all other factors.",
            "example": "123456",
            "pattern": "[0-9]{6}",
            "type": "string",
            "writeOnly": true
          }
        },
        "required": [
          "email",
          "password"
        ],
        "type": "object"
      },
      "MessageStatus": {
        "properties": {
          "counts": {
            "additionalProperties": {
              "format": "int32",
              "type": "integer"
            },
            "type": "object"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "status": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "PasswordChange": {
        "properties": {
          "confirmPassword": {
            "format": "password",
            "maxLength": 72,
            "minLength": 12,
            "type": "string",
            "writeOnly": true
          },
          "currentPassword": {
            "format": "password",
            "maxLength": 72,
            "minLength": 0,
            "type": "string",
            "writeOnly": true
          },
          "newPassword": {
            "format": "password",
            "maxLength": 72,
            "minLength": 12,
            "type": "string",
            "writeOnly": true
          }
        },
        "required": [
          "confirmPassword",
          "currentPassword",
          "newPassword"
        ],
        "type": "object"
      },
      "Permission": {
        "properties": {
          "defaultRoles": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "documented": {
            "type": "boolean"
          },
          "group": {
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "methods": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "name": {
            "type": "string"
          },
          "paths": {
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "type": "object"
      },
      "PermissionsRequest": {
        "properties": {
          "lockVersion": {
            "format": "int32",
            "minimum": 0,
            "type": "integer"
          },
          "permissions": {
            "items": {
              "maxLength": 100,
              "minLength": 0,
              "type": "string"
            },
            "maxItems": 1000,
            "minItems": 0,
            "type": "array"
          }
        },
        "required": [
          "lockVersion",
          "permissions"
        ],
        "type": "object"
      },
      "Problem": {
        "description": "RFC 7807 problem detail; problem-specific extensions may be present",
        "properties": {
          "detail": {
            "description": "Safe explanation for this occurrence",
            "type": "string"
          },
          "instance": {
            "description": "Occurrence identifier",
            "format": "uri",
            "type": "string"
          },
          "status": {
            "description": "HTTP status code",
            "format": "int32",
            "type": "integer"
          },
          "title": {
            "description": "Short human-readable title",
            "type": "string"
          },
          "type": {
            "description": "Stable problem identifier",
            "format": "uri",
            "type": "string"
          }
        },
        "type": "object"
      },
      "RatesResponse": {
        "properties": {
          "baseCurrency": {
            "type": "string"
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/CurrencyView"
            },
            "type": "array"
          },
          "lastAttemptAt": {
            "format": "date-time",
            "type": "string"
          },
          "refreshIntervalSeconds": {
            "format": "int64",
            "type": "integer"
          },
          "source": {
            "type": "string"
          },
          "stale": {
            "type": "boolean"
          },
          "status": {
            "enum": [
              "FRESH",
              "STALE",
              "UNAVAILABLE"
            ],
            "type": "string"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "type": "object"
      },
      "RecoveryResponse": {
        "properties": {
          "recoveryCodes": {
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "type": "object"
      },
      "RefreshRequest": {
        "properties": {
          "refreshToken": {
            "description": "Opaque refresh token",
            "maxLength": 512,
            "minLength": 0,
            "type": "string",
            "writeOnly": true
          }
        },
        "required": [
          "refreshToken"
        ],
        "type": "object"
      },
      "RegisterRequest": {
        "properties": {
          "company": {
            "$ref": "#/components/schemas/Company"
          },
          "confirmPassword": {
            "format": "password",
            "maxLength": 72,
            "minLength": 15,
            "type": "string",
            "writeOnly": true
          },
          "email": {
            "format": "email",
            "maxLength": 320,
            "minLength": 0,
            "type": "string"
          },
          "password": {
            "format": "password",
            "maxLength": 72,
            "minLength": 15,
            "type": "string",
            "writeOnly": true
          },
          "token": {
            "minLength": 1,
            "pattern": "[A-Za-z0-9_-]{43}",
            "type": "string",
            "writeOnly": true
          }
        },
        "required": [
          "confirmPassword",
          "email",
          "password",
          "token"
        ],
        "type": "object"
      },
      "RegistrationReceipt": {
        "properties": {
          "message": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "RoleView": {
        "properties": {
          "code": {
            "type": "string"
          },
          "defaultPermissions": {
            "type": "boolean"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "lockVersion": {
            "format": "int32",
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "permissions": {
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "type": "object"
      },
      "SecurityStatus": {
        "properties": {
          "channel": {
            "type": "string"
          },
          "email2faEnabled": {
            "type": "boolean"
          },
          "emailDeliveryAvailable": {
            "type": "boolean"
          },
          "recoveryCodesRemaining": {
            "format": "int64",
            "type": "integer"
          },
          "totpAvailable": {
            "type": "boolean"
          },
          "totpEnabled": {
            "type": "boolean"
          }
        },
        "type": "object"
      },
      "SendRequest": {
        "properties": {
          "body": {
            "maxLength": 500,
            "minLength": 0,
            "type": "string"
          },
          "clickPath": {
            "maxLength": 200,
            "minLength": 0,
            "pattern": "/(?!/)[A-Za-z0-9/_-]*",
            "type": "string"
          },
          "recipientMembershipId": {
            "format": "uuid",
            "type": "string"
          },
          "requestId": {
            "format": "uuid",
            "type": "string"
          },
          "title": {
            "maxLength": 120,
            "minLength": 0,
            "type": "string"
          }
        },
        "required": [
          "body",
          "recipientMembershipId",
          "requestId",
          "title"
        ],
        "type": "object"
      },
      "SessionItem": {
        "properties": {
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "current": {
            "type": "boolean"
          },
          "expiresAt": {
            "format": "date-time",
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "ipAddress": {
            "type": "string"
          },
          "lastActivityAt": {
            "format": "date-time",
            "type": "string"
          },
          "userAgent": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "SessionPage": {
        "properties": {
          "hasMore": {
            "type": "boolean"
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/SessionItem"
            },
            "type": "array"
          },
          "page": {
            "format": "int32",
            "type": "integer"
          },
          "size": {
            "format": "int32",
            "type": "integer"
          }
        },
        "type": "object"
      },
      "SettingChallenge": {
        "properties": {
          "currentPassword": {
            "format": "password",
            "maxLength": 72,
            "minLength": 0,
            "type": "string",
            "writeOnly": true
          },
          "purpose": {
            "enum": [
              "ENABLE",
              "DISABLE"
            ],
            "type": "string"
          }
        },
        "required": [
          "currentPassword",
          "purpose"
        ],
        "type": "object"
      },
      "SettingConfirmation": {
        "properties": {
          "challengeId": {
            "format": "uuid",
            "type": "string"
          },
          "code": {
            "example": "12345678",
            "minLength": 1,
            "pattern": "[0-9]{8}",
            "type": "string",
            "writeOnly": true
          },
          "currentPassword": {
            "format": "password",
            "maxLength": 72,
            "minLength": 0,
            "type": "string",
            "writeOnly": true
          }
        },
        "required": [
          "challengeId",
          "code",
          "currentPassword"
        ],
        "type": "object"
      },
      "SetupRequest": {
        "properties": {
          "currentPassword": {
            "format": "password",
            "maxLength": 72,
            "minLength": 0,
            "type": "string",
            "writeOnly": true
          }
        },
        "required": [
          "currentPassword"
        ],
        "type": "object"
      },
      "SetupResponse": {
        "properties": {
          "enrollmentId": {
            "format": "uuid",
            "type": "string"
          },
          "expiresAt": {
            "format": "date-time",
            "type": "string"
          },
          "otpauthUri": {
            "type": "string"
          },
          "qrDataUrl": {
            "type": "string"
          },
          "secret": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "Status": {
        "properties": {
          "delivery": {
            "type": "string"
          },
          "flow": {
            "type": "string"
          },
          "mailbox": {
            "type": "string"
          },
          "observedAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "type": "object"
      },
      "SubaccountConfigure": {
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "expectedVersion": {
            "format": "int64",
            "minimum": 1,
            "type": "integer"
          },
          "name": {
            "maxLength": 200,
            "minLength": 0,
            "type": "string"
          }
        },
        "required": [
          "enabled",
          "expectedVersion",
          "name"
        ],
        "type": "object"
      },
      "SubaccountCreate": {
        "properties": {
          "code": {
            "example": "01",
            "minLength": 1,
            "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,31}$",
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "name": {
            "maxLength": 200,
            "minLength": 0,
            "type": "string"
          }
        },
        "required": [
          "code",
          "enabled",
          "name"
        ],
        "type": "object"
      },
      "TokenResponse": {
        "properties": {
          "accessToken": {
            "description": "Short-lived bearer JWT",
            "readOnly": true,
            "type": "string"
          },
          "refreshToken": {
            "description": "One-time opaque refresh token",
            "readOnly": true,
            "type": "string"
          }
        },
        "type": "object"
      },
      "UserPage": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/UserView"
            },
            "type": "array"
          },
          "page": {
            "format": "int32",
            "type": "integer"
          },
          "size": {
            "format": "int32",
            "type": "integer"
          },
          "totalElements": {
            "format": "int64",
            "type": "integer"
          }
        },
        "type": "object"
      },
      "UserRequest": {
        "properties": {
          "contactEmail": {
            "format": "email",
            "maxLength": 320,
            "minLength": 0,
            "type": "string"
          },
          "displayName": {
            "maxLength": 200,
            "minLength": 0,
            "type": "string"
          },
          "lockVersion": {
            "format": "int32",
            "minimum": 0,
            "type": "integer"
          },
          "role": {
            "minLength": 1,
            "pattern": "ADMIN|ACCOUNTANT|MANAGER|EMPLOYEE",
            "type": "string"
          },
          "status": {
            "minLength": 1,
            "pattern": "ACTIVE|SUSPENDED",
            "type": "string"
          }
        },
        "required": [
          "displayName",
          "lockVersion",
          "role",
          "status"
        ],
        "type": "object"
      },
      "UserView": {
        "properties": {
          "contactEmail": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "lastLogin": {
            "format": "date-time",
            "type": "string"
          },
          "lockVersion": {
            "format": "int32",
            "type": "integer"
          },
          "roles": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "status": {
            "type": "string"
          },
          "userId": {
            "format": "uuid",
            "type": "string"
          }
        },
        "type": "object"
      },
      "VersionRequest": {
        "properties": {
          "lockVersion": {
            "format": "int32",
            "minimum": 0,
            "type": "integer"
          }
        },
        "required": [
          "lockVersion"
        ],
        "type": "object"
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "bearerFormat": "JWT",
        "description": "Obtained from POST /api/v1/auth/login, on the tenant's own subdomain. Presenting it on another tenant's subdomain is a 403.",
        "scheme": "bearer",
        "type": "http"
      },
      "callbackAuth": {
        "description": "Shared callback token, bound to CALLBACK_HOST.",
        "in": "header",
        "name": "X-Auth",
        "type": "apiKey"
      }
    }
  },
  "info": {
    "description": "Multi-tenant accounting. Every request acts as exactly one tenant, taken from the signed `tenant_id` claim and enforced by Postgres row-level security — the host name selects the login page and nothing else.\n\nThe ledger is append-only. A mistake is corrected by a reversing entry, never by editing what was posted. Closing a period freezes the balances it summarises, and nothing dated at or before the last close can be added, removed, or changed.\n\nMost application errors are RFC 7807 problem documents. Pre-send email validation returns its documented format/domain/mailbox report with `code`. For problem documents branch on `type`, not on the status code: several problems share a status, and titles are prose. Authentication failures can have an empty body.",
    "license": {
      "name": "Proprietary"
    },
    "title": "MonetaryAI API",
    "version": "1.0.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/api/v1/accounting-settings/{legalEntityId}": {
      "get": {
        "description": "Before first save returns FIFO, STRAIGHT_LINE, null taxRegime/vatRate and version 0. VAT is not guessed from a screenshot or statutory rules. This UI configuration is separate from immutable effective-dated policy/tax records and is not automatically consumed by posting/tax engines. Company permission: `getCompanyAccountingSettings`. Defaults: ADMIN, ACCOUNTANT, VIEWER. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "getCompanyAccountingSettings",
        "parameters": [
          {
            "in": "path",
            "name": "legalEntityId",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyAccountingSettings"
                }
              }
            },
            "description": "Settings or unsaved defaults returned"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Invalid body, enum, path, search or pagination"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Company, account or subaccount not visible in this scope"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Get inventory, depreciation and tax settings",
        "tags": [
          "Accounting settings"
        ],
        "x-default-roles": [
          "ADMIN",
          "ACCOUNTANT",
          "VIEWER"
        ],
        "x-permission-id": "getCompanyAccountingSettings"
      },
      "put": {
        "description": "Defaults to ADMIN/ACCOUNTANT. All four fields and expectedVersion are required; VAT is a percentage from 0 to 100 with at most two decimal places. Stale writes return 409; reload first. Does not amend posted entries, effective-dated histories or determine statutory rates. Settings and actor audit commit atomically. Company permission: `saveCompanyAccountingSettings`. Defaults: ADMIN, ACCOUNTANT. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "saveCompanyAccountingSettings",
        "parameters": [
          {
            "in": "path",
            "name": "legalEntityId",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AccountingSettingsSave"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyAccountingSettings"
                }
              }
            },
            "description": "Settings saved with new version"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Invalid body, enum, path, search or pagination"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Company, account or subaccount not visible in this scope"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Stale version or archived company"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Save accounting policy and tax UI settings",
        "tags": [
          "Accounting settings"
        ],
        "x-default-roles": [
          "ADMIN",
          "ACCOUNTANT"
        ],
        "x-permission-id": "saveCompanyAccountingSettings"
      }
    },
    "/api/v1/accounting-settings/{legalEntityId}/accounts": {
      "get": {
        "description": "Global NAS accounts with company name/enabled overrides plus company custom metadata. Includes all direct subaccounts in subaccountCount (including disabled); balanceType ACTIVE/PASSIVE is derived from normal debit/credit side, not enabled status. Literal q search; ordered by code. Company permission: `listCompanyAccounts`. Defaults: ADMIN, ACCOUNTANT, VIEWER. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "listCompanyAccounts",
        "parameters": [
          {
            "in": "path",
            "name": "legalEntityId",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "Literal code/name search, maximum 100 characters",
            "in": "query",
            "name": "q",
            "required": false,
            "schema": {
              "default": "",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "type",
            "required": false,
            "schema": {
              "enum": [
                "ASSET",
                "CONTRA_ASSET",
                "LIABILITY",
                "EQUITY",
                "INCOME",
                "EXPENSE"
              ],
              "type": "string"
            }
          },
          {
            "description": "Zero-based page",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 0,
              "format": "int32",
              "type": "integer"
            }
          },
          {
            "description": "Page size 1–100",
            "in": "query",
            "name": "size",
            "required": false,
            "schema": {
              "default": 50,
              "format": "int32",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyAccountPage"
                }
              }
            },
            "description": "Account page returned"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Invalid body, enum, path, search or pagination"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Company, account or subaccount not visible in this scope"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "List company chart of accounts",
        "tags": [
          "Accounting settings"
        ],
        "x-default-roles": [
          "ADMIN",
          "ACCOUNTANT",
          "VIEWER"
        ],
        "x-permission-id": "listCompanyAccounts"
      },
      "post": {
        "description": "Creates company metadata with a four-digit code that must not already exist in the global or company chart. Does not register a global ledger posting code. Defaults to ADMIN/ACCOUNTANT; mutation and actor audit commit together. Company permission: `createCompanyAccount`. Defaults: ADMIN, ACCOUNTANT. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "createCompanyAccount",
        "parameters": [
          {
            "in": "path",
            "name": "legalEntityId",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AccountCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyAccount"
                }
              }
            },
            "description": "Company account created"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Invalid body, enum, path, search or pagination"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Company, account or subaccount not visible in this scope"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Code exists or company is archived"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Add a company account",
        "tags": [
          "Accounting settings"
        ],
        "x-default-roles": [
          "ADMIN",
          "ACCOUNTANT"
        ],
        "x-permission-id": "createCompanyAccount"
      }
    },
    "/api/v1/accounting-settings/{legalEntityId}/accounts/{code}": {
      "get": {
        "description": "Global accounts not yet configured have version 0. Account code/type are immutable; normal side is derived from type. Company permission: `getCompanyAccount`. Defaults: ADMIN, ACCOUNTANT, VIEWER. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "getCompanyAccount",
        "parameters": [
          {
            "in": "path",
            "name": "legalEntityId",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "code",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyAccount"
                }
              }
            },
            "description": "Account returned"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Invalid body, enum, path, search or pagination"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Company, account or subaccount not visible in this scope"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Get account configuration",
        "tags": [
          "Accounting settings"
        ],
        "x-default-roles": [
          "ADMIN",
          "ACCOUNTANT",
          "VIEWER"
        ],
        "x-permission-id": "getCompanyAccount"
      },
      "put": {
        "description": "Defaults to ADMIN/ACCOUNTANT. Send the last-read version as expectedVersion (0 for an unconfigured global account). Creates a company override on first save without modifying global metadata. Disabling is a UI setting, not a ledger posting prohibition. Company permission: `configureCompanyAccount`. Defaults: ADMIN, ACCOUNTANT. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "configureCompanyAccount",
        "parameters": [
          {
            "in": "path",
            "name": "legalEntityId",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "code",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AccountConfigure"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyAccount"
                }
              }
            },
            "description": "Configuration saved with new version"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Invalid body, enum, path, search or pagination"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Company, account or subaccount not visible in this scope"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Stale version or archived company"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Configure account name and enabled status",
        "tags": [
          "Accounting settings"
        ],
        "x-default-roles": [
          "ADMIN",
          "ACCOUNTANT"
        ],
        "x-permission-id": "configureCompanyAccount"
      }
    },
    "/api/v1/accounting-settings/{legalEntityId}/accounts/{code}/subaccounts": {
      "get": {
        "description": "Tenant/company/parent-scoped metadata; not inferred from global NAS sections. Literal search across subaccount code/name, ordered by code/id. Company permission: `listCompanySubaccounts`. Defaults: ADMIN, ACCOUNTANT, VIEWER. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "listCompanySubaccounts",
        "parameters": [
          {
            "in": "path",
            "name": "legalEntityId",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "code",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Literal search, maximum 100 characters",
            "in": "query",
            "name": "q",
            "required": false,
            "schema": {
              "default": "",
              "type": "string"
            }
          },
          {
            "description": "Zero-based page",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 0,
              "format": "int32",
              "type": "integer"
            }
          },
          {
            "description": "Page size 1–100",
            "in": "query",
            "name": "size",
            "required": false,
            "schema": {
              "default": 50,
              "format": "int32",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanySubaccountPage"
                }
              }
            },
            "description": "Subaccount page returned"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Invalid body, enum, path, search or pagination"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Company, account or subaccount not visible in this scope"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "List direct subaccounts",
        "tags": [
          "Accounting settings"
        ],
        "x-default-roles": [
          "ADMIN",
          "ACCOUNTANT",
          "VIEWER"
        ],
        "x-permission-id": "listCompanySubaccounts"
      },
      "post": {
        "description": "Defaults to ADMIN/ACCOUNTANT. Code is unique within this company and parent; hierarchy is exactly one level. Parent must be enabled. A global parent is materialized as company metadata on first child creation; reload its version before configuring. No global ledger changes. Company permission: `createCompanySubaccount`. Defaults: ADMIN, ACCOUNTANT. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "createCompanySubaccount",
        "parameters": [
          {
            "in": "path",
            "name": "legalEntityId",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "code",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubaccountCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanySubaccount"
                }
              }
            },
            "description": "Subaccount created"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Invalid body, enum, path, search or pagination"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Company, account or subaccount not visible in this scope"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Duplicate code, disabled parent or archived company"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Add a subaccount",
        "tags": [
          "Accounting settings"
        ],
        "x-default-roles": [
          "ADMIN",
          "ACCOUNTANT"
        ],
        "x-permission-id": "createCompanySubaccount"
      }
    },
    "/api/v1/accounting-settings/{legalEntityId}/accounts/{code}/subaccounts/{subaccountId}": {
      "put": {
        "description": "Defaults to ADMIN/ACCOUNTANT. Name and enabled status may change using expectedVersion; parent and code cannot change. An enabled child requires an enabled parent. Audit is atomic. Company permission: `configureCompanySubaccount`. Defaults: ADMIN, ACCOUNTANT. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "configureCompanySubaccount",
        "parameters": [
          {
            "in": "path",
            "name": "legalEntityId",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "code",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "subaccountId",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubaccountConfigure"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanySubaccount"
                }
              }
            },
            "description": "Subaccount saved with new version"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Invalid body, enum, path, search or pagination"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Company, account or subaccount not visible in this scope"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Stale version, disabled parent or archived company"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Configure a subaccount",
        "tags": [
          "Accounting settings"
        ],
        "x-default-roles": [
          "ADMIN",
          "ACCOUNTANT"
        ],
        "x-permission-id": "configureCompanySubaccount"
      }
    },
    "/api/v1/accounting-settings/{legalEntityId}/options": {
      "get": {
        "description": "Only currently supported valuation/depreciation methods are returned. Tax regimes are configuration labels, not country-specific tax advice; no VAT rate is inferred. Company permission: `getAccountingSettingsOptions`. Defaults: ADMIN, ACCOUNTANT, VIEWER. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "getAccountingSettingsOptions",
        "parameters": [
          {
            "in": "path",
            "name": "legalEntityId",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountingOptions"
                }
              }
            },
            "description": "Dropdown options returned"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Invalid body, enum, path, search or pagination"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Company, account or subaccount not visible in this scope"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Get accounting settings dropdown options",
        "tags": [
          "Accounting settings"
        ],
        "x-default-roles": [
          "ADMIN",
          "ACCOUNTANT",
          "VIEWER"
        ],
        "x-permission-id": "getAccountingSettingsOptions"
      }
    },
    "/api/v1/audit-events": {
      "get": {
        "description": "Returns newest-first immutable audit metadata for the authenticated administrator's tenant. Payloads, request bodies, tokens, errors, and unrelated personal data are never returned. Company permission: `listAuditEvents`. Defaults: ADMIN. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "listAuditEvents",
        "parameters": [
          {
            "description": "Stored audit subject type",
            "in": "query",
            "name": "subjectType",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Stored audit action",
            "in": "query",
            "name": "action",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Exact actor membership ID",
            "in": "query",
            "name": "actorMembershipId",
            "required": false,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "Exact audit subject ID",
            "in": "query",
            "name": "subjectId",
            "required": false,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "Exact operation correlation ID",
            "in": "query",
            "name": "correlationId",
            "required": false,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "Inclusive occurred-at lower bound",
            "in": "query",
            "name": "from",
            "required": false,
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "description": "Exclusive occurred-at upper bound",
            "in": "query",
            "name": "to",
            "required": false,
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "description": "Zero-based page number",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 0,
              "format": "int32",
              "type": "integer"
            }
          },
          {
            "description": "Page size from 1 to 100",
            "in": "query",
            "name": "size",
            "required": false,
            "schema": {
              "default": 50,
              "format": "int32",
              "type": "integer"
            }
          },
          {
            "description": "true: system events; false: human events; omitted: both",
            "in": "query",
            "name": "systemActor",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "Inclusive calendar start date, yyyy-MM-dd; cannot combine with from/to",
            "in": "query",
            "name": "dateFrom",
            "required": false,
            "schema": {
              "format": "date",
              "type": "string"
            }
          },
          {
            "description": "Inclusive calendar end date, yyyy-MM-dd; cannot combine with from/to",
            "in": "query",
            "name": "dateTo",
            "required": false,
            "schema": {
              "format": "date",
              "type": "string"
            }
          },
          {
            "description": "IANA timezone for calendar dates, default Asia/Tashkent",
            "in": "query",
            "name": "timezone",
            "required": false,
            "schema": {
              "default": "Asia/Tashkent",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuditEventPage"
                }
              }
            },
            "description": "Audit-event page returned"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Filter or pagination values are invalid"
          },
          "401": {
            "description": "Authentication is required"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Only tenant administrators may read audit events"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "List audit-event metadata",
        "tags": [
          "Audit"
        ],
        "x-default-roles": [
          "ADMIN"
        ],
        "x-permission-id": "listAuditEvents"
      }
    },
    "/api/v1/audit-events/actions": {
      "get": {
        "description": "Known application actions plus historical tenant actions. CREATE/UPDATE/DELETE count committed creation, mutation and deletion/archive actions; lifecycle/login/delivery actions are OTHER. Company permission: `listAuditActions`. Defaults: ADMIN. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "listAuditActions",
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/AuditActionOption"
                  },
                  "type": "array"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Audit action filter options and categories",
        "tags": [
          "Audit"
        ],
        "x-default-roles": [
          "ADMIN"
        ],
        "x-permission-id": "listAuditActions"
      }
    },
    "/api/v1/audit-events/actors": {
      "get": {
        "description": "Includes inactive memberships for historical filtering; returns names and membership IDs only. System is selected with systemActor=true. Company permission: `listAuditActors`. Defaults: ADMIN. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "listAuditActors",
        "parameters": [
          {
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 0,
              "format": "int32",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "size",
            "required": false,
            "schema": {
              "default": 50,
              "format": "int32",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuditActorPage"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Request body, header, path, or query value is malformed"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Paginated tenant actor filter options",
        "tags": [
          "Audit"
        ],
        "x-default-roles": [
          "ADMIN"
        ],
        "x-permission-id": "listAuditActors"
      }
    },
    "/api/v1/audit-events/statistics": {
      "get": {
        "description": "Whole-tenant daily counts, independent of journal filters. Defaults to today in Asia/Tashkent. Bounds use local midnight, including DST. totalActions equals createdRecords+updatedRecords+deletedRecords+otherActions. Company permission: `getAuditStatistics`. Defaults: ADMIN. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "getAuditStatistics",
        "parameters": [
          {
            "description": "Calendar day yyyy-MM-dd; omitted means today in timezone",
            "in": "query",
            "name": "date",
            "required": false,
            "schema": {
              "format": "date",
              "type": "string"
            }
          },
          {
            "description": "IANA timezone",
            "in": "query",
            "name": "timezone",
            "required": false,
            "schema": {
              "default": "Asia/Tashkent",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuditStatistics"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Request body, header, path, or query value is malformed"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Daily audit activity statistics",
        "tags": [
          "Audit"
        ],
        "x-default-roles": [
          "ADMIN"
        ],
        "x-permission-id": "getAuditStatistics"
      }
    },
    "/api/v1/audit-events/{id}": {
      "get": {
        "description": "Same safe fields as the journal; raw payload is never exposed. Other-tenant IDs return 404. Company permission: `getAuditEvent`. Defaults: ADMIN. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "getAuditEvent",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuditEvent"
                }
              }
            },
            "description": "Event metadata"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Request body, header, path, or query value is malformed"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Event not found in this tenant"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Get safe audit-event metadata",
        "tags": [
          "Audit"
        ],
        "x-default-roles": [
          "ADMIN"
        ],
        "x-permission-id": "getAuditEvent"
      }
    },
    "/api/v1/auth/email/validate": {
      "post": {
        "description": "Does not send email, inspect app accounts or assert mailbox existence. 400 invalid format, 422 invalid mail domain, 503 temporary DNS failure. Mailbox ownership remains unverified until the recipient redeems a proof.",
        "operationId": "validateEmailDomain",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmailRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EmailValidationReport"
                }
              }
            },
            "description": "Valid syntax; domain valid or explicitly unchecked"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailValidationReport"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Invalid format or malformed request"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailValidationReport"
                }
              }
            },
            "description": "Domain does not accept email"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailValidationReport"
                }
              }
            },
            "description": "Temporary DNS unavailability"
          }
        },
        "security": [],
        "summary": "Check email format and mail domain",
        "tags": [
          "email-validation-controller"
        ]
      }
    },
    "/api/v1/auth/login": {
      "post": {
        "description": "On the configured central host, email/password selects the oldest active membership. On tenant hosts, the tenant is taken from the host, not the body. A user of one tenant cannot authenticate against another tenant's subdomain. Repeated failures, from one address or against one account, are answered with 429 and Retry-After. When email 2FA is enabled, valid credentials without challengeId/code return 202 and queue an eight-digit code to the stored account email. Repeat this same login with password, challengeId and code to receive tokens. Codes expire in five minutes, permit five guesses and require provider acknowledgement. No tokens are issued at the challenge step. For Google Authenticator, 202 channel=TOTP requires repeating login with email, password and totpCode (six digits) or one unused recoveryCode. For TOTP, challengeId and expiresAt are null and no email is sent. On the second-factor submission, supply exactly one factor: paired email challengeId/code, totpCode, or recoveryCode; mixed factors return 400. A TOTP is accepted once across all memberships; wait for the next 30-second code after enrollment. Five Authenticator factor attempts per five minutes are permitted. The backend returns accessToken/refreshToken in the 200 JSON body, not browser cookies. The Next.js frontend BFF stores them in HttpOnly cookies and handles browser redirects; this backend endpoint does not redirect.",
        "operationId": "login",
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "1. Start sign-in": {
                  "description": "1. Start sign-in",
                  "value": {
                    "email": "accountant@example.uz",
                    "password": "your-password"
                  }
                },
                "2. Email code": {
                  "description": "2. Email code",
                  "value": {
                    "challengeId": "123e4567-e89b-12d3-a456-426614174000",
                    "code": "12345678",
                    "email": "accountant@example.uz",
                    "password": "your-password"
                  }
                },
                "3. Google Authenticator": {
                  "description": "3. Google Authenticator",
                  "value": {
                    "email": "accountant@example.uz",
                    "password": "your-password",
                    "totpCode": "123456"
                  }
                },
                "4. Recovery code": {
                  "description": "4. Recovery code",
                  "value": {
                    "email": "accountant@example.uz",
                    "password": "your-password",
                    "recoveryCode": "ABCD-EFGH-JKLM-NPQR"
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/LoginRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            },
            "description": "Access and refresh tokens issued"
          },
          "202": {
            "content": {
              "application/json": {
                "examples": {
                  "Authenticator required": {
                    "description": "Authenticator required",
                    "value": {
                      "challengeId": null,
                      "channel": "TOTP",
                      "expiresAt": null
                    }
                  },
                  "Email challenge": {
                    "description": "Email challenge",
                    "value": {
                      "challengeId": "123e4567-e89b-12d3-a456-426614174000",
                      "channel": "EMAIL",
                      "expiresAt": "2026-01-01T12:05:00Z"
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/EmailChallengeResponse"
                }
              }
            },
            "description": "Second factor required; no tokens. EMAIL includes challengeId/expiresAt; TOTP sets both to null."
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Invalid email/password/factor shape, incomplete email challenge pair, or mixed factors"
          },
          "401": {
            "description": "Credentials or tenant are invalid"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Password or second-factor throttle is active; respect Retry-After"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Email delivery or Authenticator encryption is unavailable; no tokens issued"
          }
        },
        "security": [],
        "summary": "Exchange credentials for a token pair",
        "tags": [
          "Authentication"
        ]
      }
    },
    "/api/v1/auth/logout": {
      "post": {
        "description": "Revokes every active refresh token in the submitted token's family.",
        "operationId": "logout",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RefreshRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Family revoked or token already inactive"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Refresh token shape is invalid"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "security": [],
        "summary": "Revoke a refresh-token family",
        "tags": [
          "Authentication"
        ]
      }
    },
    "/api/v1/auth/magic-link/request": {
      "post": {
        "description": "Central host accepts valid email syntax with a routable mail domain for registration and returns 202. No account-existence/delivery disclosure; links point to configured /magic?token=... origin. Legacy tenant-host behavior uses the tenant host, not a body tenant identifier. After the same email-domain checks, compatibility mode returns 204, including unknown, inactive, throttled or disabled-delivery requests. This does not confirm account existence or delivery. No token is returned; delivery is opt-in and links use a trusted configured origin.",
        "operationId": "requestMagicLogin",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmailRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegistrationReceipt"
                }
              }
            },
            "description": "Registration request accepted or silently absorbed"
          },
          "204": {
            "description": "Legacy tenant sign-in request accepted or absorbed"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Email shape is invalid"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailValidationReport"
                }
              }
            },
            "description": "Mail domain does not accept email"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailValidationReport"
                }
              }
            },
            "description": "Domain lookup temporarily unavailable"
          }
        },
        "security": [],
        "summary": "Request a company registration email link",
        "tags": [
          "Authentication"
        ]
      }
    },
    "/api/v1/auth/membership-invitations/accept": {
      "post": {
        "description": "Proves an existing identity's current password, or creates a new identity with a chosen password only for an email-only invitation. Token consumption and membership roles are atomic. For identities with email 2FA, returns a 202 challenge without tokens; complete /auth/login with the current password, challengeId and emailed code on this tenant host. For Google Authenticator users, returns 202 channel=TOTP; complete login on this tenant with password and totpCode or recoveryCode. Otherwise issues the session atomically.",
        "operationId": "acceptMembershipInvitation",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AcceptRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            },
            "description": "Membership created and token pair issued"
          },
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailChallengeResponse"
                }
              }
            },
            "description": "Membership accepted; complete email 2FA via login"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Token or password shape is invalid"
          },
          "401": {
            "description": "Token or password is invalid; response is intentionally uniform"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "security": [],
        "summary": "Accept an invitation or activate an invited identity",
        "tags": [
          "Memberships"
        ]
      }
    },
    "/api/v1/auth/refresh": {
      "post": {
        "description": "Consumes the submitted token and returns a new access/refresh pair. Reuse revokes the whole token family.",
        "operationId": "refreshToken",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RefreshRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            },
            "description": "Token rotated"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Refresh token shape is invalid"
          },
          "401": {
            "description": "Token is invalid, expired, consumed, or revoked"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "security": [],
        "summary": "Rotate an opaque refresh token",
        "tags": [
          "Authentication"
        ]
      }
    },
    "/api/v1/auth/register": {
      "post": {
        "description": "Central host only. Single-use acknowledged email token, matching email and confirmed password. Company name/STIR optional; creates an isolated onboarding workspace and ADMIN membership atomically. Existing identities cannot be overwritten. Backend returns bearer tokens; browser BFF stores HttpOnly cookies.",
        "operationId": "registerCompanyOwner",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            },
            "description": "Identity, workspace and session created"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Email, password confirmation or optional company fields invalid"
          },
          "401": {
            "description": "Invalid, expired, unacknowledged, replayed or mismatched proof"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Credential attempt rate limit active"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "security": [],
        "summary": "Register an email-verified company owner",
        "tags": [
          "Authentication"
        ]
      }
    },
    "/api/v1/currency-rates": {
      "get": {
        "description": "source defaults to CBU. CBU rate is UZS per one currency unit. KAPITALBANK returns separate buyRate (bank buys) and sellRate (bank sells), with rate null to avoid silently choosing a side. UZS always equals 1. updatedAt is the last successful fetch, effectiveDate/sourceUpdatedAt are publisher dates (bank timezone Asia/Tashkent). Status UNAVAILABLE means no successful snapshot; STALE retains last good values after a failed refresh or when a refresh is overdue. Read calls do not contact upstream sources.",
        "operationId": "listCurrencyRates",
        "parameters": [
          {
            "in": "query",
            "name": "source",
            "required": false,
            "schema": {
              "enum": [
                "CBU",
                "KAPITALBANK"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/RatesResponse"
                }
              }
            },
            "description": "Exactly four currencies and source freshness"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unsupported source"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Get UZS, USD, EUR and RUB rates",
        "tags": [
          "Currency rates"
        ]
      }
    },
    "/api/v1/me": {
      "get": {
        "description": "Returns identity, membership, tenant, and role claims after signature and host-to-tenant validation.",
        "operationId": "getCurrentUser",
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/CurrentUser"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Get the current authenticated user",
        "tags": [
          "Identity"
        ]
      }
    },
    "/api/v1/me/email-delivery": {
      "get": {
        "description": "At most five registration/current-tenant magic receipts for the authenticated identity. No email query, provider identifiers, payloads or proofs. DELIVERED means mail-server acceptance, not inbox placement or mailbox existence. Only consumed recipient proof confirms ownership.",
        "operationId": "getOwnAuthEmailDelivery",
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/Status"
                  },
                  "type": "array"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Read your own recent email delivery states",
        "tags": [
          "own-email-delivery-controller"
        ]
      }
    },
    "/api/v1/me/security": {
      "get": {
        "description": "Global identity setting applies across all tenant memberships. No password or code is returned.",
        "operationId": "getOwnAccountSecurity",
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/SecurityStatus"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Read account 2FA status",
        "tags": [
          "Account security"
        ]
      }
    },
    "/api/v1/me/security/authenticator/confirm": {
      "post": {
        "description": "Requires current password, enrollmentId and TOTP code. Only a valid unexpired setup can activate. Returns ten one-use recovery codes ONCE; only hashes are stored. Explicitly replaces existing email 2FA, revokes all sessions/JWTs across memberships, and requires login again. The enrollment code is consumed; use the NEXT 30-second code for login. Five guesses per five minutes; replay and foreign enrollment rejected.",
        "operationId": "confirmOwnAuthenticator",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConfirmRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/RecoveryResponse"
                }
              }
            },
            "description": "Enabled, recovery codes returned once; login again"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Request body, header, path, or query value is malformed"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Activate Google Authenticator using its six-digit code",
        "tags": [
          "Account security"
        ]
      }
    },
    "/api/v1/me/security/authenticator/disable": {
      "post": {
        "description": "Requires current password and one fresh six-digit code OR one unused recoveryCode. Removes the secret/recovery codes and revokes every session/JWT. Password reset never disables TOTP. Login again after success.",
        "operationId": "disableOwnAuthenticator",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DisableRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Disabled, login again"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Request body, header, path, or query value is malformed"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Disable Google Authenticator using password and second factor",
        "tags": [
          "Account security"
        ]
      }
    },
    "/api/v1/me/security/authenticator/setup": {
      "post": {
        "description": "Requires current password. Returns a locally generated PNG QR and otpauth URI (SHA1, 6 digits, 30s), never an external QR service. Pending setup expires after 10 minutes; repeating setup resumes it without resetting the guess budget. Does not enable 2FA until confirm succeeds. Secrets must not be logged or cached. Already enabled returns 409; unavailable encryption returns 503.",
        "operationId": "setupOwnAuthenticator",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetupRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/SetupResponse"
                }
              }
            },
            "description": "Pending enrollment and QR generated"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Request body, header, path, or query value is malformed"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Generate Google Authenticator QR and manual setup key",
        "tags": [
          "Account security"
        ]
      }
    },
    "/api/v1/me/security/email-2fa/challenges": {
      "post": {
        "description": "Requires current password; recipient is always the account's stored email, never request input. Eight-digit code expires in five minutes and allows five guesses. At most five issues per user/hour, twenty per IP/hour and one per purpose/minute. 202 is queue acceptance, not delivery. Only provider-acknowledged codes can be redeemed.",
        "operationId": "requestEmail2faSettingChallenge",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SettingChallenge"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EmailChallengeResponse"
                }
              }
            },
            "description": "Email challenge queued"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Invalid purpose or password shape"
          },
          "401": {
            "description": "Invalid credentials, state or issuance limit reached"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Password attempt throttle is active"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Email delivery is disabled"
          }
        },
        "summary": "Email a code to enable or disable 2FA",
        "tags": [
          "Account security"
        ]
      }
    },
    "/api/v1/me/security/email-2fa/disable": {
      "post": {
        "description": "Requires current password and a separate acknowledged DISABLE code. A login or enrollment code cannot disable 2FA. Invalidates all refresh sessions and access JWTs; login again.",
        "operationId": "disableOwnEmail2fa",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SettingConfirmation"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Email 2FA disabled; login again"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Malformed challenge or code"
          },
          "401": {
            "description": "Password or challenge invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Password attempt throttle is active"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Confirm disabling email 2FA",
        "tags": [
          "Account security"
        ]
      }
    },
    "/api/v1/me/security/email-2fa/enable": {
      "post": {
        "description": "Requires current password and acknowledged ENABLE code. Invalidates every session and access token for the global identity; login again with password and email code. Wrong, expired, unacknowledged, foreign or reused challenges return 401.",
        "operationId": "enableOwnEmail2fa",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SettingConfirmation"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Email 2FA enabled; login again"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Malformed challenge or code"
          },
          "401": {
            "description": "Password or challenge invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Password attempt throttle is active"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Confirm email 2FA enrollment",
        "tags": [
          "Account security"
        ]
      }
    },
    "/api/v1/me/security/password": {
      "post": {
        "description": "Requires matching confirmation and the current password. Atomically invalidates all refresh sessions, outstanding email challenges and access JWTs across every membership. Login again after success.",
        "operationId": "changeOwnPassword",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PasswordChange"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Password changed; login again"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Password policy or confirmation is invalid"
          },
          "401": {
            "description": "Current password is invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Password attempt throttle is active"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Change password using current password",
        "tags": [
          "Account security"
        ]
      }
    },
    "/api/v1/me/sessions": {
      "delete": {
        "description": "Revokes this active membership's currently visible live refresh families in this tenant. Concurrent or later new logins are not prevented. Already issued access JWTs retain their configured expiry. Other memberships and tenants are untouched; repeated requests do not duplicate audit events.",
        "operationId": "revokeAllOwnRefreshSessions",
        "responses": {
          "204": {
            "description": "Own active refresh families revoked, or none remained"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Revoke all own active refresh sessions",
        "tags": [
          "Identity"
        ]
      },
      "get": {
        "description": "Returns family identifiers, creation, refresh-expiry, User-Agent, IP and last login/refresh activity for the authenticated active membership in this tenant. No tokens or hashes. User-Agent is untrusted client metadata; IP is the container remote address. Current is determined by the signed session_id claim (legacy tokens have no current marker). Stable newest-first pagination.",
        "operationId": "listOwnRefreshSessions",
        "parameters": [
          {
            "description": "Zero-based page number",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 0,
              "format": "int32",
              "type": "integer"
            }
          },
          {
            "description": "Page size from 1 to 100",
            "in": "query",
            "name": "size",
            "required": false,
            "schema": {
              "default": 20,
              "format": "int32",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/SessionPage"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Request body, header, path, or query value is malformed"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "List own active refresh sessions",
        "tags": [
          "Identity"
        ]
      }
    },
    "/api/v1/me/sessions/{familyId}": {
      "delete": {
        "description": "Stops future refresh for this family only. Already issued access JWTs remain valid until their configured expiry; this is not immediate access-token invalidation. Only the authenticated active membership's family in this tenant can be changed.",
        "operationId": "revokeOwnRefreshSession",
        "parameters": [
          {
            "description": "Own refresh-family identifier",
            "in": "path",
            "name": "familyId",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Refresh family revoked and audited atomically"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Request body, header, path, or query value is malformed"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Family is unknown, foreign, expired or already inactive"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Revoke one own refresh session",
        "tags": [
          "Identity"
        ]
      }
    },
    "/api/v1/membership-invitations": {
      "post": {
        "description": "Creates a 24-hour, one-time invitation. Email delivery permits recipient-bound activation of a new identity and never returns the token. Email-disabled legacy manual delivery returns a token usable only by an existing identity. Neither response confirms delivery. Company permission: `createMembershipInvitation`. Defaults: ADMIN. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "createMembershipInvitation",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/CreateResponse"
                }
              }
            },
            "description": "Legacy manual invitation created; raw token returned once"
          },
          "202": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/CreateResponse"
                }
              }
            },
            "description": "Email delivery queued; no token returned or delivery confirmed"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Email or role snapshot is invalid"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Caller is not a tenant administrator"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Add a user through a recipient-bound membership invitation",
        "tags": [
          "Memberships",
          "Users and roles"
        ],
        "x-default-roles": [
          "ADMIN"
        ],
        "x-permission-id": "createMembershipInvitation"
      }
    },
    "/api/v1/membership-invitations/{invitationId}/revocation": {
      "post": {
        "description": "Revokes one invitation in the caller's tenant without revealing invitations in another tenant. Company permission: `revokeMembershipInvitation`. Defaults: ADMIN. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "revokeMembershipInvitation",
        "parameters": [
          {
            "in": "path",
            "name": "invitationId",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Invitation revoked"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Request body, header, path, or query value is malformed"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "404": {
            "description": "Invitation is absent, foreign, or no longer revocable"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Revoke a pending membership invitation",
        "tags": [
          "Memberships"
        ],
        "x-default-roles": [
          "ADMIN"
        ],
        "x-permission-id": "revokeMembershipInvitation"
      }
    },
    "/api/v1/push/devices": {
      "post": {
        "description": "Stores the FCM token encrypted and returns only the device id/platform. Re-registering the same owned token is idempotent; another account cannot claim an active token.",
        "operationId": "registerWebPushDevice",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeviceRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeviceResponse"
                }
              }
            },
            "description": "Existing owned browser registration refreshed"
          },
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeviceResponse"
                }
              }
            },
            "description": "New web browser registered"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Request body, header, path, or query value is malformed"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Token belongs to another membership"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Active browser limit reached"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Web push is disabled"
          }
        },
        "summary": "Register the current user's web browser",
        "tags": [
          "Web push"
        ]
      }
    },
    "/api/v1/push/devices/{id}": {
      "delete": {
        "description": "Idempotently disables only an owned device and clears its encrypted token. Unknown or foreign ids do not change another user's subscription.",
        "operationId": "revokeWebPushDevice",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Owned browser revoked or already absent"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Request body, header, path, or query value is malformed"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Revoke the current user's web browser",
        "tags": [
          "Web push"
        ]
      }
    },
    "/api/v1/push/messages": {
      "post": {
        "description": "Default ADMIN access; live company permission is checked again at delivery. The request UUID is idempotent. A 202 means queued, not Firebase acceptance or browser delivery. Company permission: `enqueueWebPushMessage`. Defaults: ADMIN. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "enqueueWebPushMessage",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Enqueued"
                }
              }
            },
            "description": "Message and per-device deliveries queued"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Request body, header, path, or query value is malformed"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Request UUID was used with different content"
          },
          "422": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Recipient opted out or has no active web browser"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Tenant message limit reached"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Web push is disabled"
          }
        },
        "summary": "Enqueue a tenant-scoped web push message",
        "tags": [
          "Web push"
        ],
        "x-default-roles": [
          "ADMIN"
        ],
        "x-permission-id": "enqueueWebPushMessage"
      }
    },
    "/api/v1/push/messages/{id}": {
      "get": {
        "description": "Requires live company permission. Per-device ACCEPTED is Firebase acceptance only; UNCERTAIN is not automatically retried. COMPLETE means no pending/claimed work, not proof of browser display. Company permission: `getWebPushMessageStatus`. Defaults: ADMIN. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "getWebPushMessageStatus",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageStatus"
                }
              }
            },
            "description": "Current per-device delivery outcomes"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Request body, header, path, or query value is malformed"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Message is absent from this tenant"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Read a tenant-scoped web push message status",
        "tags": [
          "Web push"
        ],
        "x-default-roles": [
          "ADMIN"
        ],
        "x-permission-id": "getWebPushMessageStatus"
      }
    },
    "/api/v1/settings/access": {
      "get": {
        "description": "Returns the caller's live permission IDs for menu and action visibility. Does not expose other members, grant authority or replace server-side authorization. Own-profile, session and preference APIs remain independently self-scoped.",
        "operationId": "getOwnCompanyAccess",
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AccessView"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Read current effective API access",
        "tags": [
          "Users and roles"
        ]
      }
    },
    "/api/v1/settings/permissions": {
      "get": {
        "description": "Stable permission IDs match Swagger operationId values. Each entry includes its API paths, HTTP methods, group and default roles. Public and self-only APIs cannot be delegated through this catalogue. Company permission: `listCompanyPermissions`. Defaults: ADMIN. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "listCompanyPermissions",
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/Permission"
                  },
                  "type": "array"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "List configurable permissions",
        "tags": [
          "Users and roles"
        ],
        "x-default-roles": [
          "ADMIN"
        ],
        "x-permission-id": "listCompanyPermissions"
      }
    },
    "/api/v1/settings/roles": {
      "get": {
        "description": "Always returns ADMIN, ACCOUNTANT, MANAGER and EMPLOYEE with effective permission IDs and optimistic lock versions. Permission customization is isolated to the signed tenant. Company permission: `listCompanyRoles`. Defaults: ADMIN. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "listCompanyRoles",
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/RoleView"
                  },
                  "type": "array"
                }
              }
            },
            "description": "OK"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "List the four company default roles",
        "tags": [
          "Users and roles"
        ],
        "x-default-roles": [
          "ADMIN"
        ],
        "x-permission-id": "listCompanyRoles"
      }
    },
    "/api/v1/settings/roles/{code}": {
      "get": {
        "description": "Returns effective permission IDs and the current lockVersion for one of the four company defaults. Company permission: `getCompanyRole`. Defaults: ADMIN. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "getCompanyRole",
        "parameters": [
          {
            "in": "path",
            "name": "code",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/RoleView"
                }
              }
            },
            "description": "Company role and effective permissions"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Request body, header, path, or query value is malformed"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Not a configurable company default role"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Read one company role",
        "tags": [
          "Users and roles"
        ],
        "x-default-roles": [
          "ADMIN"
        ],
        "x-permission-id": "getCompanyRole"
      }
    },
    "/api/v1/settings/roles/{code}/permissions": {
      "put": {
        "description": "Send permission IDs from the catalogue and the last read lockVersion. An empty list denies all configurable APIs. Unknown/duplicate IDs are rejected. Changes apply to already-issued bearer tokens on their next request. The last permanent access administrator cannot be locked out; OWNER remains protected. Company permission: `replaceCompanyRolePermissions`. Defaults: ADMIN. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "replaceCompanyRolePermissions",
        "parameters": [
          {
            "in": "path",
            "name": "code",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PermissionsRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/RoleView"
                }
              }
            },
            "description": "Role permissions replaced; returns the incremented lockVersion"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unknown, duplicate or malformed permission ID"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unknown role code"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Stale version or removal of the last durable access administrator"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Replace a role's complete access list",
        "tags": [
          "Users and roles"
        ],
        "x-default-roles": [
          "ADMIN"
        ],
        "x-permission-id": "replaceCompanyRolePermissions"
      }
    },
    "/api/v1/settings/roles/{code}/permissions/reset": {
      "post": {
        "description": "Versioned reset to documented defaults; custom changes in other companies are untouched. Company permission: `resetCompanyRolePermissions`. Defaults: ADMIN. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "resetCompanyRolePermissions",
        "parameters": [
          {
            "in": "path",
            "name": "code",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VersionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/RoleView"
                }
              }
            },
            "description": "Role default permissions restored"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Request body, header, path, or query value is malformed"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unknown role code"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Stale version or access administrator lockout"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Restore a role's default access",
        "tags": [
          "Users and roles"
        ],
        "x-default-roles": [
          "ADMIN"
        ],
        "x-permission-id": "resetCompanyRolePermissions"
      }
    },
    "/api/v1/settings/users": {
      "get": {
        "description": "Bounded page with company display name, immutable login email, role codes, ACTIVE/SUSPENDED status, last login and lockVersion. ENDED memberships are hidden but retained for audit. Search matches literal name/email substrings; role and status filters are optional. Add a user through the recipient-bound invitation API, never by setting another person's password. Company permission: `listCompanyUsers`. Defaults: ADMIN. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "listCompanyUsers",
        "parameters": [
          {
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 0,
              "format": "int32",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "size",
            "required": false,
            "schema": {
              "default": 50,
              "format": "int32",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "role",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/UserPage"
                }
              }
            },
            "description": "Filtered company user page"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Invalid pagination or filter"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "List company users for the settings table",
        "tags": [
          "Users and roles"
        ],
        "x-default-roles": [
          "ADMIN"
        ],
        "x-permission-id": "listCompanyUsers"
      }
    },
    "/api/v1/settings/users/{id}": {
      "delete": {
        "description": "Soft deletion ends this membership and revokes its grants and sessions. The global identity, other companies and historical documents/audit remain intact. Ended memberships cannot be edited or reactivated by the settings API. Supply the last read lockVersion as a query parameter. Company permission: `deleteCompanyUser`. Defaults: ADMIN. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "deleteCompanyUser",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "lockVersion",
            "required": true,
            "schema": {
              "format": "int32",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Membership ended, credentials revoked and removal audited"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Request body, header, path, or query value is malformed"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Access denied, self removal or protected owner"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Absent, foreign or already ended membership"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Stale version or last access administrator protection"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Remove a user from this company",
        "tags": [
          "Users and roles"
        ],
        "x-default-roles": [
          "ADMIN"
        ],
        "x-permission-id": "deleteCompanyUser"
      },
      "get": {
        "description": "Returns one visible membership with local display name, immutable login email, roles, status, last login and lockVersion. Company permission: `getCompanyUser`. Defaults: ADMIN. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "getCompanyUser",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/UserView"
                }
              }
            },
            "description": "Company membership detail"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Request body, header, path, or query value is malformed"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Role denial returns a problem document; tenant-host mismatch may have an empty body"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Absent, foreign or ended membership"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Read one company user",
        "tags": [
          "Users and roles"
        ],
        "x-default-roles": [
          "ADMIN"
        ],
        "x-permission-id": "getCompanyUser"
      },
      "put": {
        "description": "Replaces company-local display name, optional contact email, one default role and ACTIVE/SUSPENDED status using lockVersion. Login email/password and global profile are never changed. Self edits and owner edits are forbidden. Existing temporary/special grants are revoked; suspension also revokes refresh sessions. Other company memberships are untouched. Company permission: `updateCompanyUser`. Defaults: ADMIN. Current company role permissions and active membership are checked on every request; signed legacy role claims alone do not authorize this operation.",
        "operationId": "updateCompanyUser",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Membership updated and atomically audited"
          },
          "400": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Request body, header, path, or query value is malformed"
          },
          "401": {
            "description": "Bearer token is absent or invalid"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Access denied, self edit or protected owner"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Absent, foreign or ended membership"
          },
          "409": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Stale version or last access administrator protection"
          },
          "500": {
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Unexpected internal failure with a support reference"
          }
        },
        "summary": "Edit a company user's name, role and status",
        "tags": [
          "Users and roles"
        ],
        "x-default-roles": [
          "ADMIN"
        ],
        "x-permission-id": "updateCompanyUser"
      }
    }
  },
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "servers": [
    {
      "description": "Generated server url",
      "url": "https://api.monetaryai.uz"
    }
  ],
  "tags": [
    {
      "description": "Credential exchange and opaque refresh-token family lifecycle",
      "name": "Authentication"
    },
    {
      "description": "Browser subscriptions and tenant-scoped Firebase delivery queue",
      "name": "Web push"
    },
    {
      "description": "Tenant-scoped immutable audit metadata",
      "name": "Audit"
    },
    {
      "description": "Company-scoped chart and UI policy/tax configuration. Bearer tenant and company visibility are enforced. Does not modify the global NAS chart, ledger entries, or effective-dated policy/tax histories; custom accounts/subaccounts are not ledger posting codes.",
      "name": "Accounting settings"
    },
    {
      "description": "Tenant membership administration and recipient-bound invitations with immutable role snapshots",
      "name": "Memberships"
    },
    {
      "description": "The authenticated membership and tenant context",
      "name": "Identity"
    },
    {
      "description": "Company-local default roles and configurable API permissions. OWNER and legacy memberships are retained.",
      "name": "Users and roles"
    },
    {
      "description": "Hourly public market snapshots; never automatically applied to accounting documents",
      "name": "Currency rates"
    },
    {
      "description": "Password changes and Google Authenticator / email two-factor authentication",
      "name": "Account security"
    }
  ]
}
