diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs
index 3385b63369..b39355d2c9 100644
--- a/crates/api_models/src/payments.rs
+++ b/crates/api_models/src/payments.rs
@@ -1288,15 +1288,56 @@ mod payment_method_data_serde {
             OptionalPaymentMethod(serde_json::Value),
         }
 
+        // This struct is an intermediate representation
+        // This is required in order to catch deserialization errors when deserializing `payment_method_data`
+        // The #[serde(flatten)] attribute applied on `payment_method_data` discards
+        // any of the error when deserializing and deserializes to an option instead
+        #[derive(serde::Deserialize, Debug)]
+        struct __InnerPaymentMethodData {
+            billing: Option
,
+            #[serde(flatten)]
+            payment_method_data: Option,
+        }
+
         let deserialize_to_inner = __Inner::deserialize(deserializer)?;
+
         match deserialize_to_inner {
             __Inner::OptionalPaymentMethod(value) => {
-                let parsed_value = serde_json::from_value::(value)
+                let parsed_value = serde_json::from_value::<__InnerPaymentMethodData>(value)
                     .map_err(|serde_json_error| {
                         serde::de::Error::custom(serde_json_error.to_string())
                     })?;
 
-                Ok(Some(parsed_value))
+                let payment_method_data = if let Some(payment_method_data_value) =
+                    parsed_value.payment_method_data
+                {
+                    // Even though no data is passed, the flatten serde_json::Value is deserialized as Some(Object {})
+                    if let serde_json::Value::Object(ref inner_map) = payment_method_data_value {
+                        if inner_map.is_empty() {
+                            None
+                        } else {
+                            Some(
+                                serde_json::from_value::(
+                                    payment_method_data_value,
+                                )
+                                .map_err(|serde_json_error| {
+                                    serde::de::Error::custom(serde_json_error.to_string())
+                                })?,
+                            )
+                        }
+                    } else {
+                        Err(serde::de::Error::custom(
+                            "Expected a map for payment_method_data",
+                        ))?
+                    }
+                } else {
+                    None
+                };
+
+                Ok(Some(PaymentMethodDataRequest {
+                    payment_method_data,
+                    billing: parsed_value.billing,
+                }))
             }
             __Inner::RewardString(inner_string) => {
                 let payment_method_data = match inner_string.as_str() {
@@ -1305,7 +1346,7 @@ mod payment_method_data_serde {
                 };
 
                 Ok(Some(PaymentMethodDataRequest {
-                    payment_method_data,
+                    payment_method_data: Some(payment_method_data),
                     billing: None,
                 }))
             }
@@ -1320,21 +1361,29 @@ mod payment_method_data_serde {
         S: Serializer,
     {
         if let Some(payment_method_data_request) = payment_method_data_request {
-            match payment_method_data_request.payment_method_data {
-                PaymentMethodData::Reward => serializer.serialize_str("reward"),
-                PaymentMethodData::CardRedirect(_)
-                | PaymentMethodData::BankDebit(_)
-                | PaymentMethodData::BankRedirect(_)
-                | PaymentMethodData::BankTransfer(_)
-                | PaymentMethodData::CardToken(_)
-                | PaymentMethodData::Crypto(_)
-                | PaymentMethodData::GiftCard(_)
-                | PaymentMethodData::PayLater(_)
-                | PaymentMethodData::Upi(_)
-                | PaymentMethodData::Voucher(_)
-                | PaymentMethodData::Card(_)
-                | PaymentMethodData::MandatePayment
-                | PaymentMethodData::Wallet(_) => payment_method_data_request.serialize(serializer),
+            if let Some(payment_method_data) =
+                payment_method_data_request.payment_method_data.as_ref()
+            {
+                match payment_method_data {
+                    PaymentMethodData::Reward => serializer.serialize_str("reward"),
+                    PaymentMethodData::CardRedirect(_)
+                    | PaymentMethodData::BankDebit(_)
+                    | PaymentMethodData::BankRedirect(_)
+                    | PaymentMethodData::BankTransfer(_)
+                    | PaymentMethodData::CardToken(_)
+                    | PaymentMethodData::Crypto(_)
+                    | PaymentMethodData::GiftCard(_)
+                    | PaymentMethodData::PayLater(_)
+                    | PaymentMethodData::Upi(_)
+                    | PaymentMethodData::Voucher(_)
+                    | PaymentMethodData::Card(_)
+                    | PaymentMethodData::MandatePayment
+                    | PaymentMethodData::Wallet(_) => {
+                        payment_method_data_request.serialize(serializer)
+                    }
+                }
+            } else {
+                payment_method_data_request.serialize(serializer)
             }
         } else {
             serializer.serialize_none()
@@ -1345,7 +1394,7 @@ mod payment_method_data_serde {
 #[derive(Debug, Clone, serde::Deserialize, serde::Serialize, ToSchema, Eq, PartialEq)]
 pub struct PaymentMethodDataRequest {
     #[serde(flatten)]
-    pub payment_method_data: PaymentMethodData,
+    pub payment_method_data: Option,
     /// billing details for the payment method.
     /// This billing details will be passed to the processor as billing address.
     /// If not passed, then payment.billing will be considered
@@ -4715,7 +4764,7 @@ mod payments_request_api_contract {
         let payments_request = serde_json::from_str::(payments_request);
         assert!(payments_request.is_ok());
 
-        if let PaymentMethodData::Card(card_data) = payments_request
+        if let Some(PaymentMethodData::Card(card_data)) = payments_request
             .unwrap()
             .payment_method_data
             .unwrap()
@@ -4747,7 +4796,7 @@ mod payments_request_api_contract {
                 .payment_method_data
                 .unwrap()
                 .payment_method_data,
-            PaymentMethodData::Reward
+            Some(PaymentMethodData::Reward)
         );
     }
 }
diff --git a/crates/router/src/compatibility/stripe/payment_intents/types.rs b/crates/router/src/compatibility/stripe/payment_intents/types.rs
index 404d0e93db..eed80a1128 100644
--- a/crates/router/src/compatibility/stripe/payment_intents/types.rs
+++ b/crates/router/src/compatibility/stripe/payment_intents/types.rs
@@ -335,7 +335,9 @@ impl TryFrom for payments::PaymentsRequest {
                 pmd.payment_method_details
                     .as_ref()
                     .map(|spmd| payments::PaymentMethodDataRequest {
-                        payment_method_data: payments::PaymentMethodData::from(spmd.to_owned()),
+                        payment_method_data: Some(payments::PaymentMethodData::from(
+                            spmd.to_owned(),
+                        )),
                         billing: pmd.billing_details.clone().map(payments::Address::from),
                     })
             }),
diff --git a/crates/router/src/compatibility/stripe/setup_intents/types.rs b/crates/router/src/compatibility/stripe/setup_intents/types.rs
index d29bf235b5..03335d4272 100644
--- a/crates/router/src/compatibility/stripe/setup_intents/types.rs
+++ b/crates/router/src/compatibility/stripe/setup_intents/types.rs
@@ -246,7 +246,9 @@ impl TryFrom for payments::PaymentsRequest {
                 pmd.payment_method_details
                     .as_ref()
                     .map(|spmd| payments::PaymentMethodDataRequest {
-                        payment_method_data: payments::PaymentMethodData::from(spmd.to_owned()),
+                        payment_method_data: Some(payments::PaymentMethodData::from(
+                            spmd.to_owned(),
+                        )),
                         billing: pmd.billing_details.clone().map(payments::Address::from),
                     })
             }),
diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs
index be04d2fb1a..702b63b5c0 100644
--- a/crates/router/src/core/payments/helpers.rs
+++ b/crates/router/src/core/payments/helpers.rs
@@ -1159,7 +1159,7 @@ pub fn verify_mandate_details_for_recurring_payments(
 
 #[instrument(skip_all)]
 pub fn payment_attempt_status_fsm(
-    payment_method_data: &Option,
+    payment_method_data: Option<&api::payments::PaymentMethodData>,
     confirm: Option,
 ) -> storage_enums::AttemptStatus {
     match payment_method_data {
@@ -1172,7 +1172,7 @@ pub fn payment_attempt_status_fsm(
 }
 
 pub fn payment_intent_status_fsm(
-    payment_method_data: &Option,
+    payment_method_data: Option<&api::PaymentMethodData>,
     confirm: Option,
 ) -> storage_enums::IntentStatus {
     match payment_method_data {
@@ -2129,8 +2129,14 @@ pub(crate) fn validate_amount_to_capture(
 pub(crate) fn validate_payment_method_fields_present(
     req: &api::PaymentsRequest,
 ) -> RouterResult<()> {
+    let payment_method_data =
+        req.payment_method_data
+            .as_ref()
+            .and_then(|request_payment_method_data| {
+                request_payment_method_data.payment_method_data.as_ref()
+            });
     utils::when(
-        req.payment_method.is_none() && req.payment_method_data.is_some(),
+        req.payment_method.is_none() && payment_method_data.is_some(),
         || {
             Err(errors::ApiErrorResponse::MissingRequiredField {
                 field_name: "payment_method",
@@ -2152,7 +2158,7 @@ pub(crate) fn validate_payment_method_fields_present(
 
     utils::when(
         req.payment_method.is_some()
-            && req.payment_method_data.is_none()
+            && payment_method_data.is_none()
             && req.payment_token.is_none()
             && req.recurring_details.is_none(),
         || {
@@ -2194,14 +2200,14 @@ pub(crate) fn validate_payment_method_fields_present(
         };
 
     utils::when(
-        req.payment_method.is_some() && req.payment_method_data.is_some(),
+        req.payment_method.is_some() && payment_method_data.is_some(),
         || {
-            req.payment_method_data
-                .clone()
-                .map_or(Ok(()), |req_payment_method_data| {
+            payment_method_data
+                .cloned()
+                .map_or(Ok(()), |payment_method_data| {
                     req.payment_method.map_or(Ok(()), |req_payment_method| {
                         validate_payment_method_and_payment_method_data(
-                            req_payment_method_data.payment_method_data,
+                            payment_method_data,
                             req_payment_method,
                         )
                     })
@@ -3409,7 +3415,7 @@ impl AttemptType {
     // In case if fields are not overridden by the request then they contain the same data that was in the previous attempt provided it is populated in this function.
     #[inline(always)]
     fn make_new_payment_attempt(
-        payment_method_data: &Option,
+        payment_method_data: Option<&api_models::payments::PaymentMethodData>,
         old_payment_attempt: PaymentAttempt,
         new_attempt_count: i16,
         storage_scheme: enums::MerchantStorageScheme,
@@ -3507,7 +3513,11 @@ impl AttemptType {
                 let new_payment_attempt = db
                     .insert_payment_attempt(
                         Self::make_new_payment_attempt(
-                            &request.payment_method_data,
+                            request.payment_method_data.as_ref().and_then(
+                                |request_payment_method_data| {
+                                    request_payment_method_data.payment_method_data.as_ref()
+                                },
+                            ),
                             fetched_payment_attempt,
                             new_attempt_count,
                             storage_scheme,
@@ -3524,7 +3534,11 @@ impl AttemptType {
                         fetched_payment_intent,
                         storage::PaymentIntentUpdate::StatusAndAttemptUpdate {
                             status: payment_intent_status_fsm(
-                                &request.payment_method_data,
+                                request.payment_method_data.as_ref().and_then(
+                                    |request_payment_method_data| {
+                                        request_payment_method_data.payment_method_data.as_ref()
+                                    },
+                                ),
                                 Some(true),
                             ),
                             active_attempt_id: new_payment_attempt.attempt_id.clone(),
diff --git a/crates/router/src/core/payments/operations/payment_complete_authorize.rs b/crates/router/src/core/payments/operations/payment_complete_authorize.rs
index d4dc52ce27..d31ec14a72 100644
--- a/crates/router/src/core/payments/operations/payment_complete_authorize.rs
+++ b/crates/router/src/core/payments/operations/payment_complete_authorize.rs
@@ -138,7 +138,7 @@ impl
                     &request
                         .payment_method_data
                         .as_ref()
-                        .map(|pmd| pmd.payment_method_data.clone()),
+                        .and_then(|pmd| pmd.payment_method_data.clone()),
                     &request.payment_method_type,
                     &mandate_type,
                     &token,
@@ -284,7 +284,7 @@ impl
             payment_method_data: request
                 .payment_method_data
                 .as_ref()
-                .map(|pmd| pmd.payment_method_data.clone()),
+                .and_then(|pmd| pmd.payment_method_data.clone()),
             payment_method_info,
             force_sync: None,
             refunds: vec![],
diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs
index 79680cb80c..125f79956a 100644
--- a/crates/router/src/core/payments/operations/payment_confirm.rs
+++ b/crates/router/src/core/payments/operations/payment_confirm.rs
@@ -341,7 +341,7 @@ impl
             request
                 .payment_method_data
                 .as_ref()
-                .map(|pmd| pmd.payment_method_data.clone()),
+                .and_then(|pmd| pmd.payment_method_data.clone()),
         )?;
 
         payment_attempt.browser_info = browser_info;
@@ -412,7 +412,7 @@ impl
         let n_request_payment_method_data = request
             .payment_method_data
             .as_ref()
-            .map(|pmd| pmd.payment_method_data.clone());
+            .and_then(|pmd| pmd.payment_method_data.clone());
 
         let store = state.clone().store;
 
@@ -524,7 +524,7 @@ impl
             &request
                 .payment_method_data
                 .as_ref()
-                .map(|pmd| pmd.payment_method_data.clone()),
+                .and_then(|pmd| pmd.payment_method_data.clone()),
             &request.payment_method_type,
             &mandate_type,
             &token,
@@ -570,11 +570,12 @@ impl
         let payment_method_data_after_card_bin_call = request
             .payment_method_data
             .as_ref()
+            .and_then(|request_payment_method_data| {
+                request_payment_method_data.payment_method_data.as_ref()
+            })
             .zip(additional_pm_data)
             .map(|(payment_method_data, additional_payment_data)| {
-                payment_method_data
-                    .payment_method_data
-                    .apply_additional_payment_data(additional_payment_data)
+                payment_method_data.apply_additional_payment_data(additional_payment_data)
             });
         let authentication = payment_attempt.authentication_id.as_ref().async_map(|authentication_id| async move {
             state
diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs
index 78162fbfa6..aaebccd880 100644
--- a/crates/router/src/core/payments/operations/payment_create.rs
+++ b/crates/router/src/core/payments/operations/payment_create.rs
@@ -396,11 +396,14 @@ impl
         let payment_method_data_after_card_bin_call = request
             .payment_method_data
             .as_ref()
+            .and_then(|payment_method_data_from_request| {
+                payment_method_data_from_request
+                    .payment_method_data
+                    .as_ref()
+            })
             .zip(additional_payment_data)
             .map(|(payment_method_data, additional_payment_data)| {
-                payment_method_data
-                    .payment_method_data
-                    .apply_additional_payment_data(additional_payment_data)
+                payment_method_data.apply_additional_payment_data(additional_payment_data)
             });
 
         let amount = payment_attempt.get_total_amount().into();
@@ -702,7 +705,7 @@ impl ValidateRequest ValidateRequest,
     )> {
+        let payment_method_data =
+            request
+                .payment_method_data
+                .as_ref()
+                .and_then(|payment_method_data_request| {
+                    payment_method_data_request.payment_method_data.as_ref()
+                });
+
         let created_at @ modified_at @ last_synced = Some(common_utils::date_time::now());
-        let status =
-            helpers::payment_attempt_status_fsm(&request.payment_method_data, request.confirm);
+        let status = helpers::payment_attempt_status_fsm(payment_method_data, request.confirm);
         let (amount, currency) = (money.0, Some(money.1));
 
         let mut additional_pm_data = request
             .payment_method_data
             .as_ref()
+            .and_then(|payment_method_data_request| {
+                payment_method_data_request.payment_method_data.as_ref()
+            })
             .async_map(|payment_method_data| async {
-                helpers::get_additional_payment_data(
-                    &payment_method_data.payment_method_data,
-                    &*state.store,
-                )
-                .await
+                helpers::get_additional_payment_data(payment_method_data, &*state.store).await
             })
             .await;
 
@@ -944,8 +953,16 @@ impl PaymentCreate {
         session_expiry: PrimitiveDateTime,
     ) -> RouterResult {
         let created_at @ modified_at @ last_synced = Some(common_utils::date_time::now());
-        let status =
-            helpers::payment_intent_status_fsm(&request.payment_method_data, request.confirm);
+
+        let status = helpers::payment_intent_status_fsm(
+            request
+                .payment_method_data
+                .as_ref()
+                .and_then(|request_payment_method_data| {
+                    request_payment_method_data.payment_method_data.as_ref()
+                }),
+            request.confirm,
+        );
         let client_secret =
             crate::utils::generate_id(consts::ID_LENGTH, format!("{payment_id}_secret").as_str());
         let (amount, currency) = (money.0, Some(money.1));
diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs
index ecf1fe998b..804d1dbc80 100644
--- a/crates/router/src/core/payments/operations/payment_update.rs
+++ b/crates/router/src/core/payments/operations/payment_update.rs
@@ -81,7 +81,7 @@ impl
             request
                 .payment_method_data
                 .as_ref()
-                .map(|pmd| pmd.payment_method_data.clone()),
+                .and_then(|pmd| pmd.payment_method_data.clone()),
         )?;
 
         helpers::validate_payment_status_against_not_allowed_statuses(
@@ -265,7 +265,7 @@ impl
                 &request
                     .payment_method_data
                     .as_ref()
-                    .map(|pmd| pmd.payment_method_data.clone()),
+                    .and_then(|pmd| pmd.payment_method_data.clone()),
                 &request.payment_method_type,
                 &mandate_type,
                 &token,
@@ -430,7 +430,7 @@ impl
             payment_method_data: request
                 .payment_method_data
                 .as_ref()
-                .map(|pmd| pmd.payment_method_data.clone()),
+                .and_then(|pmd| pmd.payment_method_data.clone()),
             payment_method_info,
             force_sync: None,
             refunds: vec![],
diff --git a/crates/router/src/types/api/payments.rs b/crates/router/src/types/api/payments.rs
index 4fc3fb4452..e36c68c27d 100644
--- a/crates/router/src/types/api/payments.rs
+++ b/crates/router/src/types/api/payments.rs
@@ -261,7 +261,7 @@ mod payments_test {
         PaymentsRequest {
             amount: Some(Amount::from(200)),
             payment_method_data: Some(PaymentMethodDataRequest {
-                payment_method_data: PaymentMethodData::Card(card()),
+                payment_method_data: Some(PaymentMethodData::Card(card())),
                 billing: None,
             }),
             ..PaymentsRequest::default()
diff --git a/crates/router/tests/payments.rs b/crates/router/tests/payments.rs
index 7a990464da..646a11d4cd 100644
--- a/crates/router/tests/payments.rs
+++ b/crates/router/tests/payments.rs
@@ -317,7 +317,7 @@ async fn payments_create_core() {
         setup_future_usage: Some(api_enums::FutureUsage::OnSession),
         authentication_type: Some(api_enums::AuthenticationType::NoThreeDs),
         payment_method_data: Some(api::PaymentMethodDataRequest {
-            payment_method_data: api::PaymentMethodData::Card(api::Card {
+            payment_method_data: Some(api::PaymentMethodData::Card(api::Card {
                 card_number: "4242424242424242".to_string().try_into().unwrap(),
                 card_exp_month: "10".to_string().into(),
                 card_exp_year: "35".to_string().into(),
@@ -329,7 +329,7 @@ async fn payments_create_core() {
                 card_issuing_country: None,
                 bank_code: None,
                 nick_name: Some(masking::Secret::new("nick_name".into())),
-            }),
+            })),
             billing: None,
         }),
         payment_method: Some(api_enums::PaymentMethod::Card),
@@ -499,7 +499,7 @@ async fn payments_create_core_adyen_no_redirect() {
         setup_future_usage: Some(api_enums::FutureUsage::OnSession),
         authentication_type: Some(api_enums::AuthenticationType::NoThreeDs),
         payment_method_data: Some(api::PaymentMethodDataRequest {
-            payment_method_data: api::PaymentMethodData::Card(api::Card {
+            payment_method_data: Some(api::PaymentMethodData::Card(api::Card {
                 card_number: "5555 3412 4444 1115".to_string().try_into().unwrap(),
                 card_exp_month: "03".to_string().into(),
                 card_exp_year: "2030".to_string().into(),
@@ -511,7 +511,7 @@ async fn payments_create_core_adyen_no_redirect() {
                 card_issuing_country: None,
                 bank_code: None,
                 nick_name: Some(masking::Secret::new("nick_name".into())),
-            }),
+            })),
             billing: None,
         }),
         payment_method: Some(api_enums::PaymentMethod::Card),
diff --git a/crates/router/tests/payments2.rs b/crates/router/tests/payments2.rs
index cce589fb03..9b622d11fd 100644
--- a/crates/router/tests/payments2.rs
+++ b/crates/router/tests/payments2.rs
@@ -77,7 +77,7 @@ async fn payments_create_core() {
         setup_future_usage: None,
         authentication_type: Some(api_enums::AuthenticationType::NoThreeDs),
         payment_method_data: Some(api::PaymentMethodDataRequest {
-            payment_method_data: api::PaymentMethodData::Card(api::Card {
+            payment_method_data: Some(api::PaymentMethodData::Card(api::Card {
                 card_number: "4242424242424242".to_string().try_into().unwrap(),
                 card_exp_month: "10".to_string().into(),
                 card_exp_year: "35".to_string().into(),
@@ -89,7 +89,7 @@ async fn payments_create_core() {
                 card_issuing_country: None,
                 bank_code: None,
                 nick_name: Some(masking::Secret::new("nick_name".into())),
-            }),
+            })),
             billing: None,
         }),
         payment_method: Some(api_enums::PaymentMethod::Card),
@@ -266,7 +266,7 @@ async fn payments_create_core_adyen_no_redirect() {
         setup_future_usage: Some(api_enums::FutureUsage::OffSession),
         authentication_type: Some(api_enums::AuthenticationType::NoThreeDs),
         payment_method_data: Some(api::PaymentMethodDataRequest {
-            payment_method_data: api::PaymentMethodData::Card(api::Card {
+            payment_method_data: Some(api::PaymentMethodData::Card(api::Card {
                 card_number: "5555 3412 4444 1115".to_string().try_into().unwrap(),
                 card_exp_month: "03".to_string().into(),
                 card_exp_year: "2030".to_string().into(),
@@ -278,7 +278,7 @@ async fn payments_create_core_adyen_no_redirect() {
                 card_type: None,
                 card_issuing_country: None,
                 nick_name: Some(masking::Secret::new("nick_name".into())),
-            }),
+            })),
             billing: None,
         }),
 
diff --git a/openapi/openapi_spec.json b/openapi/openapi_spec.json
index d795387853..d278c50a38 100644
--- a/openapi/openapi_spec.json
+++ b/openapi/openapi_spec.json
@@ -12787,7 +12787,12 @@
       "PaymentMethodDataRequest": {
         "allOf": [
           {
-            "$ref": "#/components/schemas/PaymentMethodData"
+            "allOf": [
+              {
+                "$ref": "#/components/schemas/PaymentMethodData"
+              }
+            ],
+            "nullable": true
           },
           {
             "type": "object",