Bug: refactor(users): Add V2 user_roles data support



In V2 user_roles data, merchant_id will be null for org level users.

Currently in the BE, we throw 500 if merchant_id is not found in user_role.

So, we should fix this case and get merchant_id from db using org_id if merchant_id is not present in the user_role.
diff --git a/crates/api_models/src/events/user.rs b/crates/api_models/src/events/user.rs
index 590179c052c..8d1ae60b325 100644
--- a/crates/api_models/src/events/user.rs
+++ b/crates/api_models/src/events/user.rs
@@ -16,11 +16,11 @@ use crate::user::{
     GetSsoAuthUrlRequest, GetUserAuthenticationMethodsRequest, GetUserDetailsResponse,
     GetUserRoleDetailsRequest, GetUserRoleDetailsResponse, InviteUserRequest, ListUsersResponse,
     ReInviteUserRequest, RecoveryCodes, ResetPasswordRequest, RotatePasswordRequest,
-    SendVerifyEmailRequest, SignInResponse, SignUpRequest, SignUpWithMerchantIdRequest,
-    SsoSignInRequest, SwitchMerchantRequest, SwitchOrganizationRequest, SwitchProfileRequest,
-    TokenOrPayloadResponse, TokenResponse, TwoFactorAuthStatusResponse,
-    UpdateUserAccountDetailsRequest, UpdateUserAuthenticationMethodRequest, UserFromEmailRequest,
-    UserMerchantCreate, VerifyEmailRequest, VerifyRecoveryCodeRequest, VerifyTotpRequest,
+    SendVerifyEmailRequest, SignUpRequest, SignUpWithMerchantIdRequest, SsoSignInRequest,
+    SwitchMerchantRequest, SwitchOrganizationRequest, SwitchProfileRequest, TokenResponse,
+    TwoFactorAuthStatusResponse, UpdateUserAccountDetailsRequest,
+    UpdateUserAuthenticationMethodRequest, UserFromEmailRequest, UserMerchantCreate,
+    VerifyEmailRequest, VerifyRecoveryCodeRequest, VerifyTotpRequest,
 };
 
 impl ApiEventMetric for DashboardEntryResponse {
@@ -40,12 +40,6 @@ impl ApiEventMetric for VerifyTokenResponse {
     }
 }
 
-impl<T> ApiEventMetric for TokenOrPayloadResponse<T> {
-    fn get_api_event_type(&self) -> Option<ApiEventsType> {
-        Some(ApiEventsType::Miscellaneous)
-    }
-}
-
 common_utils::impl_api_event_type!(
     Miscellaneous,
     (
@@ -72,7 +66,6 @@ common_utils::impl_api_event_type!(
         VerifyEmailRequest,
         SendVerifyEmailRequest,
         AcceptInviteFromEmailRequest,
-        SignInResponse,
         UpdateUserAccountDetailsRequest,
         GetUserDetailsResponse,
         GetUserRoleDetailsRequest,
diff --git a/crates/api_models/src/events/user_role.rs b/crates/api_models/src/events/user_role.rs
index 5b5da0ec50a..f88c318477a 100644
--- a/crates/api_models/src/events/user_role.rs
+++ b/crates/api_models/src/events/user_role.rs
@@ -2,9 +2,8 @@ use common_utils::events::{ApiEventMetric, ApiEventsType};
 
 use crate::user_role::{
     role::{
-        CreateRoleRequest, GetRoleFromTokenResponse, GetRoleRequest, ListRolesResponse,
-        RoleInfoResponse, RoleInfoWithGroupsResponse, RoleInfoWithPermissionsResponse,
-        UpdateRoleRequest,
+        CreateRoleRequest, GetRoleRequest, ListRolesResponse, RoleInfoWithGroupsResponse,
+        RoleInfoWithPermissionsResponse, UpdateRoleRequest,
     },
     AcceptInvitationRequest, AuthorizationInfoResponse, DeleteUserRoleRequest,
     MerchantSelectRequest, UpdateUserRoleRequest,
@@ -23,8 +22,6 @@ common_utils::impl_api_event_type!(
         CreateRoleRequest,
         UpdateRoleRequest,
         ListRolesResponse,
-        RoleInfoResponse,
-        GetRoleFromTokenResponse,
         RoleInfoWithGroupsResponse
     )
 );
diff --git a/crates/api_models/src/user.rs b/crates/api_models/src/user.rs
index 97d0c63fdf1..abc09c8bbee 100644
--- a/crates/api_models/src/user.rs
+++ b/crates/api_models/src/user.rs
@@ -23,8 +23,6 @@ pub struct SignUpRequest {
     pub password: Secret<String>,
 }
 
-pub type SignUpResponse = DashboardEntryResponse;
-
 #[derive(serde::Serialize, Debug, Clone)]
 pub struct DashboardEntryResponse {
     pub token: Secret<String>,
@@ -40,22 +38,6 @@ pub struct DashboardEntryResponse {
 
 pub type SignInRequest = SignUpRequest;
 
-#[derive(Debug, serde::Serialize)]
-#[serde(tag = "flow_type", rename_all = "snake_case")]
-pub enum SignInResponse {
-    MerchantSelect(MerchantSelectResponse),
-    DashboardEntry(DashboardEntryResponse),
-}
-
-#[derive(Debug, serde::Serialize)]
-pub struct MerchantSelectResponse {
-    pub token: Secret<String>,
-    pub name: Secret<String>,
-    pub email: pii::Email,
-    pub verification_days_left: Option<i64>,
-    pub merchants: Vec<UserMerchantAccount>,
-}
-
 #[derive(serde::Deserialize, Debug, Clone, serde::Serialize)]
 pub struct ConnectAccountRequest {
     pub email: pii::Email,
@@ -202,8 +184,6 @@ pub struct VerifyEmailRequest {
     pub token: Secret<String>,
 }
 
-pub type VerifyEmailResponse = SignInResponse;
-
 #[derive(serde::Deserialize, Debug, serde::Serialize)]
 pub struct SendVerifyEmailRequest {
     pub email: pii::Email,
@@ -232,11 +212,6 @@ pub struct UpdateUserAccountDetailsRequest {
     pub preferred_merchant_id: Option<id_type::MerchantId>,
 }
 
-#[derive(Debug, serde::Deserialize, serde::Serialize)]
-pub struct TokenOnlyQueryParam {
-    pub token_only: Option<bool>,
-}
-
 #[derive(Debug, serde::Deserialize, serde::Serialize)]
 pub struct SkipTwoFactorAuthQueryParam {
     pub skip_two_factor_auth: Option<bool>,
@@ -254,12 +229,6 @@ pub struct TwoFactorAuthStatusResponse {
     pub recovery_code: bool,
 }
 
-#[derive(Debug, serde::Serialize)]
-#[serde(untagged)]
-pub enum TokenOrPayloadResponse<T> {
-    Token(TokenResponse),
-    Payload(T),
-}
 #[derive(Debug, serde::Deserialize, serde::Serialize)]
 pub struct UserFromEmailRequest {
     pub token: Secret<String>,
diff --git a/crates/api_models/src/user_role.rs b/crates/api_models/src/user_role.rs
index c9f222cb7be..ed6911016b1 100644
--- a/crates/api_models/src/user_role.rs
+++ b/crates/api_models/src/user_role.rs
@@ -121,9 +121,8 @@ pub enum UserStatus {
 #[derive(Debug, serde::Deserialize, serde::Serialize)]
 pub struct MerchantSelectRequest {
     pub merchant_ids: Vec<common_utils::id_type::MerchantId>,
-    // TODO: Remove this once the token only api is being used
-    pub need_dashboard_entry_response: Option<bool>,
 }
+
 #[derive(Debug, serde::Deserialize, serde::Serialize)]
 pub struct AcceptInvitationRequest {
     pub merchant_ids: Vec<common_utils::id_type::MerchantId>,
diff --git a/crates/api_models/src/user_role/role.rs b/crates/api_models/src/user_role/role.rs
index 73b25c84af5..acbad9152ae 100644
--- a/crates/api_models/src/user_role/role.rs
+++ b/crates/api_models/src/user_role/role.rs
@@ -1,4 +1,5 @@
-use common_enums::{EntityType, PermissionGroup, RoleScope};
+pub use common_enums::PermissionGroup;
+use common_enums::{EntityType, RoleScope};
 
 use super::Permission;
 
@@ -17,26 +18,7 @@ pub struct UpdateRoleRequest {
 }
 
 #[derive(Debug, serde::Serialize)]
-pub struct ListRolesResponse(pub Vec<RoleInfoResponse>);
-
-#[derive(Debug, serde::Deserialize)]
-pub struct GetGroupsQueryParam {
-    pub groups: Option<bool>,
-}
-
-#[derive(Debug, serde::Serialize)]
-#[serde(untagged)]
-pub enum GetRoleFromTokenResponse {
-    Permissions(Vec<Permission>),
-    Groups(Vec<PermissionGroup>),
-}
-
-#[derive(Debug, serde::Serialize)]
-#[serde(untagged)]
-pub enum RoleInfoResponse {
-    Permissions(RoleInfoWithPermissionsResponse),
-    Groups(RoleInfoWithGroupsResponse),
-}
+pub struct ListRolesResponse(pub Vec<RoleInfoWithGroupsResponse>);
 
 #[derive(Debug, serde::Serialize)]
 pub struct RoleInfoWithPermissionsResponse {
diff --git a/crates/router/src/core/user.rs b/crates/router/src/core/user.rs
index ace8c3babc6..93a557d5688 100644
--- a/crates/router/src/core/user.rs
+++ b/crates/router/src/core/user.rs
@@ -121,42 +121,10 @@ pub async fn get_user_details(
     ))
 }
 
-pub async fn signup(
-    state: SessionState,
-    request: user_api::SignUpRequest,
-) -> UserResponse<user_api::TokenOrPayloadResponse<user_api::SignUpResponse>> {
-    let new_user = domain::NewUser::try_from(request)?;
-    new_user
-        .get_new_merchant()
-        .get_new_organization()
-        .insert_org_in_db(state.clone())
-        .await?;
-    let user_from_db = new_user
-        .insert_user_and_merchant_in_db(state.clone())
-        .await?;
-    let user_role = new_user
-        .insert_org_level_user_role_in_db(
-            state.clone(),
-            common_utils::consts::ROLE_ID_ORGANIZATION_ADMIN.to_string(),
-            UserStatus::Active,
-            None,
-        )
-        .await?;
-    utils::user_role::set_role_permissions_in_cache_by_user_role(&state, &user_role).await;
-
-    let token =
-        utils::user::generate_jwt_auth_token_without_profile(&state, &user_from_db, &user_role)
-            .await?;
-    let response =
-        utils::user::get_dashboard_entry_response(&state, user_from_db, user_role, token.clone())?;
-
-    auth::cookies::set_cookie_response(user_api::TokenOrPayloadResponse::Payload(response), token)
-}
-
 pub async fn signup_token_only_flow(
     state: SessionState,
     request: user_api::SignUpRequest,
-) -> UserResponse<user_api::TokenOrPayloadResponse<user_api::SignUpResponse>> {
+) -> UserResponse<user_api::TokenResponse> {
     let new_user = domain::NewUser::try_from(request)?;
     new_user
         .get_new_merchant()
@@ -182,61 +150,17 @@ pub async fn signup_token_only_flow(
         .get_token_with_user_role(&state, &user_role)
         .await?;
 
-    let response = user_api::TokenOrPayloadResponse::Token(user_api::TokenResponse {
+    let response = user_api::TokenResponse {
         token: token.clone(),
         token_type: next_flow.get_flow().into(),
-    });
+    };
     auth::cookies::set_cookie_response(response, token)
 }
 
-pub async fn signin(
-    state: SessionState,
-    request: user_api::SignInRequest,
-) -> UserResponse<user_api::TokenOrPayloadResponse<user_api::SignInResponse>> {
-    let user_from_db: domain::UserFromStorage = state
-        .global_store
-        .find_user_by_email(&request.email)
-        .await
-        .map_err(|e| {
-            if e.current_context().is_db_not_found() {
-                e.change_context(UserErrors::InvalidCredentials)
-            } else {
-                e.change_context(UserErrors::InternalServerError)
-            }
-        })?
-        .into();
-
-    user_from_db.compare_password(&request.password)?;
-
-    let signin_strategy =
-        if let Some(preferred_merchant_id) = user_from_db.get_preferred_merchant_id() {
-            let preferred_role = user_from_db
-                .get_role_from_db_by_merchant_id(&state, &preferred_merchant_id)
-                .await
-                .to_not_found_response(UserErrors::InternalServerError)
-                .attach_printable("User role with preferred_merchant_id not found")?;
-            domain::SignInWithRoleStrategyType::SingleRole(domain::SignInWithSingleRoleStrategy {
-                user: user_from_db,
-                user_role: Box::new(preferred_role),
-            })
-        } else {
-            let user_roles = user_from_db.get_roles_from_db(&state).await?;
-            domain::SignInWithRoleStrategyType::decide_signin_strategy_by_user_roles(
-                user_from_db,
-                user_roles,
-            )
-            .await?
-        };
-
-    let response = signin_strategy.get_signin_response(&state).await?;
-    let token = utils::user::get_token_from_signin_response(&response);
-    auth::cookies::set_cookie_response(user_api::TokenOrPayloadResponse::Payload(response), token)
-}
-
 pub async fn signin_token_only_flow(
     state: SessionState,
     request: user_api::SignInRequest,
-) -> UserResponse<user_api::TokenOrPayloadResponse<user_api::SignInResponse>> {
+) -> UserResponse<user_api::TokenResponse> {
     let user_from_db: domain::UserFromStorage = state
         .global_store
         .find_user_by_email(&request.email)
@@ -251,10 +175,10 @@ pub async fn signin_token_only_flow(
 
     let token = next_flow.get_token(&state).await?;
 
-    let response = user_api::TokenOrPayloadResponse::Token(user_api::TokenResponse {
+    let response = user_api::TokenResponse {
         token: token.clone(),
         token_type: next_flow.get_flow().into(),
-    });
+    };
     auth::cookies::set_cookie_response(response, token)
 }
 
@@ -573,105 +497,11 @@ pub async fn reset_password_token_only_flow(
     auth::cookies::remove_cookie_response()
 }
 
-#[cfg(feature = "email")]
-pub async fn reset_password(
-    state: SessionState,
-    request: user_api::ResetPasswordRequest,
-) -> UserResponse<()> {
-    let token = request.token.expose();
-    let email_token = auth::decode_jwt::<email_types::EmailToken>(&token, &state)
-        .await
-        .change_context(UserErrors::LinkInvalid)?;
-
-    auth::blacklist::check_email_token_in_blacklist(&state, &token).await?;
-
-    let password = domain::UserPassword::new(request.password)?;
-    let hash_password = utils::user::password::generate_password_hash(password.get_secret())?;
-
-    let user = state
-        .global_store
-        .update_user_by_email(
-            &email_token
-                .get_email()
-                .change_context(UserErrors::InternalServerError)?,
-            storage_user::UserUpdate::PasswordUpdate {
-                password: hash_password,
-            },
-        )
-        .await
-        .change_context(UserErrors::InternalServerError)?;
-
-    if let Some(inviter_merchant_id) = email_token.get_merchant_id() {
-        let key_manager_state = &(&state).into();
-
-        let key_store = state
-            .store
-            .get_merchant_key_store_by_merchant_id(
-                key_manager_state,
-                inviter_merchant_id,
-                &state.store.get_master_key().to_vec().into(),
-            )
-            .await
-            .change_context(UserErrors::InternalServerError)
-            .attach_printable("merchant_key_store not found")?;
-
-        let merchant_account = state
-            .store
-            .find_merchant_account_by_merchant_id(
-                key_manager_state,
-                inviter_merchant_id,
-                &key_store,
-            )
-            .await
-            .change_context(UserErrors::InternalServerError)
-            .attach_printable("merchant_account not found")?;
-
-        let (update_v1_result, update_v2_result) =
-            utils::user_role::update_v1_and_v2_user_roles_in_db(
-                &state,
-                user.user_id.clone().as_str(),
-                &merchant_account.organization_id,
-                inviter_merchant_id,
-                None,
-                UserRoleUpdate::UpdateStatus {
-                    status: UserStatus::Active,
-                    modified_by: user.user_id.clone(),
-                },
-            )
-            .await;
-
-        if update_v1_result
-            .as_ref()
-            .is_err_and(|err| !err.current_context().is_db_not_found())
-            || update_v2_result
-                .as_ref()
-                .is_err_and(|err| !err.current_context().is_db_not_found())
-        {
-            return Err(report!(UserErrors::InternalServerError));
-        }
-
-        if update_v1_result.is_err() && update_v2_result.is_err() {
-            return Err(report!(UserErrors::InvalidRoleOperation))
-                .attach_printable("User not found in the organization")?;
-        }
-    }
-
-    let _ = auth::blacklist::insert_email_token_in_blacklist(&state, &token)
-        .await
-        .map_err(|error| logger::error!(?error));
-    let _ = auth::blacklist::insert_user_in_blacklist(&state, &user.user_id)
-        .await
-        .map_err(|error| logger::error!(?error));
-
-    auth::cookies::remove_cookie_response()
-}
-
 pub async fn invite_multiple_user(
     state: SessionState,
     user_from_token: auth::UserFromToken,
     requests: Vec<user_api::InviteUserRequest>,
     req_state: ReqState,
-    is_token_only: Option<bool>,
     auth_id: Option<String>,
 ) -> UserResponse<Vec<InviteMultipleUserResponse>> {
     if requests.len() > 10 {
@@ -680,16 +510,7 @@ pub async fn invite_multiple_user(
     }
 
     let responses = futures::future::join_all(requests.iter().map(|request| async {
-        match handle_invitation(
-            &state,
-            &user_from_token,
-            request,
-            &req_state,
-            is_token_only,
-            &auth_id,
-        )
-        .await
-        {
+        match handle_invitation(&state, &user_from_token, request, &req_state, &auth_id).await {
             Ok(response) => response,
             Err(error) => InviteMultipleUserResponse {
                 email: request.email.clone(),
@@ -709,7 +530,6 @@ async fn handle_invitation(
     user_from_token: &auth::UserFromToken,
     request: &user_api::InviteUserRequest,
     req_state: &ReqState,
-    is_token_only: Option<bool>,
     auth_id: &Option<String>,
 ) -> UserResult<InviteMultipleUserResponse> {
     let inviter_user = user_from_token.get_user_from_db(state).await?;
@@ -756,15 +576,8 @@ async fn handle_invitation(
         .err()
         .unwrap_or(false)
     {
-        handle_new_user_invitation(
-            state,
-            user_from_token,
-            request,
-            req_state.clone(),
-            is_token_only,
-            auth_id,
-        )
-        .await
+        handle_new_user_invitation(state, user_from_token, request, req_state.clone(), auth_id)
+            .await
     } else {
         Err(UserErrors::InternalServerError.into())
     }
@@ -877,7 +690,6 @@ async fn handle_new_user_invitation(
     user_from_token: &auth::UserFromToken,
     request: &user_api::InviteUserRequest,
     req_state: ReqState,
-    is_token_only: Option<bool>,
     auth_id: &Option<String>,
 ) -> UserResult<InviteMultipleUserResponse> {
     let new_user = domain::NewUser::try_from((request.clone(), user_from_token.clone()))?;
@@ -912,8 +724,6 @@ async fn handle_new_user_invitation(
     .await?;
 
     let is_email_sent;
-    // TODO: Adding this to avoid clippy lints, remove this once the token only flow is being used
-    let _ = is_token_only;
 
     #[cfg(feature = "email")]
     {
@@ -921,8 +731,7 @@ async fn handle_new_user_invitation(
         // Will be adding actual usage for this variable later
         let _ = req_state.clone();
         let invitee_email = domain::UserEmail::from_pii_email(request.email.clone())?;
-        let email_contents: Box<dyn EmailData + Send + 'static> = if let Some(true) = is_token_only
-        {
+        let email_contents: Box<dyn EmailData + Send + 'static> =
             Box::new(email_types::InviteRegisteredUser {
                 recipient_email: invitee_email,
                 user_name: domain::UserName::new(new_user.get_name())?,
@@ -930,17 +739,7 @@ async fn handle_new_user_invitation(
                 subject: "You have been invited to join Hyperswitch Community!",
                 merchant_id: user_from_token.merchant_id.clone(),
                 auth_id: auth_id.clone(),
-            })
-        } else {
-            Box::new(email_types::InviteUser {
-                recipient_email: invitee_email,
-                user_name: domain::UserName::new(new_user.get_name())?,
-                settings: state.conf.clone(),
-                subject: "You have been invited to join Hyperswitch Community!",
-                merchant_id: user_from_token.merchant_id.clone(),
-                auth_id: auth_id.clone(),
-            })
-        };
+            });
         let send_email_result = state
             .email_client
             .compose_and_send_email(email_contents, state.conf.proxy.https_url.as_ref())
@@ -1047,115 +846,12 @@ pub async fn resend_invite(
     Ok(ApplicationResponse::StatusOk)
 }
 
-#[cfg(feature = "email")]
-pub async fn accept_invite_from_email(
-    state: SessionState,
-    request: user_api::AcceptInviteFromEmailRequest,
-) -> UserResponse<user_api::DashboardEntryResponse> {
-    let token = request.token.expose();
-
-    let email_token = auth::decode_jwt::<email_types::EmailToken>(&token, &state)
-        .await
-        .change_context(UserErrors::LinkInvalid)?;
-
-    auth::blacklist::check_email_token_in_blacklist(&state, &token).await?;
-
-    let user: domain::UserFromStorage = state
-        .global_store
-        .find_user_by_email(
-            &email_token
-                .get_email()
-                .change_context(UserErrors::InternalServerError)?,
-        )
-        .await
-        .change_context(UserErrors::InternalServerError)?
-        .into();
-
-    let merchant_id = email_token
-        .get_merchant_id()
-        .ok_or(UserErrors::InternalServerError)?;
-
-    let key_manager_state = &(&state).into();
-
-    let key_store = state
-        .store
-        .get_merchant_key_store_by_merchant_id(
-            key_manager_state,
-            merchant_id,
-            &state.store.get_master_key().to_vec().into(),
-        )
-        .await
-        .change_context(UserErrors::InternalServerError)
-        .attach_printable("merchant_key_store not found")?;
-
-    let merchant_account = state
-        .store
-        .find_merchant_account_by_merchant_id(key_manager_state, merchant_id, &key_store)
-        .await
-        .change_context(UserErrors::InternalServerError)
-        .attach_printable("merchant_account not found")?;
-
-    let (update_v1_result, update_v2_result) = utils::user_role::update_v1_and_v2_user_roles_in_db(
-        &state,
-        user.get_user_id(),
-        &merchant_account.organization_id,
-        merchant_id,
-        None,
-        UserRoleUpdate::UpdateStatus {
-            status: UserStatus::Active,
-            modified_by: user.get_user_id().to_string(),
-        },
-    )
-    .await;
-
-    if update_v1_result
-        .as_ref()
-        .is_err_and(|err| !err.current_context().is_db_not_found())
-        || update_v2_result
-            .as_ref()
-            .is_err_and(|err| !err.current_context().is_db_not_found())
-    {
-        return Err(report!(UserErrors::InternalServerError));
-    }
-
-    if update_v1_result.is_err() && update_v2_result.is_err() {
-        return Err(report!(UserErrors::InvalidRoleOperation))
-            .attach_printable("User not found in the organization")?;
-    }
-
-    let _ = auth::blacklist::insert_email_token_in_blacklist(&state, &token)
-        .await
-        .map_err(|error| logger::error!(?error));
-
-    let user_from_db: domain::UserFromStorage = state
-        .global_store
-        .update_user_by_user_id(user.get_user_id(), storage_user::UserUpdate::VerifyUser)
-        .await
-        .change_context(UserErrors::InternalServerError)?
-        .into();
-
-    let user_role = user_from_db
-        .get_preferred_or_active_user_role_from_db(&state)
-        .await
-        .change_context(UserErrors::InternalServerError)?;
-
-    let token =
-        utils::user::generate_jwt_auth_token_without_profile(&state, &user_from_db, &user_role)
-            .await?;
-    utils::user_role::set_role_permissions_in_cache_by_user_role(&state, &user_role).await;
-
-    let response =
-        utils::user::get_dashboard_entry_response(&state, user_from_db, user_role, token.clone())?;
-
-    auth::cookies::set_cookie_response(response, token)
-}
-
 #[cfg(feature = "email")]
 pub async fn accept_invite_from_email_token_only_flow(
     state: SessionState,
     user_token: auth::UserFromSinglePurposeToken,
     request: user_api::AcceptInviteFromEmailRequest,
-) -> UserResponse<user_api::TokenOrPayloadResponse<user_api::DashboardEntryResponse>> {
+) -> UserResponse<user_api::TokenResponse> {
     let token = request.token.expose();
 
     let email_token = auth::decode_jwt::<email_types::EmailToken>(&token, &state)
@@ -1261,10 +957,10 @@ pub async fn accept_invite_from_email_token_only_flow(
         .get_token_with_user_role(&state, &user_role)
         .await?;
 
-    let response = user_api::TokenOrPayloadResponse::Token(user_api::TokenResponse {
+    let response = user_api::TokenResponse {
         token: token.clone(),
         token_type: next_flow.get_flow().into(),
-    });
+    };
     auth::cookies::set_cookie_response(response, token)
 }
 
@@ -1503,7 +1199,7 @@ pub async fn list_merchants_for_user(
         .await
         .change_context(UserErrors::InternalServerError)?;
 
-    let merchant_accounts = state
+    let merchant_accounts_map = state
         .store
         .list_multiple_merchant_accounts(
             &(&state).into(),
@@ -1517,17 +1213,62 @@ pub async fn list_merchants_for_user(
                 .collect::<Result<Vec<_>, _>>()?,
         )
         .await
-        .change_context(UserErrors::InternalServerError)?;
+        .change_context(UserErrors::InternalServerError)?
+        .into_iter()
+        .map(|merchant_account| (merchant_account.get_id().clone(), merchant_account))
+        .collect::<HashMap<_, _>>();
 
-    let roles =
-        utils::user_role::get_multiple_role_info_for_user_roles(&state, &user_roles).await?;
+    let roles_map = futures::future::try_join_all(user_roles.iter().map(|user_role| async {
+        let Some(merchant_id) = &user_role.merchant_id else {
+            return Err(report!(UserErrors::InternalServerError))
+                .attach_printable("merchant_id not found for user_role");
+        };
+        let Some(org_id) = &user_role.org_id else {
+            return Err(report!(UserErrors::InternalServerError)
+                .attach_printable("org_id not found in user_role"));
+        };
+        roles::RoleInfo::from_role_id(&state, &user_role.role_id, merchant_id, org_id)
+            .await
+            .change_context(UserErrors::InternalServerError)
+            .attach_printable("Unable to find role info for user role")
+    }))
+    .await?
+    .into_iter()
+    .map(|role_info| (role_info.get_role_id().to_owned(), role_info))
+    .collect::<HashMap<_, _>>();
 
     Ok(ApplicationResponse::Json(
-        utils::user::get_multiple_merchant_details_with_status(
-            user_roles,
-            merchant_accounts,
-            roles,
-        )?,
+        user_roles
+            .into_iter()
+            .map(|user_role| {
+                let Some(merchant_id) = &user_role.merchant_id else {
+                    return Err(report!(UserErrors::InternalServerError))
+                        .attach_printable("merchant_id not found for user_role");
+                };
+                let Some(org_id) = &user_role.org_id else {
+                    return Err(report!(UserErrors::InternalServerError)
+                        .attach_printable("org_id not found in user_role"));
+                };
+                let merchant_account = merchant_accounts_map
+                    .get(merchant_id)
+                    .ok_or(UserErrors::InternalServerError)
+                    .attach_printable("Merchant account for user role doesn't exist")?;
+
+                let role_info = roles_map
+                    .get(&user_role.role_id)
+                    .ok_or(UserErrors::InternalServerError)
+                    .attach_printable("Role info for user role doesn't exist")?;
+
+                Ok(user_api::UserMerchantAccount {
+                    merchant_id: merchant_id.to_owned(),
+                    merchant_name: merchant_account.merchant_name.clone(),
+                    is_active: user_role.status == UserStatus::Active,
+                    role_id: user_role.role_id,
+                    role_name: role_info.get_role_name().to_string(),
+                    org_id: org_id.to_owned(),
+                })
+            })
+            .collect::<Result<Vec<_>, _>>()?,
     ))
 }
 
@@ -1650,71 +1391,12 @@ pub async fn list_users_for_merchant_account(
     )))
 }
 
-#[cfg(feature = "email")]
-pub async fn verify_email(
-    state: SessionState,
-    req: user_api::VerifyEmailRequest,
-) -> UserResponse<user_api::SignInResponse> {
-    let token = req.token.clone().expose();
-    let email_token = auth::decode_jwt::<email_types::EmailToken>(&token, &state)
-        .await
-        .change_context(UserErrors::LinkInvalid)?;
-
-    auth::blacklist::check_email_token_in_blacklist(&state, &token).await?;
-
-    let user = state
-        .global_store
-        .find_user_by_email(
-            &email_token
-                .get_email()
-                .change_context(UserErrors::InternalServerError)?,
-        )
-        .await
-        .change_context(UserErrors::InternalServerError)?;
-
-    let user = state
-        .global_store
-        .update_user_by_user_id(user.user_id.as_str(), storage_user::UserUpdate::VerifyUser)
-        .await
-        .change_context(UserErrors::InternalServerError)?;
-
-    let user_from_db: domain::UserFromStorage = user.into();
-
-    let signin_strategy =
-        if let Some(preferred_merchant_id) = user_from_db.get_preferred_merchant_id() {
-            let preferred_role = user_from_db
-                .get_role_from_db_by_merchant_id(&state, &preferred_merchant_id)
-                .await
-                .change_context(UserErrors::InternalServerError)
-                .attach_printable("User role with preferred_merchant_id not found")?;
-            domain::SignInWithRoleStrategyType::SingleRole(domain::SignInWithSingleRoleStrategy {
-                user: user_from_db,
-                user_role: Box::new(preferred_role),
-            })
-        } else {
-            let user_roles = user_from_db.get_roles_from_db(&state).await?;
-            domain::SignInWithRoleStrategyType::decide_signin_strategy_by_user_roles(
-                user_from_db,
-                user_roles,
-            )
-            .await?
-        };
-
-    let _ = auth::blacklist::insert_email_token_in_blacklist(&state, &token)
-        .await
-        .map_err(|error| logger::error!(?error));
-
-    let response = signin_strategy.get_signin_response(&state).await?;
-    let token = utils::user::get_token_from_signin_response(&response);
-    auth::cookies::set_cookie_response(response, token)
-}
-
 #[cfg(feature = "email")]
 pub async fn verify_email_token_only_flow(
     state: SessionState,
     user_token: auth::UserFromSinglePurposeToken,
     req: user_api::VerifyEmailRequest,
-) -> UserResponse<user_api::TokenOrPayloadResponse<user_api::SignInResponse>> {
+) -> UserResponse<user_api::TokenResponse> {
     let token = req.token.clone().expose();
     let email_token = auth::decode_jwt::<email_types::EmailToken>(&token, &state)
         .await
@@ -1754,10 +1436,10 @@ pub async fn verify_email_token_only_flow(
     let next_flow = current_flow.next(user_from_db, &state).await?;
     let token = next_flow.get_token(&state).await?;
 
-    let response = user_api::TokenOrPayloadResponse::Token(user_api::TokenResponse {
+    let response = user_api::TokenResponse {
         token: token.clone(),
         token_type: next_flow.get_flow().into(),
-    });
+    };
 
     auth::cookies::set_cookie_response(response, token)
 }
@@ -2839,24 +2521,7 @@ pub async fn switch_org_for_user(
         ))?
         .to_owned();
 
-    let merchant_id = if let Some(merchant_id) = &user_role.merchant_id {
-        merchant_id.clone()
-    } else {
-        state
-            .store
-            .list_merchant_accounts_by_organization_id(
-                key_manager_state,
-                request.org_id.get_string_repr(),
-            )
-            .await
-            .change_context(UserErrors::InternalServerError)
-            .attach_printable("Failed to list merchant accounts by organization_id")?
-            .first()
-            .ok_or(UserErrors::InternalServerError)
-            .attach_printable("No merchant account found for the given organization_id")?
-            .get_id()
-            .clone()
-    };
+    let merchant_id = utils::user_role::get_single_merchant_id(&state, &user_role).await?;
 
     let profile_id = if let Some(profile_id) = &user_role.profile_id {
         profile_id.clone()
diff --git a/crates/router/src/core/user_role.rs b/crates/router/src/core/user_role.rs
index 971b34b0667..4204e91678d 100644
--- a/crates/router/src/core/user_role.rs
+++ b/crates/router/src/core/user_role.rs
@@ -24,20 +24,6 @@ pub mod role;
 use common_enums::{EntityType, PermissionGroup};
 use strum::IntoEnumIterator;
 
-// TODO: To be deprecated once groups are stable
-pub async fn get_authorization_info_with_modules(
-    _state: SessionState,
-) -> UserResponse<user_role_api::AuthorizationInfoResponse> {
-    Ok(ApplicationResponse::Json(
-        user_role_api::AuthorizationInfoResponse(
-            info::get_module_authorization_info()
-                .into_iter()
-                .map(|module_info| user_role_api::AuthorizationInfo::Module(module_info.into()))
-                .collect(),
-        ),
-    ))
-}
-
 pub async fn get_authorization_info_with_groups(
     _state: SessionState,
 ) -> UserResponse<user_role_api::AuthorizationInfoResponse> {
@@ -50,6 +36,7 @@ pub async fn get_authorization_info_with_groups(
         ),
     ))
 }
+
 pub async fn get_authorization_info_with_group_tag(
 ) -> UserResponse<user_role_api::AuthorizationInfoResponse> {
     static GROUPS_WITH_PARENT_TAGS: Lazy<Vec<user_role_api::ParentInfo>> = Lazy::new(|| {
@@ -309,85 +296,11 @@ pub async fn accept_invitation(
     Ok(ApplicationResponse::StatusOk)
 }
 
-pub async fn merchant_select(
-    state: SessionState,
-    user_token: auth::UserFromSinglePurposeToken,
-    req: user_role_api::MerchantSelectRequest,
-) -> UserResponse<user_api::TokenOrPayloadResponse<user_api::DashboardEntryResponse>> {
-    let merchant_accounts = state
-        .store
-        .list_multiple_merchant_accounts(&(&state).into(), req.merchant_ids)
-        .await
-        .change_context(UserErrors::InternalServerError)?;
-
-    let update_result =
-        futures::future::join_all(merchant_accounts.iter().map(|merchant_account| async {
-            let (update_v1_result, update_v2_result) =
-                utils::user_role::update_v1_and_v2_user_roles_in_db(
-                    &state,
-                    user_token.user_id.as_str(),
-                    &merchant_account.organization_id,
-                    merchant_account.get_id(),
-                    None,
-                    UserRoleUpdate::UpdateStatus {
-                        status: UserStatus::Active,
-                        modified_by: user_token.user_id.clone(),
-                    },
-                )
-                .await;
-
-            if update_v1_result.is_err_and(|err| !err.current_context().is_db_not_found())
-                || update_v2_result.is_err_and(|err| !err.current_context().is_db_not_found())
-            {
-                Err(report!(UserErrors::InternalServerError))
-            } else {
-                Ok(())
-            }
-        }))
-        .await;
-
-    if update_result.iter().all(Result::is_err) {
-        return Err(UserErrors::MerchantIdNotFound.into());
-    }
-
-    if let Some(true) = req.need_dashboard_entry_response {
-        let user_from_db: domain::UserFromStorage = state
-            .global_store
-            .find_user_by_id(user_token.user_id.as_str())
-            .await
-            .change_context(UserErrors::InternalServerError)?
-            .into();
-
-        let user_role = user_from_db
-            .get_preferred_or_active_user_role_from_db(&state)
-            .await
-            .change_context(UserErrors::InternalServerError)?;
-
-        utils::user_role::set_role_permissions_in_cache_by_user_role(&state, &user_role).await;
-
-        let token =
-            utils::user::generate_jwt_auth_token_without_profile(&state, &user_from_db, &user_role)
-                .await?;
-        let response = utils::user::get_dashboard_entry_response(
-            &state,
-            user_from_db,
-            user_role,
-            token.clone(),
-        )?;
-        return auth::cookies::set_cookie_response(
-            user_api::TokenOrPayloadResponse::Payload(response),
-            token,
-        );
-    }
-
-    Ok(ApplicationResponse::StatusOk)
-}
-
 pub async fn merchant_select_token_only_flow(
     state: SessionState,
     user_token: auth::UserFromSinglePurposeToken,
     req: user_role_api::MerchantSelectRequest,
-) -> UserResponse<user_api::TokenOrPayloadResponse<user_api::DashboardEntryResponse>> {
+) -> UserResponse<user_api::TokenResponse> {
     let merchant_accounts = state
         .store
         .list_multiple_merchant_accounts(&(&state).into(), req.merchant_ids)
@@ -444,10 +357,10 @@ pub async fn merchant_select_token_only_flow(
         .get_token_with_user_role(&state, &user_role)
         .await?;
 
-    let response = user_api::TokenOrPayloadResponse::Token(user_api::TokenResponse {
+    let response = user_api::TokenResponse {
         token: token.clone(),
         token_type: next_flow.get_flow().into(),
-    });
+    };
     auth::cookies::set_cookie_response(response, token)
 }
 
diff --git a/crates/router/src/core/user_role/role.rs b/crates/router/src/core/user_role/role.rs
index d79b3136422..7a2c7020512 100644
--- a/crates/router/src/core/user_role/role.rs
+++ b/crates/router/src/core/user_role/role.rs
@@ -16,30 +16,10 @@ use crate::{
     utils,
 };
 
-pub async fn get_role_from_token_with_permissions(
-    state: SessionState,
-    user_from_token: UserFromToken,
-) -> UserResponse<role_api::GetRoleFromTokenResponse> {
-    let role_info = user_from_token
-        .get_role_info_from_db(&state)
-        .await
-        .attach_printable("Invalid role_id in JWT")?;
-
-    let permissions = role_info
-        .get_permissions_set()
-        .into_iter()
-        .map(Into::into)
-        .collect();
-
-    Ok(ApplicationResponse::Json(
-        role_api::GetRoleFromTokenResponse::Permissions(permissions),
-    ))
-}
-
 pub async fn get_role_from_token_with_groups(
     state: SessionState,
     user_from_token: UserFromToken,
-) -> UserResponse<role_api::GetRoleFromTokenResponse> {
+) -> UserResponse<Vec<role_api::PermissionGroup>> {
     let role_info = user_from_token
         .get_role_info_from_db(&state)
         .await
@@ -47,9 +27,7 @@ pub async fn get_role_from_token_with_groups(
 
     let permissions = role_info.get_permission_groups().to_vec();
 
-    Ok(ApplicationResponse::Json(
-        role_api::GetRoleFromTokenResponse::Groups(permissions),
-    ))
+    Ok(ApplicationResponse::Json(permissions))
 }
 
 pub async fn create_role(
@@ -105,56 +83,6 @@ pub async fn create_role(
     ))
 }
 
-// TODO: To be deprecated once groups are stable
-pub async fn list_invitable_roles_with_permissions(
-    state: SessionState,
-    user_from_token: UserFromToken,
-) -> UserResponse<role_api::ListRolesResponse> {
-    let predefined_roles_map = PREDEFINED_ROLES
-        .iter()
-        .filter(|(_, role_info)| role_info.is_invitable())
-        .map(|(role_id, role_info)| {
-            role_api::RoleInfoResponse::Permissions(role_api::RoleInfoWithPermissionsResponse {
-                permissions: role_info
-                    .get_permissions_set()
-                    .into_iter()
-                    .map(Into::into)
-                    .collect(),
-                role_id: role_id.to_string(),
-                role_name: role_info.get_role_name().to_string(),
-                role_scope: role_info.get_scope(),
-            })
-        });
-
-    let custom_roles_map = state
-        .store
-        .list_all_roles(&user_from_token.merchant_id, &user_from_token.org_id)
-        .await
-        .change_context(UserErrors::InternalServerError)?
-        .into_iter()
-        .filter_map(|role| {
-            let role_info = roles::RoleInfo::from(role);
-            role_info
-                .is_invitable()
-                .then_some(role_api::RoleInfoResponse::Permissions(
-                    role_api::RoleInfoWithPermissionsResponse {
-                        permissions: role_info
-                            .get_permissions_set()
-                            .into_iter()
-                            .map(Into::into)
-                            .collect(),
-                        role_id: role_info.get_role_id().to_string(),
-                        role_name: role_info.get_role_name().to_string(),
-                        role_scope: role_info.get_scope(),
-                    },
-                ))
-        });
-
-    Ok(ApplicationResponse::Json(role_api::ListRolesResponse(
-        predefined_roles_map.chain(custom_roles_map).collect(),
-    )))
-}
-
 pub async fn list_invitable_roles_with_groups(
     state: SessionState,
     user_from_token: UserFromToken,
@@ -162,14 +90,14 @@ pub async fn list_invitable_roles_with_groups(
     let predefined_roles_map = PREDEFINED_ROLES
         .iter()
         .filter(|(_, role_info)| role_info.is_invitable())
-        .map(|(role_id, role_info)| {
-            role_api::RoleInfoResponse::Groups(role_api::RoleInfoWithGroupsResponse {
+        .map(
+            |(role_id, role_info)| role_api::RoleInfoWithGroupsResponse {
                 groups: role_info.get_permission_groups().to_vec(),
                 role_id: role_id.to_string(),
                 role_name: role_info.get_role_name().to_string(),
                 role_scope: role_info.get_scope(),
-            })
-        });
+            },
+        );
 
     let custom_roles_map = state
         .store
@@ -181,14 +109,12 @@ pub async fn list_invitable_roles_with_groups(
             let role_info = roles::RoleInfo::from(role);
             role_info
                 .is_invitable()
-                .then_some(role_api::RoleInfoResponse::Groups(
-                    role_api::RoleInfoWithGroupsResponse {
-                        groups: role_info.get_permission_groups().to_vec(),
-                        role_id: role_info.get_role_id().to_string(),
-                        role_name: role_info.get_role_name().to_string(),
-                        role_scope: role_info.get_scope(),
-                    },
-                ))
+                .then_some(role_api::RoleInfoWithGroupsResponse {
+                    groups: role_info.get_permission_groups().to_vec(),
+                    role_id: role_info.get_role_id().to_string(),
+                    role_name: role_info.get_role_name().to_string(),
+                    role_scope: role_info.get_scope(),
+                })
         });
 
     Ok(ApplicationResponse::Json(role_api::ListRolesResponse(
@@ -196,46 +122,11 @@ pub async fn list_invitable_roles_with_groups(
     )))
 }
 
-// TODO: To be deprecated once groups are stable
-pub async fn get_role_with_permissions(
-    state: SessionState,
-    user_from_token: UserFromToken,
-    role: role_api::GetRoleRequest,
-) -> UserResponse<role_api::RoleInfoResponse> {
-    let role_info = roles::RoleInfo::from_role_id(
-        &state,
-        &role.role_id,
-        &user_from_token.merchant_id,
-        &user_from_token.org_id,
-    )
-    .await
-    .to_not_found_response(UserErrors::InvalidRoleId)?;
-
-    if role_info.is_internal() {
-        return Err(UserErrors::InvalidRoleId.into());
-    }
-
-    let permissions = role_info
-        .get_permissions_set()
-        .into_iter()
-        .map(Into::into)
-        .collect();
-
-    Ok(ApplicationResponse::Json(
-        role_api::RoleInfoResponse::Permissions(role_api::RoleInfoWithPermissionsResponse {
-            permissions,
-            role_id: role.role_id,
-            role_name: role_info.get_role_name().to_string(),
-            role_scope: role_info.get_scope(),
-        }),
-    ))
-}
-
 pub async fn get_role_with_groups(
     state: SessionState,
     user_from_token: UserFromToken,
     role: role_api::GetRoleRequest,
-) -> UserResponse<role_api::RoleInfoResponse> {
+) -> UserResponse<role_api::RoleInfoWithGroupsResponse> {
     let role_info = roles::RoleInfo::from_role_id(
         &state,
         &role.role_id,
@@ -250,12 +141,12 @@ pub async fn get_role_with_groups(
     }
 
     Ok(ApplicationResponse::Json(
-        role_api::RoleInfoResponse::Groups(role_api::RoleInfoWithGroupsResponse {
+        role_api::RoleInfoWithGroupsResponse {
             groups: role_info.get_permission_groups().to_vec(),
             role_id: role.role_id,
             role_name: role_info.get_role_name().to_string(),
             role_scope: role_info.get_scope(),
-        }),
+        },
     ))
 }
 
diff --git a/crates/router/src/db/user_role.rs b/crates/router/src/db/user_role.rs
index 57090632725..eadd1ef4a5b 100644
--- a/crates/router/src/db/user_role.rs
+++ b/crates/router/src/db/user_role.rs
@@ -357,11 +357,7 @@ impl UserRoleInterface for MockDb {
 
         for user_role in user_roles.iter() {
             let Some(user_role_merchant_id) = &user_role.merchant_id else {
-                return Err(errors::StorageError::DatabaseError(
-                    report!(errors::DatabaseError::Others)
-                        .attach_printable("merchant_id not found for user_role"),
-                )
-                .into());
+                continue;
             };
             if user_role.user_id == user_id
                 && user_role_merchant_id == merchant_id
diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs
index 8201380cc29..42f46e39d2e 100644
--- a/crates/router/src/routes/app.rs
+++ b/crates/router/src/routes/app.rs
@@ -1681,6 +1681,7 @@ impl User {
 
         route = route
             .service(web::resource("").route(web::get().to(get_user_details)))
+            .service(web::resource("/signin").route(web::post().to(user_signin)))
             .service(web::resource("/v2/signin").route(web::post().to(user_signin)))
             // signin/signup with sso using openidconnect
             .service(web::resource("/oidc").route(web::post().to(sso_sign)))
@@ -1796,6 +1797,7 @@ impl User {
                     web::resource("/signup_with_merchant_id")
                         .route(web::post().to(user_signup_with_merchant_id)),
                 )
+                .service(web::resource("/verify_email").route(web::post().to(verify_email)))
                 .service(web::resource("/v2/verify_email").route(web::post().to(verify_email)))
                 .service(
                     web::resource("/verify_email_request")
diff --git a/crates/router/src/routes/user.rs b/crates/router/src/routes/user.rs
index c52c5d1321c..1d5e3d601b6 100644
--- a/crates/router/src/routes/user.rs
+++ b/crates/router/src/routes/user.rs
@@ -62,22 +62,16 @@ pub async fn user_signup(
     state: web::Data<AppState>,
     http_req: HttpRequest,
     json_payload: web::Json<user_api::SignUpRequest>,
-    query: web::Query<user_api::TokenOnlyQueryParam>,
 ) -> HttpResponse {
     let flow = Flow::UserSignUp;
     let req_payload = json_payload.into_inner();
-    let is_token_only = query.into_inner().token_only;
     Box::pin(api::server_wrap(
         flow.clone(),
         state,
         &http_req,
         req_payload.clone(),
         |state, _: (), req_body, _| async move {
-            if let Some(true) = is_token_only {
-                user_core::signup_token_only_flow(state, req_body).await
-            } else {
-                user_core::signup(state, req_body).await
-            }
+            user_core::signup_token_only_flow(state, req_body).await
         },
         &auth::NoAuth,
         api_locking::LockAction::NotApplicable,
@@ -89,22 +83,16 @@ pub async fn user_signin(
     state: web::Data<AppState>,
     http_req: HttpRequest,
     json_payload: web::Json<user_api::SignInRequest>,
-    query: web::Query<user_api::TokenOnlyQueryParam>,
 ) -> HttpResponse {
     let flow = Flow::UserSignIn;
     let req_payload = json_payload.into_inner();
-    let is_token_only = query.into_inner().token_only;
     Box::pin(api::server_wrap(
         flow.clone(),
         state,
         &http_req,
         req_payload.clone(),
         |state, _: (), req_body, _| async move {
-            if let Some(true) = is_token_only {
-                user_core::signin_token_only_flow(state, req_body).await
-            } else {
-                user_core::signin(state, req_body).await
-            }
+            user_core::signin_token_only_flow(state, req_body).await
         },
         &auth::NoAuth,
         api_locking::LockAction::NotApplicable,
@@ -409,46 +397,27 @@ pub async fn reset_password(
     state: web::Data<AppState>,
     req: HttpRequest,
     payload: web::Json<user_api::ResetPasswordRequest>,
-    query: web::Query<user_api::TokenOnlyQueryParam>,
 ) -> HttpResponse {
     let flow = Flow::ResetPassword;
-    let is_token_only = query.into_inner().token_only;
-    if let Some(true) = is_token_only {
-        Box::pin(api::server_wrap(
-            flow,
-            state.clone(),
-            &req,
-            payload.into_inner(),
-            |state, user, payload, _| {
-                user_core::reset_password_token_only_flow(state, user, payload)
-            },
-            &auth::SinglePurposeJWTAuth(TokenPurpose::ResetPassword),
-            api_locking::LockAction::NotApplicable,
-        ))
-        .await
-    } else {
-        Box::pin(api::server_wrap(
-            flow,
-            state.clone(),
-            &req,
-            payload.into_inner(),
-            |state, _: (), payload, _| user_core::reset_password(state, payload),
-            &auth::NoAuth,
-            api_locking::LockAction::NotApplicable,
-        ))
-        .await
-    }
+    Box::pin(api::server_wrap(
+        flow,
+        state.clone(),
+        &req,
+        payload.into_inner(),
+        |state, user, payload, _| user_core::reset_password_token_only_flow(state, user, payload),
+        &auth::SinglePurposeJWTAuth(TokenPurpose::ResetPassword),
+        api_locking::LockAction::NotApplicable,
+    ))
+    .await
 }
 
 pub async fn invite_multiple_user(
     state: web::Data<AppState>,
     req: HttpRequest,
     payload: web::Json<Vec<user_api::InviteUserRequest>>,
-    token_only_query_param: web::Query<user_api::TokenOnlyQueryParam>,
     auth_id_query_param: web::Query<user_api::AuthIdQueryParam>,
 ) -> HttpResponse {
     let flow = Flow::InviteMultipleUser;
-    let is_token_only = token_only_query_param.into_inner().token_only;
     let auth_id = auth_id_query_param.into_inner().auth_id;
     Box::pin(api::server_wrap(
         flow,
@@ -456,14 +425,7 @@ pub async fn invite_multiple_user(
         &req,
         payload.into_inner(),
         |state, user, payload, req_state| {
-            user_core::invite_multiple_user(
-                state,
-                user,
-                payload,
-                req_state,
-                is_token_only,
-                auth_id.clone(),
-            )
+            user_core::invite_multiple_user(state, user, payload, req_state, auth_id.clone())
         },
         &auth::JWTAuth(Permission::UsersWrite),
         api_locking::LockAction::NotApplicable,
@@ -499,37 +461,20 @@ pub async fn accept_invite_from_email(
     state: web::Data<AppState>,
     req: HttpRequest,
     payload: web::Json<user_api::AcceptInviteFromEmailRequest>,
-    query: web::Query<user_api::TokenOnlyQueryParam>,
 ) -> HttpResponse {
     let flow = Flow::AcceptInviteFromEmail;
-    let is_token_only = query.into_inner().token_only;
-    if let Some(true) = is_token_only {
-        Box::pin(api::server_wrap(
-            flow.clone(),
-            state,
-            &req,
-            payload.into_inner(),
-            |state, user, req_payload, _| {
-                user_core::accept_invite_from_email_token_only_flow(state, user, req_payload)
-            },
-            &auth::SinglePurposeJWTAuth(TokenPurpose::AcceptInvitationFromEmail),
-            api_locking::LockAction::NotApplicable,
-        ))
-        .await
-    } else {
-        Box::pin(api::server_wrap(
-            flow,
-            state.clone(),
-            &req,
-            payload.into_inner(),
-            |state, _: (), request_payload, _| {
-                user_core::accept_invite_from_email(state, request_payload)
-            },
-            &auth::NoAuth,
-            api_locking::LockAction::NotApplicable,
-        ))
-        .await
-    }
+    Box::pin(api::server_wrap(
+        flow.clone(),
+        state,
+        &req,
+        payload.into_inner(),
+        |state, user, req_payload, _| {
+            user_core::accept_invite_from_email_token_only_flow(state, user, req_payload)
+        },
+        &auth::SinglePurposeJWTAuth(TokenPurpose::AcceptInvitationFromEmail),
+        api_locking::LockAction::NotApplicable,
+    ))
+    .await
 }
 
 #[cfg(feature = "email")]
@@ -537,35 +482,20 @@ pub async fn verify_email(
     state: web::Data<AppState>,
     http_req: HttpRequest,
     json_payload: web::Json<user_api::VerifyEmailRequest>,
-    query: web::Query<user_api::TokenOnlyQueryParam>,
 ) -> HttpResponse {
     let flow = Flow::VerifyEmail;
-    let is_token_only = query.into_inner().token_only;
-    if let Some(true) = is_token_only {
-        Box::pin(api::server_wrap(
-            flow.clone(),
-            state,
-            &http_req,
-            json_payload.into_inner(),
-            |state, user, req_payload, _| {
-                user_core::verify_email_token_only_flow(state, user, req_payload)
-            },
-            &auth::SinglePurposeJWTAuth(TokenPurpose::VerifyEmail),
-            api_locking::LockAction::NotApplicable,
-        ))
-        .await
-    } else {
-        Box::pin(api::server_wrap(
-            flow.clone(),
-            state,
-            &http_req,
-            json_payload.into_inner(),
-            |state, _: (), req_payload, _| user_core::verify_email(state, req_payload),
-            &auth::NoAuth,
-            api_locking::LockAction::NotApplicable,
-        ))
-        .await
-    }
+    Box::pin(api::server_wrap(
+        flow.clone(),
+        state,
+        &http_req,
+        json_payload.into_inner(),
+        |state, user, req_payload, _| {
+            user_core::verify_email_token_only_flow(state, user, req_payload)
+        },
+        &auth::SinglePurposeJWTAuth(TokenPurpose::VerifyEmail),
+        api_locking::LockAction::NotApplicable,
+    ))
+    .await
 }
 
 #[cfg(feature = "email")]
diff --git a/crates/router/src/routes/user_role.rs b/crates/router/src/routes/user_role.rs
index a730321e190..5f1e4301d45 100644
--- a/crates/router/src/routes/user_role.rs
+++ b/crates/router/src/routes/user_role.rs
@@ -1,8 +1,5 @@
 use actix_web::{web, HttpRequest, HttpResponse};
-use api_models::{
-    user as user_api,
-    user_role::{self as user_role_api, role as role_api},
-};
+use api_models::user_role::{self as user_role_api, role as role_api};
 use common_enums::TokenPurpose;
 use router_env::Flow;
 
@@ -22,22 +19,15 @@ use crate::{
 pub async fn get_authorization_info(
     state: web::Data<AppState>,
     http_req: HttpRequest,
-    query: web::Query<role_api::GetGroupsQueryParam>,
 ) -> HttpResponse {
     let flow = Flow::GetAuthorizationInfo;
-    let respond_with_groups = query.into_inner().groups.unwrap_or(false);
     Box::pin(api::server_wrap(
         flow,
         state.clone(),
         &http_req,
         (),
         |state, _: (), _, _| async move {
-            // TODO: Permissions to be deprecated once groups are stable
-            if respond_with_groups {
-                user_role_core::get_authorization_info_with_groups(state).await
-            } else {
-                user_role_core::get_authorization_info_with_modules(state).await
-            }
+            user_role_core::get_authorization_info_with_groups(state).await
         },
         &auth::JWTAuth(Permission::UsersRead),
         api_locking::LockAction::NotApplicable,
@@ -45,13 +35,8 @@ pub async fn get_authorization_info(
     .await
 }
 
-pub async fn get_role_from_token(
-    state: web::Data<AppState>,
-    req: HttpRequest,
-    query: web::Query<role_api::GetGroupsQueryParam>,
-) -> HttpResponse {
+pub async fn get_role_from_token(state: web::Data<AppState>, req: HttpRequest) -> HttpResponse {
     let flow = Flow::GetRoleFromToken;
-    let respond_with_groups = query.into_inner().groups.unwrap_or(false);
 
     Box::pin(api::server_wrap(
         flow,
@@ -59,12 +44,7 @@ pub async fn get_role_from_token(
         &req,
         (),
         |state, user, _, _| async move {
-            // TODO: Permissions to be deprecated once groups are stable
-            if respond_with_groups {
-                role_core::get_role_from_token_with_groups(state, user).await
-            } else {
-                role_core::get_role_from_token_with_permissions(state, user).await
-            }
+            role_core::get_role_from_token_with_groups(state, user).await
         },
         &auth::DashboardNoPermissionAuth,
         api_locking::LockAction::NotApplicable,
@@ -90,25 +70,15 @@ pub async fn create_role(
     .await
 }
 
-pub async fn list_all_roles(
-    state: web::Data<AppState>,
-    req: HttpRequest,
-    query: web::Query<role_api::GetGroupsQueryParam>,
-) -> HttpResponse {
+pub async fn list_all_roles(state: web::Data<AppState>, req: HttpRequest) -> HttpResponse {
     let flow = Flow::ListRoles;
-    let respond_with_groups = query.into_inner().groups.unwrap_or(false);
     Box::pin(api::server_wrap(
         flow,
         state.clone(),
         &req,
         (),
         |state, user, _, _| async move {
-            // TODO: Permissions to be deprecated once groups are stable
-            if respond_with_groups {
-                role_core::list_invitable_roles_with_groups(state, user).await
-            } else {
-                role_core::list_invitable_roles_with_permissions(state, user).await
-            }
+            role_core::list_invitable_roles_with_groups(state, user).await
         },
         &auth::JWTAuth(Permission::UsersRead),
         api_locking::LockAction::NotApplicable,
@@ -120,25 +90,18 @@ pub async fn get_role(
     state: web::Data<AppState>,
     req: HttpRequest,
     path: web::Path<String>,
-    query: web::Query<role_api::GetGroupsQueryParam>,
 ) -> HttpResponse {
     let flow = Flow::GetRole;
     let request_payload = user_role_api::role::GetRoleRequest {
         role_id: path.into_inner(),
     };
-    let respond_with_groups = query.into_inner().groups.unwrap_or(false);
     Box::pin(api::server_wrap(
         flow,
         state.clone(),
         &req,
         request_payload,
         |state, user, payload, _| async move {
-            // TODO: Permissions to be deprecated once groups are stable
-            if respond_with_groups {
-                role_core::get_role_with_groups(state, user, payload).await
-            } else {
-                role_core::get_role_with_permissions(state, user, payload).await
-            }
+            role_core::get_role_with_groups(state, user, payload).await
         },
         &auth::JWTAuth(Permission::UsersRead),
         api_locking::LockAction::NotApplicable,
@@ -209,22 +172,16 @@ pub async fn merchant_select(
     state: web::Data<AppState>,
     req: HttpRequest,
     json_payload: web::Json<user_role_api::MerchantSelectRequest>,
-    query: web::Query<user_api::TokenOnlyQueryParam>,
 ) -> HttpResponse {
     let flow = Flow::MerchantSelect;
     let payload = json_payload.into_inner();
-    let is_token_only = query.into_inner().token_only;
     Box::pin(api::server_wrap(
         flow,
         state.clone(),
         &req,
         payload,
         |state, user, req_body, _| async move {
-            if let Some(true) = is_token_only {
-                user_role_core::merchant_select_token_only_flow(state, user, req_body).await
-            } else {
-                user_role_core::merchant_select(state, user, req_body).await
-            }
+            user_role_core::merchant_select_token_only_flow(state, user, req_body).await
         },
         &auth::SinglePurposeJWTAuth(TokenPurpose::AcceptInvite),
         api_locking::LockAction::NotApplicable,
diff --git a/crates/router/src/services/authorization/predefined_permissions.rs b/crates/router/src/services/authorization/predefined_permissions.rs
deleted file mode 100644
index 50f9a7196b8..00000000000
--- a/crates/router/src/services/authorization/predefined_permissions.rs
+++ /dev/null
@@ -1,346 +0,0 @@
-use std::collections::HashMap;
-
-#[cfg(feature = "olap")]
-use error_stack::ResultExt;
-use once_cell::sync::Lazy;
-
-use super::permissions::Permission;
-use crate::consts;
-#[cfg(feature = "olap")]
-use crate::core::errors::{UserErrors, UserResult};
-
-#[allow(dead_code)]
-pub struct RoleInfo {
-    permissions: Vec<Permission>,
-    name: Option<&'static str>,
-    is_invitable: bool,
-    is_deletable: bool,
-    is_updatable: bool,
-}
-
-impl RoleInfo {
-    pub fn get_permissions(&self) -> &Vec<Permission> {
-        &self.permissions
-    }
-
-    pub fn get_name(&self) -> Option<&'static str> {
-        self.name
-    }
-
-    pub fn is_invitable(&self) -> bool {
-        self.is_invitable
-    }
-}
-
-pub static PREDEFINED_PERMISSIONS: Lazy<HashMap<&'static str, RoleInfo>> = Lazy::new(|| {
-    let mut roles = HashMap::new();
-    roles.insert(
-        consts::user_role::ROLE_ID_INTERNAL_ADMIN,
-        RoleInfo {
-            permissions: vec![
-                Permission::PaymentRead,
-                Permission::PaymentWrite,
-                Permission::RefundRead,
-                Permission::RefundWrite,
-                Permission::ApiKeyRead,
-                Permission::ApiKeyWrite,
-                Permission::MerchantAccountRead,
-                Permission::MerchantAccountWrite,
-                Permission::MerchantConnectorAccountRead,
-                Permission::MerchantConnectorAccountWrite,
-                Permission::RoutingRead,
-                Permission::RoutingWrite,
-                Permission::ThreeDsDecisionManagerWrite,
-                Permission::ThreeDsDecisionManagerRead,
-                Permission::SurchargeDecisionManagerWrite,
-                Permission::SurchargeDecisionManagerRead,
-                Permission::DisputeRead,
-                Permission::DisputeWrite,
-                Permission::MandateRead,
-                Permission::MandateWrite,
-                Permission::CustomerRead,
-                Permission::CustomerWrite,
-                Permission::Analytics,
-                Permission::UsersRead,
-                Permission::UsersWrite,
-                Permission::MerchantAccountCreate,
-                Permission::PayoutRead,
-                Permission::PayoutWrite,
-            ],
-            name: None,
-            is_invitable: false,
-            is_deletable: false,
-            is_updatable: false,
-        },
-    );
-    roles.insert(
-        consts::user_role::ROLE_ID_INTERNAL_VIEW_ONLY_USER,
-        RoleInfo {
-            permissions: vec![
-                Permission::PaymentRead,
-                Permission::RefundRead,
-                Permission::ApiKeyRead,
-                Permission::MerchantAccountRead,
-                Permission::MerchantConnectorAccountRead,
-                Permission::RoutingRead,
-                Permission::ThreeDsDecisionManagerRead,
-                Permission::SurchargeDecisionManagerRead,
-                Permission::Analytics,
-                Permission::DisputeRead,
-                Permission::MandateRead,
-                Permission::CustomerRead,
-                Permission::UsersRead,
-                Permission::PayoutRead,
-            ],
-            name: None,
-            is_invitable: false,
-            is_deletable: false,
-            is_updatable: false,
-        },
-    );
-
-    roles.insert(
-        consts::user_role::ROLE_ID_ORGANIZATION_ADMIN,
-        RoleInfo {
-            permissions: vec![
-                Permission::PaymentRead,
-                Permission::PaymentWrite,
-                Permission::RefundRead,
-                Permission::RefundWrite,
-                Permission::ApiKeyRead,
-                Permission::ApiKeyWrite,
-                Permission::MerchantAccountRead,
-                Permission::MerchantAccountWrite,
-                Permission::MerchantConnectorAccountRead,
-                Permission::MerchantConnectorAccountWrite,
-                Permission::RoutingRead,
-                Permission::RoutingWrite,
-                Permission::ThreeDsDecisionManagerWrite,
-                Permission::ThreeDsDecisionManagerRead,
-                Permission::SurchargeDecisionManagerWrite,
-                Permission::SurchargeDecisionManagerRead,
-                Permission::DisputeRead,
-                Permission::DisputeWrite,
-                Permission::MandateRead,
-                Permission::MandateWrite,
-                Permission::CustomerRead,
-                Permission::CustomerWrite,
-                Permission::Analytics,
-                Permission::UsersRead,
-                Permission::UsersWrite,
-                Permission::MerchantAccountCreate,
-                Permission::PayoutRead,
-                Permission::PayoutWrite,
-            ],
-            name: Some("Organization Admin"),
-            is_invitable: false,
-            is_deletable: false,
-            is_updatable: false,
-        },
-    );
-
-    // MERCHANT ROLES
-    roles.insert(
-        consts::user_role::ROLE_ID_MERCHANT_ADMIN,
-        RoleInfo {
-            permissions: vec![
-                Permission::PaymentRead,
-                Permission::PaymentWrite,
-                Permission::RefundRead,
-                Permission::RefundWrite,
-                Permission::ApiKeyRead,
-                Permission::ApiKeyWrite,
-                Permission::MerchantAccountRead,
-                Permission::MerchantAccountWrite,
-                Permission::MerchantConnectorAccountRead,
-                Permission::MerchantConnectorAccountWrite,
-                Permission::RoutingRead,
-                Permission::RoutingWrite,
-                Permission::ThreeDsDecisionManagerWrite,
-                Permission::ThreeDsDecisionManagerRead,
-                Permission::SurchargeDecisionManagerWrite,
-                Permission::SurchargeDecisionManagerRead,
-                Permission::DisputeRead,
-                Permission::DisputeWrite,
-                Permission::MandateRead,
-                Permission::MandateWrite,
-                Permission::CustomerRead,
-                Permission::CustomerWrite,
-                Permission::Analytics,
-                Permission::UsersRead,
-                Permission::UsersWrite,
-                Permission::PayoutRead,
-                Permission::PayoutWrite,
-            ],
-            name: Some("Admin"),
-            is_invitable: true,
-            is_deletable: true,
-            is_updatable: true,
-        },
-    );
-    roles.insert(
-        consts::user_role::ROLE_ID_MERCHANT_VIEW_ONLY,
-        RoleInfo {
-            permissions: vec![
-                Permission::PaymentRead,
-                Permission::RefundRead,
-                Permission::ApiKeyRead,
-                Permission::MerchantAccountRead,
-                Permission::MerchantConnectorAccountRead,
-                Permission::RoutingRead,
-                Permission::ThreeDsDecisionManagerRead,
-                Permission::SurchargeDecisionManagerRead,
-                Permission::DisputeRead,
-                Permission::MandateRead,
-                Permission::CustomerRead,
-                Permission::Analytics,
-                Permission::UsersRead,
-                Permission::PayoutRead,
-            ],
-            name: Some("View Only"),
-            is_invitable: true,
-            is_deletable: true,
-            is_updatable: true,
-        },
-    );
-    roles.insert(
-        consts::user_role::ROLE_ID_MERCHANT_IAM_ADMIN,
-        RoleInfo {
-            permissions: vec![
-                Permission::PaymentRead,
-                Permission::RefundRead,
-                Permission::ApiKeyRead,
-                Permission::MerchantAccountRead,
-                Permission::MerchantConnectorAccountRead,
-                Permission::RoutingRead,
-                Permission::ThreeDsDecisionManagerRead,
-                Permission::SurchargeDecisionManagerRead,
-                Permission::DisputeRead,
-                Permission::MandateRead,
-                Permission::CustomerRead,
-                Permission::Analytics,
-                Permission::UsersRead,
-                Permission::UsersWrite,
-                Permission::PayoutRead,
-            ],
-            name: Some("IAM"),
-            is_invitable: true,
-            is_deletable: true,
-            is_updatable: true,
-        },
-    );
-    roles.insert(
-        consts::user_role::ROLE_ID_MERCHANT_DEVELOPER,
-        RoleInfo {
-            permissions: vec![
-                Permission::PaymentRead,
-                Permission::RefundRead,
-                Permission::ApiKeyRead,
-                Permission::ApiKeyWrite,
-                Permission::MerchantAccountRead,
-                Permission::MerchantConnectorAccountRead,
-                Permission::RoutingRead,
-                Permission::ThreeDsDecisionManagerRead,
-                Permission::SurchargeDecisionManagerRead,
-                Permission::DisputeRead,
-                Permission::MandateRead,
-                Permission::CustomerRead,
-                Permission::Analytics,
-                Permission::UsersRead,
-                Permission::PayoutRead,
-            ],
-            name: Some("Developer"),
-            is_invitable: true,
-            is_deletable: true,
-            is_updatable: true,
-        },
-    );
-    roles.insert(
-        consts::user_role::ROLE_ID_MERCHANT_OPERATOR,
-        RoleInfo {
-            permissions: vec![
-                Permission::PaymentRead,
-                Permission::PaymentWrite,
-                Permission::RefundRead,
-                Permission::RefundWrite,
-                Permission::ApiKeyRead,
-                Permission::MerchantAccountRead,
-                Permission::MerchantConnectorAccountRead,
-                Permission::MerchantConnectorAccountWrite,
-                Permission::RoutingRead,
-                Permission::RoutingWrite,
-                Permission::ThreeDsDecisionManagerRead,
-                Permission::ThreeDsDecisionManagerWrite,
-                Permission::SurchargeDecisionManagerRead,
-                Permission::SurchargeDecisionManagerWrite,
-                Permission::DisputeRead,
-                Permission::MandateRead,
-                Permission::CustomerRead,
-                Permission::Analytics,
-                Permission::UsersRead,
-                Permission::PayoutRead,
-                Permission::PayoutWrite,
-            ],
-            name: Some("Operator"),
-            is_invitable: true,
-            is_deletable: true,
-            is_updatable: true,
-        },
-    );
-    roles.insert(
-        consts::user_role::ROLE_ID_MERCHANT_CUSTOMER_SUPPORT,
-        RoleInfo {
-            permissions: vec![
-                Permission::PaymentRead,
-                Permission::RefundRead,
-                Permission::RefundWrite,
-                Permission::DisputeRead,
-                Permission::DisputeWrite,
-                Permission::MerchantAccountRead,
-                Permission::MerchantConnectorAccountRead,
-                Permission::MandateRead,
-                Permission::CustomerRead,
-                Permission::Analytics,
-                Permission::PayoutRead,
-            ],
-            name: Some("Customer Support"),
-            is_invitable: true,
-            is_deletable: true,
-            is_updatable: true,
-        },
-    );
-    roles
-});
-
-pub fn get_role_name_from_id(role_id: &str) -> Option<&'static str> {
-    PREDEFINED_PERMISSIONS
-        .get(role_id)
-        .and_then(|role_info| role_info.name)
-}
-
-#[cfg(feature = "olap")]
-pub fn is_role_invitable(role_id: &str) -> UserResult<bool> {
-    PREDEFINED_PERMISSIONS
-        .get(role_id)
-        .map(|role_info| role_info.is_invitable)
-        .ok_or(UserErrors::InvalidRoleId.into())
-        .attach_printable(format!("role_id = {} doesn't exist", role_id))
-}
-
-#[cfg(feature = "olap")]
-pub fn is_role_deletable(role_id: &str) -> UserResult<bool> {
-    PREDEFINED_PERMISSIONS
-        .get(role_id)
-        .map(|role_info| role_info.is_deletable)
-        .ok_or(UserErrors::InvalidRoleId.into())
-        .attach_printable(format!("role_id = {} doesn't exist", role_id))
-}
-
-#[cfg(feature = "olap")]
-pub fn is_role_updatable(role_id: &str) -> UserResult<bool> {
-    PREDEFINED_PERMISSIONS
-        .get(role_id)
-        .map(|role_info| role_info.is_updatable)
-        .ok_or(UserErrors::InvalidRoleId.into())
-        .attach_printable(format!("role_id = {} doesn't exist", role_id))
-}
diff --git a/crates/router/src/types/domain/user.rs b/crates/router/src/types/domain/user.rs
index 42cb71458d5..58a0a68df51 100644
--- a/crates/router/src/types/domain/user.rs
+++ b/crates/router/src/types/domain/user.rs
@@ -3,7 +3,7 @@ use std::{collections::HashSet, ops, str::FromStr};
 use api_models::{
     admin as admin_api, organization as api_org, user as user_api, user_role as user_role_api,
 };
-use common_enums::{EntityType, TokenPurpose};
+use common_enums::EntityType;
 use common_utils::{
     crypto::Encryptable, errors::CustomResult, id_type, new_type::MerchantName, pii, type_name,
     types::keymanager::Identifier,
@@ -32,13 +32,9 @@ use crate::{
     },
     db::{user_role::InsertUserRolePayload, GlobalStorageInterface},
     routes::SessionState,
-    services::{
-        self,
-        authentication::{self as auth, UserFromToken},
-        authorization::info,
-    },
+    services::{self, authentication::UserFromToken, authorization::info},
     types::transformers::ForeignFrom,
-    utils::{self, user::password},
+    utils::user::password,
 };
 
 pub mod dashboard_metadata;
@@ -1115,130 +1111,6 @@ impl From<info::PermissionModule> for user_role_api::PermissionModule {
     }
 }
 
-pub enum SignInWithRoleStrategyType {
-    SingleRole(SignInWithSingleRoleStrategy),
-    MultipleRoles(SignInWithMultipleRolesStrategy),
-}
-
-impl SignInWithRoleStrategyType {
-    pub async fn decide_signin_strategy_by_user_roles(
-        user: UserFromStorage,
-        user_roles: Vec<UserRole>,
-    ) -> UserResult<Self> {
-        if user_roles.is_empty() {
-            return Err(UserErrors::InternalServerError.into());
-        }
-
-        if let Some(user_role) = user_roles
-            .iter()
-            .find(|role| role.status == UserStatus::Active)
-        {
-            Ok(Self::SingleRole(SignInWithSingleRoleStrategy {
-                user,
-                user_role: Box::new(user_role.clone()),
-            }))
-        } else {
-            Ok(Self::MultipleRoles(SignInWithMultipleRolesStrategy {
-                user,
-                user_roles,
-            }))
-        }
-    }
-
-    pub async fn get_signin_response(
-        self,
-        state: &SessionState,
-    ) -> UserResult<user_api::SignInResponse> {
-        match self {
-            Self::SingleRole(strategy) => strategy.get_signin_response(state).await,
-            Self::MultipleRoles(strategy) => strategy.get_signin_response(state).await,
-        }
-    }
-}
-
-pub struct SignInWithSingleRoleStrategy {
-    pub user: UserFromStorage,
-    pub user_role: Box<UserRole>,
-}
-
-impl SignInWithSingleRoleStrategy {
-    async fn get_signin_response(
-        self,
-        state: &SessionState,
-    ) -> UserResult<user_api::SignInResponse> {
-        let token = utils::user::generate_jwt_auth_token_without_profile(
-            state,
-            &self.user,
-            &self.user_role,
-        )
-        .await?;
-        utils::user_role::set_role_permissions_in_cache_by_user_role(state, &self.user_role).await;
-
-        let dashboard_entry_response =
-            utils::user::get_dashboard_entry_response(state, self.user, *self.user_role, token)?;
-
-        Ok(user_api::SignInResponse::DashboardEntry(
-            dashboard_entry_response,
-        ))
-    }
-}
-
-pub struct SignInWithMultipleRolesStrategy {
-    pub user: UserFromStorage,
-    pub user_roles: Vec<UserRole>,
-}
-
-impl SignInWithMultipleRolesStrategy {
-    async fn get_signin_response(
-        self,
-        state: &SessionState,
-    ) -> UserResult<user_api::SignInResponse> {
-        let merchant_accounts = state
-            .store
-            .list_multiple_merchant_accounts(
-                &state.into(),
-                self.user_roles
-                    .iter()
-                    .map(|role| {
-                        role.merchant_id
-                            .clone()
-                            .ok_or(UserErrors::InternalServerError)
-                    })
-                    .collect::<Result<Vec<_>, _>>()?,
-            )
-            .await
-            .change_context(UserErrors::InternalServerError)?;
-
-        let roles =
-            utils::user_role::get_multiple_role_info_for_user_roles(state, &self.user_roles)
-                .await?;
-
-        let merchant_details = utils::user::get_multiple_merchant_details_with_status(
-            self.user_roles,
-            merchant_accounts,
-            roles,
-        )?;
-
-        Ok(user_api::SignInResponse::MerchantSelect(
-            user_api::MerchantSelectResponse {
-                name: self.user.get_name(),
-                email: self.user.get_email(),
-                token: auth::SinglePurposeToken::new_token(
-                    self.user.get_user_id().to_string(),
-                    TokenPurpose::AcceptInvite,
-                    Origin::SignIn,
-                    &state.conf,
-                    vec![],
-                )
-                .await?
-                .into(),
-                merchants: merchant_details,
-                verification_days_left: utils::user::get_verification_days_left(state, &self.user)?,
-            },
-        ))
-    }
-}
-
 impl ForeignFrom<UserStatus> for user_role_api::UserStatus {
     fn foreign_from(value: UserStatus) -> Self {
         match value {
diff --git a/crates/router/src/types/domain/user/decision_manager.rs b/crates/router/src/types/domain/user/decision_manager.rs
index 92f1d4ba5ba..4206b16df6d 100644
--- a/crates/router/src/types/domain/user/decision_manager.rs
+++ b/crates/router/src/types/domain/user/decision_manager.rs
@@ -1,6 +1,6 @@
 use common_enums::TokenPurpose;
 use diesel_models::{enums::UserStatus, user_role::UserRole};
-use error_stack::report;
+use error_stack::{report, ResultExt};
 use masking::Secret;
 
 use super::UserFromStorage;
@@ -109,16 +109,14 @@ impl JWTFlow {
     ) -> UserResult<Secret<String>> {
         auth::AuthToken::new_token(
             next_flow.user.get_user_id().to_string(),
-            user_role
-                .merchant_id
-                .clone()
-                .ok_or(report!(UserErrors::InternalServerError))?,
+            utils::user_role::get_single_merchant_id(state, user_role).await?,
             user_role.role_id.clone(),
             &state.conf,
             user_role
                 .org_id
                 .clone()
-                .ok_or(report!(UserErrors::InternalServerError))?,
+                .ok_or(report!(UserErrors::InternalServerError))
+                .attach_printable("org_id not found")?,
             None,
         )
         .await
diff --git a/crates/router/src/utils/user.rs b/crates/router/src/utils/user.rs
index b2170e7294a..a1bd6972dab 100644
--- a/crates/router/src/utils/user.rs
+++ b/crates/router/src/utils/user.rs
@@ -1,11 +1,11 @@
-use std::{collections::HashMap, sync::Arc};
+use std::sync::Arc;
 
 use api_models::user as user_api;
 use common_enums::UserAuthType;
 use common_utils::{
     encryption::Encryption, errors::CustomResult, id_type, type_name, types::keymanager::Identifier,
 };
-use diesel_models::{enums::UserStatus, user_role::UserRole};
+use diesel_models::user_role::UserRole;
 use error_stack::{report, ResultExt};
 use masking::{ExposeInterface, Secret};
 use redis_interface::RedisConnectionPool;
@@ -128,28 +128,6 @@ pub async fn generate_jwt_auth_token_with_attributes(
     Ok(Secret::new(token))
 }
 
-pub fn get_dashboard_entry_response(
-    state: &SessionState,
-    user: UserFromStorage,
-    user_role: UserRole,
-    token: Secret<String>,
-) -> UserResult<user_api::DashboardEntryResponse> {
-    let verification_days_left = get_verification_days_left(state, &user)?;
-
-    Ok(user_api::DashboardEntryResponse {
-        merchant_id: user_role.merchant_id.ok_or(
-            report!(UserErrors::InternalServerError)
-                .attach_printable("merchant_id not found for user_role"),
-        )?,
-        token,
-        name: user.get_name(),
-        email: user.get_email(),
-        user_id: user.get_user_id().to_string(),
-        verification_days_left,
-        user_role: user_role.role_id,
-    })
-}
-
 #[allow(unused_variables)]
 pub fn get_verification_days_left(
     state: &SessionState,
@@ -161,54 +139,6 @@ pub fn get_verification_days_left(
     return Ok(None);
 }
 
-pub fn get_multiple_merchant_details_with_status(
-    user_roles: Vec<UserRole>,
-    merchant_accounts: Vec<MerchantAccount>,
-    roles: Vec<RoleInfo>,
-) -> UserResult<Vec<user_api::UserMerchantAccount>> {
-    let merchant_account_map = merchant_accounts
-        .into_iter()
-        .map(|merchant_account| (merchant_account.get_id().clone(), merchant_account))
-        .collect::<HashMap<_, _>>();
-
-    let role_map = roles
-        .into_iter()
-        .map(|role_info| (role_info.get_role_id().to_string(), role_info))
-        .collect::<HashMap<_, _>>();
-
-    user_roles
-        .into_iter()
-        .map(|user_role| {
-            let Some(merchant_id) = &user_role.merchant_id else {
-                return Err(report!(UserErrors::InternalServerError))
-                    .attach_printable("merchant_id not found for user_role");
-            };
-            let Some(org_id) = &user_role.org_id else {
-                return Err(report!(UserErrors::InternalServerError)
-                    .attach_printable("org_id not found in user_role"));
-            };
-            let merchant_account = merchant_account_map
-                .get(merchant_id)
-                .ok_or(UserErrors::InternalServerError)
-                .attach_printable("Merchant account for user role doesn't exist")?;
-
-            let role_info = role_map
-                .get(&user_role.role_id)
-                .ok_or(UserErrors::InternalServerError)
-                .attach_printable("Role info for user role doesn't exist")?;
-
-            Ok(user_api::UserMerchantAccount {
-                merchant_id: merchant_id.to_owned(),
-                merchant_name: merchant_account.merchant_name.clone(),
-                is_active: user_role.status == UserStatus::Active,
-                role_id: user_role.role_id,
-                role_name: role_info.get_role_name().to_string(),
-                org_id: org_id.to_owned(),
-            })
-        })
-        .collect()
-}
-
 pub async fn get_user_from_db_by_email(
     state: &SessionState,
     email: domain::UserEmail,
@@ -220,13 +150,6 @@ pub async fn get_user_from_db_by_email(
         .map(UserFromStorage::from)
 }
 
-pub fn get_token_from_signin_response(resp: &user_api::SignInResponse) -> Secret<String> {
-    match resp {
-        user_api::SignInResponse::DashboardEntry(data) => data.token.clone(),
-        user_api::SignInResponse::MerchantSelect(data) => data.token.clone(),
-    }
-}
-
 pub fn get_redis_connection(state: &SessionState) -> UserResult<Arc<RedisConnectionPool>> {
     state
         .store
diff --git a/crates/router/src/utils/user_role.rs b/crates/router/src/utils/user_role.rs
index 1791b5308b4..dbe3ed6d585 100644
--- a/crates/router/src/utils/user_role.rs
+++ b/crates/router/src/utils/user_role.rs
@@ -1,7 +1,7 @@
 use std::collections::HashSet;
 
 use api_models::user_role as user_role_api;
-use common_enums::PermissionGroup;
+use common_enums::{EntityType, PermissionGroup};
 use common_utils::id_type;
 use diesel_models::{
     enums::UserRoleVersion,
@@ -13,7 +13,7 @@ use storage_impl::errors::StorageError;
 
 use crate::{
     consts,
-    core::errors::{StorageErrorExt, UserErrors, UserResult},
+    core::errors::{UserErrors, UserResult},
     routes::SessionState,
     services::authorization::{self as authz, permissions::Permission, roles},
     types::domain,
@@ -167,28 +167,6 @@ pub async fn set_role_permissions_in_cache_if_required(
     .attach_printable("Error setting permissions in redis")
 }
 
-pub async fn get_multiple_role_info_for_user_roles(
-    state: &SessionState,
-    user_roles: &[UserRole],
-) -> UserResult<Vec<roles::RoleInfo>> {
-    futures::future::try_join_all(user_roles.iter().map(|user_role| async {
-        let Some(merchant_id) = &user_role.merchant_id else {
-            return Err(report!(UserErrors::InternalServerError))
-                .attach_printable("merchant_id not found for user_role");
-        };
-        let Some(org_id) = &user_role.org_id else {
-            return Err(report!(UserErrors::InternalServerError)
-                .attach_printable("org_id not found in user_role"));
-        };
-        let role = roles::RoleInfo::from_role_id(state, &user_role.role_id, merchant_id, org_id)
-            .await
-            .to_not_found_response(UserErrors::InternalServerError)
-            .attach_printable("Role for user role doesn't exist")?;
-        Ok::<_, Report<UserErrors>>(role)
-    }))
-    .await
-}
-
 pub async fn update_v1_and_v2_user_roles_in_db(
     state: &SessionState,
     user_id: &str,
@@ -234,3 +212,38 @@ pub async fn update_v1_and_v2_user_roles_in_db(
 
     (updated_v1_role, updated_v2_role)
 }
+
+pub async fn get_single_merchant_id(
+    state: &SessionState,
+    user_role: &UserRole,
+) -> UserResult<id_type::MerchantId> {
+    match user_role.entity_type {
+        Some(EntityType::Organization) => Ok(state
+            .store
+            .list_merchant_accounts_by_organization_id(
+                &state.into(),
+                user_role
+                    .org_id
+                    .as_ref()
+                    .ok_or(UserErrors::InternalServerError)
+                    .attach_printable("org_id not found")?
+                    .get_string_repr(),
+            )
+            .await
+            .change_context(UserErrors::InternalServerError)
+            .attach_printable("Failed to get merchant list for org")?
+            .first()
+            .ok_or(UserErrors::InternalServerError)
+            .attach_printable("No merchants found for org_id")?
+            .get_id()
+            .clone()),
+        Some(EntityType::Merchant)
+        | Some(EntityType::Internal)
+        | Some(EntityType::Profile)
+        | None => user_role
+            .merchant_id
+            .clone()
+            .ok_or(UserErrors::InternalServerError)
+            .attach_printable("merchant_id not found"),
+    }
+}
diff --git a/postman/collection-dir/users/Flow Testcases/Sign In/.meta.json b/postman/collection-dir/users/Flow Testcases/Sign In/.meta.json
index 84ed2cb9494..75badf2502c 100644
--- a/postman/collection-dir/users/Flow Testcases/Sign In/.meta.json	
+++ b/postman/collection-dir/users/Flow Testcases/Sign In/.meta.json	
@@ -2,7 +2,7 @@
   "childrenOrder": [
     "Signin",
     "Signin Wrong",
-    "Signin Token Only",
-    "Signin Token Only Wrong"
+    "Signin V2 - To be deprecated",
+    "Signin V2 Wrong"
   ]
 }
diff --git a/postman/collection-dir/users/Flow Testcases/Sign In/Signin Token Only Wrong/.event.meta.json b/postman/collection-dir/users/Flow Testcases/Sign In/Signin V2 - To be deprecated/.event.meta.json
similarity index 100%
rename from postman/collection-dir/users/Flow Testcases/Sign In/Signin Token Only Wrong/.event.meta.json
rename to postman/collection-dir/users/Flow Testcases/Sign In/Signin V2 - To be deprecated/.event.meta.json
diff --git a/postman/collection-dir/users/Flow Testcases/Sign In/Signin Token Only/event.test.js b/postman/collection-dir/users/Flow Testcases/Sign In/Signin V2 - To be deprecated/event.test.js
similarity index 61%
rename from postman/collection-dir/users/Flow Testcases/Sign In/Signin Token Only/event.test.js
rename to postman/collection-dir/users/Flow Testcases/Sign In/Signin V2 - To be deprecated/event.test.js
index 9105ce122cb..c8d654d21e9 100644
--- a/postman/collection-dir/users/Flow Testcases/Sign In/Signin Token Only/event.test.js	
+++ b/postman/collection-dir/users/Flow Testcases/Sign In/Signin V2 - To be deprecated/event.test.js	
@@ -1,24 +1,24 @@
 console.log("[LOG]::x-request-id - " + pm.response.headers.get("x-request-id"));
 
 // Validate status 2xx
-pm.test("[POST]::user/v2/signin?token_only=true - Status code is 2xx", function () {
+pm.test("[POST]::user/v2/signin - Status code is 2xx", function () {
   pm.response.to.be.success;
 });
 
 // Validate if response header has matching content-type
-pm.test("[POST]::user/v2/signin?token_only=true - Content-Type is application/json", function () {
+pm.test("[POST]::user/v2/signin - Content-Type is application/json", function () {
   pm.expect(pm.response.headers.get("Content-Type")).to.include(
     "application/json",
   );
 });
 
 // Validate if response has JSON Body
-pm.test("[POST]::user/v2/signin?token_only=true - Response has JSON Body", function () {
+pm.test("[POST]::user/v2/signin - Response has JSON Body", function () {
   pm.response.to.have.jsonBody();
 });
 
 // Validate specific JSON response content
-pm.test("[POST]::user/v2/signin?token_only=true - Response contains token", function () {
+pm.test("[POST]::user/v2/signin - Response contains token", function () {
   var jsonData = pm.response.json();
   pm.expect(jsonData).to.have.property("token");
   pm.expect(jsonData.token).to.be.a("string").and.to.not.be.empty;
diff --git a/postman/collection-dir/users/Flow Testcases/Sign In/Signin Token Only/request.json b/postman/collection-dir/users/Flow Testcases/Sign In/Signin V2 - To be deprecated/request.json
similarity index 75%
rename from postman/collection-dir/users/Flow Testcases/Sign In/Signin Token Only/request.json
rename to postman/collection-dir/users/Flow Testcases/Sign In/Signin V2 - To be deprecated/request.json
index 62028501a50..1d23f6e9652 100644
--- a/postman/collection-dir/users/Flow Testcases/Sign In/Signin Token Only/request.json	
+++ b/postman/collection-dir/users/Flow Testcases/Sign In/Signin V2 - To be deprecated/request.json	
@@ -18,7 +18,7 @@
     }
   },
   "url": {
-    "raw": "{{baseUrl}}/user/v2/signin?token_only=true",
+    "raw": "{{baseUrl}}/user/v2/signin",
     "host": [
       "{{baseUrl}}"
     ],
@@ -26,12 +26,6 @@
       "user",
       "v2",
       "signin"
-    ],
-    "query": [
-      {
-        "key": "token_only",
-        "value": "true"
-      }
     ]
   }
 }
diff --git a/postman/collection-dir/users/Flow Testcases/Sign In/Signin Token Only Wrong/response.json b/postman/collection-dir/users/Flow Testcases/Sign In/Signin V2 - To be deprecated/response.json
similarity index 100%
rename from postman/collection-dir/users/Flow Testcases/Sign In/Signin Token Only Wrong/response.json
rename to postman/collection-dir/users/Flow Testcases/Sign In/Signin V2 - To be deprecated/response.json
diff --git a/postman/collection-dir/users/Flow Testcases/Sign In/Signin Token Only/.event.meta.json b/postman/collection-dir/users/Flow Testcases/Sign In/Signin V2 Wrong/.event.meta.json
similarity index 100%
rename from postman/collection-dir/users/Flow Testcases/Sign In/Signin Token Only/.event.meta.json
rename to postman/collection-dir/users/Flow Testcases/Sign In/Signin V2 Wrong/.event.meta.json
diff --git a/postman/collection-dir/users/Flow Testcases/Sign In/Signin Token Only Wrong/event.test.js b/postman/collection-dir/users/Flow Testcases/Sign In/Signin V2 Wrong/event.test.js
similarity index 57%
rename from postman/collection-dir/users/Flow Testcases/Sign In/Signin Token Only Wrong/event.test.js
rename to postman/collection-dir/users/Flow Testcases/Sign In/Signin V2 Wrong/event.test.js
index a9297538452..3cc82ebb013 100644
--- a/postman/collection-dir/users/Flow Testcases/Sign In/Signin Token Only Wrong/event.test.js	
+++ b/postman/collection-dir/users/Flow Testcases/Sign In/Signin V2 Wrong/event.test.js	
@@ -1,18 +1,18 @@
 console.log("[LOG]::x-request-id - " + pm.response.headers.get("x-request-id"));
 
 // Validate status 4xx
-pm.test("[POST]::/user/v2/signin?token_only=true - Status code is 401", function () {
+pm.test("[POST]::/user/v2/signin - Status code is 401", function () {
   pm.response.to.have.status(401);
 });
 
 // Validate if response header has matching content-type
-pm.test("[POST]::user/v2/signin?token_only=true - Content-Type is application/json", function () {
+pm.test("[POST]::user/v2/signin - Content-Type is application/json", function () {
   pm.expect(pm.response.headers.get("Content-Type")).to.include(
     "application/json",
   );
 });
 
 // Validate if response has JSON Body
-pm.test("[POST]::user/v2/signin?token_only=true - Response has JSON Body", function () {
+pm.test("[POST]::user/v2/signin - Response has JSON Body", function () {
   pm.response.to.have.jsonBody();
 });
\ No newline at end of file
diff --git a/postman/collection-dir/users/Flow Testcases/Sign In/Signin Token Only Wrong/request.json b/postman/collection-dir/users/Flow Testcases/Sign In/Signin V2 Wrong/request.json
similarity index 75%
rename from postman/collection-dir/users/Flow Testcases/Sign In/Signin Token Only Wrong/request.json
rename to postman/collection-dir/users/Flow Testcases/Sign In/Signin V2 Wrong/request.json
index 7fee4c465c8..775b0972d57 100644
--- a/postman/collection-dir/users/Flow Testcases/Sign In/Signin Token Only Wrong/request.json	
+++ b/postman/collection-dir/users/Flow Testcases/Sign In/Signin V2 Wrong/request.json	
@@ -18,7 +18,7 @@
     }
   },
   "url": {
-    "raw": "{{baseUrl}}/user/v2/signin?token_only=true",
+    "raw": "{{baseUrl}}/user/v2/signin",
     "host": [
       "{{baseUrl}}"
     ],
@@ -26,12 +26,6 @@
       "user",
       "v2",
       "signin"
-    ],
-    "query": [
-      {
-        "key": "token_only",
-        "value": "true"
-      }
     ]
   }
 }
diff --git a/postman/collection-dir/users/Flow Testcases/Sign In/Signin Token Only/response.json b/postman/collection-dir/users/Flow Testcases/Sign In/Signin V2 Wrong/response.json
similarity index 100%
rename from postman/collection-dir/users/Flow Testcases/Sign In/Signin Token Only/response.json
rename to postman/collection-dir/users/Flow Testcases/Sign In/Signin V2 Wrong/response.json
diff --git a/postman/collection-dir/users/Flow Testcases/Sign In/Signin Wrong/event.test.js b/postman/collection-dir/users/Flow Testcases/Sign In/Signin Wrong/event.test.js
index 6cb6b69ba6c..bd346bc0cb3 100644
--- a/postman/collection-dir/users/Flow Testcases/Sign In/Signin Wrong/event.test.js	
+++ b/postman/collection-dir/users/Flow Testcases/Sign In/Signin Wrong/event.test.js	
@@ -1,18 +1,18 @@
 console.log("[LOG]::x-request-id - " + pm.response.headers.get("x-request-id"));
 
 // Validate status code is 4xx Bad Request
-pm.test("[POST]::/user/v2/signin - Status code is 401", function () {
+pm.test("[POST]::/user/signin - Status code is 401", function () {
   pm.response.to.have.status(401);
 });
 
 // Validate if response header has matching content-type
-pm.test("[POST]::/user/v2/signin - Content-Type is application/json", function () {
+pm.test("[POST]::/user/signin - Content-Type is application/json", function () {
   pm.expect(pm.response.headers.get("Content-Type")).to.include(
     "application/json",
   );
 });
 
 // Validate if response has JSON Body
-pm.test("[POST]::/user/v2/signin - Response has JSON Body", function () {
+pm.test("[POST]::/user/signin - Response has JSON Body", function () {
   pm.response.to.have.jsonBody();
 });
\ No newline at end of file
diff --git a/postman/collection-dir/users/Flow Testcases/Sign In/Signin Wrong/request.json b/postman/collection-dir/users/Flow Testcases/Sign In/Signin Wrong/request.json
index 775b0972d57..0cd97ee6de1 100644
--- a/postman/collection-dir/users/Flow Testcases/Sign In/Signin Wrong/request.json	
+++ b/postman/collection-dir/users/Flow Testcases/Sign In/Signin Wrong/request.json	
@@ -18,13 +18,12 @@
     }
   },
   "url": {
-    "raw": "{{baseUrl}}/user/v2/signin",
+    "raw": "{{baseUrl}}/user/signin",
     "host": [
       "{{baseUrl}}"
     ],
     "path": [
       "user",
-      "v2",
       "signin"
     ]
   }
diff --git a/postman/collection-dir/users/Flow Testcases/Sign In/Signin/event.test.js b/postman/collection-dir/users/Flow Testcases/Sign In/Signin/event.test.js
index 4724ff5981f..23dc84eb8a9 100644
--- a/postman/collection-dir/users/Flow Testcases/Sign In/Signin/event.test.js	
+++ b/postman/collection-dir/users/Flow Testcases/Sign In/Signin/event.test.js	
@@ -1,24 +1,24 @@
 console.log("[LOG]::x-request-id - " + pm.response.headers.get("x-request-id"));
 
 // Validate status 2xx
-pm.test("[POST]::/user/v2/signin - Status code is 2xx", function () {
+pm.test("[POST]::/user/signin - Status code is 2xx", function () {
   pm.response.to.be.success;
 });
 
 // Validate if response header has matching content-type
-pm.test("[POST]::/user/v2/signin - Content-Type is application/json", function () {
+pm.test("[POST]::/user/signin - Content-Type is application/json", function () {
   pm.expect(pm.response.headers.get("Content-Type")).to.include(
     "application/json",
   );
 });
 
 // Validate if response has JSON Body
-pm.test("[POST]::/user/v2/signin - Response has JSON Body", function () {
+pm.test("[POST]::/user/signin - Response has JSON Body", function () {
   pm.response.to.have.jsonBody();
 });
 
 // Validate specific JSON response content
-pm.test("[POST]::/user/v2/signin - Response contains token", function () {
+pm.test("[POST]::/user/signin - Response contains token", function () {
   var jsonData = pm.response.json();
   pm.expect(jsonData).to.have.property("token");
   pm.expect(jsonData.token).to.be.a("string").and.to.not.be.empty;
diff --git a/postman/collection-dir/users/Flow Testcases/Sign In/Signin/request.json b/postman/collection-dir/users/Flow Testcases/Sign In/Signin/request.json
index 1d23f6e9652..17f0eccff36 100644
--- a/postman/collection-dir/users/Flow Testcases/Sign In/Signin/request.json	
+++ b/postman/collection-dir/users/Flow Testcases/Sign In/Signin/request.json	
@@ -18,13 +18,12 @@
     }
   },
   "url": {
-    "raw": "{{baseUrl}}/user/v2/signin",
+    "raw": "{{baseUrl}}/user/signin",
     "host": [
       "{{baseUrl}}"
     ],
     "path": [
       "user",
-      "v2",
       "signin"
     ]
   }
diff --git a/postman/collection-json/users.postman_collection.json b/postman/collection-json/users.postman_collection.json
index 142eaf3b232..ac6ee2f8cb0 100644
--- a/postman/collection-json/users.postman_collection.json
+++ b/postman/collection-json/users.postman_collection.json
@@ -1,567 +1,553 @@
 {
-  "event": [
-    {
-      "listen": "prerequest",
-      "script": {
-        "exec": [
-          ""
-        ],
-        "type": "text/javascript"
-      }
-    },
-    {
-      "listen": "test",
-      "script": {
-        "exec": [
-          ""
-        ],
-        "type": "text/javascript"
-      }
-    }
-  ],
-  "item": [
-    {
-      "name": "Health check",
-      "item": [
-        {
-          "name": "New Request",
-          "event": [
-            {
-              "listen": "test",
-              "script": {
-                "exec": [
-                  "// Validate status 2xx",
-                  "pm.test(\"[POST]::/health - Status code is 2xx\", function () {",
-                  "  pm.response.to.be.success;",
-                  "});",
-                  ""
-                ],
-                "type": "text/javascript"
-              }
-            }
-          ],
-          "request": {
-            "method": "GET",
-            "header": [],
-            "url": {
-              "raw": "{{baseUrl}}/health",
-              "host": [
-                "{{baseUrl}}"
-              ],
-              "path": [
-                "health"
-              ]
-            }
-          },
-          "response": []
-        }
-      ]
-    },
-    {
-      "name": "Flow Testcases",
-      "item": [
-        {
-          "name": "Sign Up",
-          "item": [
-            {
-              "name": "Connect Account",
-              "event": [
-                {
-                  "listen": "test",
-                  "script": {
-                    "exec": [
-                      "console.log(\"[LOG]::x-request-id - \" + pm.response.headers.get(\"x-request-id\"));",
-                      "",
-                      "// Validate status 2xx",
-                      "pm.test(\"[POST]::/user/connect_account - Status code is 2xx\", function () {",
-                      "  pm.response.to.be.success;",
-                      "});",
-                      "",
-                      "// Validate if response header has matching content-type",
-                      "pm.test(\"[POST]::/user/connect_account - Content-Type is application/json\", function () {",
-                      "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
-                      "    \"application/json\",",
-                      "  );",
-                      "});",
-                      "",
-                      "// Validate if response has JSON Body",
-                      "pm.test(\"[POST]::/user/connect_account - Response has JSON Body\", function () {",
-                      "  pm.response.to.have.jsonBody();",
-                      "});",
-                      "",
-                      "// Validate specific JSON response content",
-                      "pm.test(\"[POST]::/user/connect_account - Response contains is_email_sent\", function () {",
-                      "  var jsonData = pm.response.json();",
-                      "  pm.expect(jsonData).to.have.property(\"is_email_sent\");",
-                      "  pm.expect(jsonData.is_email_sent).to.be.true;",
-                      "});",
-                      "",
-                      ""
-                    ],
-                    "type": "text/javascript"
-                  }
-                },
-                {
-                  "listen": "prerequest",
-                  "script": {
-                    "exec": [
-                      "",
-                      "var baseEmail = pm.environment.get('user_base_email_for_signup');",
-                      "var emailDomain = pm.environment.get(\"user_domain_for_signup\");",
-                      "",
-                      "// Generate a unique email address",
-                      "var uniqueEmail = baseEmail + new Date().getTime() + emailDomain;",
-                      "// Set the unique email address as an environment variable",
-                      "pm.environment.set('unique_email', uniqueEmail);",
-                      ""
-                    ],
-                    "type": "text/javascript"
-                  }
-                }
-              ],
-              "request": {
-                "method": "POST",
-                "header": [
-                  {
-                    "key": "Content-Type",
-                    "value": "application/json"
-                  },
-                  {
-                    "key": "Cookie",
-                    "value": "Cookie_1=value"
-                  }
-                ],
-                "body": {
-                  "mode": "raw",
-                  "raw": "{\"email\":\"{{unique_email}}\"}"
-                },
-                "url": {
-                  "raw": "{{baseUrl}}/user/connect_account",
-                  "host": [
-                    "{{baseUrl}}"
-                  ],
-                  "path": [
-                    "user",
-                    "connect_account"
-                  ]
-                }
-              },
-              "response": []
-            }
-          ]
-        },
-        {
-          "name": "Sign In",
-          "item": [
-            {
-              "name": "Signin",
-              "event": [
-                {
-                  "listen": "test",
-                  "script": {
-                    "exec": [
-                      "console.log(\"[LOG]::x-request-id - \" + pm.response.headers.get(\"x-request-id\"));",
-                      "",
-                      "// Validate status 2xx",
-                      "pm.test(\"[POST]::/user/v2/signin - Status code is 2xx\", function () {",
-                      "  pm.response.to.be.success;",
-                      "});",
-                      "",
-                      "// Validate if response header has matching content-type",
-                      "pm.test(\"[POST]::/user/v2/signin - Content-Type is application/json\", function () {",
-                      "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
-                      "    \"application/json\",",
-                      "  );",
-                      "});",
-                      "",
-                      "// Validate if response has JSON Body",
-                      "pm.test(\"[POST]::/user/v2/signin - Response has JSON Body\", function () {",
-                      "  pm.response.to.have.jsonBody();",
-                      "});",
-                      "",
-                      "// Validate specific JSON response content",
-                      "pm.test(\"[POST]::/user/v2/signin - Response contains token\", function () {",
-                      "  var jsonData = pm.response.json();",
-                      "  pm.expect(jsonData).to.have.property(\"token\");",
-                      "  pm.expect(jsonData.token).to.be.a(\"string\").and.to.not.be.empty;",
-                      "});"
-                    ],
-                    "type": "text/javascript"
-                  }
-                },
-                {
-                  "listen": "prerequest",
-                  "script": {
-                    "exec": [
-                      ""
-                    ],
-                    "type": "text/javascript"
-                  }
-                }
-              ],
-              "request": {
-                "method": "POST",
-                "header": [
-                  {
-                    "key": "Content-Type",
-                    "value": "application/json"
-                  },
-                  {
-                    "key": "Cookie",
-                    "value": "Cookie_1=value"
-                  }
-                ],
-                "body": {
-                  "mode": "raw",
-                  "raw": "{\"email\":\"{{user_email}}\",\"password\":\"{{user_password}}\"}"
-                },
-                "url": {
-                  "raw": "{{baseUrl}}/user/v2/signin",
-                  "host": [
-                    "{{baseUrl}}"
-                  ],
-                  "path": [
-                    "user",
-                    "v2",
-                    "signin"
-                  ]
-                }
-              },
-              "response": []
-            },
-            {
-              "name": "Signin Wrong",
-              "event": [
-                {
-                  "listen": "test",
-                  "script": {
-                    "exec": [
-                      "console.log(\"[LOG]::x-request-id - \" + pm.response.headers.get(\"x-request-id\"));",
-                      "",
-                      "// Validate status code is 4xx Bad Request",
-                      "pm.test(\"[POST]::/user/v2/signin - Status code is 401\", function () {",
-                      "  pm.response.to.have.status(401);",
-                      "});",
-                      "",
-                      "// Validate if response header has matching content-type",
-                      "pm.test(\"[POST]::/user/v2/signin - Content-Type is application/json\", function () {",
-                      "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
-                      "    \"application/json\",",
-                      "  );",
-                      "});",
-                      "",
-                      "// Validate if response has JSON Body",
-                      "pm.test(\"[POST]::/user/v2/signin - Response has JSON Body\", function () {",
-                      "  pm.response.to.have.jsonBody();",
-                      "});"
-                    ],
-                    "type": "text/javascript"
-                  }
-                }
-              ],
-              "request": {
-                "method": "POST",
-                "header": [
-                  {
-                    "key": "Content-Type",
-                    "value": "application/json"
-                  },
-                  {
-                    "key": "Cookie",
-                    "value": "Cookie_1=value"
-                  }
-                ],
-                "body": {
-                  "mode": "raw",
-                  "raw": "{\"email\":\"{{user_email}}\",\"password\":\"{{wrong_password}}\"}"
-                },
-                "url": {
-                  "raw": "{{baseUrl}}/user/v2/signin",
-                  "host": [
-                    "{{baseUrl}}"
-                  ],
-                  "path": [
-                    "user",
-                    "v2",
-                    "signin"
-                  ]
-                }
-              },
-              "response": []
-            },
-            {
-              "name": "Signin Token Only",
-              "event": [
-                {
-                  "listen": "test",
-                  "script": {
-                    "exec": [
-                      "console.log(\"[LOG]::x-request-id - \" + pm.response.headers.get(\"x-request-id\"));",
-                      "",
-                      "// Validate status 2xx",
-                      "pm.test(\"[POST]::user/v2/signin?token_only=true - Status code is 2xx\", function () {",
-                      "  pm.response.to.be.success;",
-                      "});",
-                      "",
-                      "// Validate if response header has matching content-type",
-                      "pm.test(\"[POST]::user/v2/signin?token_only=true - Content-Type is application/json\", function () {",
-                      "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
-                      "    \"application/json\",",
-                      "  );",
-                      "});",
-                      "",
-                      "// Validate if response has JSON Body",
-                      "pm.test(\"[POST]::user/v2/signin?token_only=true - Response has JSON Body\", function () {",
-                      "  pm.response.to.have.jsonBody();",
-                      "});",
-                      "",
-                      "// Validate specific JSON response content",
-                      "pm.test(\"[POST]::user/v2/signin?token_only=true - Response contains token\", function () {",
-                      "  var jsonData = pm.response.json();",
-                      "  pm.expect(jsonData).to.have.property(\"token\");",
-                      "  pm.expect(jsonData.token).to.be.a(\"string\").and.to.not.be.empty;",
-                      "});"
-                    ],
-                    "type": "text/javascript"
-                  }
-                }
-              ],
-              "request": {
-                "method": "POST",
-                "header": [
-                  {
-                    "key": "Content-Type",
-                    "value": "application/json"
-                  },
-                  {
-                    "key": "Cookie",
-                    "value": "Cookie_1=value"
-                  }
-                ],
-                "body": {
-                  "mode": "raw",
-                  "raw": "{\"email\":\"{{user_email}}\",\"password\":\"{{user_password}}\"}"
-                },
-                "url": {
-                  "raw": "{{baseUrl}}/user/v2/signin?token_only=true",
-                  "host": [
-                    "{{baseUrl}}"
-                  ],
-                  "path": [
-                    "user",
-                    "v2",
-                    "signin"
-                  ],
-                  "query": [
-                    {
-                      "key": "token_only",
-                      "value": "true"
-                    }
-                  ]
-                }
-              },
-              "response": []
-            },
-            {
-              "name": "Signin Token Only Wrong",
-              "event": [
-                {
-                  "listen": "test",
-                  "script": {
-                    "exec": [
-                      "console.log(\"[LOG]::x-request-id - \" + pm.response.headers.get(\"x-request-id\"));",
-                      "",
-                      "// Validate status 4xx",
-                      "pm.test(\"[POST]::/user/v2/signin?token_only=true - Status code is 401\", function () {",
-                      "  pm.response.to.have.status(401);",
-                      "});",
-                      "",
-                      "// Validate if response header has matching content-type",
-                      "pm.test(\"[POST]::user/v2/signin?token_only=true - Content-Type is application/json\", function () {",
-                      "  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
-                      "    \"application/json\",",
-                      "  );",
-                      "});",
-                      "",
-                      "// Validate if response has JSON Body",
-                      "pm.test(\"[POST]::user/v2/signin?token_only=true - Response has JSON Body\", function () {",
-                      "  pm.response.to.have.jsonBody();",
-                      "});"
-                    ],
-                    "type": "text/javascript"
-                  }
-                }
-              ],
-              "request": {
-                "method": "POST",
-                "header": [
-                  {
-                    "key": "Content-Type",
-                    "value": "application/json"
-                  },
-                  {
-                    "key": "Cookie",
-                    "value": "Cookie_1=value"
-                  }
-                ],
-                "body": {
-                  "mode": "raw",
-                  "raw": "{\"email\":\"{{user_email}}\",\"password\":\"{{wrong_password}}\"}"
-                },
-                "url": {
-                  "raw": "{{baseUrl}}/user/v2/signin?token_only=true",
-                  "host": [
-                    "{{baseUrl}}"
-                  ],
-                  "path": [
-                    "user",
-                    "v2",
-                    "signin"
-                  ],
-                  "query": [
-                    {
-                      "key": "token_only",
-                      "value": "true"
-                    }
-                  ]
-                }
-              },
-              "response": []
-            }
-          ]
-        }
-      ]
-    }
-  ],
-  "info": {
-    "_postman_id": "b5b40c9a-7e58-42c7-8b89-0adb208c45c9",
-    "name": "users",
-    "description": "## Get started\n\nJuspay Router provides a collection of APIs that enable you to process and manage payments. Our APIs accept and return JSON in the HTTP body, and return standard HTTP response codes.  \nYou can consume the APIs directly using your favorite HTTP/REST library.  \nWe have a testing environment referred to \"sandbox\", which you can setup to test API calls without affecting production data.\n\n### Base URLs\n\nUse the following base URLs when making requests to the APIs:\n\n| Environment | Base URL |\n| --- | --- |\n| Sandbox | [https://sandbox.hyperswitch.io](https://sandbox.hyperswitch.io) |\n| Production | [https://router.juspay.io](https://router.juspay.io) |\n\n# Authentication\n\nWhen you sign up for an account, you are given a secret key (also referred as api-key). You may authenticate all API requests with Juspay server by providing the appropriate key in the request Authorization header.  \nNever share your secret api keys. Keep them guarded and secure.\n\nContact Support:  \nName: Juspay Support  \nEmail: [support@juspay.in](mailto:support@juspay.in)",
-    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
-    "_exporter_id": "26710321"
-  },
-  "variable": [
-    {
-      "key": "baseUrl",
-      "value": "",
-      "type": "string"
-    },
-    {
-      "key": "admin_api_key",
-      "value": "",
-      "type": "string"
-    },
-    {
-      "key": "api_key",
-      "value": "",
-      "type": "string"
-    },
-    {
-      "key": "merchant_id",
-      "value": ""
-    },
-    {
-      "key": "payment_id",
-      "value": ""
-    },
-    {
-      "key": "customer_id",
-      "value": ""
-    },
-    {
-      "key": "mandate_id",
-      "value": ""
-    },
-    {
-      "key": "payment_method_id",
-      "value": ""
-    },
-    {
-      "key": "refund_id",
-      "value": ""
-    },
-    {
-      "key": "merchant_connector_id",
-      "value": ""
-    },
-    {
-      "key": "client_secret",
-      "value": "",
-      "type": "string"
-    },
-    {
-      "key": "connector_api_key",
-      "value": "",
-      "type": "string"
-    },
-    {
-      "key": "publishable_key",
-      "value": "",
-      "type": "string"
-    },
-    {
-      "key": "api_key_id",
-      "value": "",
-      "type": "string"
-    },
-    {
-      "key": "payment_token",
-      "value": ""
-    },
-    {
-      "key": "gateway_merchant_id",
-      "value": "",
-      "type": "string"
-    },
-    {
-      "key": "certificate",
-      "value": "",
-      "type": "string"
-    },
-    {
-      "key": "certificate_keys",
-      "value": "",
-      "type": "string"
-    },
-    {
-      "key": "connector_api_secret",
-      "value": "",
-      "type": "string"
-    },
-    {
-      "key": "connector_key1",
-      "value": "",
-      "type": "string"
-    },
-    {
-      "key": "connector_key2",
-      "value": "",
-      "type": "string"
-    },
-    {
-      "key": "user_email",
-      "value": "",
-      "type": "string"
-    },
-    {
-      "key": "user_password",
-      "value": "",
-      "type": "string"
-    },
-    {
-      "key": "wrong_password",
-      "value": "",
-      "type": "string"
-    },
-    {
-      "key": "user_base_email_for_signup",
-      "value": "",
-      "type": "string"
-    },
-    {
-      "key": "user_domain_for_signup",
-      "value": "",
-      "type": "string"
-    }
-  ]
-}
+	"info": {
+		"_postman_id": "b5b40c9a-7e58-42c7-8b89-0adb208c45c9",
+		"name": "users",
+		"description": "## Get started\n\nJuspay Router provides a collection of APIs that enable you to process and manage payments. Our APIs accept and return JSON in the HTTP body, and return standard HTTP response codes.  \nYou can consume the APIs directly using your favorite HTTP/REST library.  \nWe have a testing environment referred to \"sandbox\", which you can setup to test API calls without affecting production data.\n\n### Base URLs\n\nUse the following base URLs when making requests to the APIs:\n\n| Environment | Base URL |\n| --- | --- |\n| Sandbox | [https://sandbox.hyperswitch.io](https://sandbox.hyperswitch.io) |\n| Production | [https://router.juspay.io](https://router.juspay.io) |\n\n# Authentication\n\nWhen you sign up for an account, you are given a secret key (also referred as api-key). You may authenticate all API requests with Juspay server by providing the appropriate key in the request Authorization header.  \nNever share your secret api keys. Keep them guarded and secure.\n\nContact Support:  \nName: Juspay Support  \nEmail: [support@juspay.in](mailto:support@juspay.in)",
+		"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
+		"_exporter_id": "26710321"
+	},
+	"item": [
+		{
+			"name": "Health check",
+			"item": [
+				{
+					"name": "New Request",
+					"event": [
+						{
+							"listen": "test",
+							"script": {
+								"exec": [
+									"// Validate status 2xx",
+									"pm.test(\"[POST]::/health - Status code is 2xx\", function () {",
+									"  pm.response.to.be.success;",
+									"});",
+									""
+								],
+								"type": "text/javascript"
+							}
+						}
+					],
+					"request": {
+						"method": "GET",
+						"header": [],
+						"url": {
+							"raw": "{{baseUrl}}/health",
+							"host": [
+								"{{baseUrl}}"
+							],
+							"path": [
+								"health"
+							]
+						}
+					},
+					"response": []
+				}
+			]
+		},
+		{
+			"name": "Flow Testcases",
+			"item": [
+				{
+					"name": "Sign Up",
+					"item": [
+						{
+							"name": "Connect Account",
+							"event": [
+								{
+									"listen": "test",
+									"script": {
+										"exec": [
+											"console.log(\"[LOG]::x-request-id - \" + pm.response.headers.get(\"x-request-id\"));",
+											"",
+											"// Validate status 2xx",
+											"pm.test(\"[POST]::/user/connect_account - Status code is 2xx\", function () {",
+											"  pm.response.to.be.success;",
+											"});",
+											"",
+											"// Validate if response header has matching content-type",
+											"pm.test(\"[POST]::/user/connect_account - Content-Type is application/json\", function () {",
+											"  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+											"    \"application/json\",",
+											"  );",
+											"});",
+											"",
+											"// Validate if response has JSON Body",
+											"pm.test(\"[POST]::/user/connect_account - Response has JSON Body\", function () {",
+											"  pm.response.to.have.jsonBody();",
+											"});",
+											"",
+											"// Validate specific JSON response content",
+											"pm.test(\"[POST]::/user/connect_account - Response contains is_email_sent\", function () {",
+											"  var jsonData = pm.response.json();",
+											"  pm.expect(jsonData).to.have.property(\"is_email_sent\");",
+											"  pm.expect(jsonData.is_email_sent).to.be.true;",
+											"});",
+											"",
+											""
+										],
+										"type": "text/javascript"
+									}
+								},
+								{
+									"listen": "prerequest",
+									"script": {
+										"exec": [
+											"",
+											"var baseEmail = pm.environment.get('user_base_email_for_signup');",
+											"var emailDomain = pm.environment.get(\"user_domain_for_signup\");",
+											"",
+											"// Generate a unique email address",
+											"var uniqueEmail = baseEmail + new Date().getTime() + emailDomain;",
+											"// Set the unique email address as an environment variable",
+											"pm.environment.set('unique_email', uniqueEmail);",
+											""
+										],
+										"type": "text/javascript"
+									}
+								}
+							],
+							"request": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Content-Type",
+										"value": "application/json"
+									},
+									{
+										"key": "Cookie",
+										"value": "Cookie_1=value"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n    \"email\": \"{{unique_email}}\"\n}"
+								},
+								"url": {
+									"raw": "{{baseUrl}}/user/connect_account",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"user",
+										"connect_account"
+									]
+								}
+							},
+							"response": []
+						}
+					]
+				},
+				{
+					"name": "Sign In",
+					"item": [
+						{
+							"name": "Signin",
+							"event": [
+								{
+									"listen": "test",
+									"script": {
+										"exec": [
+											"console.log(\"[LOG]::x-request-id - \" + pm.response.headers.get(\"x-request-id\"));",
+											"",
+											"// Validate status 2xx",
+											"pm.test(\"[POST]::/user/signin - Status code is 2xx\", function () {",
+											"  pm.response.to.be.success;",
+											"});",
+											"",
+											"// Validate if response header has matching content-type",
+											"pm.test(\"[POST]::/user/signin - Content-Type is application/json\", function () {",
+											"  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+											"    \"application/json\",",
+											"  );",
+											"});",
+											"",
+											"// Validate if response has JSON Body",
+											"pm.test(\"[POST]::/user/signin - Response has JSON Body\", function () {",
+											"  pm.response.to.have.jsonBody();",
+											"});",
+											"",
+											"// Validate specific JSON response content",
+											"pm.test(\"[POST]::/user/signin - Response contains token\", function () {",
+											"  var jsonData = pm.response.json();",
+											"  pm.expect(jsonData).to.have.property(\"token\");",
+											"  pm.expect(jsonData.token).to.be.a(\"string\").and.to.not.be.empty;",
+											"});"
+										],
+										"type": "text/javascript"
+									}
+								},
+								{
+									"listen": "prerequest",
+									"script": {
+										"exec": [
+											""
+										],
+										"type": "text/javascript"
+									}
+								}
+							],
+							"request": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Content-Type",
+										"value": "application/json"
+									},
+									{
+										"key": "Cookie",
+										"value": "Cookie_1=value"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n    \"email\": \"{{user_email}}\",\n    \"password\": \"{{user_password}}\"\n}"
+								},
+								"url": {
+									"raw": "{{baseUrl}}/user/signin",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"user",
+										"signin"
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "Signin Wrong",
+							"event": [
+								{
+									"listen": "test",
+									"script": {
+										"exec": [
+											"console.log(\"[LOG]::x-request-id - \" + pm.response.headers.get(\"x-request-id\"));",
+											"",
+											"// Validate status code is 4xx Bad Request",
+											"pm.test(\"[POST]::/user/signin - Status code is 401\", function () {",
+											"  pm.response.to.have.status(401);",
+											"});",
+											"",
+											"// Validate if response header has matching content-type",
+											"pm.test(\"[POST]::/user/signin - Content-Type is application/json\", function () {",
+											"  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+											"    \"application/json\",",
+											"  );",
+											"});",
+											"",
+											"// Validate if response has JSON Body",
+											"pm.test(\"[POST]::/user/signin - Response has JSON Body\", function () {",
+											"  pm.response.to.have.jsonBody();",
+											"});"
+										],
+										"type": "text/javascript"
+									}
+								}
+							],
+							"request": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Content-Type",
+										"value": "application/json"
+									},
+									{
+										"key": "Cookie",
+										"value": "Cookie_1=value"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n    \"email\": \"{{user_email}}\",\n    \"password\": \"{{wrong_password}}\"\n}"
+								},
+								"url": {
+									"raw": "{{baseUrl}}/user/signin",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"user",
+										"signin"
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "Signin V2 - To be deprecated",
+							"event": [
+								{
+									"listen": "test",
+									"script": {
+										"exec": [
+											"console.log(\"[LOG]::x-request-id - \" + pm.response.headers.get(\"x-request-id\"));",
+											"",
+											"// Validate status 2xx",
+											"pm.test(\"[POST]::user/v2/signin - Status code is 2xx\", function () {",
+											"  pm.response.to.be.success;",
+											"});",
+											"",
+											"// Validate if response header has matching content-type",
+											"pm.test(\"[POST]::user/v2/signin - Content-Type is application/json\", function () {",
+											"  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+											"    \"application/json\",",
+											"  );",
+											"});",
+											"",
+											"// Validate if response has JSON Body",
+											"pm.test(\"[POST]::user/v2/signin - Response has JSON Body\", function () {",
+											"  pm.response.to.have.jsonBody();",
+											"});",
+											"",
+											"// Validate specific JSON response content",
+											"pm.test(\"[POST]::user/v2/signin - Response contains token\", function () {",
+											"  var jsonData = pm.response.json();",
+											"  pm.expect(jsonData).to.have.property(\"token\");",
+											"  pm.expect(jsonData.token).to.be.a(\"string\").and.to.not.be.empty;",
+											"});"
+										],
+										"type": "text/javascript"
+									}
+								}
+							],
+							"request": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Content-Type",
+										"value": "application/json"
+									},
+									{
+										"key": "Cookie",
+										"value": "Cookie_1=value"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n \"email\": \"{{user_email}}\",\n \"password\": \"{{user_password}}\"  \n}"
+								},
+								"url": {
+									"raw": "{{baseUrl}}/user/v2/signin",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"user",
+										"v2",
+										"signin"
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "Signin V2 Wrong",
+							"event": [
+								{
+									"listen": "test",
+									"script": {
+										"exec": [
+											"console.log(\"[LOG]::x-request-id - \" + pm.response.headers.get(\"x-request-id\"));",
+											"",
+											"// Validate status 4xx",
+											"pm.test(\"[POST]::/user/v2/signin - Status code is 401\", function () {",
+											"  pm.response.to.have.status(401);",
+											"});",
+											"",
+											"// Validate if response header has matching content-type",
+											"pm.test(\"[POST]::user/v2/signin - Content-Type is application/json\", function () {",
+											"  pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(",
+											"    \"application/json\",",
+											"  );",
+											"});",
+											"",
+											"// Validate if response has JSON Body",
+											"pm.test(\"[POST]::user/v2/signin - Response has JSON Body\", function () {",
+											"  pm.response.to.have.jsonBody();",
+											"});"
+										],
+										"type": "text/javascript"
+									}
+								}
+							],
+							"request": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Content-Type",
+										"value": "application/json"
+									},
+									{
+										"key": "Cookie",
+										"value": "Cookie_1=value"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n \"email\": \"{{user_email}}\",\n \"password\": \"{{wrong_password}}\"  \n}"
+								},
+								"url": {
+									"raw": "{{baseUrl}}/user/v2/signin",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"user",
+										"v2",
+										"signin"
+									]
+								}
+							},
+							"response": []
+						}
+					]
+				}
+			]
+		}
+	],
+	"event": [
+		{
+			"listen": "prerequest",
+			"script": {
+				"type": "text/javascript",
+				"exec": [
+					""
+				]
+			}
+		},
+		{
+			"listen": "test",
+			"script": {
+				"type": "text/javascript",
+				"exec": [
+					""
+				]
+			}
+		}
+	],
+	"variable": [
+		{
+			"key": "baseUrl",
+			"value": "",
+			"type": "string"
+		},
+		{
+			"key": "admin_api_key",
+			"value": "",
+			"type": "string"
+		},
+		{
+			"key": "api_key",
+			"value": "",
+			"type": "string"
+		},
+		{
+			"key": "merchant_id",
+			"value": ""
+		},
+		{
+			"key": "payment_id",
+			"value": ""
+		},
+		{
+			"key": "customer_id",
+			"value": ""
+		},
+		{
+			"key": "mandate_id",
+			"value": ""
+		},
+		{
+			"key": "payment_method_id",
+			"value": ""
+		},
+		{
+			"key": "refund_id",
+			"value": ""
+		},
+		{
+			"key": "merchant_connector_id",
+			"value": ""
+		},
+		{
+			"key": "client_secret",
+			"value": "",
+			"type": "string"
+		},
+		{
+			"key": "connector_api_key",
+			"value": "",
+			"type": "string"
+		},
+		{
+			"key": "publishable_key",
+			"value": "",
+			"type": "string"
+		},
+		{
+			"key": "api_key_id",
+			"value": "",
+			"type": "string"
+		},
+		{
+			"key": "payment_token",
+			"value": ""
+		},
+		{
+			"key": "gateway_merchant_id",
+			"value": "",
+			"type": "string"
+		},
+		{
+			"key": "certificate",
+			"value": "",
+			"type": "string"
+		},
+		{
+			"key": "certificate_keys",
+			"value": "",
+			"type": "string"
+		},
+		{
+			"key": "connector_api_secret",
+			"value": "",
+			"type": "string"
+		},
+		{
+			"key": "connector_key1",
+			"value": "",
+			"type": "string"
+		},
+		{
+			"key": "connector_key2",
+			"value": "",
+			"type": "string"
+		},
+		{
+			"key": "user_email",
+			"value": "",
+			"type": "string"
+		},
+		{
+			"key": "user_password",
+			"value": "",
+			"type": "string"
+		},
+		{
+			"key": "wrong_password",
+			"value": "",
+			"type": "string"
+		},
+		{
+			"key": "user_base_email_for_signup",
+			"value": "",
+			"type": "string"
+		},
+		{
+			"key": "user_domain_for_signup",
+			"value": "",
+			"type": "string"
+		}
+	]
+}
\ No newline at end of file

## Type of Change
<!-- Put an `x` in the boxes that apply -->

- [ ] Bugfix
- [ ] New feature
- [ ] Enhancement
- [x] Refactoring
- [ ] Dependency updates
- [ ] Documentation
- [ ] CI/CD

## Description
<!-- Describe your changes in detail -->
- Deprecate all the APIs which are used when `is_token_only` and `groups` query params are false.
- Add logic to get merchant_id from the db if not found in user_role.

### Additional Changes

- [x] This PR modifies the API contract
- [ ] This PR modifies the database schema
- [ ] This PR modifies application configuration/environment variables

<!--
Provide links to the files with corresponding changes.

Following are the paths where you can find config files:
1. `config`
2. `crates/router/src/configs`
3. `loadtest/config`
-->


## Motivation and Context
<!--
Why is this change required? What problem does it solve?
If it fixes an open issue, please link to the issue here.

If you don't have an issue, we'd recommend starting with one first so the PR
can focus on the implementation (unless it is an obvious bug or documentation fix
that will have little conversation).
-->
Closes #5761.
Closes #5762.

## How did you test it?
<!--
Did you write an integration/unit/API test to verify the code changes?
Or did you test this change manually (provide relevant screenshots)?
-->
From the following endpoints, `token_only` query parameter is removed.
- `/v2/signin`
- `/reset_password`
- `/v2/verify_email`
- `/accept_invite_from_email`
- `/invite/accept` - Post only

All the above APIs will give the following response.
```
{
    "token": "JWT",
    "token_type": "type"
}
```

From the following endpoints, `groups` query parameter is removed.
- `/role` - Get only
- `/role/list`
- `/role/{role_id}` - Get only

They will always respond with groups from now on.

2 new APIs are added.
```
curl --location 'http://localhost:8080/user/signin' \
--header 'Content-Type: application/json' \
--data-raw '{
    "email": "email",
    "password": "password"
}
'
```

```
curl --location 'http://localhost:8080/user/verify_email' \
--header 'Content-Type: application/json' \
--header 'Authorization: ••••••' \
--data '{
    "token": "email token"
}'
```

Both will give the following response if hit correctly.
```
{
    "token": "JWT",
    "token_type": "type"
}
```


## Checklist
<!-- Put an `x` in the boxes that apply -->

- [x] I formatted the code `cargo +nightly fmt --all`
- [x] I addressed lints thrown by `cargo clippy`
- [x] I reviewed the submitted code
- [ ] I added unit tests for my changes where possible
