{"openapi":"3.1.0","info":{"title":"CHC Admin API","description":"Admin Portal API — JWT-based tenant resolve (tenant_id từ JWT claims). KHÔNG cần `X-T-Slug` header.","version":"0.1.0"},"paths":{"/api/admin/_ping":{"get":{"tags":["admin"],"summary":"Admin namespace ping","operationId":"admin_ping_api_admin__ping_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Admin Ping Api Admin  Ping Get"}}}}}}},"/api/admin/auth/login":{"post":{"tags":["auth"],"summary":"Admin Login","operationId":"admin_login_api_admin_auth_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginResponse"}}}},"400":{"description":"Error response — codes: reset_token_invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"reset_token_invalid","message":"Đường dẫn đặt lại mật khẩu không hợp lệ hoặc đã hết hạn"}}}}},"401":{"description":"Error response — codes: invalid_credentials, missing_bearer, token_revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"invalid_credentials","message":"Email hoặc mật khẩu không đúng"}},"examples":{"invalid_credentials":{"summary":"invalid_credentials","value":{"error":{"code":"invalid_credentials","message":"Email hoặc mật khẩu không đúng"}}},"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}}}}}},"404":{"description":"Error response — codes: tenant_not_found, lookup_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"tenant_not_found","message":"Không tìm thấy tenant"}},"examples":{"tenant_not_found":{"summary":"tenant_not_found","value":{"error":{"code":"tenant_not_found","message":"Không tìm thấy tenant"}}},"lookup_not_found":{"summary":"lookup_not_found","value":{"error":{"code":"lookup_not_found","message":"Không tìm thấy bản ghi"}}}}}}},"409":{"description":"Error response — codes: account_locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"account_locked","message":"Tài khoản đã bị khoá tạm thời do đăng nhập sai nhiều lần"}}}}},"410":{"description":"Error response — codes: reset_token_invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"reset_token_invalid","message":"Đường dẫn đặt lại mật khẩu không hợp lệ hoặc đã hết hạn"}}}}},"422":{"description":"Error response — codes: onboarding_required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/auth/logout":{"post":{"tags":["auth"],"summary":"Admin Logout","operationId":"admin_logout_api_admin_auth_logout_post","responses":{"204":{"description":"Successful Response"},"400":{"description":"Error response — codes: reset_token_invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"reset_token_invalid","message":"Đường dẫn đặt lại mật khẩu không hợp lệ hoặc đã hết hạn"}}}}},"401":{"description":"Error response — codes: invalid_credentials, missing_bearer, token_revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"invalid_credentials","message":"Email hoặc mật khẩu không đúng"}},"examples":{"invalid_credentials":{"summary":"invalid_credentials","value":{"error":{"code":"invalid_credentials","message":"Email hoặc mật khẩu không đúng"}}},"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}}}}}},"404":{"description":"Error response — codes: tenant_not_found, lookup_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"tenant_not_found","message":"Không tìm thấy tenant"}},"examples":{"tenant_not_found":{"summary":"tenant_not_found","value":{"error":{"code":"tenant_not_found","message":"Không tìm thấy tenant"}}},"lookup_not_found":{"summary":"lookup_not_found","value":{"error":{"code":"lookup_not_found","message":"Không tìm thấy bản ghi"}}}}}}},"409":{"description":"Error response — codes: account_locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"account_locked","message":"Tài khoản đã bị khoá tạm thời do đăng nhập sai nhiều lần"}}}}},"410":{"description":"Error response — codes: reset_token_invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"reset_token_invalid","message":"Đường dẫn đặt lại mật khẩu không hợp lệ hoặc đã hết hạn"}}}}},"422":{"description":"Error response — codes: onboarding_required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/auth/refresh":{"post":{"tags":["auth"],"summary":"Admin Refresh","operationId":"admin_refresh_api_admin_auth_refresh_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshResponse"}}}},"400":{"description":"Error response — codes: reset_token_invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"reset_token_invalid","message":"Đường dẫn đặt lại mật khẩu không hợp lệ hoặc đã hết hạn"}}}}},"401":{"description":"Error response — codes: invalid_credentials, missing_bearer, token_revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"invalid_credentials","message":"Email hoặc mật khẩu không đúng"}},"examples":{"invalid_credentials":{"summary":"invalid_credentials","value":{"error":{"code":"invalid_credentials","message":"Email hoặc mật khẩu không đúng"}}},"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}}}}}},"404":{"description":"Error response — codes: tenant_not_found, lookup_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"tenant_not_found","message":"Không tìm thấy tenant"}},"examples":{"tenant_not_found":{"summary":"tenant_not_found","value":{"error":{"code":"tenant_not_found","message":"Không tìm thấy tenant"}}},"lookup_not_found":{"summary":"lookup_not_found","value":{"error":{"code":"lookup_not_found","message":"Không tìm thấy bản ghi"}}}}}}},"409":{"description":"Error response — codes: account_locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"account_locked","message":"Tài khoản đã bị khoá tạm thời do đăng nhập sai nhiều lần"}}}}},"410":{"description":"Error response — codes: reset_token_invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"reset_token_invalid","message":"Đường dẫn đặt lại mật khẩu không hợp lệ hoặc đã hết hạn"}}}}},"422":{"description":"Error response — codes: onboarding_required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/auth/forgot":{"post":{"tags":["auth"],"summary":"Admin Forgot","operationId":"admin_forgot_api_admin_auth_forgot_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericAccepted"}}}},"400":{"description":"Error response — codes: reset_token_invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"reset_token_invalid","message":"Đường dẫn đặt lại mật khẩu không hợp lệ hoặc đã hết hạn"}}}}},"401":{"description":"Error response — codes: invalid_credentials, missing_bearer, token_revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"invalid_credentials","message":"Email hoặc mật khẩu không đúng"}},"examples":{"invalid_credentials":{"summary":"invalid_credentials","value":{"error":{"code":"invalid_credentials","message":"Email hoặc mật khẩu không đúng"}}},"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}}}}}},"404":{"description":"Error response — codes: tenant_not_found, lookup_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"tenant_not_found","message":"Không tìm thấy tenant"}},"examples":{"tenant_not_found":{"summary":"tenant_not_found","value":{"error":{"code":"tenant_not_found","message":"Không tìm thấy tenant"}}},"lookup_not_found":{"summary":"lookup_not_found","value":{"error":{"code":"lookup_not_found","message":"Không tìm thấy bản ghi"}}}}}}},"409":{"description":"Error response — codes: account_locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"account_locked","message":"Tài khoản đã bị khoá tạm thời do đăng nhập sai nhiều lần"}}}}},"410":{"description":"Error response — codes: reset_token_invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"reset_token_invalid","message":"Đường dẫn đặt lại mật khẩu không hợp lệ hoặc đã hết hạn"}}}}},"422":{"description":"Error response — codes: onboarding_required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/auth/reset":{"post":{"tags":["auth"],"summary":"Admin Reset","operationId":"admin_reset_api_admin_auth_reset_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetRequest"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"400":{"description":"Error response — codes: reset_token_invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"reset_token_invalid","message":"Đường dẫn đặt lại mật khẩu không hợp lệ hoặc đã hết hạn"}}}}},"401":{"description":"Error response — codes: invalid_credentials, missing_bearer, token_revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"invalid_credentials","message":"Email hoặc mật khẩu không đúng"}},"examples":{"invalid_credentials":{"summary":"invalid_credentials","value":{"error":{"code":"invalid_credentials","message":"Email hoặc mật khẩu không đúng"}}},"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}}}}}},"404":{"description":"Error response — codes: tenant_not_found, lookup_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"tenant_not_found","message":"Không tìm thấy tenant"}},"examples":{"tenant_not_found":{"summary":"tenant_not_found","value":{"error":{"code":"tenant_not_found","message":"Không tìm thấy tenant"}}},"lookup_not_found":{"summary":"lookup_not_found","value":{"error":{"code":"lookup_not_found","message":"Không tìm thấy bản ghi"}}}}}}},"409":{"description":"Error response — codes: account_locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"account_locked","message":"Tài khoản đã bị khoá tạm thời do đăng nhập sai nhiều lần"}}}}},"410":{"description":"Error response — codes: reset_token_invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"reset_token_invalid","message":"Đường dẫn đặt lại mật khẩu không hợp lệ hoặc đã hết hạn"}}}}},"422":{"description":"Error response — codes: onboarding_required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/auth/change-password":{"post":{"tags":["auth"],"summary":"Admin Change Password","operationId":"admin_change_password_api_admin_auth_change_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePasswordRequest"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"400":{"description":"Error response — codes: reset_token_invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"reset_token_invalid","message":"Đường dẫn đặt lại mật khẩu không hợp lệ hoặc đã hết hạn"}}}}},"401":{"description":"Error response — codes: invalid_credentials, missing_bearer, token_revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"invalid_credentials","message":"Email hoặc mật khẩu không đúng"}},"examples":{"invalid_credentials":{"summary":"invalid_credentials","value":{"error":{"code":"invalid_credentials","message":"Email hoặc mật khẩu không đúng"}}},"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}}}}}},"404":{"description":"Error response — codes: tenant_not_found, lookup_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"tenant_not_found","message":"Không tìm thấy tenant"}},"examples":{"tenant_not_found":{"summary":"tenant_not_found","value":{"error":{"code":"tenant_not_found","message":"Không tìm thấy tenant"}}},"lookup_not_found":{"summary":"lookup_not_found","value":{"error":{"code":"lookup_not_found","message":"Không tìm thấy bản ghi"}}}}}}},"409":{"description":"Error response — codes: account_locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"account_locked","message":"Tài khoản đã bị khoá tạm thời do đăng nhập sai nhiều lần"}}}}},"410":{"description":"Error response — codes: reset_token_invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"reset_token_invalid","message":"Đường dẫn đặt lại mật khẩu không hợp lệ hoặc đã hết hạn"}}}}},"422":{"description":"Error response — codes: onboarding_required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/auth/change-password-expert":{"post":{"tags":["auth"],"summary":"Admin Change Password Expert","operationId":"admin_change_password_expert_api_admin_auth_change_password_expert_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePasswordRequest"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"400":{"description":"Error response — codes: reset_token_invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"reset_token_invalid","message":"Đường dẫn đặt lại mật khẩu không hợp lệ hoặc đã hết hạn"}}}}},"401":{"description":"Error response — codes: invalid_credentials, missing_bearer, token_revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"invalid_credentials","message":"Email hoặc mật khẩu không đúng"}},"examples":{"invalid_credentials":{"summary":"invalid_credentials","value":{"error":{"code":"invalid_credentials","message":"Email hoặc mật khẩu không đúng"}}},"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}}}}}},"404":{"description":"Error response — codes: tenant_not_found, lookup_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"tenant_not_found","message":"Không tìm thấy tenant"}},"examples":{"tenant_not_found":{"summary":"tenant_not_found","value":{"error":{"code":"tenant_not_found","message":"Không tìm thấy tenant"}}},"lookup_not_found":{"summary":"lookup_not_found","value":{"error":{"code":"lookup_not_found","message":"Không tìm thấy bản ghi"}}}}}}},"409":{"description":"Error response — codes: account_locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"account_locked","message":"Tài khoản đã bị khoá tạm thời do đăng nhập sai nhiều lần"}}}}},"410":{"description":"Error response — codes: reset_token_invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"reset_token_invalid","message":"Đường dẫn đặt lại mật khẩu không hợp lệ hoặc đã hết hạn"}}}}},"422":{"description":"Error response — codes: onboarding_required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/users/{user_id}/unlock":{"post":{"tags":["auth"],"summary":"Admin Unlock User","operationId":"admin_unlock_user_api_admin_users__user_id__unlock_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"204":{"description":"Successful Response"},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin, super_admin_only","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}},"super_admin_only":{"summary":"super_admin_only","value":{"error":{"code":"super_admin_only","message":"Chỉ super admin được thực hiện"}}}}}}},"404":{"description":"Error response — codes: user_not_found, admin_not_found, expert_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"user_not_found","message":"Không tìm thấy người dùng"}},"examples":{"user_not_found":{"summary":"user_not_found","value":{"error":{"code":"user_not_found","message":"Không tìm thấy người dùng"}}},"admin_not_found":{"summary":"admin_not_found","value":{"error":{"code":"admin_not_found","message":"Không tìm thấy admin"}}},"expert_not_found":{"summary":"expert_not_found","value":{"error":{"code":"expert_not_found","message":"Không tìm thấy expert"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/admins/{admin_id}/unlock":{"post":{"tags":["auth"],"summary":"Admin Unlock Admin","operationId":"admin_unlock_admin_api_admin_admins__admin_id__unlock_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"admin_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Admin Id"}}],"responses":{"204":{"description":"Successful Response"},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin, super_admin_only","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}},"super_admin_only":{"summary":"super_admin_only","value":{"error":{"code":"super_admin_only","message":"Chỉ super admin được thực hiện"}}}}}}},"404":{"description":"Error response — codes: user_not_found, admin_not_found, expert_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"user_not_found","message":"Không tìm thấy người dùng"}},"examples":{"user_not_found":{"summary":"user_not_found","value":{"error":{"code":"user_not_found","message":"Không tìm thấy người dùng"}}},"admin_not_found":{"summary":"admin_not_found","value":{"error":{"code":"admin_not_found","message":"Không tìm thấy admin"}}},"expert_not_found":{"summary":"expert_not_found","value":{"error":{"code":"expert_not_found","message":"Không tìm thấy expert"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/experts/{expert_id}/unlock":{"post":{"tags":["auth"],"summary":"Admin Unlock Expert","operationId":"admin_unlock_expert_api_admin_experts__expert_id__unlock_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"expert_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Expert Id"}}],"responses":{"204":{"description":"Successful Response"},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin, super_admin_only","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}},"super_admin_only":{"summary":"super_admin_only","value":{"error":{"code":"super_admin_only","message":"Chỉ super admin được thực hiện"}}}}}}},"404":{"description":"Error response — codes: user_not_found, admin_not_found, expert_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"user_not_found","message":"Không tìm thấy người dùng"}},"examples":{"user_not_found":{"summary":"user_not_found","value":{"error":{"code":"user_not_found","message":"Không tìm thấy người dùng"}}},"admin_not_found":{"summary":"admin_not_found","value":{"error":{"code":"admin_not_found","message":"Không tìm thấy admin"}}},"expert_not_found":{"summary":"expert_not_found","value":{"error":{"code":"expert_not_found","message":"Không tìm thấy expert"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/tenants":{"get":{"tags":["tenants"],"summary":"Admin Tenants List","operationId":"admin_tenants_list_api_admin_tenants_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Page Size"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/TenantStatus"},{"type":"null"}],"title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantListResponse"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}},"post":{"tags":["tenants"],"summary":"Admin Tenants Create","operationId":"admin_tenants_create_api_admin_tenants_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantDetail"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/tenants/{tenant_id}":{"get":{"tags":["tenants"],"summary":"Admin Tenants Detail","operationId":"admin_tenants_detail_api_admin_tenants__tenant_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tenant Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantDetail"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}},"patch":{"tags":["tenants"],"summary":"Admin Tenants Update","operationId":"admin_tenants_update_api_admin_tenants__tenant_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tenant Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantDetail"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/tenants/{tenant_id}/disable":{"post":{"tags":["tenants"],"summary":"Admin Tenants Disable","operationId":"admin_tenants_disable_api_admin_tenants__tenant_id__disable_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tenant Id"}}],"responses":{"204":{"description":"Successful Response"},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/tenants/{tenant_id}/enable":{"post":{"tags":["tenants"],"summary":"Admin Tenants Enable","operationId":"admin_tenants_enable_api_admin_tenants__tenant_id__enable_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tenant Id"}}],"responses":{"204":{"description":"Successful Response"},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/users":{"get":{"tags":["users"],"summary":"Admin Users List","operationId":"admin_users_list_api_admin_users_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Page Size"}},{"name":"tenant_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Tenant Id"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/UserStatus"},{"type":"null"}],"title":"Status"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Search"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserListResponse"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}},"post":{"tags":["users"],"summary":"Admin Users Create","operationId":"admin_users_create_api_admin_users_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDetail"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/users/{user_id}":{"get":{"tags":["users"],"summary":"Admin Users Detail","operationId":"admin_users_detail_api_admin_users__user_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDetail"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}},"patch":{"tags":["users"],"summary":"Admin Users Update","operationId":"admin_users_update_api_admin_users__user_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDetail"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}},"delete":{"tags":["users"],"summary":"Admin Users Soft Delete","operationId":"admin_users_soft_delete_api_admin_users__user_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"204":{"description":"Successful Response"},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/users/{user_id}/activate":{"post":{"tags":["users"],"summary":"Admin Users Activate","operationId":"admin_users_activate_api_admin_users__user_id__activate_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"204":{"description":"Successful Response"},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/users/{user_id}/deactivate":{"post":{"tags":["users"],"summary":"Admin Users Deactivate","operationId":"admin_users_deactivate_api_admin_users__user_id__deactivate_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"204":{"description":"Successful Response"},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/admins":{"get":{"tags":["admins"],"summary":"Admin Admins List","operationId":"admin_admins_list_api_admin_admins_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Page Size"}},{"name":"tenant_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Tenant Id"}},{"name":"role","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/AdminRole"},{"type":"null"}],"title":"Role"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/AdminStatus"},{"type":"null"}],"title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminListResponse"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}},"post":{"tags":["admins"],"summary":"Admin Admins Create","operationId":"admin_admins_create_api_admin_admins_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminDetail"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin, super_admin_only","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}},"super_admin_only":{"summary":"super_admin_only","value":{"error":{"code":"super_admin_only","message":"Chỉ super admin được thực hiện"}}}}}}},"409":{"description":"Error response — codes: email_already_used_in_other_role, admin_email_already_used","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"email_already_used_in_other_role","message":"Email đã được dùng cho vai trò khác"}},"examples":{"email_already_used_in_other_role":{"summary":"email_already_used_in_other_role","value":{"error":{"code":"email_already_used_in_other_role","message":"Email đã được dùng cho vai trò khác"}}},"admin_email_already_used":{"summary":"admin_email_already_used","value":{"error":{"code":"admin_email_already_used","message":"Email admin đã được sử dụng"}}}}}}},"422":{"description":"Error response — codes: tenant_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/admins/{admin_id}":{"get":{"tags":["admins"],"summary":"Admin Admins Detail","operationId":"admin_admins_detail_api_admin_admins__admin_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"admin_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Admin Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminDetail"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"404":{"description":"Error response — codes: admin_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"admin_not_found","message":"Không tìm thấy admin"}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}},"patch":{"tags":["admins"],"summary":"Admin Admins Update","operationId":"admin_admins_update_api_admin_admins__admin_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"admin_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Admin Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminDetail"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin, super_admin_only","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}},"super_admin_only":{"summary":"super_admin_only","value":{"error":{"code":"super_admin_only","message":"Chỉ super admin được thực hiện"}}}}}}},"404":{"description":"Error response — codes: admin_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"admin_not_found","message":"Không tìm thấy admin"}}}}},"409":{"description":"Error response — codes: last_tenant_admin_must_remain","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"last_tenant_admin_must_remain","message":"Phải giữ lại ít nhất 1 admin cho tenant"}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}},"delete":{"tags":["admins"],"summary":"Admin Admins Soft Delete","operationId":"admin_admins_soft_delete_api_admin_admins__admin_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"admin_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Admin Id"}}],"responses":{"204":{"description":"Successful Response"},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin, super_admin_only","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}},"super_admin_only":{"summary":"super_admin_only","value":{"error":{"code":"super_admin_only","message":"Chỉ super admin được thực hiện"}}}}}}},"404":{"description":"Error response — codes: admin_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"admin_not_found","message":"Không tìm thấy admin"}}}}},"409":{"description":"Error response — codes: last_tenant_admin_must_remain","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"last_tenant_admin_must_remain","message":"Phải giữ lại ít nhất 1 admin cho tenant"}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/experts/me":{"get":{"tags":["experts"],"summary":"Admin Experts Self","operationId":"admin_experts_self_api_admin_experts_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpertSelfResponse"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/experts/{expert_id}":{"delete":{"tags":["experts"],"summary":"Admin Experts Soft Delete","operationId":"admin_experts_soft_delete_api_admin_experts__expert_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"expert_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Expert Id"}}],"responses":{"204":{"description":"Successful Response"},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}},"get":{"tags":["experts"],"summary":"Admin Experts Detail","operationId":"admin_experts_detail_api_admin_experts__expert_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"expert_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Expert Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ExpertDetailFull"},{"$ref":"#/components/schemas/ExpertDetailMasked"}],"title":"Response Admin Experts Detail Api Admin Experts  Expert Id  Get"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}},"patch":{"tags":["experts"],"summary":"Admin Experts Update","operationId":"admin_experts_update_api_admin_experts__expert_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"expert_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Expert Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpertUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpertDetailFull"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/experts":{"get":{"tags":["experts"],"summary":"Admin Experts List","operationId":"admin_experts_list_api_admin_experts_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Page Size"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/ExpertStatus"},{"type":"null"}],"title":"Status"}},{"name":"module","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Module"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpertListResponse"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}},"post":{"tags":["experts"],"summary":"Admin Experts Create","operationId":"admin_experts_create_api_admin_experts_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpertCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpertDetailFull"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/experts/{expert_id}/stats":{"get":{"tags":["experts"],"summary":"Admin Experts Stats","operationId":"admin_experts_stats_api_admin_experts__expert_id__stats_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"expert_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Expert Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpertStatsResponse"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/settings/profile":{"get":{"tags":["settings"],"summary":"Admin Settings Profile Read","operationId":"admin_settings_profile_read_api_admin_settings_profile_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminProfileResponse"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}}},"security":[{"HTTPBearer":[]}]},"put":{"tags":["settings"],"summary":"Admin Settings Profile Update","operationId":"admin_settings_profile_update_api_admin_settings_profile_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminProfileResponse"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/settings/language":{"put":{"tags":["settings"],"summary":"Admin Settings Language Update","operationId":"admin_settings_language_update_api_admin_settings_language_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LanguageUpdate"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/dashboard":{"get":{"tags":["dashboard"],"summary":"Admin Dashboard","operationId":"admin_dashboard_api_admin_dashboard_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"etariff_range","in":"query","required":false,"schema":{"enum":["week","month"],"type":"string","description":"E-Tariff usage bar-chart range: 'week' or 'month'","default":"week","title":"Etariff Range"},"description":"E-Tariff usage bar-chart range: 'week' or 'month'"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminDashboardResponse"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/requests":{"get":{"tags":["requests"],"summary":"Admin Request List","operationId":"admin_request_list_api_admin_requests_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"tenant_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Tenant Id"}},{"name":"expert_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Expert Id"}},{"name":"has_note","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Note"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Search"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminRequestListResponse"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/requests/expert":{"get":{"tags":["requests"],"summary":"Expert Request List","operationId":"expert_request_list_api_admin_requests_expert_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminRequestListResponse"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/requests/status-counts":{"get":{"tags":["requests"],"summary":"Admin Request Status Counts","operationId":"admin_request_status_counts_api_admin_requests_status_counts_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Tenant Id"}},{"name":"expert_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Expert Id"}},{"name":"has_note","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Note"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Search"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminStatusCountsResponse"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Error response — codes: status_invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/requests/{request_id}/assign":{"post":{"tags":["requests"],"summary":"Admin Request Assign","operationId":"admin_request_assign_api_admin_requests__request_id__assign_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Request Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminRequestSummary"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/requests/{request_id}/note":{"patch":{"tags":["requests"],"summary":"Admin Request Note","operationId":"admin_request_note_api_admin_requests__request_id__note_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Request Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotePatchRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminRequestSummary"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/requests/{request_id}/approve":{"post":{"tags":["requests"],"summary":"Admin Request Approve","operationId":"admin_request_approve_api_admin_requests__request_id__approve_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Request Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApproveResponse"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/requests/{request_id}/files/{kind}":{"get":{"tags":["requests"],"summary":"Admin Request File Download","operationId":"admin_request_file_download_api_admin_requests__request_id__files__kind__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Request Id"}},{"name":"kind","in":"path","required":true,"schema":{"$ref":"#/components/schemas/AdminFileKind"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminFileDownloadResponse"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/requests/{request_id}/retry-ai":{"post":{"tags":["requests"],"summary":"Force retry AI processing (super_admin)","description":"Reset ``ai_failed=false`` + bump ``ai_attempt_count``. State stays ``ai_processing``. Phase 08 Q17 BLOCKED → endpoint logs warning ``ai_provider_pending_Q17_no_celery_enqueue`` instead of enqueueing the worker; switch is a one-line change once Q17 unblocks.","operationId":"admin_request_retry_ai_api_admin_requests__request_id__retry_ai_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Request Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiActionResponse"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/requests/{request_id}/skip-to-manual":{"post":{"tags":["requests"],"summary":"Skip AI processing → awaiting_assign (super_admin)","description":"Move ``ai_processing → awaiting_assign`` (no WP Draft). Clears ``ai_failed`` + ``ai_last_error``. Tenant_admin picks the row up via ``POST /requests/{id}/assign`` next.","operationId":"admin_request_skip_to_manual_api_admin_requests__request_id__skip_to_manual_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Request Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiActionResponse"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/requests/{request_id}":{"get":{"tags":["requests"],"summary":"Admin Request Detail","operationId":"admin_request_detail_api_admin_requests__request_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Request Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminRequestDetail"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/requests/{request_id}/expert":{"get":{"tags":["requests"],"summary":"Expert Request Detail","operationId":"expert_request_detail_api_admin_requests__request_id__expert_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Request Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminRequestDetail"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/ses/webhook/bounce":{"post":{"tags":["ses-webhook"],"summary":"SES bounce webhook (SNS stub Phase 12.5)","operationId":"bounce_webhook_api_admin_ses_webhook_bounce_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Bounce Webhook Api Admin Ses Webhook Bounce Post"}}}}}}},"/api/admin/ses/webhook/complaint":{"post":{"tags":["ses-webhook"],"summary":"SES complaint webhook (SNS stub Phase 12.5)","operationId":"complaint_webhook_api_admin_ses_webhook_complaint_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Complaint Webhook Api Admin Ses Webhook Complaint Post"}}}}}}},"/api/admin/ses/suppression":{"post":{"tags":["ses-suppression"],"summary":"Manually suppress an email address (super_admin only)","operationId":"insert_suppression_endpoint_api_admin_ses_suppression_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionInsertRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"title":"Response Insert Suppression Endpoint Api Admin Ses Suppression Post"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}},"get":{"tags":["ses-suppression"],"summary":"Look up suppression record for an email (super_admin only)","operationId":"get_suppression_endpoint_api_admin_ses_suppression_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"email","in":"query","required":true,"schema":{"type":"string","description":"Email address to look up","title":"Email"},"description":"Email address to look up"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/SuppressionRecord"},{"type":"object","additionalProperties":{"type":"string"}}],"title":"Response Get Suppression Endpoint Api Admin Ses Suppression Get"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}},"/api/admin/system-settings":{"get":{"tags":["system-settings"],"summary":"List all whitelisted system settings (super_admin)","operationId":"admin_system_settings_list_api_admin_system_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemSettingListResponse"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}}},"security":[{"HTTPBearer":[]}]}},"/api/admin/system-settings/{key}":{"get":{"tags":["system-settings"],"summary":"Read 1 system setting by key (super_admin)","operationId":"admin_system_settings_detail_api_admin_system_settings__key__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemSettingItem"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}},"put":{"tags":["system-settings"],"summary":"Update 1 system setting (super_admin)","description":"Body ``{value: str}`` — service coerces per ``KeyMeta.type`` (``int`` / ``csv_emails``) and rejects 422 on type mismatch / out-of-range / unwhitelisted key. Idempotent: same value rejects audit-log duplicate.","operationId":"admin_system_settings_update_api_admin_system_settings__key__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemSettingUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemSettingItem"}}}},"401":{"description":"Error response — codes: missing_bearer, token_revoked, admin_inactive_or_missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}},"examples":{"missing_bearer":{"summary":"missing_bearer","value":{"error":{"code":"missing_bearer","message":"Thiếu thông tin xác thực"}}},"token_revoked":{"summary":"token_revoked","value":{"error":{"code":"token_revoked","message":"Phiên đăng nhập đã hết hạn, vui lòng đăng nhập lại"}}},"admin_inactive_or_missing":{"summary":"admin_inactive_or_missing","value":{"error":{"code":"admin_inactive_or_missing","message":"Tài khoản admin không tồn tại hoặc đã bị vô hiệu hoá"}}}}}}},"403":{"description":"Error response — codes: insufficient_role, role_not_admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}},"examples":{"insufficient_role":{"summary":"insufficient_role","value":{"error":{"code":"insufficient_role","message":"Bạn không có quyền truy cập"}}},"role_not_admin":{"summary":"role_not_admin","value":{"error":{"code":"role_not_admin","message":"Vai trò không phải admin"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}}}}}}},"components":{"schemas":{"AdminCreate":{"properties":{"tenant_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Tenant Id","description":"Required for role=tenant_admin; MUST be null for role=super_admin (cross-tenant). Service-layer guard enforces.","examples":["660e8400-e29b-41d4-a716-446655440001"]},"role":{"$ref":"#/components/schemas/AdminRole","description":"`super_admin` (cross-tenant, no tenant_id) or `tenant_admin` (1 tenant).","examples":["tenant_admin"]},"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name","description":"Display name shown in audit log + admin list view.","examples":["Nguyễn Văn A"]},"email":{"type":"string","maxLength":320,"minLength":3,"pattern":"^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$","title":"Email","description":"Login email. Cross-table unique with users + experts (D11). Immutable post-create (BR-007 pattern).","examples":["admin@example.com"]},"phone":{"anyOf":[{"type":"string","maxLength":30},{"type":"null"}],"title":"Phone","description":"Optional VN phone (free-form, no E.164 normalization at MVP).","examples":["0901234567"]}},"additionalProperties":false,"type":"object","required":["role","name","email"],"title":"AdminCreate","description":"``POST /api/admin/admins`` body (super_admin only).\n\n``tenant_id`` is required for ``role=tenant_admin`` and rejected for\n``role=super_admin`` (cross-tenant) — service-layer guard validates\nthe pairing because the rule depends on enum values."},"AdminDashboardResponse":{"properties":{"kpi":{"$ref":"#/components/schemas/AdminKpi"},"etariff_usage":{"$ref":"#/components/schemas/AdminEtariffUsage"},"tenants_compare":{"anyOf":[{"items":{"$ref":"#/components/schemas/TenantsCompareItem"},"type":"array"},{"type":"null"}],"title":"Tenants Compare"},"top_users":{"anyOf":[{"items":{"$ref":"#/components/schemas/TopUserItem"},"type":"array"},{"type":"null"}],"title":"Top Users"}},"type":"object","required":["kpi","etariff_usage"],"title":"AdminDashboardResponse","example":{"etariff_usage":{"batch_jobs_30d":18,"breakdown":[{"id":"660e8400-e29b-41d4-a716-446655440001","name":"ABC Logistics","percent":38,"value":542}],"buckets":[{"label":"T2","value":88},{"label":"T3","value":102},{"label":"T4","value":76},{"label":"T5","value":134},{"label":"T6","value":156},{"label":"T7","value":42},{"label":"CN","value":28}],"limit":100,"range":"week","requests_lookups_30d":612,"total":626,"used_today":23},"kpi":{"awaiting_assign":7,"completed_pending_review":4,"processing":12,"requests_sla_overdue":1,"requests_sla_warning":3,"requests_total":348,"satisfaction_score":4.65,"users_total":124},"tenants_compare":[{"name":"Acme Corporation Vietnam","requests_count":348,"satisfaction_score":4.65,"tenant_id":"660e8400-e29b-41d4-a716-446655440001","users_count":124}]}},"AdminDetail":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Tenant Id"},"role":{"$ref":"#/components/schemas/AdminRole"},"email":{"type":"string","title":"Email"},"name":{"type":"string","title":"Name"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"status":{"$ref":"#/components/schemas/AdminStatus"},"force_password_change":{"type":"boolean","title":"Force Password Change"},"last_login_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Login At"},"last_assign_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Assign At"},"last_approve_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Approve At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"users_created_count":{"type":"integer","title":"Users Created Count","default":0}},"type":"object","required":["id","tenant_id","role","email","name","phone","status","force_password_change","last_login_at","last_assign_at","last_approve_at","created_at","created_by"],"title":"AdminDetail","description":"``GET /api/admin/admins/{id}`` response.\n\n``users_created_count`` / ``last_assign_at`` / ``last_approve_at``\nare stub-friendly: ``last_*`` come straight from the row, the count\nis computed by the service via a subquery.","example":{"created_at":"2026-04-15T09:00:00+07:00","created_by":"550e8400-e29b-41d4-a716-446655440000","email":"admin@acme-corp.vn","force_password_change":false,"id":"990e8400-e29b-41d4-a716-446655440004","last_approve_at":"2026-05-09T17:10:00+07:00","last_assign_at":"2026-05-09T16:45:00+07:00","last_login_at":"2026-05-09T08:30:00+07:00","name":"Nguyễn Văn A","phone":"0901234567","role":"tenant_admin","status":"active","tenant_id":"660e8400-e29b-41d4-a716-446655440001","users_created_count":12}},"AdminEtariffUsage":{"properties":{"used_today":{"type":"integer","title":"Used Today"},"limit":{"type":"integer","title":"Limit"},"requests_lookups_30d":{"type":"integer","title":"Requests Lookups 30D"},"batch_jobs_30d":{"type":"integer","title":"Batch Jobs 30D"},"range":{"type":"string","enum":["week","month"],"title":"Range"},"total":{"type":"integer","title":"Total"},"buckets":{"items":{"$ref":"#/components/schemas/EtariffUsageBucket"},"type":"array","title":"Buckets"},"breakdown":{"items":{"$ref":"#/components/schemas/EtariffUsageSegment"},"type":"array","title":"Breakdown"}},"type":"object","required":["used_today","limit","requests_lookups_30d","batch_jobs_30d","range","total","buckets","breakdown"],"title":"AdminEtariffUsage"},"AdminFileDownloadResponse":{"properties":{"url":{"type":"string","title":"Url"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"}},"type":"object","required":["url","expires_at"],"title":"AdminFileDownloadResponse","example":{"expires_at":"2026-05-09T21:30:00+07:00","url":"https://chc-private.s3.amazonaws.com/ecus/770e8400.../ecus-export-2026-05-09.xlsx?X-Amz-Algorithm=..."}},"AdminFileKind":{"type":"string","enum":["ecus","wp_draft","wp_final","report"],"title":"AdminFileKind"},"AdminKpi":{"properties":{"requests_total":{"type":"integer","title":"Requests Total"},"awaiting_assign":{"type":"integer","title":"Awaiting Assign"},"processing":{"type":"integer","title":"Processing"},"completed_pending_review":{"type":"integer","title":"Completed Pending Review"},"satisfaction_score":{"anyOf":[{"type":"number","maximum":5.0,"minimum":0.0},{"type":"null"}],"title":"Satisfaction Score"},"users_total":{"type":"integer","title":"Users Total"},"requests_sla_warning":{"type":"integer","title":"Requests Sla Warning"},"requests_sla_overdue":{"type":"integer","title":"Requests Sla Overdue"}},"type":"object","required":["requests_total","awaiting_assign","processing","completed_pending_review","users_total","requests_sla_warning","requests_sla_overdue"],"title":"AdminKpi"},"AdminListItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Tenant Id"},"role":{"$ref":"#/components/schemas/AdminRole"},"email":{"type":"string","title":"Email"},"name":{"type":"string","title":"Name"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"status":{"$ref":"#/components/schemas/AdminStatus"},"last_login_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Login At"},"last_assign_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Assign At"},"last_approve_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Approve At"},"users_created_count":{"type":"integer","title":"Users Created Count","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","tenant_id","role","email","name","phone","status","last_login_at","last_assign_at","last_approve_at","created_at"],"title":"AdminListItem","description":"``GET /api/admin/admins`` row — list view shows the 4 activity fields\nsurfaced by the prototype \"Hoạt động\" panel: last_login_at, last_assign_at,\nlast_approve_at, users_created_count."},"AdminListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminListItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"}},"type":"object","required":["items","total","page","page_size","total_pages"],"title":"AdminListResponse","example":{"items":[{"created_at":"2026-04-15T09:00:00+07:00","email":"admin@acme-corp.vn","id":"990e8400-e29b-41d4-a716-446655440004","last_approve_at":"2026-05-09T17:10:00+07:00","last_assign_at":"2026-05-09T16:45:00+07:00","last_login_at":"2026-05-09T08:30:00+07:00","name":"Nguyễn Văn A","phone":"0901234567","role":"tenant_admin","status":"active","tenant_id":"660e8400-e29b-41d4-a716-446655440001","users_created_count":12}],"page":1,"page_size":50,"total":1,"total_pages":1}},"AdminProfileResponse":{"properties":{"name":{"type":"string","title":"Name"},"email":{"type":"string","title":"Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"language":{"$ref":"#/components/schemas/LanguageCode","default":"vi"}},"type":"object","required":["name","email"],"title":"AdminProfileResponse","description":"``GET /api/admin/settings/profile`` — admin pool VI-only (BR-032).\n\nPhase 16 S3.7 (Q-PH16-02 override 2026-05-09): split from the prior\nshared ``ProfileResponse`` so the schema itself locks ``language=vi``\nfor admin callers — FE no longer has to handle a nullable language\non admin endpoints.","example":{"email":"admin@acme-corp.vn","language":"vi","name":"Nguyễn Văn A","phone":"0901234567"}},"AdminRequestDetail":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"code":{"type":"string","title":"Code"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"company_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Name"},"company_email_result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Email Result","description":"Email nhận kết quả của user đặt request (snapshot từ users.email_result tại thời điểm xem). Null khi user chưa cấu hình.","examples":["result@acme-corp.vn"]},"expert_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Expert Id"},"expert_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Expert Name"},"status":{"$ref":"#/components/schemas/RequestStatus"},"sla_status":{"$ref":"#/components/schemas/SLAStatus"},"sla_due_at":{"type":"string","format":"date-time","title":"Sla Due At"},"has_downloaded":{"type":"boolean","title":"Has Downloaded"},"has_rated":{"type":"boolean","title":"Has Rated"},"modules":{"items":{"$ref":"#/components/schemas/ChcModule"},"type":"array","title":"Modules"},"has_note":{"type":"boolean","title":"Has Note"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"files":{"items":{"$ref":"#/components/schemas/FileSummary"},"type":"array","title":"Files"},"ai_failed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ai Failed"},"ai_attempt_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ai Attempt Count"},"ai_last_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ai Last Error"},"internal_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Internal Note"},"expert_rating_avg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Expert Rating Avg","description":"Snapshot expert.rating_avg tại thời điểm xem (chỉ trả khi expert được assign).","examples":[4.8]},"expert_completed_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Expert Completed Count","description":"Số request expert đã hoàn thành — snapshot từ experts.completed_count.","examples":[156]},"rating_stars":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rating Stars","description":"User rating 1-5 sao (chỉ trả khi has_rated=true; BR-019).","examples":[5]},"rating_comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rating Comment","description":"Comment đi kèm rating (nullable kể cả khi có stars).","examples":["Kết quả nhanh, chính xác."]},"history":{"items":{"$ref":"#/components/schemas/HistoryEntry"},"type":"array","title":"History"},"available_actions":{"items":{"type":"string"},"type":"array","title":"Available Actions","description":"Server-derived list of actions FE may invoke given (status, role, ai_failed). Subset of: assign / reassign / approve / note_edit / retry_ai / skip_to_manual / upload_result / cancel. Map per state machine + role (Phase 16 S3.5).","examples":[["note_edit","reassign","approve"]]}},"type":"object","required":["id","code","tenant_id","user_id","status","sla_status","sla_due_at","has_downloaded","has_rated","modules","has_note","created_at"],"title":"AdminRequestDetail","example":{"available_actions":["note_edit","reassign","approve"],"code":"REQ-2026-000123","company_email_result":"result@acme-corp.vn","company_name":"Công ty TNHH Acme Việt Nam","created_at":"2026-05-09T10:15:00+07:00","expert_completed_count":156,"expert_id":"880e8400-e29b-41d4-a716-446655440003","expert_name":"Lê Quang Phi","expert_rating_avg":4.8,"files":[{"filename":"ecus-export-2026-05-09.xlsx","kind":"ecus","size_bytes":524288,"uploaded_at":"2026-05-09T10:15:00+07:00"},{"filename":"wp-final-2026-05-09.xlsx","kind":"wp_final","size_bytes":102400,"uploaded_at":"2026-05-09T16:30:00+07:00"}],"has_downloaded":false,"has_note":true,"has_rated":false,"history":[{"action":"created","actor_role":"user","created_at":"2026-05-09T10:15:00+07:00","note":"Khách tạo đơn (modules: item_code_generator)","payload":{"modules":["item_code_generator"]}},{"action":"ai_completed","actor_role":"system","created_at":"2026-05-09T10:19:50+07:00","note":"AI xử lý xong (247s, 8200 dòng)","payload":{"ai_processing_seconds":247,"from":"ai_processing","rows_processed":8200,"to":"awaiting_assign"}},{"action":"assigned","actor_role":"tenant_admin","created_at":"2026-05-09T11:00:00+07:00","note":"Phân công expert (880e8400-e29b-41d4-a716-446655440003)","payload":{"expert_id":"880e8400-e29b-41d4-a716-446655440003"}},{"action":"result_uploaded","actor_role":"expert","created_at":"2026-05-09T16:30:00+07:00","note":"Expert upload kết quả (2 file)","payload":{"files_count":2}},{"action":"approved","actor_role":"super_admin","created_at":"2026-05-09T17:05:00+07:00","note":"Admin duyệt giao kết quả cho khách"}],"id":"770e8400-e29b-41d4-a716-446655440002","internal_note":"Khách VIP — ưu tiên trả kết quả trước 17h.","modules":["item_code_generator","tariff_classification"],"rating_comment":"Kết quả nhanh, chính xác.","rating_stars":5,"sla_due_at":"2026-05-12T17:00:00+07:00","sla_status":"on_time","status":"completed","tenant_id":"660e8400-e29b-41d4-a716-446655440001","user_id":"aa0e8400-e29b-41d4-a716-446655440005"}},"AdminRequestListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminRequestSummary"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"}},"type":"object","required":["items","total","page","page_size","total_pages"],"title":"AdminRequestListResponse","example":{"items":[{"code":"REQ-2026-000123","company_email_result":"result@acme-corp.vn","company_name":"Công ty TNHH Acme Việt Nam","created_at":"2026-05-09T10:15:00+07:00","expert_id":"880e8400-e29b-41d4-a716-446655440003","expert_name":"Lê Quang Phi","files":[{"filename":"ecus-export-2026-05-09.xlsx","kind":"ecus","size_bytes":524288,"uploaded_at":"2026-05-09T10:15:00+07:00"}],"has_downloaded":false,"has_note":true,"has_rated":false,"id":"770e8400-e29b-41d4-a716-446655440002","modules":["item_code_generator","tariff_classification"],"sla_due_at":"2026-05-12T17:00:00+07:00","sla_status":"on_time","status":"completed","tenant_id":"660e8400-e29b-41d4-a716-446655440001","user_id":"aa0e8400-e29b-41d4-a716-446655440005"}],"page":1,"page_size":20,"total":1,"total_pages":1}},"AdminRequestSummary":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"code":{"type":"string","title":"Code"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"company_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Name"},"company_email_result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Email Result","description":"Email nhận kết quả của user đặt request (snapshot từ users.email_result tại thời điểm xem). Null khi user chưa cấu hình.","examples":["result@acme-corp.vn"]},"expert_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Expert Id"},"expert_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Expert Name"},"status":{"$ref":"#/components/schemas/RequestStatus"},"sla_status":{"$ref":"#/components/schemas/SLAStatus"},"sla_due_at":{"type":"string","format":"date-time","title":"Sla Due At"},"has_downloaded":{"type":"boolean","title":"Has Downloaded"},"has_rated":{"type":"boolean","title":"Has Rated"},"modules":{"items":{"$ref":"#/components/schemas/ChcModule"},"type":"array","title":"Modules"},"has_note":{"type":"boolean","title":"Has Note"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"files":{"items":{"$ref":"#/components/schemas/FileSummary"},"type":"array","title":"Files"},"ai_failed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ai Failed"},"ai_attempt_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ai Attempt Count"},"ai_last_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ai Last Error"}},"type":"object","required":["id","code","tenant_id","user_id","status","sla_status","sla_due_at","has_downloaded","has_rated","modules","has_note","created_at"],"title":"AdminRequestSummary"},"AdminRole":{"type":"string","enum":["super_admin","tenant_admin"],"title":"AdminRole"},"AdminStatus":{"type":"string","enum":["active","inactive"],"title":"AdminStatus"},"AdminStatusCountsResponse":{"properties":{"counts":{"additionalProperties":{"type":"integer"},"type":"object","title":"Counts"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["counts","total"],"title":"AdminStatusCountsResponse","description":"Per-status request count for admin filter chips (Phase 18 Task 1).\n\nAlways returns all 7 internal status keys (count=0 when empty) so the\nFE can render a stable chip set regardless of current data. ``total``\nis the sum across statuses respecting the same role scope + filters\nused by the list endpoint (minus ``status`` itself).","example":{"counts":{"ai_processing":1,"awaiting_assign":3,"cancelled":2,"completed":5,"delivered":12,"pending":4,"processing":7},"total":34}},"AdminUpdate":{"properties":{"tenant_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Tenant Id","description":"Reassign tenant_admin to a different tenant (rare; super_admin only).","examples":["660e8400-e29b-41d4-a716-446655440001"]},"name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Name","description":"Updated display name. Null = no change.","examples":["Nguyễn Văn A"]},"phone":{"anyOf":[{"type":"string","maxLength":30},{"type":"null"}],"title":"Phone","description":"Updated VN phone. Null = no change.","examples":["0901234567"]},"status":{"anyOf":[{"$ref":"#/components/schemas/AdminStatus"},{"type":"null"}],"description":"Toggle active/inactive (B-007 v1.3 soft-delete pattern; no separate /activate route).","examples":["active"]}},"additionalProperties":false,"type":"object","title":"AdminUpdate","description":"``PATCH /api/admin/admins/{id}`` partial.\n\nExcludes: ``email`` (immutable), ``role`` (super_admin promotes/\ndemotes via direct SQL only; switching role is rare and audited),\n``password`` (use ``/auth/change-password``)."},"AiActionResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"code":{"type":"string","title":"Code"},"status":{"type":"string","title":"Status"},"ai_failed":{"type":"boolean","title":"Ai Failed"},"ai_attempt_count":{"type":"integer","title":"Ai Attempt Count"}},"type":"object","required":["id","code","status","ai_failed","ai_attempt_count"],"title":"AiActionResponse","description":"Echo of post-action request state (retry-ai or skip-to-manual).","example":{"ai_attempt_count":2,"ai_failed":false,"code":"CHC-2026-00123","id":"550e8400-e29b-41d4-a716-446655440000","status":"ai_processing"}},"ApproveResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"code":{"type":"string","title":"Code"},"status":{"type":"string","title":"Status"},"approved_by":{"type":"string","format":"uuid","title":"Approved By"},"approved_at":{"type":"string","format":"date-time","title":"Approved At"}},"type":"object","required":["id","code","status","approved_by","approved_at"],"title":"ApproveResponse","example":{"approved_at":"2026-05-09T17:30:00+07:00","approved_by":"990e8400-e29b-41d4-a716-446655440004","code":"REQ-2026-000123","id":"770e8400-e29b-41d4-a716-446655440002","status":"delivered"}},"AssignRequest":{"properties":{"expert_id":{"type":"string","format":"uuid","title":"Expert Id","description":"Target expert UUID. Service verifies expert.status=active + expertise_modules ⊇ request.modules.","examples":["880e8400-e29b-41d4-a716-446655440003"]},"internal_note":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Internal Note","description":"Optional internal note attached at assign time (super_admin / tenant_admin only — IC-C-004).","examples":["Ưu tiên xử lý trước 17h hôm nay; khách VIP tenant Acme."]}},"additionalProperties":false,"type":"object","required":["expert_id"],"title":"AssignRequest"},"ChangePasswordRequest":{"properties":{"current":{"type":"string","maxLength":200,"minLength":1,"title":"Current","description":"Current plaintext password. Mismatch returns 401 invalid_credentials.","examples":["P@ssw0rd123!"]},"new":{"type":"string","maxLength":200,"minLength":1,"title":"New","description":"New plaintext password. Server bcrypt-hashes; subsequent logins require this value.","examples":["NewP@ssw0rd456!"]}},"additionalProperties":false,"type":"object","required":["current","new"],"title":"ChangePasswordRequest"},"ChcModule":{"type":"string","enum":["item_code_generator","tariff_classification","customs_valuation","non_tariff_measures","exim_statistics"],"title":"ChcModule","description":"5 CHC service modules — single source of truth (BR-009).\n\nPhase 16 S3.3 consolidates two duplicate frozensets that previously\nlived in `app/admin/schemas/experts.py` (`_CHC_MODULES`) and\n`app/user/schemas/request.py` (`MODULES_5SET`). Pydantic v2 enum\nvalidation replaces the manual `model_post_init` checks."},"CompanyType":{"type":"string","enum":["fdi","xnk","epe","kcn_kkt","san_xuat","thuong_mai","dai_ly_logistics","khac"],"title":"CompanyType"},"EtariffUsageBucket":{"properties":{"label":{"type":"string","title":"Label"},"value":{"type":"integer","title":"Value"}},"type":"object","required":["label","value"],"title":"EtariffUsageBucket"},"EtariffUsageSegment":{"properties":{"id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Id"},"name":{"type":"string","title":"Name"},"value":{"type":"integer","title":"Value"},"percent":{"type":"integer","maximum":100.0,"minimum":0.0,"title":"Percent"}},"type":"object","required":["name","value","percent"],"title":"EtariffUsageSegment"},"ExpertCreate":{"properties":{"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name","description":"Display name shown in admin UI + assignment dropdown + cross-tenant request detail.","examples":["Lê Quang Phi"]},"email":{"type":"string","maxLength":320,"minLength":3,"pattern":"^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$","title":"Email","description":"Personal email (IC-m-001 v1.2 — @chc.com restriction removed). Cross-table unique with admins/users (D11). Masked from non-super_admin per BR-036.","examples":["expert@example.com"]},"phone":{"anyOf":[{"type":"string","maxLength":30},{"type":"null"}],"title":"Phone","description":"Optional VN phone. Masked from non-super_admin per BR-036.","examples":["0901234567"]},"expertise_modules":{"items":{"$ref":"#/components/schemas/ChcModule"},"type":"array","minItems":1,"title":"Expertise Modules","description":"≥1 of 5 CHC modules (BR-009). Pydantic v2 enum validation rejects unknown values automatically (Phase 16 S3.3 dropped manual model_post_init check).","examples":[["item_code_generator","tariff_classification"]]}},"additionalProperties":false,"type":"object","required":["name","email","expertise_modules"],"title":"ExpertCreate","description":"``POST /api/admin/experts`` body (super_admin only)."},"ExpertDetailFull":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"email":{"type":"string","title":"Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"expertise_modules":{"items":{"$ref":"#/components/schemas/ChcModule"},"type":"array","title":"Expertise Modules"},"rating_avg":{"type":"number","title":"Rating Avg"},"completed_count":{"type":"integer","title":"Completed Count"},"status":{"$ref":"#/components/schemas/ExpertStatus"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"current_load":{"type":"integer","title":"Current Load","default":0}},"type":"object","required":["id","name","email","phone","expertise_modules","rating_avg","completed_count","status","created_at"],"title":"ExpertDetailFull","description":"``GET /api/admin/experts/{id}`` — super_admin / self response.","example":{"completed_count":152,"created_at":"2026-01-10T10:00:00+07:00","current_load":3,"email":"phi.le@example.com","expertise_modules":["item_code_generator","tariff_classification"],"id":"880e8400-e29b-41d4-a716-446655440003","name":"Lê Quang Phi","phone":"0901234567","rating_avg":4.7,"status":"active"}},"ExpertDetailMasked":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"expertise_modules":{"items":{"$ref":"#/components/schemas/ChcModule"},"type":"array","title":"Expertise Modules"},"rating_avg":{"type":"number","title":"Rating Avg"},"completed_count":{"type":"integer","title":"Completed Count"},"status":{"$ref":"#/components/schemas/ExpertStatus"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"current_load":{"type":"integer","title":"Current Load","default":0}},"type":"object","required":["id","name","expertise_modules","rating_avg","completed_count","status","created_at"],"title":"ExpertDetailMasked","description":"``GET /api/admin/experts/{id}`` — non-super_admin response (BR-036).","example":{"completed_count":152,"created_at":"2026-01-10T10:00:00+07:00","current_load":3,"expertise_modules":["item_code_generator","tariff_classification"],"id":"880e8400-e29b-41d4-a716-446655440003","name":"Lê Quang Phi","rating_avg":4.7,"status":"active"}},"ExpertListResponse":{"properties":{"items":{"items":{"anyOf":[{"$ref":"#/components/schemas/ExpertDetailFull"},{"$ref":"#/components/schemas/ExpertDetailMasked"}]},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"}},"type":"object","required":["items","total","page","page_size","total_pages"],"title":"ExpertListResponse","example":{"items":[{"completed_count":152,"created_at":"2026-01-10T10:00:00+07:00","current_load":3,"email":"phi.le@example.com","expertise_modules":["item_code_generator","tariff_classification"],"id":"880e8400-e29b-41d4-a716-446655440003","name":"Lê Quang Phi","phone":"0901234567","rating_avg":4.7,"status":"active"}],"page":1,"page_size":50,"total":1,"total_pages":1}},"ExpertSelfResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"email":{"type":"string","title":"Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"expertise_modules":{"items":{"$ref":"#/components/schemas/ChcModule"},"type":"array","title":"Expertise Modules"},"rating_avg":{"type":"number","title":"Rating Avg"},"completed_count":{"type":"integer","title":"Completed Count"},"status":{"$ref":"#/components/schemas/ExpertStatus"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"current_load":{"type":"integer","title":"Current Load","default":0},"assigned_requests":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Assigned Requests"}},"type":"object","required":["id","name","email","phone","expertise_modules","rating_avg","completed_count","status","created_at"],"title":"ExpertSelfResponse","description":"``GET /api/admin/experts/me`` — expert self with assignment list.\n\nPhase 07 will populate ``assigned_requests``; Phase 05 returns an\nempty list as a deliberate stub so the API contract is stable.","example":{"assigned_requests":["770e8400-e29b-41d4-a716-446655440002","770e8400-e29b-41d4-a716-446655440005"],"completed_count":152,"created_at":"2026-01-10T10:00:00+07:00","current_load":3,"email":"phi.le@example.com","expertise_modules":["item_code_generator","tariff_classification"],"id":"880e8400-e29b-41d4-a716-446655440003","name":"Lê Quang Phi","phone":"0901234567","rating_avg":4.7,"status":"active"}},"ExpertStatsResponse":{"properties":{"expert_id":{"type":"string","format":"uuid","title":"Expert Id"},"rating_avg":{"type":"number","title":"Rating Avg"},"completed_count":{"type":"integer","title":"Completed Count"},"scope":{"type":"string","title":"Scope"}},"type":"object","required":["expert_id","rating_avg","completed_count","scope"],"title":"ExpertStatsResponse","description":"``GET /api/admin/experts/{id}/stats`` (G-M-011 role-aware).\n\n``scope`` distinguishes the cross-tenant cached read (super_admin)\nfrom the in-tenant subquery (tenant_admin) so the FE can decide\nwhether to label the figure as global or tenant-only.","example":{"completed_count":152,"expert_id":"880e8400-e29b-41d4-a716-446655440003","rating_avg":4.7,"scope":"cross_tenant"}},"ExpertStatus":{"type":"string","enum":["active","inactive"],"title":"ExpertStatus"},"ExpertUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Name","description":"Updated display name. Null = no change.","examples":["Lê Quang Phi"]},"phone":{"anyOf":[{"type":"string","maxLength":30},{"type":"null"}],"title":"Phone","description":"Updated VN phone. Null = no change.","examples":["0901234567"]},"expertise_modules":{"anyOf":[{"items":{"$ref":"#/components/schemas/ChcModule"},"type":"array","minItems":1},{"type":"null"}],"title":"Expertise Modules","description":"Replace expertise list (≥1 module). Null = no change.","examples":[["customs_valuation","non_tariff_measures"]]},"status":{"anyOf":[{"$ref":"#/components/schemas/ExpertStatus"},{"type":"null"}],"description":"Toggle active/inactive (B-003 v1.3 single-PATCH soft-delete + re-activate).","examples":["active"]}},"additionalProperties":false,"type":"object","title":"ExpertUpdate","description":"``PATCH /api/admin/experts/{id}`` partial (super_admin only).\n\nB-003 v1.3: ``status`` field admits both ``active`` and ``inactive``\nso super_admin can re-activate a soft-deleted expert via a single\nPATCH (no separate ``/activate`` endpoint at MVP)."},"FileSummary":{"properties":{"kind":{"type":"string","title":"Kind"},"filename":{"type":"string","title":"Filename"},"size_bytes":{"type":"integer","title":"Size Bytes"},"uploaded_at":{"type":"string","format":"date-time","title":"Uploaded At"}},"type":"object","required":["kind","filename","size_bytes","uploaded_at"],"title":"FileSummary"},"ForgotRequest":{"properties":{"email":{"type":"string","maxLength":320,"minLength":3,"pattern":"^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$","title":"Email","description":"Account email. Server returns 202 generic regardless of existence (anti-enumeration).","examples":["user@example.com"]}},"additionalProperties":false,"type":"object","required":["email"],"title":"ForgotRequest"},"GenericAccepted":{"properties":{"detail":{"type":"string","title":"Detail","default":"if_email_exists_link_sent"}},"type":"object","title":"GenericAccepted","description":"Anti-enumeration response for ``/auth/forgot``.","example":{"detail":"if_email_exists_link_sent"}},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HistoryEntry":{"properties":{"action":{"type":"string","title":"Action","description":"Lifecycle action key (stable identifier).","examples":["created","assigned","ai_processing_started","ai_completed","result_uploaded","approved","cancelled"]},"actor_role":{"type":"string","title":"Actor Role","description":"Actor role string (mirrors ActorRole enum).","examples":["user","system","tenant_admin","super_admin","expert"]},"created_at":{"type":"string","format":"date-time","title":"Created At"},"payload":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Payload","description":"Original payload_json from request_history; shape depends on action. Use ``note`` for a pre-rendered Vietnamese display string.","examples":[{"modules":["item_code_generator"]},{"expert_id":"880e8400-e29b-41d4-a716-446655440003"},{"ai_processing_seconds":247,"from":"ai_processing","rows_processed":8200,"to":"awaiting_assign"}]},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note","description":"Server-derived Vietnamese display string (KHÔNG phải user-editable note — đó là `internal_note` field on AdminRequestDetail).","examples":["Khách tạo đơn với module item_code_generator","Phân công expert Lê Quang Phi","AI xử lý xong (247s, 8200 dòng)","Expert upload kết quả","Admin duyệt giao kết quả"]}},"type":"object","required":["action","actor_role","created_at"],"title":"HistoryEntry","description":"Status/lifecycle history row for FE timeline rendering.\n\n``payload`` exposes the original ``request_history.payload_json`` so FE\ncan show contextual data (assigned expert, status from→to, AI error type).\n``note`` is a server-derived Vietnamese display string mapping\n``(action, payload)`` → human-readable text — FE may use it directly or\nrender its own per-locale string from the raw fields."},"LanguageCode":{"type":"string","enum":["vi","en","ko","zh"],"title":"LanguageCode"},"LanguageUpdate":{"properties":{"language":{"$ref":"#/components/schemas/LanguageCode","description":"4-locale enum (vi / en / ko / zh) — BR-032. Admin pool VI-only at runtime; user pool free choice.","examples":["vi"]}},"additionalProperties":false,"type":"object","required":["language"],"title":"LanguageUpdate","description":"``PUT /api/{admin,user}/settings/language`` body."},"LoginRequest":{"properties":{"email":{"type":"string","maxLength":320,"minLength":3,"pattern":"^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$","title":"Email","description":"Login email (case-insensitive). Pool resolution: admin pool tries first, user pool fallback (per Phase 03 baseline).","examples":["user@example.com"]},"password":{"type":"string","maxLength":200,"minLength":1,"title":"Password","description":"Plaintext password — bcrypt verified server-side. Lockout after 5 failures within 15 min (P7).","examples":["P@ssw0rd123!"]},"remember_me":{"type":"boolean","title":"Remember Me","description":"Reserved for FE preference; server still issues 3-day access + 7-day refresh regardless (override 2026-05-03).","default":false,"examples":[false]}},"additionalProperties":false,"type":"object","required":["email","password"],"title":"LoginRequest","description":"Body of ``POST /api/{user,admin}/auth/login``."},"LoginResponse":{"properties":{"access_token":{"type":"string","title":"Access Token"},"refresh_token":{"type":"string","title":"Refresh Token"},"token_type":{"type":"string","title":"Token Type","default":"bearer"},"role":{"type":"string","title":"Role"},"force_password_change":{"type":"boolean","title":"Force Password Change"}},"type":"object","required":["access_token","refresh_token","role","force_password_change"],"title":"LoginResponse","example":{"access_token":"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI1NTBlODQwMC1lMjliLTQxZDQtYTcxNi00NDY2NTU0NDAwMDAiLCJyb2xlIjoidGVuYW50X2FkbWluIn0.signature","force_password_change":false,"refresh_token":"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI1NTBlODQwMC1lMjliLTQxZDQtYTcxNi00NDY2NTU0NDAwMDAiLCJqdGkiOiI4ODBlODQwMC1lMjliLTQxZDQtYTcxNi00NDY2NTU0NDAwMDMifQ.signature","role":"tenant_admin","token_type":"bearer"}},"NotePatchRequest":{"properties":{"internal_note":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Internal Note","description":"Replace internal note. Null clears the note. Visible to super_admin + tenant_admin only (BR-014).","examples":["Chuyên gia phản hồi: cần thêm sample chemicalcomposition trước 16h."]}},"additionalProperties":false,"type":"object","title":"NotePatchRequest"},"ProfileUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Name","description":"Updated display name. Null = no change.","examples":["Trần Thị B"]},"phone":{"anyOf":[{"type":"string","maxLength":30},{"type":"null"}],"title":"Phone","description":"Updated VN phone. Null = no change.","examples":["0901234567"]}},"additionalProperties":false,"type":"object","title":"ProfileUpdate","description":"``PUT /api/{admin,user}/settings/profile`` partial body.\n\nExcludes: ``email`` (immutable BR-007), ``password`` (use\n``/auth/change-password`` per IC-M-011), ``company_*`` (use\n``/settings/company`` for users, no admin equivalent)."},"RefreshRequest":{"properties":{"refresh_token":{"type":"string","minLength":1,"title":"Refresh Token","description":"Opaque JWT refresh token from prior /auth/login. Server rotates: returns new refresh + blacklists the old jti (D9 rotation).","examples":["eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1NTBlODQwMC0uLi4ifQ.signature"]}},"additionalProperties":false,"type":"object","required":["refresh_token"],"title":"RefreshRequest"},"RefreshResponse":{"properties":{"access_token":{"type":"string","title":"Access Token"},"refresh_token":{"type":"string","title":"Refresh Token"},"token_type":{"type":"string","title":"Token Type","default":"bearer"}},"type":"object","required":["access_token","refresh_token"],"title":"RefreshResponse","description":"Rotation D9: server always returns a new refresh alongside the access.","example":{"access_token":"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI1NTBlODQwMC1lMjliLTQxZDQtYTcxNi00NDY2NTU0NDAwMDAifQ.new_access_signature","refresh_token":"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI1NTBlODQwMC1lMjliLTQxZDQtYTcxNi00NDY2NTU0NDAwMDAiLCJqdGkiOiI5OTBlODQwMC1lMjliLTQxZDQtYTcxNi00NDY2NTU0NDAwMDQifQ.new_refresh_signature","token_type":"bearer"}},"RequestStatus":{"type":"string","enum":["pending","ai_processing","awaiting_assign","processing","completed","delivered","cancelled"],"title":"RequestStatus"},"ResetRequest":{"properties":{"token":{"type":"string","maxLength":512,"minLength":20,"title":"Token","description":"URL-safe random token from email link (≥32 bytes pre-hash, single-use, expires 30 min — P7).","examples":["a8f3c2b1d0e9f8a7b6c5d4e3f2a1b0c9d8e7f6a5"]},"new_password":{"type":"string","maxLength":200,"minLength":1,"title":"New Password","description":"New plaintext password. Server bcrypt-hashes and clears force_password_change flag.","examples":["NewP@ssw0rd456!"]}},"additionalProperties":false,"type":"object","required":["token","new_password"],"title":"ResetRequest"},"SLAStatus":{"type":"string","enum":["on_time","near_overdue","overdue"],"title":"SLAStatus"},"SuppressionInsertRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"reason":{"type":"string","title":"Reason"},"bounce_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bounce Type"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata"}},"type":"object","required":["email","reason"],"title":"SuppressionInsertRequest"},"SuppressionRecord":{"properties":{"email":{"type":"string","title":"Email"},"reason":{"type":"string","title":"Reason"},"bounce_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bounce Type"},"suppressed_at":{"type":"string","title":"Suppressed At"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata"}},"type":"object","required":["email","reason","bounce_type","suppressed_at","metadata"],"title":"SuppressionRecord"},"SystemSettingItem":{"properties":{"key":{"type":"string","title":"Key"},"value":{"type":"string","title":"Value"},"type":{"type":"string","title":"Type"},"default":{"type":"string","title":"Default"},"description":{"type":"string","title":"Description"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"},"updated_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Updated By"}},"type":"object","required":["key","value","type","default","description"],"title":"SystemSettingItem","description":"Single key + its current value + meta + last-write trace.","example":{"default":"3","description":"Số lần retry max trước khi mark ai_failed=true (BRD §5.2.4).","key":"ai_max_retry","type":"int","updated_at":"2026-05-09T18:30:00+07:00","updated_by":"990e8400-e29b-41d4-a716-446655440004","value":"3"}},"SystemSettingListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/SystemSettingItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["items","total"],"title":"SystemSettingListResponse"},"SystemSettingUpdateRequest":{"properties":{"value":{"type":"string","maxLength":2000,"minLength":0,"title":"Value"}},"additionalProperties":false,"type":"object","required":["value"],"title":"SystemSettingUpdateRequest","description":"Body of ``PUT /api/admin/system-settings/{key}``.\n\n``value`` is always a string on the wire; the service coerces per\n``KeyMeta.type`` (int / csv_emails) and rejects 422 on type mismatch.","example":{"value":"5"}},"TenantCreate":{"properties":{"slug":{"type":"string","maxLength":30,"minLength":2,"pattern":"^[a-z0-9][a-z0-9-]{0,28}[a-z0-9]$","title":"Slug","description":"Subdomain identifier (lowercase alnum + hyphen, 2-30 chars, no leading/trailing hyphen). Immutable post-create (BR-024).","examples":["acme-corp"]},"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name","description":"Internal canonical tenant name (admin-facing label).","examples":["Acme Corporation Vietnam"]},"tagline":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Tagline","description":"Optional brand tagline shown in user portal header.","examples":["Giải pháp khai báo hải quan toàn diện"]},"logo_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Logo Url","description":"Public bucket URL from POST /api/uploads/presigned-url (kind=branding_logo). Validator rejects URLs outside S3_PUBLIC_BUCKET_URL_PREFIX (audit C-2 fix).","examples":["https://chc-public.s3.amazonaws.com/branding/logo/acme-corp-logo.png"]},"favicon_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Favicon Url","description":"Public bucket URL from POST /api/uploads/presigned-url (kind=branding_favicon). Same validator as logo_url.","examples":["https://chc-public.s3.amazonaws.com/branding/favicon/acme-corp-favicon.ico"]},"primary_color":{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$","title":"Primary Color","description":"Primary brand color hex (uppercase preferred for prototype consistency).","examples":["#1E40AF"]},"display_name":{"type":"string","maxLength":200,"minLength":1,"title":"Display Name","description":"User-facing display name shown in brand bar / emails (may differ from internal `name`).","examples":["Acme Vietnam"]},"footer_text":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Footer Text","description":"Optional footer copyright text rendered in user portal.","examples":["© 2026 Acme Corporation Vietnam. Tất cả các quyền được bảo lưu."]},"email_domain":{"anyOf":[{"type":"string","maxLength":200,"pattern":"^[a-z0-9.-]+\\.[a-z]{2,}$"},{"type":"null"}],"title":"Email Domain","description":"SES-verified sender domain for tenant-branded emails. Null falls back to platform domain.","examples":["mail.acme-corp.vn"]},"etariff_daily_quota":{"type":"integer","maximum":1000000.0,"minimum":0.0,"title":"Etariff Daily Quota","description":"Tenant-shared daily quota (per-tenant pool). Reset 00:00 Asia/Saigon.","default":50,"examples":[100]},"contact_name":{"type":"string","maxLength":200,"minLength":1,"title":"Contact Name","description":"Tenant Owner contact name (legal/billing — G-C-002, NOT tenant_admin).","examples":["Nguyễn Văn A"]},"contact_email":{"type":"string","maxLength":320,"minLength":3,"pattern":"^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$","title":"Contact Email","description":"Tenant Owner contact email (legal/billing).","examples":["owner@acme-corp.vn"]},"contact_phone":{"anyOf":[{"type":"string","maxLength":30},{"type":"null"}],"title":"Contact Phone","description":"Optional Tenant Owner contact phone.","examples":["0901234567"]}},"additionalProperties":false,"type":"object","required":["slug","name","primary_color","display_name","contact_name","contact_email"],"title":"TenantCreate","description":"``POST /api/admin/tenants`` body — IC-C-002 enumerate 12 fields.\n\nTenant Owner trio (``contact_*``) per G-C-002: name + email required,\nphone optional. ``slug`` immutable post-create (BR-024).\n\nPhase 04.6: ``logo_url`` / ``favicon_url`` MUST be public URLs from\nthe platform's public bucket — produced by\n``POST /api/uploads/presigned-url`` (kind = ``branding_logo`` /\n``branding_favicon``). Arbitrary external URLs rejected at schema."},"TenantDetail":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"tagline":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tagline"},"logo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Url"},"favicon_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Favicon Url"},"primary_color":{"type":"string","title":"Primary Color"},"display_name":{"type":"string","title":"Display Name"},"footer_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Footer Text"},"email_domain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email Domain"},"etariff_daily_quota":{"type":"integer","title":"Etariff Daily Quota"},"contact_name":{"type":"string","title":"Contact Name"},"contact_email":{"type":"string","title":"Contact Email"},"contact_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Phone"},"status":{"$ref":"#/components/schemas/TenantStatus"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"}},"type":"object","required":["id","slug","name","tagline","logo_url","favicon_url","primary_color","display_name","footer_text","email_domain","etariff_daily_quota","contact_name","contact_email","contact_phone","status","created_at","updated_at","created_by"],"title":"TenantDetail","description":"``GET /api/admin/tenants/{id}`` response — full row schema.","example":{"contact_email":"owner@acme-corp.vn","contact_name":"Nguyễn Văn A","contact_phone":"0901234567","created_at":"2026-04-15T09:00:00+07:00","created_by":"550e8400-e29b-41d4-a716-446655440000","display_name":"Acme Vietnam","email_domain":"mail.acme-corp.vn","etariff_daily_quota":100,"favicon_url":"https://chc-public.s3.amazonaws.com/branding/favicon/acme-corp-favicon.ico","footer_text":"© 2026 Acme Corporation Vietnam. Tất cả các quyền được bảo lưu.","id":"660e8400-e29b-41d4-a716-446655440001","logo_url":"https://chc-public.s3.amazonaws.com/branding/logo/acme-corp-logo.png","name":"Acme Corporation Vietnam","primary_color":"#1E40AF","slug":"acme-corp","status":"active","tagline":"Giải pháp khai báo hải quan toàn diện","updated_at":"2026-05-09T10:00:00+07:00"}},"TenantListItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"primary_color":{"type":"string","title":"Primary Color"},"logo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Url"},"email_domain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email Domain"},"etariff_daily_quota":{"type":"integer","title":"Etariff Daily Quota"},"status":{"$ref":"#/components/schemas/TenantStatus"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"users_count":{"type":"integer","title":"Users Count","default":0},"requests_count":{"type":"integer","title":"Requests Count","default":0},"rating_avg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rating Avg"}},"type":"object","required":["id","slug","name","primary_color","logo_url","email_domain","etariff_daily_quota","status","created_at"],"title":"TenantListItem","description":"``GET /api/admin/tenants`` row — list view augmented with the 3\naggregate fields the admin overview card renders: users_count (active +\nnon-deleted), requests_count (lifetime), rating_avg (avg star across all\nrated requests, ``null`` when nothing rated yet)."},"TenantListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/TenantListItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"}},"type":"object","required":["items","total","page","page_size","total_pages"],"title":"TenantListResponse","example":{"items":[{"created_at":"2026-04-15T09:00:00+07:00","email_domain":"mail.acme-corp.vn","etariff_daily_quota":100,"id":"660e8400-e29b-41d4-a716-446655440001","logo_url":"https://chc-public.s3.amazonaws.com/branding/logo/acme-corp-logo.png","name":"Acme Corporation Vietnam","primary_color":"#1E40AF","rating_avg":4.72,"requests_count":348,"slug":"acme-corp","status":"active","users_count":12}],"page":1,"page_size":50,"total":1,"total_pages":1}},"TenantStatus":{"type":"string","enum":["active","disabled"],"title":"TenantStatus"},"TenantUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Name","description":"Updated internal name. Null = no change.","examples":["Acme Corporation Vietnam"]},"tagline":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Tagline","description":"Updated tagline. Null = no change.","examples":["Giải pháp khai báo hải quan toàn diện"]},"logo_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Logo Url","description":"Updated logo public URL. Null = no change.","examples":["https://chc-public.s3.amazonaws.com/branding/logo/acme-corp-logo-v2.png"]},"favicon_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Favicon Url","description":"Updated favicon public URL. Null = no change.","examples":["https://chc-public.s3.amazonaws.com/branding/favicon/acme-corp-favicon-v2.ico"]},"primary_color":{"anyOf":[{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"null"}],"title":"Primary Color","description":"Updated brand color hex. Null = no change.","examples":["#1E40AF"]},"display_name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Display Name","description":"Updated user-facing display name. Null = no change.","examples":["Acme Vietnam"]},"footer_text":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Footer Text","description":"Updated footer text. Null = no change.","examples":["© 2026 Acme Corporation Vietnam. Tất cả các quyền được bảo lưu."]},"email_domain":{"anyOf":[{"type":"string","maxLength":200,"pattern":"^[a-z0-9.-]+\\.[a-z]{2,}$"},{"type":"null"}],"title":"Email Domain","description":"Updated SES sender domain. Null = no change (NOT clear — clear via separate workflow).","examples":["mail.acme-corp.vn"]},"etariff_daily_quota":{"anyOf":[{"type":"integer","maximum":1000000.0,"minimum":0.0},{"type":"null"}],"title":"Etariff Daily Quota","description":"Updated daily quota. Null = no change.","examples":[200]},"contact_name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Contact Name","description":"Updated Tenant Owner name. Null = no change.","examples":["Nguyễn Văn A"]},"contact_email":{"anyOf":[{"type":"string","maxLength":320,"minLength":3,"pattern":"^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$"},{"type":"null"}],"title":"Contact Email","description":"Updated Tenant Owner email. Null = no change.","examples":["owner@acme-corp.vn"]},"contact_phone":{"anyOf":[{"type":"string","maxLength":30},{"type":"null"}],"title":"Contact Phone","description":"Updated Tenant Owner phone. Null = no change.","examples":["0901234567"]}},"additionalProperties":false,"type":"object","title":"TenantUpdate","description":"``PATCH /api/admin/tenants/{id}`` partial — slug omitted (BR-024)."},"TenantsCompareItem":{"properties":{"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"name":{"type":"string","title":"Name"},"requests_count":{"type":"integer","title":"Requests Count"},"satisfaction_score":{"anyOf":[{"type":"number","maximum":5.0,"minimum":0.0},{"type":"null"}],"title":"Satisfaction Score"},"users_count":{"type":"integer","title":"Users Count"}},"type":"object","required":["tenant_id","name","requests_count","users_count"],"title":"TenantsCompareItem"},"TopUserItem":{"properties":{"user_id":{"type":"string","format":"uuid","title":"User Id"},"name":{"type":"string","title":"Name"},"requests_count":{"type":"integer","title":"Requests Count"}},"type":"object","required":["user_id","name","requests_count"],"title":"TopUserItem"},"UserCreate":{"properties":{"tenant_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Tenant Id","description":"Required for super_admin (cross-tenant target). tenant_admin auto-derives from JWT and must omit OR match.","examples":["660e8400-e29b-41d4-a716-446655440001"]},"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name","description":"Display name shown in user portal + admin user list.","examples":["Trần Thị B"]},"email_login":{"type":"string","maxLength":320,"minLength":3,"pattern":"^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$","title":"Email Login","description":"Login email. Immutable post-create (BR-007). Cross-table unique with admins/experts (D11).","examples":["user@example.com"]},"company_name":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Company Name","description":"Optional company name (admin pre-fills before onboarding; user can update later).","examples":["Công ty TNHH Acme Việt Nam"]},"phone":{"anyOf":[{"type":"string","maxLength":30},{"type":"null"}],"title":"Phone","description":"Optional VN phone.","examples":["0901234567"]},"language":{"$ref":"#/components/schemas/LanguageCode","description":"Initial UI language (BR-032 4-locale enum: vi / en / ko / zh). Default vi.","default":"vi","examples":["vi"]}},"additionalProperties":false,"type":"object","required":["name","email_login"],"title":"UserCreate","description":"``POST /api/admin/users`` body (IC-C-001).\n\n``tenant_id`` optional only for super_admin (route-layer enforces:\nsuper_admin can target any tenant; tenant_admin auto-derives from\nthe JWT and rejects body ``tenant_id`` mismatch)."},"UserDetail":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"email_login":{"type":"string","title":"Email Login"},"email_contact":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email Contact"},"email_result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email Result"},"name":{"type":"string","title":"Name"},"company_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Name"},"company_tax_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Tax Id"},"company_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Address"},"company_industry":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Industry"},"company_type":{"anyOf":[{"$ref":"#/components/schemas/CompanyType"},{"type":"null"}]},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"status":{"$ref":"#/components/schemas/UserStatus"},"onboarding_completed":{"type":"boolean","title":"Onboarding Completed"},"force_password_change":{"type":"boolean","title":"Force Password Change"},"language":{"$ref":"#/components/schemas/LanguageCode"},"last_login_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Login At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"}},"type":"object","required":["id","tenant_id","email_login","email_contact","email_result","name","company_name","company_tax_id","company_address","company_industry","company_type","phone","status","onboarding_completed","force_password_change","language","last_login_at","created_at","created_by"],"title":"UserDetail","description":"``GET /api/admin/users/{id}`` response — full row schema.","example":{"company_address":"123 Nguyễn Huệ, P. Bến Nghé, Q.1, TP.HCM","company_industry":"Sản xuất linh kiện điện tử","company_name":"Công ty TNHH Acme Việt Nam","company_tax_id":"0312345678","company_type":"san_xuat","created_at":"2026-04-20T11:30:00+07:00","created_by":"990e8400-e29b-41d4-a716-446655440004","email_contact":"contact@acme-corp.vn","email_login":"user@example.com","email_result":"result@acme-corp.vn","force_password_change":false,"id":"aa0e8400-e29b-41d4-a716-446655440005","language":"vi","last_login_at":"2026-05-09T08:00:00+07:00","name":"Trần Thị B","onboarding_completed":true,"phone":"0901234567","status":"active","tenant_id":"660e8400-e29b-41d4-a716-446655440001"}},"UserListItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"email_login":{"type":"string","title":"Email Login"},"name":{"type":"string","title":"Name"},"company_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Name"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"status":{"$ref":"#/components/schemas/UserStatus"},"onboarding_completed":{"type":"boolean","title":"Onboarding Completed"},"language":{"$ref":"#/components/schemas/LanguageCode"},"last_login_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Login At"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","tenant_id","email_login","name","company_name","phone","status","onboarding_completed","language","last_login_at","created_at"],"title":"UserListItem","description":"``GET /api/admin/users`` row — subset for list view."},"UserListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/UserListItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"}},"type":"object","required":["items","total","page","page_size","total_pages"],"title":"UserListResponse","example":{"items":[{"company_name":"Công ty TNHH Acme Việt Nam","created_at":"2026-04-20T11:30:00+07:00","email_login":"user@example.com","id":"aa0e8400-e29b-41d4-a716-446655440005","language":"vi","last_login_at":"2026-05-09T08:00:00+07:00","name":"Trần Thị B","onboarding_completed":true,"phone":"0901234567","status":"active","tenant_id":"660e8400-e29b-41d4-a716-446655440001"}],"page":1,"page_size":50,"total":1,"total_pages":1}},"UserStatus":{"type":"string","enum":["active","inactive"],"title":"UserStatus"},"UserUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Name","description":"Updated display name. Null = no change.","examples":["Trần Thị B"]},"company_name":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Company Name","description":"Updated company name. Null = no change.","examples":["Công ty TNHH Acme Việt Nam"]},"phone":{"anyOf":[{"type":"string","maxLength":30},{"type":"null"}],"title":"Phone","description":"Updated VN phone. Null = no change.","examples":["0901234567"]},"language":{"anyOf":[{"$ref":"#/components/schemas/LanguageCode"},{"type":"null"}],"description":"Updated UI language (vi / en / ko / zh per BR-032). Null = no change.","examples":["vi"]},"status":{"anyOf":[{"$ref":"#/components/schemas/UserStatus"},{"type":"null"}],"description":"Toggle active/inactive (B-007 v1.3 soft-delete). Null = no change.","examples":["active"]}},"additionalProperties":false,"type":"object","title":"UserUpdate","description":"``PATCH /api/admin/users/{id}`` partial.\n\nExcludes: ``email_login`` (BR-007 immutable), ``company_tax_id``\n(BR-008 immutable post-onboarding), ``password`` (use\n``/auth/change-password``), ``tenant_id`` (immutable; move via\nsuper_admin direct SQL if ever needed)."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"ErrorBody":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable error key (see GET /api/public/error-catalog). FE switches logic / shows icon based on this value.","example":"request_not_found"},"message":{"type":"string","description":"Localized human-readable text. Language picked from Accept-Language header (vi/en/ko/zh); /api/admin/* always returns vi.","example":"Không tìm thấy đơn hàng"}}},"ErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"$ref":"#/components/schemas/ErrorBody"}},"example":{"error":{"code":"request_not_found","message":"Không tìm thấy đơn hàng"}}},"ValidationErrorDetail":{"type":"object","properties":{"field":{"type":"string","example":"body.email"},"message":{"type":"string","example":"Field required"},"type":{"type":"string","example":"missing"}}},"ValidationErrorBody":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","example":"validation_error"},"message":{"type":"string","example":"Dữ liệu không hợp lệ"},"details":{"type":"array","items":{"$ref":"#/components/schemas/ValidationErrorDetail"}}}},"ValidationErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"$ref":"#/components/schemas/ValidationErrorBody"}},"example":{"error":{"code":"validation_error","message":"Dữ liệu không hợp lệ","details":[{"field":"body.email","message":"Field required","type":"missing"}]}}}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}}}