Bug: feat(core): setup platform merchant account



- Setup platform merchant account.
Platform merchant account is a special type of merchant account which can do operations on behalf of other merchant account present in the same organisation.
- Add APIs to create a platform merchant account / convert a merchant account into platform account.
- Feature should be disabled in sandbox and production.
diff --git a/config/deployments/integration_test.toml b/config/deployments/integration_test.toml
index 7fdc0c6d5e8..65ce1fdbc0a 100644
--- a/config/deployments/integration_test.toml
+++ b/config/deployments/integration_test.toml
@@ -428,3 +428,6 @@ card_networks = "Visa, AmericanExpress, Mastercard"
 
 [network_tokenization_supported_connectors]
 connector_list = "cybersource"
+
+[platform]
+enabled = true
diff --git a/config/deployments/production.toml b/config/deployments/production.toml
index 9c91c12f3b4..8900b0ac385 100644
--- a/config/deployments/production.toml
+++ b/config/deployments/production.toml
@@ -444,3 +444,6 @@ card_networks = "Visa, AmericanExpress, Mastercard"
 
 [network_tokenization_supported_connectors]
 connector_list = "cybersource"
+
+[platform]
+enabled = false
diff --git a/config/deployments/sandbox.toml b/config/deployments/sandbox.toml
index 152f4f04cd8..ae4afb2ec3f 100644
--- a/config/deployments/sandbox.toml
+++ b/config/deployments/sandbox.toml
@@ -446,3 +446,6 @@ card_networks = "Visa, AmericanExpress, Mastercard"
 
 [network_tokenization_supported_connectors]
 connector_list = "cybersource"
+
+[platform]
+enabled = false
diff --git a/config/development.toml b/config/development.toml
index 133823d6cb3..7e3c3c8ba07 100644
--- a/config/development.toml
+++ b/config/development.toml
@@ -830,3 +830,6 @@ entity_logo_url = "https://example.com/logo.svg" # Logo URL of the entity to be
 foreground_color = "#000000"                     # Foreground color of email text
 primary_color = "#006DF9"                        # Primary color of email body
 background_color = "#FFFFFF"                     # Background color of email body
+
+[platform]
+enabled = true
diff --git a/config/docker_compose.toml b/config/docker_compose.toml
index 1ad2ef91336..09b27d6bd7f 100644
--- a/config/docker_compose.toml
+++ b/config/docker_compose.toml
@@ -710,3 +710,6 @@ entity_logo_url = "https://example.com/logo.svg" # Logo URL of the entity to be
 foreground_color = "#000000"                     # Foreground color of email text
 primary_color = "#006DF9"                        # Primary color of email body
 background_color = "#FFFFFF"                     # Background color of email body
+
+[platform]
+enabled = true
diff --git a/crates/diesel_models/src/merchant_account.rs b/crates/diesel_models/src/merchant_account.rs
index 12d51311e87..b5c2bc28572 100644
--- a/crates/diesel_models/src/merchant_account.rs
+++ b/crates/diesel_models/src/merchant_account.rs
@@ -51,6 +51,7 @@ pub struct MerchantAccount {
     pub payment_link_config: Option<serde_json::Value>,
     pub pm_collect_link_config: Option<serde_json::Value>,
     pub version: common_enums::ApiVersion,
+    pub is_platform_account: bool,
 }
 
 #[cfg(feature = "v1")]
@@ -83,6 +84,7 @@ pub struct MerchantAccountSetter {
     pub payment_link_config: Option<serde_json::Value>,
     pub pm_collect_link_config: Option<serde_json::Value>,
     pub version: common_enums::ApiVersion,
+    pub is_platform_account: bool,
 }
 
 #[cfg(feature = "v1")]
@@ -117,6 +119,7 @@ impl From<MerchantAccountSetter> for MerchantAccount {
             payment_link_config: item.payment_link_config,
             pm_collect_link_config: item.pm_collect_link_config,
             version: item.version,
+            is_platform_account: item.is_platform_account,
         }
     }
 }
@@ -148,6 +151,7 @@ pub struct MerchantAccount {
     pub recon_status: storage_enums::ReconStatus,
     pub version: common_enums::ApiVersion,
     pub id: common_utils::id_type::MerchantId,
+    pub is_platform_account: bool,
 }
 
 #[cfg(feature = "v2")]
@@ -165,6 +169,7 @@ impl From<MerchantAccountSetter> for MerchantAccount {
             organization_id: item.organization_id,
             recon_status: item.recon_status,
             version: item.version,
+            is_platform_account: item.is_platform_account,
         }
     }
 }
@@ -182,6 +187,7 @@ pub struct MerchantAccountSetter {
     pub organization_id: common_utils::id_type::OrganizationId,
     pub recon_status: storage_enums::ReconStatus,
     pub version: common_enums::ApiVersion,
+    pub is_platform_account: bool,
 }
 
 impl MerchantAccount {
@@ -228,6 +234,7 @@ pub struct MerchantAccountNew {
     pub payment_link_config: Option<serde_json::Value>,
     pub pm_collect_link_config: Option<serde_json::Value>,
     pub version: common_enums::ApiVersion,
+    pub is_platform_account: bool,
 }
 
 #[cfg(feature = "v2")]
@@ -244,6 +251,7 @@ pub struct MerchantAccountNew {
     pub recon_status: storage_enums::ReconStatus,
     pub id: common_utils::id_type::MerchantId,
     pub version: common_enums::ApiVersion,
+    pub is_platform_account: bool,
 }
 
 #[cfg(feature = "v2")]
@@ -258,6 +266,7 @@ pub struct MerchantAccountUpdateInternal {
     pub modified_at: time::PrimitiveDateTime,
     pub organization_id: Option<common_utils::id_type::OrganizationId>,
     pub recon_status: Option<storage_enums::ReconStatus>,
+    pub is_platform_account: Option<bool>,
 }
 
 #[cfg(feature = "v2")]
@@ -272,6 +281,7 @@ impl MerchantAccountUpdateInternal {
             modified_at,
             organization_id,
             recon_status,
+            is_platform_account,
         } = self;
 
         MerchantAccount {
@@ -286,6 +296,7 @@ impl MerchantAccountUpdateInternal {
             recon_status: recon_status.unwrap_or(source.recon_status),
             version: source.version,
             id: source.id,
+            is_platform_account: is_platform_account.unwrap_or(source.is_platform_account),
         }
     }
 }
@@ -319,6 +330,7 @@ pub struct MerchantAccountUpdateInternal {
     pub recon_status: Option<storage_enums::ReconStatus>,
     pub payment_link_config: Option<serde_json::Value>,
     pub pm_collect_link_config: Option<serde_json::Value>,
+    pub is_platform_account: Option<bool>,
 }
 
 #[cfg(feature = "v1")]
@@ -350,6 +362,7 @@ impl MerchantAccountUpdateInternal {
             recon_status,
             payment_link_config,
             pm_collect_link_config,
+            is_platform_account,
         } = self;
 
         MerchantAccount {
@@ -385,6 +398,7 @@ impl MerchantAccountUpdateInternal {
             payment_link_config: payment_link_config.or(source.payment_link_config),
             pm_collect_link_config: pm_collect_link_config.or(source.pm_collect_link_config),
             version: source.version,
+            is_platform_account: is_platform_account.unwrap_or(source.is_platform_account),
         }
     }
 }
diff --git a/crates/diesel_models/src/payment_intent.rs b/crates/diesel_models/src/payment_intent.rs
index 8b834ee5d82..20c14d0dd10 100644
--- a/crates/diesel_models/src/payment_intent.rs
+++ b/crates/diesel_models/src/payment_intent.rs
@@ -74,6 +74,7 @@ pub struct PaymentIntent {
     pub id: common_utils::id_type::GlobalPaymentId,
     pub psd2_sca_exemption_type: Option<storage_enums::ScaExemptionType>,
     pub split_payments: Option<common_types::payments::SplitPaymentsRequest>,
+    pub platform_merchant_id: Option<common_utils::id_type::MerchantId>,
 }
 
 #[cfg(feature = "v1")]
@@ -140,6 +141,7 @@ pub struct PaymentIntent {
     pub skip_external_tax_calculation: Option<bool>,
     pub psd2_sca_exemption_type: Option<storage_enums::ScaExemptionType>,
     pub split_payments: Option<common_types::payments::SplitPaymentsRequest>,
+    pub platform_merchant_id: Option<common_utils::id_type::MerchantId>,
 }
 
 #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, diesel::AsExpression, PartialEq)]
@@ -300,6 +302,7 @@ pub struct PaymentIntentNew {
     pub enable_payment_link: Option<bool>,
     pub apply_mit_exemption: Option<bool>,
     pub id: common_utils::id_type::GlobalPaymentId,
+    pub platform_merchant_id: Option<common_utils::id_type::MerchantId>,
 }
 
 #[cfg(feature = "v1")]
@@ -366,6 +369,7 @@ pub struct PaymentIntentNew {
     pub tax_details: Option<TaxDetails>,
     pub skip_external_tax_calculation: Option<bool>,
     pub psd2_sca_exemption_type: Option<storage_enums::ScaExemptionType>,
+    pub platform_merchant_id: Option<common_utils::id_type::MerchantId>,
     pub split_payments: Option<common_types::payments::SplitPaymentsRequest>,
 }
 
diff --git a/crates/diesel_models/src/schema.rs b/crates/diesel_models/src/schema.rs
index 366c917d2d1..95bb714cb71 100644
--- a/crates/diesel_models/src/schema.rs
+++ b/crates/diesel_models/src/schema.rs
@@ -717,6 +717,7 @@ diesel::table! {
         payment_link_config -> Nullable<Jsonb>,
         pm_collect_link_config -> Nullable<Jsonb>,
         version -> ApiVersion,
+        is_platform_account -> Bool,
     }
 }
 
@@ -970,6 +971,8 @@ diesel::table! {
         skip_external_tax_calculation -> Nullable<Bool>,
         psd2_sca_exemption_type -> Nullable<ScaExemptionType>,
         split_payments -> Nullable<Jsonb>,
+        #[max_length = 64]
+        platform_merchant_id -> Nullable<Varchar>,
     }
 }
 
diff --git a/crates/diesel_models/src/schema_v2.rs b/crates/diesel_models/src/schema_v2.rs
index fcfe05e5731..9faf3830605 100644
--- a/crates/diesel_models/src/schema_v2.rs
+++ b/crates/diesel_models/src/schema_v2.rs
@@ -708,6 +708,7 @@ diesel::table! {
         version -> ApiVersion,
         #[max_length = 64]
         id -> Varchar,
+        is_platform_account -> Bool,
     }
 }
 
@@ -933,6 +934,8 @@ diesel::table! {
         id -> Varchar,
         psd2_sca_exemption_type -> Nullable<ScaExemptionType>,
         split_payments -> Nullable<Jsonb>,
+        #[max_length = 64]
+        platform_merchant_id -> Nullable<Varchar>,
     }
 }
 
diff --git a/crates/hyperswitch_domain_models/src/errors/api_error_response.rs b/crates/hyperswitch_domain_models/src/errors/api_error_response.rs
index 850cc470316..6fa9f9450c8 100644
--- a/crates/hyperswitch_domain_models/src/errors/api_error_response.rs
+++ b/crates/hyperswitch_domain_models/src/errors/api_error_response.rs
@@ -279,7 +279,10 @@ pub enum ApiErrorResponse {
         message = "Cookies are not found in the request"
     )]
     CookieNotFound,
-
+    #[error(error_type = ErrorType::InvalidRequestError, code = "IR_43", message = "API does not support platform account operation")]
+    PlatformAccountAuthNotSupported,
+    #[error(error_type = ErrorType::InvalidRequestError, code = "IR_44", message = "Invalid platform account operation")]
+    InvalidPlatformOperation,
     #[error(error_type = ErrorType::InvalidRequestError, code = "WE_01", message = "Failed to authenticate the webhook")]
     WebhookAuthenticationFailed,
     #[error(error_type = ErrorType::InvalidRequestError, code = "WE_02", message = "Bad request received in webhook")]
@@ -667,6 +670,12 @@ impl ErrorSwitch<api_models::errors::types::ApiErrorResponse> for ApiErrorRespon
                     ..Default::default()
                 })
             )),
+            Self::PlatformAccountAuthNotSupported => {
+                AER::BadRequest(ApiError::new("IR", 43, "API does not support platform operation", None))
+            }
+            Self::InvalidPlatformOperation => {
+                AER::Unauthorized(ApiError::new("IR", 44, "Invalid platform account operation", None))
+            }
         }
     }
 }
diff --git a/crates/hyperswitch_domain_models/src/merchant_account.rs b/crates/hyperswitch_domain_models/src/merchant_account.rs
index a6d2114f0fe..c42b0005513 100644
--- a/crates/hyperswitch_domain_models/src/merchant_account.rs
+++ b/crates/hyperswitch_domain_models/src/merchant_account.rs
@@ -47,6 +47,7 @@ pub struct MerchantAccount {
     pub payment_link_config: Option<serde_json::Value>,
     pub pm_collect_link_config: Option<serde_json::Value>,
     pub version: common_enums::ApiVersion,
+    pub is_platform_account: bool,
 }
 
 #[cfg(feature = "v1")]
@@ -81,6 +82,7 @@ pub struct MerchantAccountSetter {
     pub payment_link_config: Option<serde_json::Value>,
     pub pm_collect_link_config: Option<serde_json::Value>,
     pub version: common_enums::ApiVersion,
+    pub is_platform_account: bool,
 }
 
 #[cfg(feature = "v1")]
@@ -115,6 +117,7 @@ impl From<MerchantAccountSetter> for MerchantAccount {
             payment_link_config: item.payment_link_config,
             pm_collect_link_config: item.pm_collect_link_config,
             version: item.version,
+            is_platform_account: item.is_platform_account,
         }
     }
 }
@@ -133,6 +136,7 @@ pub struct MerchantAccountSetter {
     pub modified_at: time::PrimitiveDateTime,
     pub organization_id: common_utils::id_type::OrganizationId,
     pub recon_status: diesel_models::enums::ReconStatus,
+    pub is_platform_account: bool,
 }
 
 #[cfg(feature = "v2")]
@@ -149,6 +153,7 @@ impl From<MerchantAccountSetter> for MerchantAccount {
             modified_at,
             organization_id,
             recon_status,
+            is_platform_account,
         } = item;
         Self {
             id,
@@ -161,6 +166,7 @@ impl From<MerchantAccountSetter> for MerchantAccount {
             modified_at,
             organization_id,
             recon_status,
+            is_platform_account,
         }
     }
 }
@@ -178,6 +184,7 @@ pub struct MerchantAccount {
     pub modified_at: time::PrimitiveDateTime,
     pub organization_id: common_utils::id_type::OrganizationId,
     pub recon_status: diesel_models::enums::ReconStatus,
+    pub is_platform_account: bool,
 }
 
 impl MerchantAccount {
@@ -233,6 +240,7 @@ pub enum MerchantAccountUpdate {
     },
     UnsetDefaultProfile,
     ModifiedAtUpdate,
+    ToPlatformAccount,
 }
 
 #[cfg(feature = "v2")]
@@ -252,6 +260,7 @@ pub enum MerchantAccountUpdate {
         recon_status: diesel_models::enums::ReconStatus,
     },
     ModifiedAtUpdate,
+    ToPlatformAccount,
 }
 
 #[cfg(feature = "v1")]
@@ -307,6 +316,7 @@ impl From<MerchantAccountUpdate> for MerchantAccountUpdateInternal {
                 organization_id: None,
                 is_recon_enabled: None,
                 recon_status: None,
+                is_platform_account: None,
             },
             MerchantAccountUpdate::StorageSchemeUpdate { storage_scheme } => Self {
                 storage_scheme: Some(storage_scheme),
@@ -334,6 +344,7 @@ impl From<MerchantAccountUpdate> for MerchantAccountUpdateInternal {
                 recon_status: None,
                 payment_link_config: None,
                 pm_collect_link_config: None,
+                is_platform_account: None,
             },
             MerchantAccountUpdate::ReconUpdate { recon_status } => Self {
                 recon_status: Some(recon_status),
@@ -361,6 +372,7 @@ impl From<MerchantAccountUpdate> for MerchantAccountUpdateInternal {
                 default_profile: None,
                 payment_link_config: None,
                 pm_collect_link_config: None,
+                is_platform_account: None,
             },
             MerchantAccountUpdate::UnsetDefaultProfile => Self {
                 default_profile: Some(None),
@@ -388,6 +400,7 @@ impl From<MerchantAccountUpdate> for MerchantAccountUpdateInternal {
                 recon_status: None,
                 payment_link_config: None,
                 pm_collect_link_config: None,
+                is_platform_account: None,
             },
             MerchantAccountUpdate::ModifiedAtUpdate => Self {
                 modified_at: now,
@@ -415,6 +428,35 @@ impl From<MerchantAccountUpdate> for MerchantAccountUpdateInternal {
                 recon_status: None,
                 payment_link_config: None,
                 pm_collect_link_config: None,
+                is_platform_account: None,
+            },
+            MerchantAccountUpdate::ToPlatformAccount => Self {
+                modified_at: now,
+                merchant_name: None,
+                merchant_details: None,
+                return_url: None,
+                webhook_details: None,
+                sub_merchants_enabled: None,
+                parent_merchant_id: None,
+                enable_payment_response_hash: None,
+                payment_response_hash_key: None,
+                redirect_to_merchant_with_http_post: None,
+                publishable_key: None,
+                storage_scheme: None,
+                locker_id: None,
+                metadata: None,
+                routing_algorithm: None,
+                primary_business_details: None,
+                intent_fulfillment_time: None,
+                frm_routing_algorithm: None,
+                payout_routing_algorithm: None,
+                organization_id: None,
+                is_recon_enabled: None,
+                default_profile: None,
+                recon_status: None,
+                payment_link_config: None,
+                pm_collect_link_config: None,
+                is_platform_account: Some(true),
             },
         }
     }
@@ -440,6 +482,7 @@ impl From<MerchantAccountUpdate> for MerchantAccountUpdateInternal {
                 storage_scheme: None,
                 organization_id: None,
                 recon_status: None,
+                is_platform_account: None,
             },
             MerchantAccountUpdate::StorageSchemeUpdate { storage_scheme } => Self {
                 storage_scheme: Some(storage_scheme),
@@ -450,6 +493,7 @@ impl From<MerchantAccountUpdate> for MerchantAccountUpdateInternal {
                 metadata: None,
                 organization_id: None,
                 recon_status: None,
+                is_platform_account: None,
             },
             MerchantAccountUpdate::ReconUpdate { recon_status } => Self {
                 recon_status: Some(recon_status),
@@ -460,6 +504,7 @@ impl From<MerchantAccountUpdate> for MerchantAccountUpdateInternal {
                 storage_scheme: None,
                 metadata: None,
                 organization_id: None,
+                is_platform_account: None,
             },
             MerchantAccountUpdate::ModifiedAtUpdate => Self {
                 modified_at: now,
@@ -470,6 +515,18 @@ impl From<MerchantAccountUpdate> for MerchantAccountUpdateInternal {
                 metadata: None,
                 organization_id: None,
                 recon_status: None,
+                is_platform_account: None,
+            },
+            MerchantAccountUpdate::ToPlatformAccount => Self {
+                modified_at: now,
+                merchant_name: None,
+                merchant_details: None,
+                publishable_key: None,
+                storage_scheme: None,
+                metadata: None,
+                organization_id: None,
+                recon_status: None,
+                is_platform_account: Some(true),
             },
         }
     }
@@ -495,6 +552,7 @@ impl super::behaviour::Conversion for MerchantAccount {
             organization_id: self.organization_id,
             recon_status: self.recon_status,
             version: crate::consts::API_VERSION,
+            is_platform_account: self.is_platform_account,
         };
 
         Ok(diesel_models::MerchantAccount::from(setter))
@@ -554,6 +612,7 @@ impl super::behaviour::Conversion for MerchantAccount {
                 modified_at: item.modified_at,
                 organization_id: item.organization_id,
                 recon_status: item.recon_status,
+                is_platform_account: item.is_platform_account,
             })
         }
         .await
@@ -575,6 +634,7 @@ impl super::behaviour::Conversion for MerchantAccount {
             organization_id: self.organization_id,
             recon_status: self.recon_status,
             version: crate::consts::API_VERSION,
+            is_platform_account: self.is_platform_account,
         })
     }
 }
@@ -614,6 +674,7 @@ impl super::behaviour::Conversion for MerchantAccount {
             payment_link_config: self.payment_link_config,
             pm_collect_link_config: self.pm_collect_link_config,
             version: self.version,
+            is_platform_account: self.is_platform_account,
         };
 
         Ok(diesel_models::MerchantAccount::from(setter))
@@ -691,6 +752,7 @@ impl super::behaviour::Conversion for MerchantAccount {
                 payment_link_config: item.payment_link_config,
                 pm_collect_link_config: item.pm_collect_link_config,
                 version: item.version,
+                is_platform_account: item.is_platform_account,
             })
         }
         .await
@@ -729,6 +791,7 @@ impl super::behaviour::Conversion for MerchantAccount {
             payment_link_config: self.payment_link_config,
             pm_collect_link_config: self.pm_collect_link_config,
             version: crate::consts::API_VERSION,
+            is_platform_account: self.is_platform_account,
         })
     }
 }
diff --git a/crates/hyperswitch_domain_models/src/payments.rs b/crates/hyperswitch_domain_models/src/payments.rs
index 1c88b83d087..095b4c33a46 100644
--- a/crates/hyperswitch_domain_models/src/payments.rs
+++ b/crates/hyperswitch_domain_models/src/payments.rs
@@ -109,6 +109,7 @@ pub struct PaymentIntent {
     pub tax_details: Option<TaxDetails>,
     pub skip_external_tax_calculation: Option<bool>,
     pub psd2_sca_exemption_type: Option<storage_enums::ScaExemptionType>,
+    pub platform_merchant_id: Option<id_type::MerchantId>,
 }
 
 impl PaymentIntent {
@@ -365,6 +366,8 @@ pub struct PaymentIntent {
     pub payment_link_config: Option<diesel_models::PaymentLinkConfigRequestForPayments>,
     /// The straight through routing algorithm id that is used for this payment. This overrides the default routing algorithm that is configured in business profile.
     pub routing_algorithm_id: Option<id_type::RoutingId>,
+    /// Identifier for the platform merchant.
+    pub platform_merchant_id: Option<id_type::MerchantId>,
 }
 
 #[cfg(feature = "v2")]
@@ -411,6 +414,7 @@ impl PaymentIntent {
         profile: &business_profile::Profile,
         request: api_models::payments::PaymentsCreateIntentRequest,
         decrypted_payment_intent: DecryptedPaymentIntent,
+        platform_merchant_id: Option<&merchant_account::MerchantAccount>,
     ) -> CustomResult<Self, errors::api_error_response::ApiErrorResponse> {
         let connector_metadata = request
             .get_connector_metadata_as_value()
@@ -504,6 +508,8 @@ impl PaymentIntent {
                 .payment_link_config
                 .map(ApiModelToDieselModelConvertor::convert_from),
             routing_algorithm_id: request.routing_algorithm_id,
+            platform_merchant_id: platform_merchant_id
+                .map(|merchant_account| merchant_account.get_id().to_owned()),
         })
     }
 }
diff --git a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs
index cbd3a8137ca..953d39c131a 100644
--- a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs
+++ b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs
@@ -1326,6 +1326,7 @@ impl behaviour::Conversion for PaymentIntent {
             customer_present,
             routing_algorithm_id,
             payment_link_config,
+            platform_merchant_id,
         } = self;
         Ok(DieselPaymentIntent {
             skip_external_tax_calculation: Some(amount_details.get_external_tax_action_as_bool()),
@@ -1396,6 +1397,7 @@ impl behaviour::Conversion for PaymentIntent {
             payment_link_config,
             routing_algorithm_id,
             psd2_sca_exemption_type: None,
+            platform_merchant_id,
             split_payments: None,
         })
     }
@@ -1522,6 +1524,7 @@ impl behaviour::Conversion for PaymentIntent {
                 customer_present: storage_model.customer_present.into(),
                 payment_link_config: storage_model.payment_link_config,
                 routing_algorithm_id: storage_model.routing_algorithm_id,
+                platform_merchant_id: storage_model.platform_merchant_id,
             })
         }
         .await
@@ -1594,6 +1597,7 @@ impl behaviour::Conversion for PaymentIntent {
             tax_details: amount_details.tax_details,
             enable_payment_link: Some(self.enable_payment_link.as_bool()),
             apply_mit_exemption: Some(self.apply_mit_exemption.as_bool()),
+            platform_merchant_id: self.platform_merchant_id,
         })
     }
 }
@@ -1660,6 +1664,7 @@ impl behaviour::Conversion for PaymentIntent {
             tax_details: self.tax_details,
             skip_external_tax_calculation: self.skip_external_tax_calculation,
             psd2_sca_exemption_type: self.psd2_sca_exemption_type,
+            platform_merchant_id: self.platform_merchant_id,
         })
     }
 
@@ -1748,6 +1753,7 @@ impl behaviour::Conversion for PaymentIntent {
                 organization_id: storage_model.organization_id,
                 skip_external_tax_calculation: storage_model.skip_external_tax_calculation,
                 psd2_sca_exemption_type: storage_model.psd2_sca_exemption_type,
+                platform_merchant_id: storage_model.platform_merchant_id,
             })
         }
         .await
@@ -1812,6 +1818,7 @@ impl behaviour::Conversion for PaymentIntent {
             tax_details: self.tax_details,
             skip_external_tax_calculation: self.skip_external_tax_calculation,
             psd2_sca_exemption_type: self.psd2_sca_exemption_type,
+            platform_merchant_id: self.platform_merchant_id,
         })
     }
 }
diff --git a/crates/router/build.rs b/crates/router/build.rs
index b33c168833d..7c8043c48ad 100644
--- a/crates/router/build.rs
+++ b/crates/router/build.rs
@@ -1,8 +1,8 @@
 fn main() {
-    // Set thread stack size to 8 MiB for debug builds
+    // Set thread stack size to 10 MiB for debug builds
     // Reference: https://doc.rust-lang.org/std/thread/#stack-size
     #[cfg(debug_assertions)]
-    println!("cargo:rustc-env=RUST_MIN_STACK=8388608"); // 8 * 1024 * 1024 = 8 MiB
+    println!("cargo:rustc-env=RUST_MIN_STACK=10485760"); // 10 * 1024 * 1024 = 10 MiB
 
     #[cfg(feature = "vergen")]
     router_env::vergen::generate_cargo_instructions();
diff --git a/crates/router/src/compatibility/stripe/errors.rs b/crates/router/src/compatibility/stripe/errors.rs
index 6cf078b5f81..630d4dfdca0 100644
--- a/crates/router/src/compatibility/stripe/errors.rs
+++ b/crates/router/src/compatibility/stripe/errors.rs
@@ -278,6 +278,10 @@ pub enum StripeErrorCode {
     InvalidTenant,
     #[error(error_type = StripeErrorType::HyperswitchError, code = "HE_01", message = "Failed to convert amount to {amount_type} type")]
     AmountConversionFailed { amount_type: &'static str },
+    #[error(error_type = StripeErrorType::HyperswitchError, code = "", message = "Platform Bad Request")]
+    PlatformBadRequest,
+    #[error(error_type = StripeErrorType::HyperswitchError, code = "", message = "Platform Unauthorized Request")]
+    PlatformUnauthorizedRequest,
     // [#216]: https://github.com/juspay/hyperswitch/issues/216
     // Implement the remaining stripe error codes
 
@@ -678,6 +682,8 @@ impl From<errors::ApiErrorResponse> for StripeErrorCode {
             errors::ApiErrorResponse::AmountConversionFailed { amount_type } => {
                 Self::AmountConversionFailed { amount_type }
             }
+            errors::ApiErrorResponse::PlatformAccountAuthNotSupported => Self::PlatformBadRequest,
+            errors::ApiErrorResponse::InvalidPlatformOperation => Self::PlatformUnauthorizedRequest,
         }
     }
 }
@@ -687,7 +693,7 @@ impl actix_web::ResponseError for StripeErrorCode {
         use reqwest::StatusCode;
 
         match self {
-            Self::Unauthorized => StatusCode::UNAUTHORIZED,
+            Self::Unauthorized | Self::PlatformUnauthorizedRequest => StatusCode::UNAUTHORIZED,
             Self::InvalidRequestUrl | Self::GenericNotFoundError { .. } => StatusCode::NOT_FOUND,
             Self::ParameterUnknown { .. } | Self::HyperswitchUnprocessableEntity { .. } => {
                 StatusCode::UNPROCESSABLE_ENTITY
@@ -751,6 +757,7 @@ impl actix_web::ResponseError for StripeErrorCode {
             | Self::CurrencyConversionFailed
             | Self::PaymentMethodDeleteFailed
             | Self::ExtendedCardInfoNotFound
+            | Self::PlatformBadRequest
             | Self::LinkConfigurationError { .. } => StatusCode::BAD_REQUEST,
             Self::RefundFailed
             | Self::PayoutFailed
diff --git a/crates/router/src/compatibility/stripe/payment_intents.rs b/crates/router/src/compatibility/stripe/payment_intents.rs
index 5bbb4e7cf22..6652f42ee00 100644
--- a/crates/router/src/compatibility/stripe/payment_intents.rs
+++ b/crates/router/src/compatibility/stripe/payment_intents.rs
@@ -92,6 +92,7 @@ pub async fn payment_intents_create(
                 payments::CallConnectorAction::Trigger,
                 eligible_connectors,
                 hyperswitch_domain_models::payments::HeaderPayload::default(),
+                auth.platform_merchant_account,
             )
         },
         &auth::HeaderAuth(auth::ApiKeyAuth),
@@ -162,6 +163,7 @@ pub async fn payment_intents_retrieve(
                 payments::CallConnectorAction::Trigger,
                 None,
                 hyperswitch_domain_models::payments::HeaderPayload::default(),
+                auth.platform_merchant_account,
             )
         },
         &*auth_type,
@@ -240,6 +242,7 @@ pub async fn payment_intents_retrieve_with_gateway_creds(
                 payments::CallConnectorAction::Trigger,
                 None,
                 hyperswitch_domain_models::payments::HeaderPayload::default(),
+                auth.platform_merchant_account,
             )
         },
         &*auth_type,
@@ -316,6 +319,7 @@ pub async fn payment_intents_update(
                 payments::CallConnectorAction::Trigger,
                 eligible_connectors,
                 hyperswitch_domain_models::payments::HeaderPayload::default(),
+                auth.platform_merchant_account,
             )
         },
         &*auth_type,
@@ -401,6 +405,7 @@ pub async fn payment_intents_confirm(
                 payments::CallConnectorAction::Trigger,
                 eligible_connectors,
                 hyperswitch_domain_models::payments::HeaderPayload::default(),
+                auth.platform_merchant_account,
             )
         },
         &*auth_type,
@@ -472,6 +477,7 @@ pub async fn payment_intents_capture(
                 payments::CallConnectorAction::Trigger,
                 None,
                 hyperswitch_domain_models::payments::HeaderPayload::default(),
+                auth.platform_merchant_account,
             )
         },
         &auth::HeaderAuth(auth::ApiKeyAuth),
@@ -547,6 +553,7 @@ pub async fn payment_intents_cancel(
                 payments::CallConnectorAction::Trigger,
                 None,
                 hyperswitch_domain_models::payments::HeaderPayload::default(),
+                auth.platform_merchant_account,
             )
         },
         &*auth_type,
diff --git a/crates/router/src/compatibility/stripe/setup_intents.rs b/crates/router/src/compatibility/stripe/setup_intents.rs
index 919ced993aa..6dde49b0d62 100644
--- a/crates/router/src/compatibility/stripe/setup_intents.rs
+++ b/crates/router/src/compatibility/stripe/setup_intents.rs
@@ -78,6 +78,7 @@ pub async fn setup_intents_create(
                 payments::CallConnectorAction::Trigger,
                 None,
                 hyperswitch_domain_models::payments::HeaderPayload::default(),
+                auth.platform_merchant_account,
             )
         },
         &auth::HeaderAuth(auth::ApiKeyAuth),
@@ -148,6 +149,7 @@ pub async fn setup_intents_retrieve(
                 payments::CallConnectorAction::Trigger,
                 None,
                 hyperswitch_domain_models::payments::HeaderPayload::default(),
+                auth.platform_merchant_account,
             )
         },
         &*auth_type,
@@ -224,6 +226,7 @@ pub async fn setup_intents_update(
                 payments::CallConnectorAction::Trigger,
                 None,
                 hyperswitch_domain_models::payments::HeaderPayload::default(),
+                auth.platform_merchant_account,
             )
         },
         &*auth_type,
@@ -301,6 +304,7 @@ pub async fn setup_intents_confirm(
                 payments::CallConnectorAction::Trigger,
                 None,
                 hyperswitch_domain_models::payments::HeaderPayload::default(),
+                auth.platform_merchant_account,
             )
         },
         &*auth_type,
diff --git a/crates/router/src/configs/secrets_transformers.rs b/crates/router/src/configs/secrets_transformers.rs
index 3862f70536f..7b74aca7647 100644
--- a/crates/router/src/configs/secrets_transformers.rs
+++ b/crates/router/src/configs/secrets_transformers.rs
@@ -546,5 +546,6 @@ pub(crate) async fn fetch_raw_secrets(
         network_tokenization_service,
         network_tokenization_supported_connectors: conf.network_tokenization_supported_connectors,
         theme: conf.theme,
+        platform: conf.platform,
     }
 }
diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs
index ccd43d25b8e..ad5d9e89aaa 100644
--- a/crates/router/src/configs/settings.rs
+++ b/crates/router/src/configs/settings.rs
@@ -129,6 +129,12 @@ pub struct Settings<S: SecretState> {
     pub network_tokenization_service: Option<SecretStateContainer<NetworkTokenizationService, S>>,
     pub network_tokenization_supported_connectors: NetworkTokenizationSupportedConnectors,
     pub theme: ThemeSettings,
+    pub platform: Platform,
+}
+
+#[derive(Debug, Deserialize, Clone, Default)]
+pub struct Platform {
+    pub enabled: bool,
 }
 
 #[derive(Debug, Deserialize, Clone, Default)]
diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs
index ccb563b0610..05aaf99421b 100644
--- a/crates/router/src/core/admin.rs
+++ b/crates/router/src/core/admin.rs
@@ -402,6 +402,7 @@ impl MerchantAccountCreateBridge for api::MerchantAccountCreate {
                     payment_link_config: None,
                     pm_collect_link_config,
                     version: hyperswitch_domain_models::consts::API_VERSION,
+                    is_platform_account: false,
                 },
             )
         }
@@ -669,6 +670,7 @@ impl MerchantAccountCreateBridge for api::MerchantAccountCreate {
                     modified_at: date_time::now(),
                     organization_id: organization.get_organization_id(),
                     recon_status: diesel_models::enums::ReconStatus::NotRequested,
+                    is_platform_account: false,
                 }),
             )
         }
@@ -4769,3 +4771,35 @@ async fn locker_recipient_create_call(
 
     Ok(store_resp.card_reference)
 }
+
+pub async fn enable_platform_account(
+    state: SessionState,
+    merchant_id: id_type::MerchantId,
+) -> RouterResponse<()> {
+    let db = state.store.as_ref();
+    let key_manager_state = &(&state).into();
+    let key_store = db
+        .get_merchant_key_store_by_merchant_id(
+            key_manager_state,
+            &merchant_id,
+            &db.get_master_key().to_vec().into(),
+        )
+        .await
+        .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;
+
+    let merchant_account = db
+        .find_merchant_account_by_merchant_id(key_manager_state, &merchant_id, &key_store)
+        .await
+        .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;
+
+    db.update_merchant(
+        key_manager_state,
+        merchant_account,
+        storage::MerchantAccountUpdate::ToPlatformAccount,
+        &key_store,
+    )
+    .await
+    .change_context(errors::ApiErrorResponse::InternalServerError)
+    .attach_printable("Error while enabling platform merchant account")
+    .map(|_| services::ApplicationResponse::StatusOk)
+}
diff --git a/crates/router/src/core/fraud_check.rs b/crates/router/src/core/fraud_check.rs
index 70c35b460e8..99a60817303 100644
--- a/crates/router/src/core/fraud_check.rs
+++ b/crates/router/src/core/fraud_check.rs
@@ -588,6 +588,7 @@ pub async fn post_payment_frm_core<'a, F, D>(
     customer: &Option<domain::Customer>,
     key_store: domain::MerchantKeyStore,
     should_continue_capture: &mut bool,
+    platform_merchant_account: Option<&domain::MerchantAccount>,
 ) -> RouterResult<Option<FrmData>>
 where
     F: Send + Clone,
@@ -647,6 +648,7 @@ where
                         payment_data,
                         customer,
                         should_continue_capture,
+                        platform_merchant_account,
                     )
                     .await?;
                 logger::debug!("frm_post_tasks_data: {:?}", frm_data);
diff --git a/crates/router/src/core/fraud_check/operation.rs b/crates/router/src/core/fraud_check/operation.rs
index d802339b675..721afaa1e49 100644
--- a/crates/router/src/core/fraud_check/operation.rs
+++ b/crates/router/src/core/fraud_check/operation.rs
@@ -85,6 +85,7 @@ pub trait Domain<F, D>: Send + Sync {
         _payment_data: &mut D,
         _customer: &Option<domain::Customer>,
         _should_continue_capture: &mut bool,
+        _platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<Option<FrmData>>
     where
         F: Send + Clone,
diff --git a/crates/router/src/core/fraud_check/operation/fraud_check_post.rs b/crates/router/src/core/fraud_check/operation/fraud_check_post.rs
index 308a00ffa1d..69f06e59416 100644
--- a/crates/router/src/core/fraud_check/operation/fraud_check_post.rs
+++ b/crates/router/src/core/fraud_check/operation/fraud_check_post.rs
@@ -226,6 +226,7 @@ where
         _payment_data: &mut D,
         _customer: &Option<domain::Customer>,
         _should_continue_capture: &mut bool,
+        _platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<Option<FrmData>> {
         todo!()
     }
@@ -244,6 +245,7 @@ where
         payment_data: &mut D,
         customer: &Option<domain::Customer>,
         _should_continue_capture: &mut bool,
+        platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<Option<FrmData>> {
         if matches!(frm_data.fraud_check.frm_status, FraudCheckStatus::Fraud)
             && matches!(
@@ -277,6 +279,7 @@ where
                 payments::CallConnectorAction::Trigger,
                 None,
                 HeaderPayload::default(),
+                platform_merchant_account.cloned(),
             ))
             .await?;
             logger::debug!("payment_id : {:?} has been cancelled since it has been found fraudulent by configured frm connector",payment_data.get_payment_attempt().payment_id);
@@ -334,6 +337,7 @@ where
                 payments::CallConnectorAction::Trigger,
                 None,
                 HeaderPayload::default(),
+                platform_merchant_account.cloned(),
             ))
             .await?;
             logger::debug!("payment_id : {:?} has been captured since it has been found legit by configured frm connector",payment_data.get_payment_attempt().payment_id);
diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs
index e68bd09ba46..535a6b72bd6 100644
--- a/crates/router/src/core/payments.rs
+++ b/crates/router/src/core/payments.rs
@@ -242,6 +242,7 @@ pub async fn payments_operation_core<F, Req, Op, FData, D>(
     auth_flow: services::AuthFlow,
     eligible_connectors: Option<Vec<common_enums::RoutableConnectors>>,
     header_payload: HeaderPayload,
+    platform_merchant_account: Option<domain::MerchantAccount>,
 ) -> RouterResult<(D, Req, Option<domain::Customer>, Option<u16>, Option<u128>)>
 where
     F: Send + Clone + Sync,
@@ -286,6 +287,7 @@ where
             &key_store,
             auth_flow,
             &header_payload,
+            platform_merchant_account.as_ref(),
         )
         .await?;
     core_utils::validate_profile_id_from_auth_layer(
@@ -716,6 +718,7 @@ where
                     &customer,
                     key_store.clone(),
                     &mut should_continue_capture,
+                    platform_merchant_account.as_ref(),
                 ))
                 .await?;
             }
@@ -823,8 +826,8 @@ pub async fn proxy_for_payments_operation_core<F, Req, Op, FData, D>(
     req: Req,
     call_connector_action: CallConnectorAction,
     auth_flow: services::AuthFlow,
-
     header_payload: HeaderPayload,
+    platform_merchant_account: Option<domain::MerchantAccount>,
 ) -> RouterResult<(D, Req, Option<domain::Customer>, Option<u16>, Option<u128>)>
 where
     F: Send + Clone + Sync,
@@ -869,6 +872,7 @@ where
             &key_store,
             auth_flow,
             &header_payload,
+            platform_merchant_account.as_ref(),
         )
         .await?;
 
@@ -1021,6 +1025,7 @@ pub async fn payments_intent_operation_core<F, Req, Op, D>(
     req: Req,
     payment_id: id_type::GlobalPaymentId,
     header_payload: HeaderPayload,
+    platform_merchant_account: Option<domain::MerchantAccount>,
 ) -> RouterResult<(D, Req, Option<domain::Customer>)>
 where
     F: Send + Clone + Sync,
@@ -1048,6 +1053,7 @@ where
             &profile,
             &key_store,
             &header_payload,
+            platform_merchant_account.as_ref(),
         )
         .await?;
 
@@ -1339,6 +1345,7 @@ pub async fn payments_core<F, Res, Req, Op, FData, D>(
     call_connector_action: CallConnectorAction,
     eligible_connectors: Option<Vec<enums::Connector>>,
     header_payload: HeaderPayload,
+    platform_merchant_account: Option<domain::MerchantAccount>,
 ) -> RouterResponse<Res>
 where
     F: Send + Clone + Sync,
@@ -1377,6 +1384,7 @@ where
             auth_flow,
             eligible_routable_connectors,
             header_payload.clone(),
+            platform_merchant_account,
         )
         .await?;
 
@@ -1406,6 +1414,7 @@ pub async fn proxy_for_payments_core<F, Res, Req, Op, FData, D>(
     auth_flow: services::AuthFlow,
     call_connector_action: CallConnectorAction,
     header_payload: HeaderPayload,
+    platform_merchant_account: Option<domain::MerchantAccount>,
 ) -> RouterResponse<Res>
 where
     F: Send + Clone + Sync,
@@ -1437,6 +1446,7 @@ where
             call_connector_action,
             auth_flow,
             header_payload.clone(),
+            platform_merchant_account,
         )
         .await?;
 
@@ -1465,6 +1475,7 @@ pub async fn payments_intent_core<F, Res, Req, Op, D>(
     req: Req,
     payment_id: id_type::GlobalPaymentId,
     header_payload: HeaderPayload,
+    platform_merchant_account: Option<domain::MerchantAccount>,
 ) -> RouterResponse<Res>
 where
     F: Send + Clone + Sync,
@@ -1483,6 +1494,7 @@ where
         req,
         payment_id,
         header_payload.clone(),
+        platform_merchant_account,
     )
     .await?;
 
@@ -1556,6 +1568,7 @@ where
             &profile,
             &key_store,
             &header_payload,
+            None,
         )
         .await?;
 
@@ -1624,9 +1637,11 @@ pub trait PaymentRedirectFlow: Sync {
         connector_action: CallConnectorAction,
         connector: String,
         payment_id: id_type::PaymentId,
+        platform_merchant_account: Option<domain::MerchantAccount>,
     ) -> RouterResult<Self::PaymentFlowResponse>;
 
     #[cfg(feature = "v2")]
+    #[allow(clippy::too_many_arguments)]
     async fn call_payment_flow(
         &self,
         state: &SessionState,
@@ -1635,6 +1650,7 @@ pub trait PaymentRedirectFlow: Sync {
         merchant_key_store: domain::MerchantKeyStore,
         profile: domain::Profile,
         req: PaymentsRedirectResponseData,
+        platform_merchant_account: Option<domain::MerchantAccount>,
     ) -> RouterResult<Self::PaymentFlowResponse>;
 
     fn get_payment_action(&self) -> services::PaymentAction;
@@ -1661,6 +1677,7 @@ pub trait PaymentRedirectFlow: Sync {
         merchant_account: domain::MerchantAccount,
         key_store: domain::MerchantKeyStore,
         req: PaymentsRedirectResponseData,
+        platform_merchant_account: Option<domain::MerchantAccount>,
     ) -> RouterResponse<api::RedirectionResponse> {
         metrics::REDIRECTION_TRIGGERED.add(
             1,
@@ -1715,6 +1732,7 @@ pub trait PaymentRedirectFlow: Sync {
                 flow_type,
                 connector.clone(),
                 resource_id.clone(),
+                platform_merchant_account,
             )
             .await?;
 
@@ -1722,6 +1740,7 @@ pub trait PaymentRedirectFlow: Sync {
     }
 
     #[cfg(feature = "v2")]
+    #[allow(clippy::too_many_arguments)]
     async fn handle_payments_redirect_response(
         &self,
         state: SessionState,
@@ -1730,6 +1749,7 @@ pub trait PaymentRedirectFlow: Sync {
         key_store: domain::MerchantKeyStore,
         profile: domain::Profile,
         request: PaymentsRedirectResponseData,
+        platform_merchant_account: Option<domain::MerchantAccount>,
     ) -> RouterResponse<api::RedirectionResponse> {
         metrics::REDIRECTION_TRIGGERED.add(
             1,
@@ -1744,6 +1764,7 @@ pub trait PaymentRedirectFlow: Sync {
                 key_store,
                 profile,
                 request,
+                platform_merchant_account,
             )
             .await?;
 
@@ -1770,6 +1791,7 @@ impl PaymentRedirectFlow for PaymentRedirectCompleteAuthorize {
         connector_action: CallConnectorAction,
         _connector: String,
         _payment_id: id_type::PaymentId,
+        platform_merchant_account: Option<domain::MerchantAccount>,
     ) -> RouterResult<Self::PaymentFlowResponse> {
         let key_manager_state = &state.into();
 
@@ -1805,6 +1827,7 @@ impl PaymentRedirectFlow for PaymentRedirectCompleteAuthorize {
             connector_action,
             None,
             HeaderPayload::default(),
+            platform_merchant_account,
         ))
         .await?;
         let payments_response = match response {
@@ -1910,6 +1933,7 @@ impl PaymentRedirectFlow for PaymentRedirectSync {
         connector_action: CallConnectorAction,
         _connector: String,
         _payment_id: id_type::PaymentId,
+        platform_merchant_account: Option<domain::MerchantAccount>,
     ) -> RouterResult<Self::PaymentFlowResponse> {
         let key_manager_state = &state.into();
 
@@ -1942,6 +1966,7 @@ impl PaymentRedirectFlow for PaymentRedirectSync {
                 connector_action,
                 None,
                 HeaderPayload::default(),
+                platform_merchant_account,
             ),
         )
         .await?;
@@ -2031,6 +2056,7 @@ impl PaymentRedirectFlow for PaymentRedirectSync {
         merchant_key_store: domain::MerchantKeyStore,
         profile: domain::Profile,
         req: PaymentsRedirectResponseData,
+        platform_merchant_account: Option<domain::MerchantAccount>,
     ) -> RouterResult<Self::PaymentFlowResponse> {
         let payment_id = req.payment_id.clone();
 
@@ -2057,6 +2083,7 @@ impl PaymentRedirectFlow for PaymentRedirectSync {
                 &profile,
                 &merchant_key_store,
                 &HeaderPayload::default(),
+                platform_merchant_account.as_ref(),
             )
             .await?;
 
@@ -2168,6 +2195,7 @@ impl PaymentRedirectFlow for PaymentAuthenticateCompleteAuthorize {
         connector_action: CallConnectorAction,
         connector: String,
         payment_id: id_type::PaymentId,
+        platform_merchant_account: Option<domain::MerchantAccount>,
     ) -> RouterResult<Self::PaymentFlowResponse> {
         let merchant_id = merchant_account.get_id().clone();
         let key_manager_state = &state.into();
@@ -2267,6 +2295,7 @@ impl PaymentRedirectFlow for PaymentAuthenticateCompleteAuthorize {
                 connector_action,
                 None,
                 HeaderPayload::with_source(enums::PaymentSource::ExternalAuthenticator),
+                platform_merchant_account,
             ))
             .await?
         } else {
@@ -2299,6 +2328,7 @@ impl PaymentRedirectFlow for PaymentAuthenticateCompleteAuthorize {
                     connector_action,
                     None,
                     HeaderPayload::default(),
+                    platform_merchant_account,
                 ),
             )
             .await?
diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs
index c243686a76c..eda869c3a6c 100644
--- a/crates/router/src/core/payments/helpers.rs
+++ b/crates/router/src/core/payments/helpers.rs
@@ -3614,6 +3614,7 @@ mod tests {
             tax_details: None,
             skip_external_tax_calculation: None,
             psd2_sca_exemption_type: None,
+            platform_merchant_id: None,
         };
         let req_cs = Some("1".to_string());
         assert!(authenticate_client_secret(req_cs.as_ref(), &payment_intent).is_ok());
@@ -3684,6 +3685,7 @@ mod tests {
             tax_details: None,
             skip_external_tax_calculation: None,
             psd2_sca_exemption_type: None,
+            platform_merchant_id: None,
         };
         let req_cs = Some("1".to_string());
         assert!(authenticate_client_secret(req_cs.as_ref(), &payment_intent,).is_err())
@@ -3752,6 +3754,7 @@ mod tests {
             tax_details: None,
             skip_external_tax_calculation: None,
             psd2_sca_exemption_type: None,
+            platform_merchant_id: None,
         };
         let req_cs = Some("1".to_string());
         assert!(authenticate_client_secret(req_cs.as_ref(), &payment_intent).is_err())
diff --git a/crates/router/src/core/payments/operations.rs b/crates/router/src/core/payments/operations.rs
index 38911bb2d6d..4adb9403418 100644
--- a/crates/router/src/core/payments/operations.rs
+++ b/crates/router/src/core/payments/operations.rs
@@ -190,6 +190,7 @@ pub trait GetTracker<F: Clone, D, R>: Send {
         mechant_key_store: &domain::MerchantKeyStore,
         auth_flow: services::AuthFlow,
         header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<GetTrackerResponse<'a, F, R, D>>;
 
     #[cfg(feature = "v2")]
@@ -203,6 +204,7 @@ pub trait GetTracker<F: Clone, D, R>: Send {
         profile: &domain::Profile,
         mechant_key_store: &domain::MerchantKeyStore,
         header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<GetTrackerResponse<D>>;
 }
 
diff --git a/crates/router/src/core/payments/operations/payment_approve.rs b/crates/router/src/core/payments/operations/payment_approve.rs
index a5993eb2f01..c830b7618d0 100644
--- a/crates/router/src/core/payments/operations/payment_approve.rs
+++ b/crates/router/src/core/payments/operations/payment_approve.rs
@@ -45,6 +45,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsCaptureR
         key_store: &domain::MerchantKeyStore,
         _auth_flow: services::AuthFlow,
         _header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        _platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<
         operations::GetTrackerResponse<'a, F, api::PaymentsCaptureRequest, PaymentData<F>>,
     > {
diff --git a/crates/router/src/core/payments/operations/payment_cancel.rs b/crates/router/src/core/payments/operations/payment_cancel.rs
index 427c10aab62..c6679e481f1 100644
--- a/crates/router/src/core/payments/operations/payment_cancel.rs
+++ b/crates/router/src/core/payments/operations/payment_cancel.rs
@@ -46,6 +46,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsCancelRe
         key_store: &domain::MerchantKeyStore,
         _auth_flow: services::AuthFlow,
         _header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        _platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<
         operations::GetTrackerResponse<'a, F, api::PaymentsCancelRequest, PaymentData<F>>,
     > {
diff --git a/crates/router/src/core/payments/operations/payment_capture.rs b/crates/router/src/core/payments/operations/payment_capture.rs
index f8d304bcb79..ebe49f59f64 100644
--- a/crates/router/src/core/payments/operations/payment_capture.rs
+++ b/crates/router/src/core/payments/operations/payment_capture.rs
@@ -45,6 +45,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, payments::PaymentData<F>, api::Paymen
         key_store: &domain::MerchantKeyStore,
         _auth_flow: services::AuthFlow,
         _header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        _platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<
         operations::GetTrackerResponse<
             'a,
diff --git a/crates/router/src/core/payments/operations/payment_capture_v2.rs b/crates/router/src/core/payments/operations/payment_capture_v2.rs
index 0ee62ea73c1..81ffa8e992f 100644
--- a/crates/router/src/core/payments/operations/payment_capture_v2.rs
+++ b/crates/router/src/core/payments/operations/payment_capture_v2.rs
@@ -142,6 +142,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentCaptureData<F>, PaymentsCaptureReques
         _profile: &domain::Profile,
         key_store: &domain::MerchantKeyStore,
         _header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        _platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<operations::GetTrackerResponse<PaymentCaptureData<F>>> {
         let db = &*state.store;
         let key_manager_state = &state.into();
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 914ddf251ef..72c04c6a549 100644
--- a/crates/router/src/core/payments/operations/payment_complete_authorize.rs
+++ b/crates/router/src/core/payments/operations/payment_complete_authorize.rs
@@ -48,6 +48,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsRequest>
         key_store: &domain::MerchantKeyStore,
         _auth_flow: services::AuthFlow,
         _header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        _platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<operations::GetTrackerResponse<'a, F, api::PaymentsRequest, PaymentData<F>>>
     {
         let db = &*state.store;
diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs
index 96406932445..c309685a6a2 100644
--- a/crates/router/src/core/payments/operations/payment_confirm.rs
+++ b/crates/router/src/core/payments/operations/payment_confirm.rs
@@ -77,6 +77,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsRequest>
         key_store: &domain::MerchantKeyStore,
         auth_flow: services::AuthFlow,
         header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        _platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<operations::GetTrackerResponse<'a, F, api::PaymentsRequest, PaymentData<F>>>
     {
         let key_manager_state = &state.into();
diff --git a/crates/router/src/core/payments/operations/payment_confirm_intent.rs b/crates/router/src/core/payments/operations/payment_confirm_intent.rs
index 374a33026da..71d99d03e41 100644
--- a/crates/router/src/core/payments/operations/payment_confirm_intent.rs
+++ b/crates/router/src/core/payments/operations/payment_confirm_intent.rs
@@ -158,6 +158,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentConfirmData<F>, PaymentsConfir
         profile: &domain::Profile,
         key_store: &domain::MerchantKeyStore,
         header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        _platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<operations::GetTrackerResponse<PaymentConfirmData<F>>> {
         let db = &*state.store;
         let key_manager_state = &state.into();
diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs
index 36b338f2d52..b7b3420987d 100644
--- a/crates/router/src/core/payments/operations/payment_create.rs
+++ b/crates/router/src/core/payments/operations/payment_create.rs
@@ -78,6 +78,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsRequest>
         merchant_key_store: &domain::MerchantKeyStore,
         _auth_flow: services::AuthFlow,
         header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<operations::GetTrackerResponse<'a, F, api::PaymentsRequest, PaymentData<F>>>
     {
         let db = &*state.store;
@@ -304,6 +305,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsRequest>
             attempt_id,
             profile_id.clone(),
             session_expiry,
+            platform_merchant_account,
         )
         .await?;
 
@@ -1308,6 +1310,7 @@ impl PaymentCreate {
         active_attempt_id: String,
         profile_id: common_utils::id_type::ProfileId,
         session_expiry: PrimitiveDateTime,
+        platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<storage::PaymentIntent> {
         let created_at @ modified_at @ last_synced = common_utils::date_time::now();
 
@@ -1494,6 +1497,8 @@ impl PaymentCreate {
             tax_details,
             skip_external_tax_calculation,
             psd2_sca_exemption_type: request.psd2_sca_exemption_type,
+            platform_merchant_id: platform_merchant_account
+                .map(|platform_merchant_account| platform_merchant_account.get_id().to_owned()),
         })
     }
 
diff --git a/crates/router/src/core/payments/operations/payment_create_intent.rs b/crates/router/src/core/payments/operations/payment_create_intent.rs
index f9cdd192f18..1cd0010bdf6 100644
--- a/crates/router/src/core/payments/operations/payment_create_intent.rs
+++ b/crates/router/src/core/payments/operations/payment_create_intent.rs
@@ -99,6 +99,7 @@ impl<F: Send + Clone + Sync>
         profile: &domain::Profile,
         key_store: &domain::MerchantKeyStore,
         _header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<operations::GetTrackerResponse<payments::PaymentIntentData<F>>> {
         let db = &*state.store;
         let key_manager_state = &state.into();
@@ -137,6 +138,7 @@ impl<F: Send + Clone + Sync>
                 profile,
                 request.clone(),
                 encrypted_data,
+                platform_merchant_account,
             )
             .await?;
 
diff --git a/crates/router/src/core/payments/operations/payment_get.rs b/crates/router/src/core/payments/operations/payment_get.rs
index 403ee544314..6419376f090 100644
--- a/crates/router/src/core/payments/operations/payment_get.rs
+++ b/crates/router/src/core/payments/operations/payment_get.rs
@@ -119,6 +119,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentStatusData<F>, PaymentsRetriev
         _profile: &domain::Profile,
         key_store: &domain::MerchantKeyStore,
         _header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        _platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<operations::GetTrackerResponse<PaymentStatusData<F>>> {
         let db = &*state.store;
         let key_manager_state = &state.into();
diff --git a/crates/router/src/core/payments/operations/payment_get_intent.rs b/crates/router/src/core/payments/operations/payment_get_intent.rs
index 16b44436c18..3cc26e7b67f 100644
--- a/crates/router/src/core/payments/operations/payment_get_intent.rs
+++ b/crates/router/src/core/payments/operations/payment_get_intent.rs
@@ -89,6 +89,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, payments::PaymentIntentData<F>, Payme
         _profile: &domain::Profile,
         key_store: &domain::MerchantKeyStore,
         _header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        _platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<operations::GetTrackerResponse<payments::PaymentIntentData<F>>> {
         let db = &*state.store;
         let key_manager_state = &state.into();
diff --git a/crates/router/src/core/payments/operations/payment_post_session_tokens.rs b/crates/router/src/core/payments/operations/payment_post_session_tokens.rs
index 7337f080884..0e189583d0a 100644
--- a/crates/router/src/core/payments/operations/payment_post_session_tokens.rs
+++ b/crates/router/src/core/payments/operations/payment_post_session_tokens.rs
@@ -45,6 +45,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsPostSess
         key_store: &domain::MerchantKeyStore,
         _auth_flow: services::AuthFlow,
         _header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        _platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<
         operations::GetTrackerResponse<
             'a,
diff --git a/crates/router/src/core/payments/operations/payment_reject.rs b/crates/router/src/core/payments/operations/payment_reject.rs
index a6a10be8e9a..e5321b1f984 100644
--- a/crates/router/src/core/payments/operations/payment_reject.rs
+++ b/crates/router/src/core/payments/operations/payment_reject.rs
@@ -43,6 +43,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, PaymentsCancelRequest
         key_store: &domain::MerchantKeyStore,
         _auth_flow: services::AuthFlow,
         _header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        _platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<operations::GetTrackerResponse<'a, F, PaymentsCancelRequest, PaymentData<F>>>
     {
         let db = &*state.store;
diff --git a/crates/router/src/core/payments/operations/payment_session.rs b/crates/router/src/core/payments/operations/payment_session.rs
index f93327b275c..0e94fbe09c6 100644
--- a/crates/router/src/core/payments/operations/payment_session.rs
+++ b/crates/router/src/core/payments/operations/payment_session.rs
@@ -44,6 +44,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsSessionR
         key_store: &domain::MerchantKeyStore,
         _auth_flow: services::AuthFlow,
         _header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        _platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<
         operations::GetTrackerResponse<'a, F, api::PaymentsSessionRequest, PaymentData<F>>,
     > {
diff --git a/crates/router/src/core/payments/operations/payment_session_intent.rs b/crates/router/src/core/payments/operations/payment_session_intent.rs
index 2454b9fcbf3..ec59ba3473e 100644
--- a/crates/router/src/core/payments/operations/payment_session_intent.rs
+++ b/crates/router/src/core/payments/operations/payment_session_intent.rs
@@ -101,6 +101,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, payments::PaymentIntentData<F>, Payme
         _profile: &domain::Profile,
         key_store: &domain::MerchantKeyStore,
         header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        _platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<operations::GetTrackerResponse<payments::PaymentIntentData<F>>> {
         let db = &*state.store;
         let key_manager_state = &state.into();
diff --git a/crates/router/src/core/payments/operations/payment_start.rs b/crates/router/src/core/payments/operations/payment_start.rs
index a895855cefc..1da9a1a2264 100644
--- a/crates/router/src/core/payments/operations/payment_start.rs
+++ b/crates/router/src/core/payments/operations/payment_start.rs
@@ -43,6 +43,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsStartReq
         key_store: &domain::MerchantKeyStore,
         _auth_flow: services::AuthFlow,
         _header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        _platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<
         operations::GetTrackerResponse<'a, F, api::PaymentsStartRequest, PaymentData<F>>,
     > {
diff --git a/crates/router/src/core/payments/operations/payment_status.rs b/crates/router/src/core/payments/operations/payment_status.rs
index 9aa905345c8..dd28043ba2b 100644
--- a/crates/router/src/core/payments/operations/payment_status.rs
+++ b/crates/router/src/core/payments/operations/payment_status.rs
@@ -213,6 +213,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsRetrieve
         key_store: &domain::MerchantKeyStore,
         _auth_flow: services::AuthFlow,
         _header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        _platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<
         operations::GetTrackerResponse<'a, F, api::PaymentsRetrieveRequest, PaymentData<F>>,
     > {
diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs
index c75794dd17f..0e60407aa7c 100644
--- a/crates/router/src/core/payments/operations/payment_update.rs
+++ b/crates/router/src/core/payments/operations/payment_update.rs
@@ -56,6 +56,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsRequest>
         key_store: &domain::MerchantKeyStore,
         auth_flow: services::AuthFlow,
         _header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        _platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<operations::GetTrackerResponse<'a, F, api::PaymentsRequest, PaymentData<F>>>
     {
         let (mut payment_intent, mut payment_attempt, currency): (_, _, storage_enums::Currency);
diff --git a/crates/router/src/core/payments/operations/payment_update_intent.rs b/crates/router/src/core/payments/operations/payment_update_intent.rs
index f8ce03d558e..4782d237e21 100644
--- a/crates/router/src/core/payments/operations/payment_update_intent.rs
+++ b/crates/router/src/core/payments/operations/payment_update_intent.rs
@@ -135,6 +135,7 @@ impl<F: Send + Clone> GetTracker<F, payments::PaymentIntentData<F>, PaymentsUpda
         _profile: &domain::Profile,
         key_store: &domain::MerchantKeyStore,
         _header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        _platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<operations::GetTrackerResponse<payments::PaymentIntentData<F>>> {
         let db = &*state.store;
         let key_manager_state = &state.into();
diff --git a/crates/router/src/core/payments/operations/payments_incremental_authorization.rs b/crates/router/src/core/payments/operations/payments_incremental_authorization.rs
index 035c4e8e2ec..2c816ad39d1 100644
--- a/crates/router/src/core/payments/operations/payments_incremental_authorization.rs
+++ b/crates/router/src/core/payments/operations/payments_incremental_authorization.rs
@@ -48,6 +48,7 @@ impl<F: Send + Clone + Sync>
         key_store: &domain::MerchantKeyStore,
         _auth_flow: services::AuthFlow,
         _header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        _platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<
         operations::GetTrackerResponse<
             'a,
diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs
index 859422920e1..5b9c90f3add 100644
--- a/crates/router/src/core/payments/operations/tax_calculation.rs
+++ b/crates/router/src/core/payments/operations/tax_calculation.rs
@@ -50,6 +50,7 @@ impl<F: Send + Clone + Sync>
         key_store: &domain::MerchantKeyStore,
         _auth_flow: services::AuthFlow,
         _header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
+        _platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<
         operations::GetTrackerResponse<
             'a,
diff --git a/crates/router/src/core/payments/session_operation.rs b/crates/router/src/core/payments/session_operation.rs
index d7b6ad0d345..40a2717fea7 100644
--- a/crates/router/src/core/payments/session_operation.rs
+++ b/crates/router/src/core/payments/session_operation.rs
@@ -42,6 +42,7 @@ pub async fn payments_session_core<F, Res, Req, Op, FData, D>(
     payment_id: id_type::GlobalPaymentId,
     call_connector_action: CallConnectorAction,
     header_payload: HeaderPayload,
+    platform_merchant_account: Option<domain::MerchantAccount>,
 ) -> RouterResponse<Res>
 where
     F: Send + Clone + Sync,
@@ -71,6 +72,7 @@ where
             payment_id,
             call_connector_action,
             header_payload.clone(),
+            platform_merchant_account,
         )
         .await?;
 
@@ -100,6 +102,7 @@ pub async fn payments_session_operation_core<F, Req, Op, FData, D>(
     payment_id: id_type::GlobalPaymentId,
     _call_connector_action: CallConnectorAction,
     header_payload: HeaderPayload,
+    platform_merchant_account: Option<domain::MerchantAccount>,
 ) -> RouterResult<(D, Req, Option<domain::Customer>, Option<u16>, Option<u128>)>
 where
     F: Send + Clone + Sync,
@@ -132,6 +135,7 @@ where
             &profile,
             &key_store,
             &header_payload,
+            platform_merchant_account.as_ref(),
         )
         .await?;
 
diff --git a/crates/router/src/core/webhooks/incoming.rs b/crates/router/src/core/webhooks/incoming.rs
index 73d9cfdcaee..ff9849958b5 100644
--- a/crates/router/src/core/webhooks/incoming.rs
+++ b/crates/router/src/core/webhooks/incoming.rs
@@ -617,6 +617,7 @@ async fn payments_incoming_webhook_flow(
                 consume_or_trigger_flow.clone(),
                 None,
                 HeaderPayload::default(),
+                None, //Platform merchant account
             ))
             .await;
             // When mandate details are present in successful webhooks, and consuming webhooks are skipped during payment sync if the payment status is already updated to charged, this function is used to update the connector mandate details.
@@ -1159,6 +1160,7 @@ async fn external_authentication_incoming_webhook_flow(
                     payments::CallConnectorAction::Trigger,
                     None,
                     HeaderPayload::with_source(enums::PaymentSource::ExternalAuthenticator),
+                    None, // Platform merchant account
                 ))
                 .await?;
                 match payments_response {
@@ -1356,6 +1358,7 @@ async fn frm_incoming_webhook_flow(
                     payments::CallConnectorAction::Trigger,
                     None,
                     HeaderPayload::default(),
+                    None, // Platform merchant account
                 ))
                 .await?
             }
@@ -1385,6 +1388,7 @@ async fn frm_incoming_webhook_flow(
                     payments::CallConnectorAction::Trigger,
                     None,
                     HeaderPayload::default(),
+                    None, // Platform merchant account
                 ))
                 .await?
             }
@@ -1543,6 +1547,7 @@ async fn bank_transfer_webhook_flow(
             payments::CallConnectorAction::Trigger,
             None,
             HeaderPayload::with_source(common_enums::PaymentSource::Webhook),
+            None, //Platform merchant account
         ))
         .await
     } else {
diff --git a/crates/router/src/lib.rs b/crates/router/src/lib.rs
index 625a4d9c95b..9ed724c36ef 100644
--- a/crates/router/src/lib.rs
+++ b/crates/router/src/lib.rs
@@ -90,6 +90,7 @@ pub mod headers {
     pub const X_REDIRECT_URI: &str = "x-redirect-uri";
     pub const X_TENANT_ID: &str = "x-tenant-id";
     pub const X_CLIENT_SECRET: &str = "X-Client-Secret";
+    pub const X_CONNECTED_MERCHANT_ID: &str = "x-connected-merchant-id";
     pub const X_RESOURCE_TYPE: &str = "X-Resource-Type";
 }
 
diff --git a/crates/router/src/routes/admin.rs b/crates/router/src/routes/admin.rs
index a57fd56e6c8..9557aabbe81 100644
--- a/crates/router/src/routes/admin.rs
+++ b/crates/router/src/routes/admin.rs
@@ -910,3 +910,26 @@ pub async fn merchant_account_transfer_keys(
     ))
     .await
 }
+
+/// Merchant Account - Platform Account
+///
+/// Enable platform account
+#[instrument(skip_all)]
+pub async fn merchant_account_enable_platform_account(
+    state: web::Data<AppState>,
+    req: HttpRequest,
+    path: web::Path<common_utils::id_type::MerchantId>,
+) -> HttpResponse {
+    let flow = Flow::EnablePlatformAccount;
+    let merchant_id = path.into_inner();
+    Box::pin(api::server_wrap(
+        flow,
+        state,
+        &req,
+        merchant_id,
+        |state, _, req, _| enable_platform_account(state, req),
+        &auth::AdminApiAuth,
+        api_locking::LockAction::NotApplicable,
+    ))
+    .await
+}
diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs
index 2decddb806c..5865c1014fb 100644
--- a/crates/router/src/routes/app.rs
+++ b/crates/router/src/routes/app.rs
@@ -1337,8 +1337,7 @@ impl MerchantAccount {
 #[cfg(all(feature = "olap", feature = "v1"))]
 impl MerchantAccount {
     pub fn server(state: AppState) -> Scope {
-        web::scope("/accounts")
-            .app_data(web::Data::new(state))
+        let mut routes = web::scope("/accounts")
             .service(web::resource("").route(web::post().to(admin::merchant_account_create)))
             .service(web::resource("/list").route(web::get().to(admin::merchant_account_list)))
             .service(
@@ -1358,7 +1357,14 @@ impl MerchantAccount {
                     .route(web::get().to(admin::retrieve_merchant_account))
                     .route(web::post().to(admin::update_merchant_account))
                     .route(web::delete().to(admin::delete_merchant_account)),
+            );
+        if state.conf.platform.enabled {
+            routes = routes.service(
+                web::resource("/{id}/platform")
+                    .route(web::post().to(admin::merchant_account_enable_platform_account)),
             )
+        }
+        routes.app_data(web::Data::new(state))
     }
 }
 
diff --git a/crates/router/src/routes/lock_utils.rs b/crates/router/src/routes/lock_utils.rs
index 4b43c42f3bc..198692ac2d6 100644
--- a/crates/router/src/routes/lock_utils.rs
+++ b/crates/router/src/routes/lock_utils.rs
@@ -48,7 +48,8 @@ impl From<Flow> for ApiIdentifier {
             | Flow::MerchantsAccountUpdate
             | Flow::MerchantsAccountDelete
             | Flow::MerchantTransferKey
-            | Flow::MerchantAccountList => Self::MerchantAccount,
+            | Flow::MerchantAccountList
+            | Flow::EnablePlatformAccount => Self::MerchantAccount,
 
             Flow::OrganizationCreate | Flow::OrganizationRetrieve | Flow::OrganizationUpdate => {
                 Self::Organization
diff --git a/crates/router/src/routes/payments.rs b/crates/router/src/routes/payments.rs
index a9005644beb..46f6a5e492a 100644
--- a/crates/router/src/routes/payments.rs
+++ b/crates/router/src/routes/payments.rs
@@ -85,6 +85,7 @@ pub async fn payments_create(
                 header_payload.clone(),
                 req,
                 api::AuthFlow::Merchant,
+                auth.platform_merchant_account,
             )
         },
         match env::which() {
@@ -143,6 +144,7 @@ pub async fn payments_create_intent(
                 req,
                 global_payment_id.clone(),
                 header_payload.clone(),
+                auth.platform_merchant_account,
             )
         },
         match env::which() {
@@ -206,6 +208,7 @@ pub async fn payments_get_intent(
                 req,
                 global_payment_id.clone(),
                 header_payload.clone(),
+                auth.platform_merchant_account,
             )
         },
         &auth::HeaderAuth(auth::ApiKeyAuth),
@@ -261,6 +264,7 @@ pub async fn payments_update_intent(
                 req.payload,
                 global_payment_id.clone(),
                 header_payload.clone(),
+                auth.platform_merchant_account,
             )
         },
         &auth::HeaderAuth(auth::ApiKeyAuth),
@@ -316,6 +320,7 @@ pub async fn payments_start(
                 payments::CallConnectorAction::Trigger,
                 None,
                 HeaderPayload::default(),
+                None,
             )
         },
         &auth::MerchantIdAuth(merchant_id),
@@ -390,6 +395,7 @@ pub async fn payments_retrieve(
                 payments::CallConnectorAction::Trigger,
                 None,
                 header_payload.clone(),
+                auth.platform_merchant_account,
             )
         },
         auth::auth_type(
@@ -460,6 +466,7 @@ pub async fn payments_retrieve_with_gateway_creds(
                 payments::CallConnectorAction::Trigger,
                 None,
                 HeaderPayload::default(),
+                auth.platform_merchant_account,
             )
         },
         &*auth_type,
@@ -512,6 +519,7 @@ pub async fn payments_update(
                 HeaderPayload::default(),
                 req,
                 auth_flow,
+                auth.platform_merchant_account,
             )
         },
         &*auth_type,
@@ -570,6 +578,7 @@ pub async fn payments_post_session_tokens(
                 payments::CallConnectorAction::Trigger,
                 None,
                 header_payload.clone(),
+                None,
             )
         },
         &auth::PublishableKeyAuth,
@@ -632,6 +641,7 @@ pub async fn payments_confirm(
                 header_payload.clone(),
                 req,
                 auth_flow,
+                auth.platform_merchant_account,
             )
         },
         &*auth_type,
@@ -684,6 +694,7 @@ pub async fn payments_capture(
                 payments::CallConnectorAction::Trigger,
                 None,
                 HeaderPayload::default(),
+                auth.platform_merchant_account,
             )
         },
         &auth::HeaderAuth(auth::ApiKeyAuth),
@@ -743,6 +754,7 @@ pub async fn payments_dynamic_tax_calculation(
                 payments::CallConnectorAction::Trigger,
                 None,
                 header_payload.clone(),
+                None,
             )
         },
         &auth::PublishableKeyAuth,
@@ -806,6 +818,7 @@ pub async fn payments_connector_session(
                 payment_id,
                 payments::CallConnectorAction::Trigger,
                 header_payload.clone(),
+                auth.platform_merchant_account,
             )
         },
         &auth::HeaderAuth(auth::PublishableKeyAuth),
@@ -864,6 +877,7 @@ pub async fn payments_connector_session(
                 payments::CallConnectorAction::Trigger,
                 None,
                 header_payload.clone(),
+                None,
             )
         },
         &auth::HeaderAuth(auth::PublishableKeyAuth),
@@ -913,7 +927,7 @@ pub async fn payments_redirect_response(
                 auth.merchant_account,
                 auth.key_store,
                 req,
-
+                auth.platform_merchant_account,
             )
         },
         &auth::MerchantIdAuth(merchant_id),
@@ -963,7 +977,7 @@ pub async fn payments_redirect_response_with_creds_identifier(
                 auth.merchant_account,
                 auth.key_store,
                 req,
-
+                auth.platform_merchant_account,
             )
         },
         &auth::MerchantIdAuth(merchant_id),
@@ -1014,7 +1028,7 @@ pub async fn payments_complete_authorize_redirect(
                 auth.merchant_account,
                 auth.key_store,
                 req,
-
+                auth.platform_merchant_account,
             )
         },
         &auth::MerchantIdAuth(merchant_id),
@@ -1080,6 +1094,7 @@ pub async fn payments_complete_authorize(
                 payments::CallConnectorAction::Trigger,
                 None,
                 HeaderPayload::default(),
+                None,
             )
         },
         &*auth_type,
@@ -1129,6 +1144,7 @@ pub async fn payments_cancel(
                 payments::CallConnectorAction::Trigger,
                 None,
                 HeaderPayload::default(),
+                auth.platform_merchant_account,
             )
         },
         &auth::HeaderAuth(auth::ApiKeyAuth),
@@ -1409,6 +1425,7 @@ pub async fn payments_approve(
                 payments::CallConnectorAction::Trigger,
                 None,
                 HeaderPayload::default(),
+                auth.platform_merchant_account,
             )
         },
         match env::which() {
@@ -1473,6 +1490,7 @@ pub async fn payments_reject(
                 payments::CallConnectorAction::Trigger,
                 None,
                 HeaderPayload::default(),
+                auth.platform_merchant_account,
             )
         },
         match env::which() {
@@ -1502,6 +1520,7 @@ async fn authorize_verify_select<Op>(
     header_payload: HeaderPayload,
     req: api_models::payments::PaymentsRequest,
     auth_flow: api::AuthFlow,
+    platform_merchant_account: Option<domain::MerchantAccount>,
 ) -> errors::RouterResponse<api_models::payments::PaymentsResponse>
 where
     Op: Sync
@@ -1551,6 +1570,7 @@ where
             auth_flow,
             payments::CallConnectorAction::Trigger,
             header_payload,
+            platform_merchant_account,
         )
         .await
     } else {
@@ -1578,6 +1598,7 @@ where
                     payments::CallConnectorAction::Trigger,
                     eligible_connectors,
                     header_payload,
+                    platform_merchant_account,
                 )
                 .await
             }
@@ -1601,6 +1622,7 @@ where
                     payments::CallConnectorAction::Trigger,
                     eligible_connectors,
                     header_payload,
+                    platform_merchant_account,
                 )
                 .await
             }
@@ -1649,6 +1671,7 @@ pub async fn payments_incremental_authorization(
                 payments::CallConnectorAction::Trigger,
                 None,
                 HeaderPayload::default(),
+                auth.platform_merchant_account,
             )
         },
         &auth::HeaderAuth(auth::ApiKeyAuth),
@@ -1734,6 +1757,7 @@ pub async fn post_3ds_payments_authorize(
                 auth.merchant_account,
                 auth.key_store,
                 req,
+                auth.platform_merchant_account,
             )
         },
         &auth::MerchantIdAuth(merchant_id),
@@ -2437,6 +2461,7 @@ pub async fn payments_finish_redirection(
                 auth.key_store,
                 auth.profile,
                 req,
+                auth.platform_merchant_account
             )
         },
         &auth::PublishableKeyAndProfileIdAuth {
diff --git a/crates/router/src/services/authentication.rs b/crates/router/src/services/authentication.rs
index e5412c20fe2..d35e321a7be 100644
--- a/crates/router/src/services/authentication.rs
+++ b/crates/router/src/services/authentication.rs
@@ -63,6 +63,7 @@ mod detached;
 #[derive(Clone, Debug)]
 pub struct AuthenticationData {
     pub merchant_account: domain::MerchantAccount,
+    pub platform_merchant_account: Option<domain::MerchantAccount>,
     pub key_store: domain::MerchantKeyStore,
     pub profile_id: Option<id_type::ProfileId>,
 }
@@ -73,6 +74,7 @@ pub struct AuthenticationData {
     pub merchant_account: domain::MerchantAccount,
     pub key_store: domain::MerchantKeyStore,
     pub profile: domain::Profile,
+    pub platform_merchant_account: Option<domain::MerchantAccount>,
 }
 
 #[derive(Clone, Debug)]
@@ -466,6 +468,28 @@ where
             .await
             .to_not_found_response(errors::ApiErrorResponse::Unauthorized)?;
 
+        // Get connected merchant account if API call is done by Platform merchant account on behalf of connected merchant account
+        let (merchant, platform_merchant_account) = if state.conf().platform.enabled {
+            get_platform_merchant_account(state, request_headers, merchant).await?
+        } else {
+            (merchant, None)
+        };
+
+        let key_store = if platform_merchant_account.is_some() {
+            state
+                .store()
+                .get_merchant_key_store_by_merchant_id(
+                    key_manager_state,
+                    merchant.get_id(),
+                    &state.store().get_master_key().to_vec().into(),
+                )
+                .await
+                .change_context(errors::ApiErrorResponse::Unauthorized)
+                .attach_printable("Failed to fetch merchant key store for the merchant id")?
+        } else {
+            key_store
+        };
+
         let profile = state
             .store()
             .find_business_profile_by_profile_id(key_manager_state, &key_store, &profile_id)
@@ -474,6 +498,7 @@ where
 
         let auth = AuthenticationData {
             merchant_account: merchant,
+            platform_merchant_account,
             key_store,
             profile,
         };
@@ -563,8 +588,31 @@ where
             .await
             .to_not_found_response(errors::ApiErrorResponse::Unauthorized)?;
 
+        // Get connected merchant account if API call is done by Platform merchant account on behalf of connected merchant account
+        let (merchant, platform_merchant_account) = if state.conf().platform.enabled {
+            get_platform_merchant_account(state, request_headers, merchant).await?
+        } else {
+            (merchant, None)
+        };
+
+        let key_store = if platform_merchant_account.is_some() {
+            state
+                .store()
+                .get_merchant_key_store_by_merchant_id(
+                    key_manager_state,
+                    merchant.get_id(),
+                    &state.store().get_master_key().to_vec().into(),
+                )
+                .await
+                .change_context(errors::ApiErrorResponse::Unauthorized)
+                .attach_printable("Failed to fetch merchant key store for the merchant id")?
+        } else {
+            key_store
+        };
+
         let auth = AuthenticationData {
             merchant_account: merchant,
+            platform_merchant_account,
             key_store,
             profile_id,
         };
@@ -639,7 +687,8 @@ where
                     merchant_id: Some(merchant_id),
                     key_id: Some(key_id),
                 } => {
-                    let auth = construct_authentication_data(state, &merchant_id).await?;
+                    let auth =
+                        construct_authentication_data(state, &merchant_id, request_headers).await?;
                     Ok((
                         auth.clone(),
                         AuthenticationType::ApiKey {
@@ -653,7 +702,8 @@ where
                     merchant_id: Some(merchant_id),
                     key_id: None,
                 } => {
-                    let auth = construct_authentication_data(state, &merchant_id).await?;
+                    let auth =
+                        construct_authentication_data(state, &merchant_id, request_headers).await?;
                     Ok((
                         auth.clone(),
                         AuthenticationType::PublishableKey {
@@ -716,6 +766,7 @@ where
 
         let auth_data_v2 = AuthenticationData {
             merchant_account: auth_data.merchant_account,
+            platform_merchant_account: auth_data.platform_merchant_account,
             key_store: auth_data.key_store,
             profile,
         };
@@ -727,9 +778,10 @@ where
 async fn construct_authentication_data<A>(
     state: &A,
     merchant_id: &id_type::MerchantId,
+    request_headers: &HeaderMap,
 ) -> RouterResult<AuthenticationData>
 where
-    A: SessionStateInfo,
+    A: SessionStateInfo + Sync,
 {
     let key_store = state
         .store()
@@ -752,8 +804,31 @@ where
         .await
         .to_not_found_response(errors::ApiErrorResponse::Unauthorized)?;
 
+    // Get connected merchant account if API call is done by Platform merchant account on behalf of connected merchant account
+    let (merchant, platform_merchant_account) = if state.conf().platform.enabled {
+        get_platform_merchant_account(state, request_headers, merchant).await?
+    } else {
+        (merchant, None)
+    };
+
+    let key_store = if platform_merchant_account.is_some() {
+        state
+            .store()
+            .get_merchant_key_store_by_merchant_id(
+                &(&state.session_state()).into(),
+                merchant.get_id(),
+                &state.store().get_master_key().to_vec().into(),
+            )
+            .await
+            .change_context(errors::ApiErrorResponse::Unauthorized)
+            .attach_printable("Failed to fetch merchant key store for the merchant id")?
+    } else {
+        key_store
+    };
+
     let auth = AuthenticationData {
         merchant_account: merchant,
+        platform_merchant_account,
         key_store,
         profile_id: None,
     };
@@ -1003,6 +1078,7 @@ where
 
         let auth = AuthenticationData {
             merchant_account: merchant,
+            platform_merchant_account: None,
             key_store,
             profile_id: None,
         };
@@ -1025,6 +1101,10 @@ where
         request_headers: &HeaderMap,
         state: &A,
     ) -> RouterResult<(AuthenticationData, AuthenticationType)> {
+        if state.conf().platform.enabled {
+            throw_error_if_platform_merchant_authentication_required(request_headers)?;
+        }
+
         AdminApiAuth
             .authenticate_and_fetch(request_headers, state)
             .await?;
@@ -1063,6 +1143,7 @@ where
             merchant_account: merchant,
             key_store,
             profile,
+            platform_merchant_account: None,
         };
 
         Ok((
@@ -1084,6 +1165,10 @@ where
         request_headers: &HeaderMap,
         state: &A,
     ) -> RouterResult<(AuthenticationDataWithoutProfile, AuthenticationType)> {
+        if state.conf().platform.enabled {
+            throw_error_if_platform_merchant_authentication_required(request_headers)?;
+        }
+
         AdminApiAuth
             .authenticate_and_fetch(request_headers, state)
             .await?;
@@ -1182,6 +1267,34 @@ impl<'a> HeaderMapStruct<'a> {
                 )
             })
     }
+
+    pub fn get_id_type_from_header_if_present<T>(&self, key: &str) -> RouterResult<Option<T>>
+    where
+        T: TryFrom<
+            std::borrow::Cow<'static, str>,
+            Error = error_stack::Report<errors::ValidationError>,
+        >,
+    {
+        self.headers
+            .get(key)
+            .map(|value| value.to_str())
+            .transpose()
+            .change_context(errors::ApiErrorResponse::InvalidDataValue {
+                field_name: "`{key}` in headers",
+            })
+            .attach_printable(format!(
+                "Failed to convert header value to string for header key: {}",
+                key
+            ))?
+            .map(|value| {
+                T::try_from(std::borrow::Cow::Owned(value.to_owned())).change_context(
+                    errors::ApiErrorResponse::InvalidRequestData {
+                        message: format!("`{}` header is invalid", key),
+                    },
+                )
+            })
+            .transpose()
+    }
 }
 
 /// Get the merchant-id from `x-merchant-id` header
@@ -1225,6 +1338,7 @@ where
 
         let auth = AuthenticationData {
             merchant_account: merchant,
+            platform_merchant_account: None,
             key_store,
             profile_id: None,
         };
@@ -1246,6 +1360,10 @@ where
         request_headers: &HeaderMap,
         state: &A,
     ) -> RouterResult<(AuthenticationData, AuthenticationType)> {
+        if state.conf().platform.enabled {
+            throw_error_if_platform_merchant_authentication_required(request_headers)?;
+        }
+
         AdminApiAuth
             .authenticate_and_fetch(request_headers, state)
             .await?;
@@ -1286,6 +1404,7 @@ where
             merchant_account: merchant,
             key_store,
             profile,
+            platform_merchant_account: None,
         };
         Ok((
             auth,
@@ -1306,6 +1425,10 @@ where
         request_headers: &HeaderMap,
         state: &A,
     ) -> RouterResult<(AuthenticationDataWithoutProfile, AuthenticationType)> {
+        if state.conf().platform.enabled {
+            throw_error_if_platform_merchant_authentication_required(request_headers)?;
+        }
+
         AdminApiAuth
             .authenticate_and_fetch(request_headers, state)
             .await?;
@@ -1418,9 +1541,13 @@ where
 {
     async fn authenticate_and_fetch(
         &self,
-        _request_headers: &HeaderMap,
+        request_headers: &HeaderMap,
         state: &A,
     ) -> RouterResult<(AuthenticationData, AuthenticationType)> {
+        if state.conf().platform.enabled {
+            throw_error_if_platform_merchant_authentication_required(request_headers)?;
+        }
+
         let key_manager_state = &(&state.session_state()).into();
         let key_store = state
             .store()
@@ -1440,6 +1567,7 @@ where
 
         let auth = AuthenticationData {
             merchant_account: merchant,
+            platform_merchant_account: None,
             key_store,
             profile_id: None,
         };
@@ -1463,6 +1591,10 @@ where
         request_headers: &HeaderMap,
         state: &A,
     ) -> RouterResult<(AuthenticationData, AuthenticationType)> {
+        if state.conf().platform.enabled {
+            throw_error_if_platform_merchant_authentication_required(request_headers)?;
+        }
+
         let key_manager_state = &(&state.session_state()).into();
         let profile_id =
             get_id_type_by_key_from_headers(headers::X_PROFILE_ID.to_string(), request_headers)?
@@ -1497,6 +1629,7 @@ where
             merchant_account: merchant,
             key_store,
             profile,
+            platform_merchant_account: None,
         };
         Ok((
             auth.clone(),
@@ -1525,6 +1658,10 @@ where
         request_headers: &HeaderMap,
         state: &A,
     ) -> RouterResult<(AuthenticationData, AuthenticationType)> {
+        if state.conf().platform.enabled {
+            throw_error_if_platform_merchant_authentication_required(request_headers)?;
+        }
+
         let key_manager_state = &(&state.session_state()).into();
         let key_store = state
             .store()
@@ -1556,6 +1693,7 @@ where
             merchant_account: merchant,
             key_store,
             profile,
+            platform_merchant_account: None,
         };
         Ok((
             auth.clone(),
@@ -1615,6 +1753,7 @@ where
                 merchant_account,
                 key_store,
                 profile,
+                platform_merchant_account: None,
             },
             AuthenticationType::PublishableKey { merchant_id },
         ))
@@ -1642,6 +1781,10 @@ where
         request_headers: &HeaderMap,
         state: &A,
     ) -> RouterResult<(AuthenticationData, AuthenticationType)> {
+        if state.conf().platform.enabled {
+            throw_error_if_platform_merchant_authentication_required(request_headers)?;
+        }
+
         let publishable_key =
             get_api_key(request_headers).change_context(errors::ApiErrorResponse::Unauthorized)?;
         let key_manager_state = &(&state.session_state()).into();
@@ -1655,6 +1798,7 @@ where
                 (
                     AuthenticationData {
                         merchant_account,
+                        platform_merchant_account: None,
                         key_store,
                         profile_id: None,
                     },
@@ -1703,6 +1847,7 @@ where
                 merchant_account,
                 key_store,
                 profile,
+                platform_merchant_account: None,
             },
             AuthenticationType::PublishableKey { merchant_id },
         ))
@@ -1991,6 +2136,7 @@ where
 
         let auth = AuthenticationData {
             merchant_account: merchant,
+            platform_merchant_account: None,
             key_store,
             profile_id: Some(payload.profile_id),
         };
@@ -2073,6 +2219,7 @@ where
             merchant_account: merchant,
             key_store,
             profile,
+            platform_merchant_account: None,
         };
 
         Ok((
@@ -2239,6 +2386,7 @@ where
 
         let auth = AuthenticationData {
             merchant_account: merchant,
+            platform_merchant_account: None,
             key_store,
             profile_id: Some(payload.profile_id),
         };
@@ -2314,6 +2462,7 @@ where
             merchant_account: merchant,
             key_store,
             profile,
+            platform_merchant_account: None,
         };
         Ok((
             auth.clone(),
@@ -2448,6 +2597,7 @@ where
 
         let auth = AuthenticationData {
             merchant_account: merchant,
+            platform_merchant_account: None,
             key_store,
             profile_id: Some(payload.profile_id),
         };
@@ -2519,6 +2669,7 @@ where
             // if both of them are same then proceed with the profile id present in the request
             let auth = AuthenticationData {
                 merchant_account: merchant,
+                platform_merchant_account: None,
                 key_store,
                 profile_id: Some(self.profile_id.clone()),
             };
@@ -2592,6 +2743,7 @@ where
             merchant_account: merchant,
             key_store,
             profile,
+            platform_merchant_account: None,
         };
         Ok((
             auth.clone(),
@@ -2680,6 +2832,7 @@ where
         let merchant_id = merchant.get_id().clone();
         let auth = AuthenticationData {
             merchant_account: merchant,
+            platform_merchant_account: None,
             key_store,
             profile_id: Some(payload.profile_id),
         };
@@ -2756,6 +2909,7 @@ where
             merchant_account: merchant,
             key_store,
             profile,
+            platform_merchant_account: None,
         };
         Ok((
             auth,
@@ -2816,6 +2970,7 @@ where
 
         let auth = AuthenticationData {
             merchant_account: merchant,
+            platform_merchant_account: None,
             key_store,
             profile_id: Some(payload.profile_id),
         };
@@ -2934,6 +3089,7 @@ where
 
         let auth = AuthenticationData {
             merchant_account: merchant,
+            platform_merchant_account: None,
             key_store,
             profile_id: Some(payload.profile_id),
         };
@@ -3298,6 +3454,96 @@ where
     }
 }
 
+async fn get_connected_merchant_account<A>(
+    state: &A,
+    connected_merchant_id: id_type::MerchantId,
+    platform_org_id: id_type::OrganizationId,
+) -> RouterResult<domain::MerchantAccount>
+where
+    A: SessionStateInfo + Sync,
+{
+    let key_manager_state = &(&state.session_state()).into();
+    let key_store = state
+        .store()
+        .get_merchant_key_store_by_merchant_id(
+            key_manager_state,
+            &connected_merchant_id,
+            &state.store().get_master_key().to_vec().into(),
+        )
+        .await
+        .to_not_found_response(errors::ApiErrorResponse::InvalidPlatformOperation)
+        .attach_printable("Failed to fetch merchant key store for the merchant id")?;
+
+    let connected_merchant_account = state
+        .store()
+        .find_merchant_account_by_merchant_id(key_manager_state, &connected_merchant_id, &key_store)
+        .await
+        .to_not_found_response(errors::ApiErrorResponse::InvalidPlatformOperation)
+        .attach_printable("Failed to fetch merchant account for the merchant id")?;
+
+    if platform_org_id != connected_merchant_account.organization_id {
+        return Err(errors::ApiErrorResponse::InvalidPlatformOperation)
+            .attach_printable("Access for merchant id Unauthorized");
+    }
+
+    Ok(connected_merchant_account)
+}
+
+async fn get_platform_merchant_account<A>(
+    state: &A,
+    request_headers: &HeaderMap,
+    merchant_account: domain::MerchantAccount,
+) -> RouterResult<(domain::MerchantAccount, Option<domain::MerchantAccount>)>
+where
+    A: SessionStateInfo + Sync,
+{
+    let connected_merchant_id =
+        get_and_validate_connected_merchant_id(request_headers, &merchant_account)?;
+
+    match connected_merchant_id {
+        Some(merchant_id) => {
+            let connected_merchant_account = get_connected_merchant_account(
+                state,
+                merchant_id,
+                merchant_account.organization_id.clone(),
+            )
+            .await?;
+            Ok((connected_merchant_account, Some(merchant_account)))
+        }
+        None => Ok((merchant_account, None)),
+    }
+}
+
+fn get_and_validate_connected_merchant_id(
+    request_headers: &HeaderMap,
+    merchant_account: &domain::MerchantAccount,
+) -> RouterResult<Option<id_type::MerchantId>> {
+    HeaderMapStruct::new(request_headers)
+        .get_id_type_from_header_if_present::<id_type::MerchantId>(
+            headers::X_CONNECTED_MERCHANT_ID,
+        )?
+        .map(|merchant_id| {
+            merchant_account
+                .is_platform_account
+                .then_some(merchant_id)
+                .ok_or(errors::ApiErrorResponse::InvalidPlatformOperation)
+        })
+        .transpose()
+        .attach_printable("Non platform_merchant_account using X_CONNECTED_MERCHANT_ID header")
+}
+
+fn throw_error_if_platform_merchant_authentication_required(
+    request_headers: &HeaderMap,
+) -> RouterResult<()> {
+    HeaderMapStruct::new(request_headers)
+        .get_id_type_from_header_if_present::<id_type::MerchantId>(
+            headers::X_CONNECTED_MERCHANT_ID,
+        )?
+        .map_or(Ok(()), |_| {
+            Err(errors::ApiErrorResponse::PlatformAccountAuthNotSupported.into())
+        })
+}
+
 #[cfg(feature = "recon")]
 #[async_trait]
 impl<A> AuthenticateAndFetch<UserFromTokenWithRoleInfo, A> for JWTAuth
diff --git a/crates/router/src/utils/user/sample_data.rs b/crates/router/src/utils/user/sample_data.rs
index 09cd7cfa103..bf84dd568a2 100644
--- a/crates/router/src/utils/user/sample_data.rs
+++ b/crates/router/src/utils/user/sample_data.rs
@@ -275,6 +275,7 @@ pub async fn generate_sample_data(
             tax_details: None,
             skip_external_tax_calculation: None,
             psd2_sca_exemption_type: None,
+            platform_merchant_id: None,
         };
         let (connector_transaction_id, connector_transaction_data) =
             ConnectorTransactionId::form_id_and_data(attempt_id.clone());
diff --git a/crates/router/src/workflows/outgoing_webhook_retry.rs b/crates/router/src/workflows/outgoing_webhook_retry.rs
index 1bfcc8ebe7b..c7df4aeff0c 100644
--- a/crates/router/src/workflows/outgoing_webhook_retry.rs
+++ b/crates/router/src/workflows/outgoing_webhook_retry.rs
@@ -400,6 +400,7 @@ async fn get_outgoing_webhook_content_and_event_type(
                 CallConnectorAction::Avoid,
                 None,
                 hyperswitch_domain_models::payments::HeaderPayload::default(),
+                None, //Platform merchant account
             ))
             .await?
             {
diff --git a/crates/router/src/workflows/payment_sync.rs b/crates/router/src/workflows/payment_sync.rs
index 04fa1648492..fb83922935e 100644
--- a/crates/router/src/workflows/payment_sync.rs
+++ b/crates/router/src/workflows/payment_sync.rs
@@ -91,6 +91,7 @@ impl ProcessTrackerWorkflow<SessionState> for PaymentsSyncWorkflow {
                 services::AuthFlow::Client,
                 None,
                 hyperswitch_domain_models::payments::HeaderPayload::default(),
+                None, //Platform merchant account
             ))
             .await?;
 
diff --git a/crates/router/tests/payments.rs b/crates/router/tests/payments.rs
index 37fb57e05f3..beaacb79fc0 100644
--- a/crates/router/tests/payments.rs
+++ b/crates/router/tests/payments.rs
@@ -472,6 +472,7 @@ async fn payments_create_core() {
         payments::CallConnectorAction::Trigger,
         None,
         hyperswitch_domain_models::payments::HeaderPayload::default(),
+        None,
     ))
     .await
     .unwrap();
@@ -734,6 +735,7 @@ async fn payments_create_core_adyen_no_redirect() {
         payments::CallConnectorAction::Trigger,
         None,
         hyperswitch_domain_models::payments::HeaderPayload::default(),
+        None,
     ))
     .await
     .unwrap();
diff --git a/crates/router/tests/payments2.rs b/crates/router/tests/payments2.rs
index 415ea07cb9f..1d573d007ba 100644
--- a/crates/router/tests/payments2.rs
+++ b/crates/router/tests/payments2.rs
@@ -234,6 +234,7 @@ async fn payments_create_core() {
         payments::CallConnectorAction::Trigger,
         None,
         hyperswitch_domain_models::payments::HeaderPayload::default(),
+        None,
     ))
     .await
     .unwrap();
@@ -504,6 +505,7 @@ async fn payments_create_core_adyen_no_redirect() {
         payments::CallConnectorAction::Trigger,
         None,
         hyperswitch_domain_models::payments::HeaderPayload::default(),
+        None,
     ))
     .await
     .unwrap();
diff --git a/crates/router_env/src/logger/types.rs b/crates/router_env/src/logger/types.rs
index de2577e6c34..ccbf9598a56 100644
--- a/crates/router_env/src/logger/types.rs
+++ b/crates/router_env/src/logger/types.rs
@@ -88,6 +88,8 @@ pub enum Flow {
     ConfigKeyCreate,
     /// ConfigKey fetch flow.
     ConfigKeyFetch,
+    /// Enable platform account flow.
+    EnablePlatformAccount,
     /// ConfigKey Update flow.
     ConfigKeyUpdate,
     /// ConfigKey Delete flow.
diff --git a/migrations/2024-12-03-072318_platform_merchant_account/down.sql b/migrations/2024-12-03-072318_platform_merchant_account/down.sql
new file mode 100644
index 00000000000..342380e0933
--- /dev/null
+++ b/migrations/2024-12-03-072318_platform_merchant_account/down.sql
@@ -0,0 +1,4 @@
+-- This file should undo anything in `up.sql`
+ALTER TABLE merchant_account DROP COLUMN IF EXISTS is_platform_account;
+
+ALTER TABLE payment_intent DROP COLUMN IF EXISTS platform_merchant_id;
diff --git a/migrations/2024-12-03-072318_platform_merchant_account/up.sql b/migrations/2024-12-03-072318_platform_merchant_account/up.sql
new file mode 100644
index 00000000000..cd07e163d7c
--- /dev/null
+++ b/migrations/2024-12-03-072318_platform_merchant_account/up.sql
@@ -0,0 +1,4 @@
+-- Your SQL goes here
+ALTER TABLE merchant_account ADD COLUMN IF NOT EXISTS is_platform_account BOOL NOT NULL DEFAULT FALSE;
+
+ALTER TABLE payment_intent ADD COLUMN IF NOT EXISTS platform_merchant_id VARCHAR(64);

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

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

## Description
#### About the feature
- This the first PR for the Platform Account feature.
- Feature is under development and behind the feature flag. 
- Feature is supposed to be disabled for sandbox and production environments.
#### Enabling the platform account.
- New API has been created to enable platform account.
- API requires Admin API auth.
- Once enabled, there is no way of disabling platform account as of now.
#### How it works
- A new special header is to be sent by the platform called `x-connected-merchant-id`.
- Platform will use its own API key irrespective of the merchant id present in the above header.
- Value of this header is supposed to be the merchant id of the merchant account on behalf of which the platform is performing the operation.
- **If the platform has `is_platform` true and the merchant account on behalf of which operation is performed belongs to the same organisation as platform** then the operation is allowed.
#### Payment Intent
- Operation will be performed for merchant id present in the `x-connected-merchant-id` header.
- `platform_merchant_id` column for the payment intent will be populated with platforms merchant id.
#### Other operations
- Will add context of `platform_merchant_id` in other operations as well.

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


### Additional Changes

- [x] This PR modifies the API contract
- [x] 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
#6883 
<!--
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).
-->


## How did you test it?
1. Create a merchant account(m1).
2. Use below api to convert it into platform account.
```sh
curl --location --request POST '<BASE URL>/accounts/{merchant_id}/platform' \
--header 'api-key:<ADMIN API KEY>'
```
3. Create another merchant account in the same organisation(m2).
4. Do a payment using platform's(m1) API key for connected merchant account(m2) by passing header `x-connected-merchant-id` with value as connected merchant account's merchant id.
5. Check if payment is created for connected merchant account.
6. Check if `platform_merchant_id` is populated with platform's merchant id.
<!--
Did you write an integration/unit/API test to verify the code changes?
Or did you test this change manually (provide relevant screenshots)?
-->


## 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
