Bug: [FEATURE] Stored credential Indicator



### Feature Description

Connectors like Nuvei requires a field called as storedCredentialMode which represents if the merchant is using a card details which they previously used for same connector or any other PSP. This is used for risk lowering based on PSP's.

    Make a is_stored_credential in payment request if the merchant knows this is stored_credential. ( in this case merchant stores the card in his server . No way hyperswitch knows if this is stored or not)
    if is_stored_credential = false but using payment token or mandate or recurring flow : throw error.
    if is_stored_credential = None but using payment token or mandate or recurring flow : make the is_stored_credential as true in core


### Possible Implementation

- 

### Have you spent some time checking if this feature request has been raised before?

- [x] I checked and didn't find a similar issue

### Have you read the Contributing Guidelines?

- [x] I have read the [Contributing Guidelines](https://github.com/juspay/hyperswitch/blob/main/docs/CONTRIBUTING.md)

### Are you willing to submit a PR?

None
diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs
index 840ab7537f0..55e13f5b094 100644
--- a/crates/api_models/src/payments.rs
+++ b/crates/api_models/src/payments.rs
@@ -1291,6 +1291,10 @@ pub struct PaymentsRequest {
     #[remove_in(PaymentsConfirmRequest)]
     #[schema(value_type = Option<bool>, example = true)]
     pub enable_overcapture: Option<primitive_wrappers::EnableOvercaptureBool>,
+
+    /// Boolean flag indicating whether this payment method is stored and has been previously used for payments
+    #[schema(value_type = Option<bool>, example = true)]
+    pub is_stored_credential: Option<bool>,
 }
 
 #[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
@@ -1445,6 +1449,24 @@ impl PaymentsRequest {
             })
             .transpose()
     }
+    pub fn validate_stored_credential(
+        &self,
+    ) -> common_utils::errors::CustomResult<(), ValidationError> {
+        if self.is_stored_credential == Some(false)
+            && (self.recurring_details.is_some()
+                || self.payment_token.is_some()
+                || self.mandate_id.is_some())
+        {
+            Err(ValidationError::InvalidValue {
+                message:
+                    "is_stored_credential should be true when reusing stored payment method data"
+                        .to_string(),
+            }
+            .into())
+        } else {
+            Ok(())
+        }
+    }
 }
 
 #[cfg(feature = "v1")]
@@ -5692,6 +5714,10 @@ pub struct PaymentsResponse {
     /// Contains card network response details (e.g., Visa/Mastercard advice codes).
     #[schema(value_type = Option<NetworkDetails>)]
     pub network_details: Option<NetworkDetails>,
+
+    /// Boolean flag indicating whether this payment method is stored and has been previously used for payments
+    #[schema(value_type = Option<bool>, example = true)]
+    pub is_stored_credential: Option<bool>,
 }
 
 #[cfg(feature = "v2")]
diff --git a/crates/diesel_models/src/payment_attempt.rs b/crates/diesel_models/src/payment_attempt.rs
index 8cd2525b84a..002c9f7d5b6 100644
--- a/crates/diesel_models/src/payment_attempt.rs
+++ b/crates/diesel_models/src/payment_attempt.rs
@@ -107,6 +107,7 @@ pub struct PaymentAttempt {
     pub network_transaction_id: Option<String>,
     pub is_overcapture_enabled: Option<OvercaptureEnabledBool>,
     pub network_details: Option<NetworkDetails>,
+    pub is_stored_credential: Option<bool>,
     #[diesel(deserialize_as = RequiredFromNullable<storage_enums::PaymentMethod>)]
     pub payment_method_type_v2: storage_enums::PaymentMethod,
     pub connector_payment_id: Option<ConnectorTransactionId>,
@@ -226,6 +227,7 @@ pub struct PaymentAttempt {
     pub network_transaction_id: Option<String>,
     pub is_overcapture_enabled: Option<OvercaptureEnabledBool>,
     pub network_details: Option<NetworkDetails>,
+    pub is_stored_credential: Option<bool>,
 }
 
 #[cfg(feature = "v1")]
@@ -328,6 +330,7 @@ pub struct PaymentAttemptNew {
     pub connector_response_reference_id: Option<String>,
     pub network_transaction_id: Option<String>,
     pub network_details: Option<NetworkDetails>,
+    pub is_stored_credential: Option<bool>,
     pub multiple_capture_count: Option<i16>,
     pub amount_capturable: MinorUnit,
     pub updated_by: String,
@@ -452,6 +455,7 @@ pub struct PaymentAttemptNew {
     pub connector_request_reference_id: Option<String>,
     pub network_transaction_id: Option<String>,
     pub network_details: Option<NetworkDetails>,
+    pub is_stored_credential: Option<bool>,
 }
 
 #[cfg(feature = "v1")]
@@ -487,6 +491,7 @@ pub enum PaymentAttemptUpdate {
         updated_by: String,
         merchant_connector_id: Option<id_type::MerchantConnectorAccountId>,
         routing_approach: Option<storage_enums::RoutingApproach>,
+        is_stored_credential: Option<bool>,
     },
     AuthenticationTypeUpdate {
         authentication_type: storage_enums::AuthenticationType,
@@ -529,6 +534,7 @@ pub enum PaymentAttemptUpdate {
         routing_approach: Option<storage_enums::RoutingApproach>,
         connector_request_reference_id: Option<String>,
         network_transaction_id: Option<String>,
+        is_stored_credential: Option<bool>,
         request_extended_authorization: Option<RequestExtendedAuthorizationBool>,
     },
     VoidUpdate {
@@ -1017,6 +1023,7 @@ impl PaymentAttemptUpdateInternal {
             is_overcapture_enabled: source.is_overcapture_enabled,
             network_details: source.network_details,
             attempts_group_id: source.attempts_group_id,
+            is_stored_credential: source.is_stored_credential,
         }
     }
 }
@@ -1086,6 +1093,7 @@ pub struct PaymentAttemptUpdateInternal {
     pub network_transaction_id: Option<String>,
     pub is_overcapture_enabled: Option<OvercaptureEnabledBool>,
     pub network_details: Option<NetworkDetails>,
+    pub is_stored_credential: Option<bool>,
     pub request_extended_authorization: Option<RequestExtendedAuthorizationBool>,
 }
 
@@ -1281,6 +1289,7 @@ impl PaymentAttemptUpdate {
             network_transaction_id,
             is_overcapture_enabled,
             network_details,
+            is_stored_credential,
             request_extended_authorization,
         } = PaymentAttemptUpdateInternal::from(self).populate_derived_fields(&source);
         PaymentAttempt {
@@ -1354,6 +1363,7 @@ impl PaymentAttemptUpdate {
             network_transaction_id: network_transaction_id.or(source.network_transaction_id),
             is_overcapture_enabled: is_overcapture_enabled.or(source.is_overcapture_enabled),
             network_details: network_details.or(source.network_details),
+            is_stored_credential: is_stored_credential.or(source.is_stored_credential),
             request_extended_authorization: request_extended_authorization
                 .or(source.request_extended_authorization),
             ..source
@@ -2696,6 +2706,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 network_transaction_id,
                 is_overcapture_enabled: None,
                 network_details: None,
+                is_stored_credential: None,
                 request_extended_authorization: None,
             },
             PaymentAttemptUpdate::AuthenticationTypeUpdate {
@@ -2764,6 +2775,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 network_transaction_id: None,
                 is_overcapture_enabled: None,
                 network_details: None,
+                is_stored_credential: None,
                 request_extended_authorization: None,
             },
             PaymentAttemptUpdate::ConfirmUpdate {
@@ -2803,6 +2815,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 routing_approach,
                 connector_request_reference_id,
                 network_transaction_id,
+                is_stored_credential,
                 request_extended_authorization,
             } => Self {
                 amount: Some(amount),
@@ -2867,6 +2880,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 network_transaction_id,
                 is_overcapture_enabled: None,
                 network_details: None,
+                is_stored_credential,
                 request_extended_authorization,
             },
             PaymentAttemptUpdate::VoidUpdate {
@@ -2936,6 +2950,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 network_transaction_id: None,
                 is_overcapture_enabled: None,
                 network_details: None,
+                is_stored_credential: None,
                 request_extended_authorization: None,
             },
             PaymentAttemptUpdate::RejectUpdate {
@@ -3006,6 +3021,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 network_transaction_id: None,
                 is_overcapture_enabled: None,
                 network_details: None,
+                is_stored_credential: None,
                 request_extended_authorization: None,
             },
             PaymentAttemptUpdate::BlocklistUpdate {
@@ -3076,6 +3092,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 network_transaction_id: None,
                 is_overcapture_enabled: None,
                 network_details: None,
+                is_stored_credential: None,
                 request_extended_authorization: None,
             },
             PaymentAttemptUpdate::ConnectorMandateDetailUpdate {
@@ -3144,6 +3161,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 network_transaction_id: None,
                 is_overcapture_enabled: None,
                 network_details: None,
+                is_stored_credential: None,
                 request_extended_authorization: None,
             },
             PaymentAttemptUpdate::PaymentMethodDetailsUpdate {
@@ -3212,6 +3230,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 network_transaction_id: None,
                 is_overcapture_enabled: None,
                 network_details: None,
+                is_stored_credential: None,
                 request_extended_authorization: None,
             },
             PaymentAttemptUpdate::ResponseUpdate {
@@ -3310,6 +3329,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                     network_transaction_id,
                     is_overcapture_enabled,
                     network_details: None,
+                    is_stored_credential: None,
                     request_extended_authorization: None,
                 }
             }
@@ -3398,6 +3418,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                     network_transaction_id: None,
                     is_overcapture_enabled: None,
                     network_details,
+                    is_stored_credential: None,
                     request_extended_authorization: None,
                 }
             }
@@ -3464,6 +3485,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 network_transaction_id: None,
                 is_overcapture_enabled: None,
                 network_details: None,
+                is_stored_credential: None,
                 request_extended_authorization: None,
             },
             PaymentAttemptUpdate::UpdateTrackers {
@@ -3476,6 +3498,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 updated_by,
                 merchant_connector_id,
                 routing_approach,
+                is_stored_credential,
             } => Self {
                 payment_token,
                 modified_at: common_utils::date_time::now(),
@@ -3539,6 +3562,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 network_transaction_id: None,
                 is_overcapture_enabled: None,
                 network_details: None,
+                is_stored_credential,
                 request_extended_authorization: None,
             },
             PaymentAttemptUpdate::UnresolvedResponseUpdate {
@@ -3620,6 +3644,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                     network_transaction_id: None,
                     is_overcapture_enabled: None,
                     network_details: None,
+                    is_stored_credential: None,
                     request_extended_authorization: None,
                 }
             }
@@ -3700,6 +3725,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                     network_transaction_id: None,
                     is_overcapture_enabled: None,
                     network_details: None,
+                    is_stored_credential: None,
                     request_extended_authorization: None,
                 }
             }
@@ -3770,6 +3796,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 network_transaction_id: None,
                 is_overcapture_enabled: None,
                 network_details: None,
+                is_stored_credential: None,
                 request_extended_authorization: None,
             },
             PaymentAttemptUpdate::AmountToCaptureUpdate {
@@ -3839,6 +3866,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 network_transaction_id: None,
                 is_overcapture_enabled: None,
                 network_details: None,
+                is_stored_credential: None,
                 request_extended_authorization: None,
             },
             PaymentAttemptUpdate::ConnectorResponse {
@@ -3917,6 +3945,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                     network_transaction_id: None,
                     is_overcapture_enabled: None,
                     network_details: None,
+                    is_stored_credential: None,
                     request_extended_authorization: None,
                 }
             }
@@ -3986,6 +4015,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 network_transaction_id: None,
                 is_overcapture_enabled: None,
                 network_details: None,
+                is_stored_credential: None,
                 request_extended_authorization: None,
             },
             PaymentAttemptUpdate::AuthenticationUpdate {
@@ -4057,6 +4087,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 network_transaction_id: None,
                 is_overcapture_enabled: None,
                 network_details: None,
+                is_stored_credential: None,
                 request_extended_authorization: None,
             },
             PaymentAttemptUpdate::ManualUpdate {
@@ -4137,6 +4168,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                     network_transaction_id: None,
                     is_overcapture_enabled: None,
                     network_details: None,
+                    is_stored_credential: None,
                     request_extended_authorization: None,
                 }
             }
@@ -4206,6 +4238,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
                 network_transaction_id: None,
                 is_overcapture_enabled: None,
                 network_details: None,
+                is_stored_credential: None,
                 request_extended_authorization: None,
             },
         }
diff --git a/crates/diesel_models/src/schema.rs b/crates/diesel_models/src/schema.rs
index 4de3c14806e..7cddb536033 100644
--- a/crates/diesel_models/src/schema.rs
+++ b/crates/diesel_models/src/schema.rs
@@ -1083,6 +1083,7 @@ diesel::table! {
         network_transaction_id -> Nullable<Varchar>,
         is_overcapture_enabled -> Nullable<Bool>,
         network_details -> Nullable<Jsonb>,
+        is_stored_credential -> Nullable<Bool>,
     }
 }
 
diff --git a/crates/diesel_models/src/schema_v2.rs b/crates/diesel_models/src/schema_v2.rs
index 38b8a6a6c40..93ad4299c54 100644
--- a/crates/diesel_models/src/schema_v2.rs
+++ b/crates/diesel_models/src/schema_v2.rs
@@ -1025,6 +1025,7 @@ diesel::table! {
         network_transaction_id -> Nullable<Varchar>,
         is_overcapture_enabled -> Nullable<Bool>,
         network_details -> Nullable<Jsonb>,
+        is_stored_credential -> Nullable<Bool>,
         payment_method_type_v2 -> Nullable<Varchar>,
         #[max_length = 128]
         connector_payment_id -> Nullable<Varchar>,
diff --git a/crates/diesel_models/src/user/sample_data.rs b/crates/diesel_models/src/user/sample_data.rs
index 9dc2f03a5b0..5f6aa33b0bb 100644
--- a/crates/diesel_models/src/user/sample_data.rs
+++ b/crates/diesel_models/src/user/sample_data.rs
@@ -220,6 +220,7 @@ pub struct PaymentAttemptBatchNew {
     pub connector_request_reference_id: Option<String>,
     pub network_transaction_id: Option<String>,
     pub network_details: Option<NetworkDetails>,
+    pub is_stored_credential: Option<bool>,
 }
 
 #[cfg(feature = "v1")]
@@ -309,6 +310,7 @@ impl PaymentAttemptBatchNew {
             connector_request_reference_id: self.connector_request_reference_id,
             network_transaction_id: self.network_transaction_id,
             network_details: self.network_details,
+            is_stored_credential: self.is_stored_credential,
         }
     }
 }
diff --git a/crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs b/crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs
index e9d766f912b..5463496165b 100644
--- a/crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs
+++ b/crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs
@@ -17,7 +17,7 @@ use common_utils::{
 };
 use error_stack::ResultExt;
 use hyperswitch_domain_models::{
-    address::Address,
+    address::{Address, AddressDetails},
     payment_method_data::{
         self, ApplePayWalletData, BankRedirectData, CardDetailsForNetworkTransactionId,
         GooglePayWalletData, PayLaterData, PaymentMethodData, WalletData,
@@ -106,6 +106,7 @@ trait NuveiAuthorizePreprocessingCommon {
     ) -> Result<Option<AuthenticationData>, error_stack::Report<errors::ConnectorError>> {
         Ok(None)
     }
+    fn get_is_stored_credential(&self) -> Option<StoredCredentialMode>;
 }
 
 impl NuveiAuthorizePreprocessingCommon for SetupMandateRequestData {
@@ -187,6 +188,10 @@ impl NuveiAuthorizePreprocessingCommon for SetupMandateRequestData {
     fn get_ntid(&self) -> Option<String> {
         None
     }
+
+    fn get_is_stored_credential(&self) -> Option<StoredCredentialMode> {
+        StoredCredentialMode::get_optional_stored_credential(self.is_stored_credential)
+    }
 }
 
 impl NuveiAuthorizePreprocessingCommon for PaymentsAuthorizeData {
@@ -260,6 +265,10 @@ impl NuveiAuthorizePreprocessingCommon for PaymentsAuthorizeData {
         self.enable_partial_authorization
             .map(PartialApprovalFlag::from)
     }
+
+    fn get_is_stored_credential(&self) -> Option<StoredCredentialMode> {
+        StoredCredentialMode::get_optional_stored_credential(self.is_stored_credential)
+    }
 }
 
 impl NuveiAuthorizePreprocessingCommon for PaymentsPreProcessingData {
@@ -333,6 +342,10 @@ impl NuveiAuthorizePreprocessingCommon for PaymentsPreProcessingData {
     fn get_ntid(&self) -> Option<String> {
         None
     }
+
+    fn get_is_stored_credential(&self) -> Option<StoredCredentialMode> {
+        StoredCredentialMode::get_optional_stored_credential(self.is_stored_credential)
+    }
 }
 
 #[derive(Debug, Serialize, Default, Deserialize)]
@@ -785,8 +798,36 @@ pub struct Card {
     pub issuer_country: Option<String>,
     pub is_prepaid: Option<String>,
     pub external_token: Option<ExternalToken>,
+    pub stored_credentials: Option<StoredCredentialMode>,
 }
 
+#[derive(Debug, Clone, Default, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct StoredCredentialMode {
+    pub stored_credentials_mode: Option<StoredCredentialModeType>,
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub enum StoredCredentialModeType {
+    #[serde(rename = "0")]
+    First,
+    #[serde(rename = "1")]
+    Used,
+}
+
+impl StoredCredentialMode {
+    pub fn get_optional_stored_credential(is_stored_credential: Option<bool>) -> Option<Self> {
+        is_stored_credential.and_then(|is_stored_credential| {
+            if is_stored_credential {
+                Some(Self {
+                    stored_credentials_mode: Some(StoredCredentialModeType::Used),
+                })
+            } else {
+                None
+            }
+        })
+    }
+}
 #[derive(Debug, Clone, Default, Serialize, Deserialize)]
 #[serde(rename_all = "camelCase")]
 pub struct ExternalToken {
@@ -1015,6 +1056,7 @@ pub struct NuveiCardDetails {
     card: payment_method_data::Card,
     three_d: Option<ThreeD>,
     card_holder_name: Option<Secret<String>>,
+    stored_credentials: Option<StoredCredentialMode>,
 }
 
 // Define new structs with camelCase serialization
@@ -1884,6 +1926,7 @@ where
             amount_details,
             items: l2_l3_items,
             is_partial_approval: item.request.get_is_partial_approval(),
+
             ..request
         })
     }
@@ -1903,7 +1946,7 @@ where
         None
     };
 
-    let address = item
+    let address: Option<&AddressDetails> = item
         .get_optional_billing()
         .and_then(|billing_details| billing_details.address.as_ref());
 
@@ -1999,6 +2042,7 @@ where
             card: card_details.clone(),
             three_d,
             card_holder_name: item.get_optional_billing_full_name(),
+            stored_credentials: item.request.get_is_stored_credential(),
         }),
         is_moto,
         ..Default::default()
@@ -2015,6 +2059,7 @@ impl From<NuveiCardDetails> for PaymentOption {
                 expiration_year: Some(card.card_exp_year),
                 three_d: card_details.three_d,
                 cvv: Some(card.card_cvc),
+                stored_credentials: card_details.stored_credentials,
                 ..Default::default()
             }),
             ..Default::default()
@@ -2038,6 +2083,9 @@ impl TryFrom<(&types::PaymentsCompleteAuthorizeRouterData, Secret<String>)>
                         card,
                         three_d: None,
                         card_holder_name: item.get_optional_billing_full_name(),
+                        stored_credentials: StoredCredentialMode::get_optional_stored_credential(
+                            item.request.is_stored_credential,
+                        ),
                     }),
                     device_details,
                     ..Default::default()
diff --git a/crates/hyperswitch_connectors/src/utils.rs b/crates/hyperswitch_connectors/src/utils.rs
index 85051693105..73327dfd3c3 100644
--- a/crates/hyperswitch_connectors/src/utils.rs
+++ b/crates/hyperswitch_connectors/src/utils.rs
@@ -6759,6 +6759,7 @@ pub(crate) fn convert_setup_mandate_router_data_to_authorize_router_data(
         payment_channel: data.request.payment_channel.clone(),
         enable_partial_authorization: data.request.enable_partial_authorization,
         enable_overcapture: None,
+        is_stored_credential: data.request.is_stored_credential,
     }
 }
 
diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs
index f1b50182f78..bcce5d59780 100644
--- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs
+++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs
@@ -1038,6 +1038,7 @@ pub struct PaymentAttempt {
     pub network_transaction_id: Option<String>,
     pub is_overcapture_enabled: Option<OvercaptureEnabledBool>,
     pub network_details: Option<NetworkDetails>,
+    pub is_stored_credential: Option<bool>,
 }
 
 #[cfg(feature = "v1")]
@@ -1336,6 +1337,7 @@ pub struct PaymentAttemptNew {
     pub connector_request_reference_id: Option<String>,
     pub network_transaction_id: Option<String>,
     pub network_details: Option<NetworkDetails>,
+    pub is_stored_credential: Option<bool>,
 }
 
 #[cfg(feature = "v1")]
@@ -1369,6 +1371,7 @@ pub enum PaymentAttemptUpdate {
         updated_by: String,
         merchant_connector_id: Option<id_type::MerchantConnectorAccountId>,
         routing_approach: Option<storage_enums::RoutingApproach>,
+        is_stored_credential: Option<bool>,
     },
     AuthenticationTypeUpdate {
         authentication_type: storage_enums::AuthenticationType,
@@ -1407,6 +1410,7 @@ pub enum PaymentAttemptUpdate {
         routing_approach: Option<storage_enums::RoutingApproach>,
         connector_request_reference_id: Option<String>,
         network_transaction_id: Option<String>,
+        is_stored_credential: Option<bool>,
         request_extended_authorization: Option<RequestExtendedAuthorizationBool>,
     },
     RejectUpdate {
@@ -1600,6 +1604,7 @@ impl PaymentAttemptUpdate {
                 tax_amount,
                 merchant_connector_id,
                 routing_approach,
+                is_stored_credential,
             } => DieselPaymentAttemptUpdate::UpdateTrackers {
                 payment_token,
                 connector,
@@ -1617,6 +1622,7 @@ impl PaymentAttemptUpdate {
                     }
                     _ => approach,
                 }),
+                is_stored_credential,
             },
             Self::AuthenticationTypeUpdate {
                 authentication_type,
@@ -1683,6 +1689,7 @@ impl PaymentAttemptUpdate {
                 routing_approach,
                 connector_request_reference_id,
                 network_transaction_id,
+                is_stored_credential,
                 request_extended_authorization,
             } => DieselPaymentAttemptUpdate::ConfirmUpdate {
                 amount: net_amount.get_order_amount(),
@@ -1728,6 +1735,7 @@ impl PaymentAttemptUpdate {
                 }),
                 connector_request_reference_id,
                 network_transaction_id,
+                is_stored_credential,
                 request_extended_authorization,
             },
             Self::VoidUpdate {
@@ -2178,6 +2186,7 @@ impl behaviour::Conversion for PaymentAttempt {
             network_transaction_id: self.network_transaction_id,
             is_overcapture_enabled: self.is_overcapture_enabled,
             network_details: self.network_details,
+            is_stored_credential: self.is_stored_credential,
         })
     }
 
@@ -2279,6 +2288,7 @@ impl behaviour::Conversion for PaymentAttempt {
                 network_transaction_id: storage_model.network_transaction_id,
                 is_overcapture_enabled: storage_model.is_overcapture_enabled,
                 network_details: storage_model.network_details,
+                is_stored_credential: storage_model.is_stored_credential,
             })
         }
         .await
@@ -2371,6 +2381,7 @@ impl behaviour::Conversion for PaymentAttempt {
             connector_request_reference_id: self.connector_request_reference_id,
             network_transaction_id: self.network_transaction_id,
             network_details: self.network_details,
+            is_stored_credential: self.is_stored_credential,
         })
     }
 }
@@ -2544,6 +2555,7 @@ impl behaviour::Conversion for PaymentAttempt {
             is_overcapture_enabled: None,
             network_details: None,
             attempts_group_id,
+            is_stored_credential: None,
         })
     }
 
@@ -2825,6 +2837,7 @@ impl behaviour::Conversion for PaymentAttempt {
             connector_request_reference_id,
             network_details: None,
             attempts_group_id,
+            is_stored_credential: None,
         })
     }
 }
diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs
index e21f875f25d..40e17aaaf92 100644
--- a/crates/hyperswitch_domain_models/src/router_request_types.rs
+++ b/crates/hyperswitch_domain_models/src/router_request_types.rs
@@ -88,6 +88,7 @@ pub struct PaymentsAuthorizeData {
     pub enable_partial_authorization:
         Option<common_types::primitive_wrappers::EnablePartialAuthorizationBool>,
     pub enable_overcapture: Option<common_types::primitive_wrappers::EnableOvercaptureBool>,
+    pub is_stored_credential: Option<bool>,
 }
 
 #[derive(Debug, Clone)]
@@ -343,6 +344,7 @@ impl TryFrom<SetupMandateRequestData> for PaymentsPreProcessingData {
             metadata: data.metadata,
             customer_acceptance: data.customer_acceptance,
             setup_future_usage: data.setup_future_usage,
+            is_stored_credential: data.is_stored_credential,
         })
     }
 }
@@ -564,6 +566,7 @@ pub struct PaymentsPreProcessingData {
     pub setup_future_usage: Option<storage_enums::FutureUsage>,
     // New amount for amount frame work
     pub minor_amount: Option<MinorUnit>,
+    pub is_stored_credential: Option<bool>,
 }
 
 #[derive(Debug, Clone)]
@@ -601,6 +604,7 @@ impl TryFrom<PaymentsAuthorizeData> for PaymentsPreProcessingData {
             metadata: data.metadata.map(Secret::new),
             customer_acceptance: data.customer_acceptance,
             setup_future_usage: data.setup_future_usage,
+            is_stored_credential: data.is_stored_credential,
         })
     }
 }
@@ -750,6 +754,7 @@ impl TryFrom<CompleteAuthorizeData> for PaymentsPreProcessingData {
             metadata: data.connector_meta.map(Secret::new),
             customer_acceptance: data.customer_acceptance,
             setup_future_usage: data.setup_future_usage,
+            is_stored_credential: data.is_stored_credential,
         })
     }
 }
@@ -818,6 +823,7 @@ pub struct CompleteAuthorizeData {
     pub merchant_account_id: Option<Secret<String>>,
     pub merchant_config_currency: Option<storage_enums::Currency>,
     pub threeds_method_comp_ind: Option<api_models::payments::ThreeDsCompletionIndicator>,
+    pub is_stored_credential: Option<bool>,
 }
 
 #[derive(Debug, Clone)]
@@ -1406,6 +1412,7 @@ pub struct SetupMandateRequestData {
     pub enable_partial_authorization:
         Option<common_types::primitive_wrappers::EnablePartialAuthorizationBool>,
     pub payment_channel: Option<storage_enums::PaymentChannel>,
+    pub is_stored_credential: Option<bool>,
 }
 
 #[derive(Debug, Clone)]
diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs
index ac225861b45..d91f1007232 100644
--- a/crates/router/src/core/payment_methods/cards.rs
+++ b/crates/router/src/core/payment_methods/cards.rs
@@ -3043,6 +3043,7 @@ pub async fn list_payment_methods(
             surcharge_amount: None,
             tax_amount: None,
             routing_approach,
+            is_stored_credential: None,
         };
 
         state
diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs
index 10d72baf282..9f8551e7702 100644
--- a/crates/router/src/core/payments/helpers.rs
+++ b/crates/router/src/core/payments/helpers.rs
@@ -4804,6 +4804,7 @@ impl AttemptType {
             connector_request_reference_id: None,
             network_transaction_id: None,
             network_details: None,
+            is_stored_credential: old_payment_attempt.is_stored_credential,
         }
     }
 
@@ -7843,3 +7844,20 @@ pub async fn get_merchant_connector_account_v2(
         .attach_printable("merchant_connector_id is not provided"),
     }
 }
+
+pub fn is_stored_credential(
+    recurring_details: &Option<RecurringDetails>,
+    payment_token: &Option<String>,
+    is_mandate: bool,
+    is_stored_credential_prev: Option<bool>,
+) -> Option<bool> {
+    if is_stored_credential_prev == Some(true)
+        || recurring_details.is_some()
+        || payment_token.is_some()
+        || is_mandate
+    {
+        Some(true)
+    } else {
+        is_stored_credential_prev
+    }
+}
diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs
index 2c867aa6085..6ce1aa8af7d 100644
--- a/crates/router/src/core/payments/operations/payment_confirm.rs
+++ b/crates/router/src/core/payments/operations/payment_confirm.rs
@@ -1934,7 +1934,12 @@ impl<F: Clone + Sync> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for
         };
 
         let card_discovery = payment_data.get_card_discovery_for_card_payment_method();
-
+        let is_stored_credential = helpers::is_stored_credential(
+            &payment_data.recurring_details,
+            &payment_data.pm_token,
+            payment_data.mandate_id.is_some(),
+            payment_data.payment_attempt.is_stored_credential,
+        );
         let payment_attempt_fut = tokio::spawn(
             async move {
                 m_db.update_payment_attempt_with_attempt_id(
@@ -1988,6 +1993,7 @@ impl<F: Clone + Sync> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for
                             .payment_attempt
                             .network_transaction_id
                             .clone(),
+                        is_stored_credential,
                         request_extended_authorization: payment_data
                             .payment_attempt
                             .request_extended_authorization,
@@ -2200,7 +2206,13 @@ impl<F: Send + Clone + Sync> ValidateRequest<F, api::PaymentsRequest, PaymentDat
             &request.payment_token,
             &request.mandate_id,
         )?;
-
+        request.validate_stored_credential().change_context(
+            errors::ApiErrorResponse::InvalidRequestData {
+                message:
+                    "is_stored_credential should be true when reusing stored payment method data"
+                        .to_string(),
+            },
+        )?;
         let payment_id = request
             .payment_id
             .clone()
diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs
index e88a5d51ddd..55a868beec9 100644
--- a/crates/router/src/core/payments/operations/payment_create.rs
+++ b/crates/router/src/core/payments/operations/payment_create.rs
@@ -884,7 +884,12 @@ impl<F: Clone + Sync> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for
             .map(|surcharge_details| surcharge_details.tax_on_surcharge_amount);
 
         let routing_approach = payment_data.payment_attempt.routing_approach.clone();
-
+        let is_stored_credential = helpers::is_stored_credential(
+            &payment_data.recurring_details,
+            &payment_data.pm_token,
+            payment_data.mandate_id.is_some(),
+            payment_data.payment_attempt.is_stored_credential,
+        );
         payment_data.payment_attempt = state
             .store
             .update_payment_attempt_with_attempt_id(
@@ -902,6 +907,7 @@ impl<F: Clone + Sync> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for
                     updated_by: storage_scheme.to_string(),
                     merchant_connector_id,
                     routing_approach,
+                    is_stored_credential,
                 },
                 storage_scheme,
             )
@@ -1023,6 +1029,14 @@ impl<F: Send + Clone + Sync> ValidateRequest<F, api::PaymentsRequest, PaymentDat
             &request.mandate_id,
         )?;
 
+        request.validate_stored_credential().change_context(
+            errors::ApiErrorResponse::InvalidRequestData {
+                message:
+                    "is_stored_credential should be true when reusing stored payment method data"
+                        .to_string(),
+            },
+        )?;
+
         helpers::validate_overcapture_request(
             &request.enable_overcapture,
             &request.capture_method,
@@ -1313,6 +1327,12 @@ impl PaymentCreate {
             address_id => address_id,
         };
 
+        let is_stored_credential = helpers::is_stored_credential(
+            &request.recurring_details,
+            &request.payment_token,
+            request.mandate_id.is_some(),
+            request.is_stored_credential,
+        );
         Ok((
             storage::PaymentAttemptNew {
                 payment_id: payment_id.to_owned(),
@@ -1395,6 +1415,7 @@ impl PaymentCreate {
                 connector_request_reference_id: None,
                 network_transaction_id:None,
                 network_details:None,
+                is_stored_credential
             },
             additional_pm_data,
 
diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs
index 020b7c60280..cfd57346625 100644
--- a/crates/router/src/core/payments/operations/payment_update.rs
+++ b/crates/router/src/core/payments/operations/payment_update.rs
@@ -1062,7 +1062,6 @@ impl<F: Send + Clone + Sync> ValidateRequest<F, api::PaymentsRequest, PaymentDat
             &request.payment_token,
             &request.mandate_id,
         )?;
-
         let _request_straight_through: Option<api::routing::StraightThroughAlgorithm> = request
             .routing
             .clone()
diff --git a/crates/router/src/core/payments/retry.rs b/crates/router/src/core/payments/retry.rs
index e8b7a9914b6..d76d4df6b07 100644
--- a/crates/router/src/core/payments/retry.rs
+++ b/crates/router/src/core/payments/retry.rs
@@ -748,6 +748,7 @@ pub fn make_new_payment_attempt(
         connector_request_reference_id: Default::default(),
         network_transaction_id: old_payment_attempt.network_transaction_id,
         network_details: Default::default(),
+        is_stored_credential: old_payment_attempt.is_stored_credential,
     }
 }
 
diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs
index 711b05154b8..fd18e6dda98 100644
--- a/crates/router/src/core/payments/transformers.rs
+++ b/crates/router/src/core/payments/transformers.rs
@@ -436,6 +436,7 @@ pub async fn construct_payment_router_data_for_authorize<'a>(
         payment_channel: None,
         enable_partial_authorization: payment_data.payment_intent.enable_partial_authorization,
         enable_overcapture: None,
+        is_stored_credential: None,
     };
     let connector_mandate_request_reference_id = payment_data
         .payment_attempt
@@ -1491,6 +1492,7 @@ pub async fn construct_payment_router_data_for_setup_mandate<'a>(
         payment_channel: None,
         enrolled_for_3ds: true,
         related_transaction_id: None,
+        is_stored_credential: None,
     };
     let connector_mandate_request_reference_id = payment_data
         .payment_attempt
@@ -3662,6 +3664,7 @@ where
             network_details: payment_attempt
                 .network_details
                 .map(NetworkDetails::foreign_from),
+            is_stored_credential: payment_attempt.is_stored_credential,
             request_extended_authorization: payment_attempt.request_extended_authorization,
         };
 
@@ -3963,6 +3966,7 @@ impl ForeignFrom<(storage::PaymentIntent, storage::PaymentAttempt)> for api::Pay
             enable_overcapture: pi.enable_overcapture,
             is_overcapture_enabled: pa.is_overcapture_enabled,
             network_details: pa.network_details.map(NetworkDetails::foreign_from),
+            is_stored_credential:pa.is_stored_credential,
             request_extended_authorization: pa.request_extended_authorization,
         }
     }
@@ -4296,6 +4300,7 @@ impl<F: Clone> TryFrom<PaymentAdditionalData<'_, F>> for types::PaymentsAuthoriz
             payment_channel: None,
             enable_partial_authorization: None,
             enable_overcapture: None,
+            is_stored_credential: None,
         })
     }
 }
@@ -4530,6 +4535,7 @@ impl<F: Clone> TryFrom<PaymentAdditionalData<'_, F>> for types::PaymentsAuthoriz
             payment_channel: payment_data.payment_intent.payment_channel,
             enable_partial_authorization: payment_data.payment_intent.enable_partial_authorization,
             enable_overcapture: payment_data.payment_intent.enable_overcapture,
+            is_stored_credential: payment_data.payment_attempt.is_stored_credential,
         })
     }
 }
@@ -5505,6 +5511,7 @@ impl<F: Clone> TryFrom<PaymentAdditionalData<'_, F>> for types::SetupMandateRequ
             payment_channel: payment_data.payment_intent.payment_channel,
             related_transaction_id: None,
             enrolled_for_3ds: true,
+            is_stored_credential: payment_data.payment_attempt.is_stored_credential,
         })
     }
 }
@@ -5648,6 +5655,7 @@ impl<F: Clone> TryFrom<PaymentAdditionalData<'_, F>> for types::CompleteAuthoriz
             merchant_account_id,
             merchant_config_currency,
             threeds_method_comp_ind: payment_data.threeds_method_comp_ind,
+            is_stored_credential: payment_data.payment_attempt.is_stored_credential,
         })
     }
 }
@@ -5758,6 +5766,7 @@ impl<F: Clone> TryFrom<PaymentAdditionalData<'_, F>> for types::PaymentsPreProce
             metadata: payment_data.payment_intent.metadata.map(Secret::new),
             customer_acceptance: payment_data.customer_acceptance,
             setup_future_usage: payment_data.payment_intent.setup_future_usage,
+            is_stored_credential: payment_data.payment_attempt.is_stored_credential,
         })
     }
 }
diff --git a/crates/router/src/db/events.rs b/crates/router/src/db/events.rs
index 0058c9fd566..c31b106dbfc 100644
--- a/crates/router/src/db/events.rs
+++ b/crates/router/src/db/events.rs
@@ -1411,6 +1411,7 @@ mod tests {
             is_overcapture_enabled: None,
             enable_overcapture: None,
             network_details: None,
+            is_stored_credential: None,
             request_extended_authorization: None,
         };
         let content =
diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs
index a4f024eb81c..def5782d5d5 100644
--- a/crates/router/src/types.rs
+++ b/crates/router/src/types.rs
@@ -1242,6 +1242,7 @@ impl ForeignFrom<&SetupMandateRouterData> for PaymentsAuthorizeData {
             payment_channel: None,
             enable_partial_authorization: data.request.enable_partial_authorization,
             enable_overcapture: None,
+            is_stored_credential: data.request.is_stored_credential,
         }
     }
 }
diff --git a/crates/router/src/types/api/verify_connector.rs b/crates/router/src/types/api/verify_connector.rs
index d20bcbfe64f..d233c0696c8 100644
--- a/crates/router/src/types/api/verify_connector.rs
+++ b/crates/router/src/types/api/verify_connector.rs
@@ -69,6 +69,7 @@ impl VerifyConnectorData {
             payment_channel: None,
             enable_partial_authorization: None,
             enable_overcapture: None,
+            is_stored_credential: None,
         }
     }
 
diff --git a/crates/router/src/types/storage/payment_attempt.rs b/crates/router/src/types/storage/payment_attempt.rs
index d8d3935e6f7..8332135b312 100644
--- a/crates/router/src/types/storage/payment_attempt.rs
+++ b/crates/router/src/types/storage/payment_attempt.rs
@@ -229,6 +229,7 @@ mod tests {
             connector_request_reference_id: Default::default(),
             network_transaction_id: Default::default(),
             network_details: Default::default(),
+            is_stored_credential: None,
         };
 
         let store = state
@@ -323,6 +324,7 @@ mod tests {
             connector_request_reference_id: Default::default(),
             network_transaction_id: Default::default(),
             network_details: Default::default(),
+            is_stored_credential: Default::default(),
         };
         let store = state
             .stores
@@ -430,6 +432,7 @@ mod tests {
             connector_request_reference_id: Default::default(),
             network_transaction_id: Default::default(),
             network_details: Default::default(),
+            is_stored_credential: Default::default(),
         };
         let store = state
             .stores
diff --git a/crates/router/src/utils/user/sample_data.rs b/crates/router/src/utils/user/sample_data.rs
index a49e544097c..0fd23ee2123 100644
--- a/crates/router/src/utils/user/sample_data.rs
+++ b/crates/router/src/utils/user/sample_data.rs
@@ -394,6 +394,7 @@ pub async fn generate_sample_data(
             connector_request_reference_id: None,
             network_transaction_id: None,
             network_details: None,
+            is_stored_credential: None,
         };
 
         let refund = if refunds_count < number_of_refunds && !is_failed_payment {
diff --git a/crates/router/tests/connectors/utils.rs b/crates/router/tests/connectors/utils.rs
index b2582d7e3fe..34dc5735c91 100644
--- a/crates/router/tests/connectors/utils.rs
+++ b/crates/router/tests/connectors/utils.rs
@@ -1006,6 +1006,7 @@ impl Default for PaymentAuthorizeType {
             payment_channel: None,
             enable_partial_authorization: None,
             enable_overcapture: None,
+            is_stored_credential: None,
         };
         Self(data)
     }
diff --git a/crates/router/tests/payments.rs b/crates/router/tests/payments.rs
index 2010707067a..85801152bda 100644
--- a/crates/router/tests/payments.rs
+++ b/crates/router/tests/payments.rs
@@ -471,6 +471,7 @@ async fn payments_create_core() {
         is_overcapture_enabled: None,
         enable_overcapture: None,
         network_details: None,
+        is_stored_credential: None,
         request_extended_authorization: None,
     };
     let expected_response =
@@ -756,6 +757,7 @@ async fn payments_create_core_adyen_no_redirect() {
             is_overcapture_enabled: None,
             enable_overcapture: None,
             network_details: None,
+            is_stored_credential: None,
             request_extended_authorization: None,
         },
         vec![],
diff --git a/crates/router/tests/payments2.rs b/crates/router/tests/payments2.rs
index ef7f4357640..1378fac9427 100644
--- a/crates/router/tests/payments2.rs
+++ b/crates/router/tests/payments2.rs
@@ -233,6 +233,7 @@ async fn payments_create_core() {
         is_overcapture_enabled: None,
         enable_overcapture: None,
         network_details: None,
+        is_stored_credential: None,
         request_extended_authorization: None,
     };
 
@@ -526,6 +527,7 @@ async fn payments_create_core_adyen_no_redirect() {
             is_overcapture_enabled: None,
             enable_overcapture: None,
             network_details: None,
+            is_stored_credential: None,
             request_extended_authorization: None,
         },
         vec![],
diff --git a/crates/storage_impl/src/mock_db/payment_attempt.rs b/crates/storage_impl/src/mock_db/payment_attempt.rs
index 609bb531a86..2bf5daac6b9 100644
--- a/crates/storage_impl/src/mock_db/payment_attempt.rs
+++ b/crates/storage_impl/src/mock_db/payment_attempt.rs
@@ -241,6 +241,7 @@ impl PaymentAttemptInterface for MockDb {
             network_transaction_id: payment_attempt.network_transaction_id,
             is_overcapture_enabled: None,
             network_details: payment_attempt.network_details,
+            is_stored_credential: payment_attempt.is_stored_credential,
         };
         payment_attempts.push(payment_attempt.clone());
         Ok(payment_attempt)
diff --git a/crates/storage_impl/src/payments/payment_attempt.rs b/crates/storage_impl/src/payments/payment_attempt.rs
index 6a739f0a6c5..1cfe605cd0e 100644
--- a/crates/storage_impl/src/payments/payment_attempt.rs
+++ b/crates/storage_impl/src/payments/payment_attempt.rs
@@ -695,6 +695,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
                     network_transaction_id: payment_attempt.network_transaction_id.clone(),
                     is_overcapture_enabled: None,
                     network_details: payment_attempt.network_details.clone(),
+                    is_stored_credential: payment_attempt.is_stored_credential,
                 };
 
                 let field = format!("pa_{}", created_attempt.attempt_id);
@@ -1906,6 +1907,7 @@ impl DataModelExt for PaymentAttempt {
             network_transaction_id: self.network_transaction_id,
             is_overcapture_enabled: self.is_overcapture_enabled,
             network_details: self.network_details,
+            is_stored_credential: self.is_stored_credential,
         }
     }
 
@@ -2002,6 +2004,7 @@ impl DataModelExt for PaymentAttempt {
             network_transaction_id: storage_model.network_transaction_id,
             is_overcapture_enabled: storage_model.is_overcapture_enabled,
             network_details: storage_model.network_details,
+            is_stored_credential: storage_model.is_stored_credential,
         }
     }
 }
@@ -2095,6 +2098,7 @@ impl DataModelExt for PaymentAttemptNew {
             connector_request_reference_id: self.connector_request_reference_id,
             network_transaction_id: self.network_transaction_id,
             network_details: self.network_details,
+            is_stored_credential: self.is_stored_credential,
         }
     }
 
@@ -2181,6 +2185,7 @@ impl DataModelExt for PaymentAttemptNew {
             connector_request_reference_id: storage_model.connector_request_reference_id,
             network_transaction_id: storage_model.network_transaction_id,
             network_details: storage_model.network_details,
+            is_stored_credential: storage_model.is_stored_credential,
         }
     }
 }
diff --git a/migrations/2025-09-22-084821_add_stored_credentials_payment_intent/down.sql b/migrations/2025-09-22-084821_add_stored_credentials_payment_intent/down.sql
new file mode 100644
index 00000000000..8398e8ea1ee
--- /dev/null
+++ b/migrations/2025-09-22-084821_add_stored_credentials_payment_intent/down.sql
@@ -0,0 +1,2 @@
+-- This file should undo anything in `up.sql`
+ALTER TABLE payment_attempt DROP COLUMN is_stored_credential;
diff --git a/migrations/2025-09-22-084821_add_stored_credentials_payment_intent/up.sql b/migrations/2025-09-22-084821_add_stored_credentials_payment_intent/up.sql
new file mode 100644
index 00000000000..17762e006a8
--- /dev/null
+++ b/migrations/2025-09-22-084821_add_stored_credentials_payment_intent/up.sql
@@ -0,0 +1,2 @@
+-- Your SQL goes here
+ALTER TABLE payment_attempt ADD COLUMN IF NOT EXISTS is_stored_credential BOOLEAN;

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

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

## Description
<!-- Describe your changes in detail -->

Connectors like Nuvei requires a field called as `storedCredentialMode` which represents if the merchant is using a card details which they previously used for same connector or any other PSP. This is used for risk lowering based on PSP's.

- Make a `is_stored_credential` in payment request if the merchant knows this is stored_credential. ( in this case merchant stores the card in his server . No way hyperswitch knows if this is stored or not)
- if `is_stored_credential` = false but using payment token or mandate or recurring flow  : throw error.
- if `is_stored_credential` = None but using payment token or mandate or recurring flow : make the is_stored_credential as true in core

### Test cases 



## Request    `is_stored_credential` = true

```json
{
    "amount": 30000,
    "capture_method": "automatic",
    "currency": "USD",
    "confirm": true,
    "customer_acceptance": {
        "acceptance_type": "offline",
        "accepted_at": "1963-05-03T04:07:52.723Z",
        "online": {
            "ip_address": "127.0.0.1",
            "user_agent": "amet irure esse"
        }
    },
    "connector":["nuvei"],
    "customer_id": "nidthxxinn",
    "return_url": "https://www.google.com",
    "payment_method": "card",
    "payment_method_type": "credit",
    "authentication_type": "no_three_ds",
    "description": "hellow world",
    "billing": {
        "address": {
            "zip": "560095",
            "country": "US",
            "first_name": "Sakil",
            "last_name": "Mostak",
            "line1": "Fasdf",
            "line2": "Fasdf",
            "city": "Fasdf"
        }
    },
    "browser_info": {
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
        "ip_address": "192.168.1.1",
        "java_enabled": false,
        "java_script_enabled": true,
        "language": "en-US",
        "color_depth": 24,
        "screen_height": 1080,
        "screen_width": 1920,
        "time_zone": 330,
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
    },
    "email": "hello@gmail.com",
    "is_stored_credential":true,
    "payment_method_data": {
        "card": {
            "card_number": "4000000000009995",
            "card_exp_month": "01",
            "card_exp_year": "2026",
            "card_holder_name": "John Smith",
            "card_cvc": "100"
        }
    }
}
```

## Connector Request

```json
{
  "timeStamp": "20250923113846",
  "sessionToken": "*** alloc::string::String ***",
  "merchantId": "*** alloc::string::String ***",
  "merchantSiteId": "*** alloc::string::String ***",
  "clientRequestId": "*** alloc::string::String ***",
  "amount": "300.00",
  "currency": "USD",
  "userTokenId": "nidthxxinn",
  "clientUniqueId": "",
  "transactionType": "Sale",
  "paymentOption": {
    "card": {
      "cardNumber": "400000**********",
      "cardHolderName": "*** alloc::string::String ***",
      "expirationMonth": "*** alloc::string::String ***",
      "expirationYear": "*** alloc::string::String ***",
      "CVV": "*** alloc::string::String ***",
      "storedCredentials": {
        "storedCredentialsMode": "1" // stored creds
      }
    }
  },
  "deviceDetails": {
    "ipAddress": "192.**.**.**"
  },
  "checksum": "*** alloc::string::String ***",
  "billingAddress": {
    "email": "*****@gmail.com",
    "firstName": "*** alloc::string::String ***",
    "lastName": "*** alloc::string::String ***",
    "country": "US",
    "city": "*** alloc::string::String ***",
    "address": "*** alloc::string::String ***",
    "zip": "*** alloc::string::String ***",
    "addressLine2": "*** alloc::string::String ***"
  },
  "urlDetails": {
    "successUrl": "https://google.com",
    "failureUrl": "https://google.com",
    "pendingUrl": "https://google.com"
  },
  "amountDetails": {
    "totalTax": null,
    "totalShipping": null,
    "totalHandling": null,
    "totalDiscount": null
  }
}
```

### hs response

```json
{
    "payment_id": "pay_kaDCghnJynclrXvAZ3Hr",
    "merchant_id": "merchant_1758711570",
    "status": "succeeded",
    "amount": 4324,
    "net_amount": 4324,
    "shipping_cost": null,
    "amount_capturable": 0,
    "amount_received": null,
    "connector": "nuvei",
    "client_secret": "pay_kaDCghnJynclrXvAZ3Hr_secret_yYbm6qHvrDNGSZixiLoo",
    "created": "2025-09-24T11:12:09.304Z",
    "currency": "EUR",
    "customer_id": "nidthhxxinn",
    "customer": {
        "id": "nidthhxxinn",
        "name": null,
        "email": "hello@gmail.com",
        "phone": null,
        "phone_country_code": null
    },
    "description": "hellow world",
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": "off_session",
    "off_session": null,
    "capture_on": null,
    "capture_method": "automatic",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "0005",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "378282",
            "card_extended_bin": null,
            "card_exp_month": "10",
            "card_exp_year": "50",
            "card_holder_name": "morino",
            "payment_checks": {
                "avs_result": "",
                "avs_description": null,
                "card_validation_result": "",
                "card_validation_description": null
            },
            "authentication_data": {
                "challengePreferenceReason": "12"
            }
        },
        "billing": null
    },
    "payment_token": "token_AivOwxhMg1qSr4REuZA9",
    "shipping": null,
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "joseph",
            "last_name": "Doe",
            "origin_zip": null
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": null
    },
    "order_details": null,
    "email": "hello@gmail.com",
    "name": null,
    "phone": null,
    "return_url": "https://www.google.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": null,
    "statement_descriptor_suffix": null,
    "next_action": null,
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": null,
    "payment_method_type": "credit",
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": {
        "customer_id": "nidthhxxinn",
        "created_at": 1758712329,
        "expires": 1758715929,
        "secret": "epk_20c56304f56d4bd093ccbc5e642138be"
    },
    "manual_retry_allowed": null,
    "connector_transaction_id": "7110000000017350215",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": {
        "redirect_response": null,
        "search_tags": null,
        "apple_pay_recurring_details": null,
        "gateway_system": "direct"
    },
    "reference_id": "9126580111",
    "payment_link": null,
    "profile_id": "pro_Gs5O4gNYQYl12fxACtnf",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_nnxyjSuMhV7SIzNRzEmD",
    "incremental_authorization_allowed": false,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-09-24T11:27:09.304Z",
    "fingerprint": null,
    "browser_info": {
        "language": "en-US",
        "time_zone": 330,
        "ip_address": "192.168.1.1",
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
        "color_depth": 24,
        "java_enabled": false,
        "screen_width": 1920,
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
        "screen_height": 1080,
        "java_script_enabled": true
    },
    "payment_channel": null,
    "payment_method_id": "pm_r5onP5L210YtcIwJR97v",
    "network_transaction_id": "483299310332488",
    "payment_method_status": "active",
    "updated": "2025-09-24T11:12:15.875Z",
    "split_payments": null,
    "frm_metadata": null,
    "extended_authorization_applied": null,
    "capture_before": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": "2512601111",
    "card_discovery": "manual",
    "force_3ds_challenge": false,
    "force_3ds_challenge_trigger": false,
    "issuer_error_code": null,
    "issuer_error_message": null,
    "is_iframe_redirection_enabled": null,
    "whole_connector_response": null,
    "enable_partial_authorization": null,
    "enable_overcapture": null,
    "is_overcapture_enabled": null,
    "network_details": null,
    "is_stored_credential": true //updated
}
```

## connector request when `is_stored_credential`=false

```json
{
  "timeStamp": "20250923114107",
  "sessionToken": "*** alloc::string::String ***",
  "merchantId": "*** alloc::string::String ***",
  "merchantSiteId": "*** alloc::string::String ***",
  "clientRequestId": "*** alloc::string::String ***",
  "amount": "300.00",
  "currency": "USD",
  "userTokenId": "nidthxxinn",
  "clientUniqueId": "",
  "transactionType": "Sale",
  "paymentOption": {
    "card": {
      "cardNumber": "400000**********",
      "cardHolderName": "*** alloc::string::String ***",
      "expirationMonth": "*** alloc::string::String ***",
      "expirationYear": "*** alloc::string::String ***",
      "CVV": "*** alloc::string::String ***"
    }
  },
  "deviceDetails": {
    "ipAddress": "192.**.**.**"
  },
  "checksum": "*** alloc::string::String ***",
  "billingAddress": {
    "email": "*****@gmail.com",
    "firstName": "*** alloc::string::String ***",
    "lastName": "*** alloc::string::String ***",
    "country": "US",
    "city": "*** alloc::string::String ***",
    "address": "*** alloc::string::String ***",
    "zip": "*** alloc::string::String ***",
    "addressLine2": "*** alloc::string::String ***"
  },
  "urlDetails": {
    "successUrl": "https://google.com",
    "failureUrl": "https://google.com",
    "pendingUrl": "https://google.com"
  },
  "amountDetails": {
    "totalTax": null,
    "totalShipping": null,
    "totalHandling": null,
    "totalDiscount": null
  }
}
```

## Error msg when is_stored_credential = false but using payment token flow in HS

- make CIT and get payment method token

```json
{
    "amount": 333,
    "currency": "EUR",
    "customer_id": "nidthhxxinn",
    "confirm": true,
    "off_session": true,
    "recurring_details": {
        "type": "payment_method_id",
        "data": "{{payment_method_id}}"//pass the payment method id here
    },
    "is_stored_credential": false, // false should throw error
       "browser_info": {
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
        "ip_address": "192.168.1.1",
        "java_enabled": false,
        "java_script_enabled": true,
        "language": "en-US",
        "color_depth": 24,
        "screen_height": 1080,
        "screen_width": 1920,
        "time_zone": 330,
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
    }
}
```

```json
{
    "error": {
        "type": "invalid_request",
        "message": "is_stored_credential should be true when reusing stored payment method data",
        "code": "IR_16"
    }
}
```

