Bug: [FEATURE] Integrate Plaid as an Open Banking Payment connector



### Feature Description

Integrate Plaid as an Open Banking Payment connector. 
Pre-requisite would be the Open Banking payments core Integration - #3612 

### Possible Implementation

Similar to regular connector integration

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

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

### Have you read the Contributing Guidelines?

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

### Are you willing to submit a PR?

Yes, I am willing to submit a PR!
diff --git a/config/config.example.toml b/config/config.example.toml
index 2ffb69c3e3d..eab5e84df9c 100644
--- a/config/config.example.toml
+++ b/config/config.example.toml
@@ -206,6 +206,7 @@ payme.base_url = "https://sandbox.payme.io/"
 paypal.base_url = "https://api-m.sandbox.paypal.com/"
 payu.base_url = "https://secure.snd.payu.com/"
 placetopay.base_url = "https://test.placetopay.com/rest/gateway"
+plaid.base_url = "https://sandbox.plaid.com"
 powertranz.base_url = "https://staging.ptranz.com/api/"
 prophetpay.base_url = "https://ccm-thirdparty.cps.golf/"
 rapyd.base_url = "https://sandboxapi.rapyd.net"
diff --git a/config/development.toml b/config/development.toml
index 6d4914af8b4..827fd71e452 100644
--- a/config/development.toml
+++ b/config/development.toml
@@ -127,6 +127,7 @@ cards = [
     "paypal",
     "payu",
     "placetopay",
+    "plaid",
     "powertranz",
     "prophetpay",
     "shift4",
@@ -201,6 +202,7 @@ payme.base_url = "https://sandbox.payme.io/"
 paypal.base_url = "https://api-m.sandbox.paypal.com/"
 payu.base_url = "https://secure.snd.payu.com/"
 placetopay.base_url = "https://test.placetopay.com/rest/gateway"
+plaid.base_url = "https://sandbox.plaid.com"
 powertranz.base_url = "https://staging.ptranz.com/api/"
 prophetpay.base_url = "https://ccm-thirdparty.cps.golf/"
 rapyd.base_url = "https://sandboxapi.rapyd.net"
@@ -581,4 +583,7 @@ enabled = true
 file_storage_backend = "file_system"
 
 [unmasked_headers]
-keys = "user-agent"
\ No newline at end of file
+keys = "user-agent"
+
+[locker_open_banking_connectors]
+connector_list = []
\ No newline at end of file
diff --git a/config/docker_compose.toml b/config/docker_compose.toml
index 2f94d69790b..91f8480056e 100644
--- a/config/docker_compose.toml
+++ b/config/docker_compose.toml
@@ -140,6 +140,7 @@ payme.base_url = "https://sandbox.payme.io/"
 paypal.base_url = "https://api-m.sandbox.paypal.com/"
 payu.base_url = "https://secure.snd.payu.com/"
 placetopay.base_url = "https://test.placetopay.com/rest/gateway"
+plaid.base_url = "https://sandbox.plaid.com"
 powertranz.base_url = "https://staging.ptranz.com/api/"
 prophetpay.base_url = "https://ccm-thirdparty.cps.golf/"
 rapyd.base_url = "https://sandboxapi.rapyd.net"
@@ -206,6 +207,7 @@ cards = [
     "paypal",
     "payu",
     "placetopay",
+    "plaid",
     "powertranz",
     "prophetpay",
     "shift4",
diff --git a/crates/api_models/src/admin.rs b/crates/api_models/src/admin.rs
index bf88eca0a0e..067f69b56e1 100644
--- a/crates/api_models/src/admin.rs
+++ b/crates/api_models/src/admin.rs
@@ -479,6 +479,32 @@ pub struct MerchantConnectorCreate {
     pub status: Option<api_enums::ConnectorStatus>,
 }
 
+#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
+pub enum MerchantAccountData {
+    Iban {
+        iban: Secret<String>,
+        name: String,
+    },
+    Bacs {
+        account_number: Secret<String>,
+        sort_code: Secret<String>,
+        name: String,
+    },
+}
+
+#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
+pub enum MerchantRecipientData {
+    RecipientId(Secret<String>),
+    WalletId(Secret<String>),
+    AccountData(MerchantAccountData),
+}
+#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
+pub struct OpenBankingAuthType {
+    pub api_key: Secret<String>,
+    pub key1: Secret<String>,
+    pub merchant_data: MerchantRecipientData,
+}
+
 // Different patterns of authentication.
 #[derive(Default, Debug, Clone, serde::Deserialize, serde::Serialize)]
 #[serde(tag = "auth_type")]
@@ -505,6 +531,11 @@ pub enum ConnectorAuthType {
     CurrencyAuthKey {
         auth_key_map: HashMap<common_enums::Currency, pii::SecretSerdeValue>,
     },
+    OpenBankingAuth {
+        api_key: Secret<String>,
+        key1: Secret<String>,
+        merchant_data: MerchantRecipientData,
+    },
     #[default]
     NoKey,
 }
diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs
index dee5f2d0757..a21d03aba90 100644
--- a/crates/api_models/src/payments.rs
+++ b/crates/api_models/src/payments.rs
@@ -1346,6 +1346,7 @@ impl GetPaymentMethodType for BankRedirectData {
             Self::OnlineBankingThailand { .. } => {
                 api_enums::PaymentMethodType::OnlineBankingThailand
             }
+            Self::OpenBanking { .. } => api_enums::PaymentMethodType::OpenBanking,
         }
     }
 }
@@ -1620,6 +1621,7 @@ pub enum BankRedirectData {
         #[schema(value_type = BankNames)]
         issuer: api_enums::BankNames,
     },
+    OpenBanking {},
 }
 
 #[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
@@ -2263,7 +2265,9 @@ pub enum NextActionData {
         bank_transfer_steps_and_charges_details: BankTransferNextStepsData,
     },
     /// Contains third party sdk session token response
-    ThirdPartySdkSessionToken { session_token: Option<SessionToken> },
+    ThirdPartySdkSessionToken {
+        session_token: Option<SessionTokenType>,
+    },
     /// Contains url for Qr code image, this qr code has to be shown in sdk
     QrCodeInformation {
         #[schema(value_type = String)]
@@ -3319,6 +3323,13 @@ pub struct SessionTokenForSimplifiedApplePay {
     pub initiative_context: String,
 }
 
+#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema)]
+#[serde(untagged)]
+pub enum SessionTokenType {
+    Wallet(SessionToken),
+    OpenBanking(OpenBankingSessionToken),
+}
+
 #[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema)]
 #[serde(tag = "wallet_name")]
 #[serde(rename_all = "snake_case")]
@@ -3390,6 +3401,13 @@ pub struct PaypalSessionTokenResponse {
     pub session_token: String,
 }
 
+#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema)]
+#[serde(rename_all = "lowercase")]
+pub struct OpenBankingSessionToken {
+    /// The session token for OpenBanking Connectors
+    pub open_banking_session_token: String,
+}
+
 #[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema)]
 #[serde(rename_all = "lowercase")]
 pub struct ApplepaySessionTokenResponse {
@@ -3523,7 +3541,7 @@ pub struct PaymentsSessionResponse {
     #[schema(value_type = String)]
     pub client_secret: Secret<String, pii::ClientSecret>,
     /// The list of session token object
-    pub session_token: Vec<SessionToken>,
+    pub session_token: Vec<SessionTokenType>,
 }
 
 #[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
diff --git a/crates/common_enums/src/enums.rs b/crates/common_enums/src/enums.rs
index 9cf138ed330..58c0152d8db 100644
--- a/crates/common_enums/src/enums.rs
+++ b/crates/common_enums/src/enums.rs
@@ -163,6 +163,7 @@ pub enum RoutableConnectors {
     Worldline,
     Worldpay,
     Zen,
+    Plaid,
 }
 
 impl AttemptStatus {
@@ -1345,6 +1346,7 @@ pub enum PaymentMethodType {
     FamilyMart,
     Seicomart,
     PayEasy,
+    OpenBanking,
 }
 
 /// Indicates the type of payment method. Eg: 'card', 'wallet', etc.
diff --git a/crates/common_enums/src/transformers.rs b/crates/common_enums/src/transformers.rs
index 63abfdb3f73..86ec6d3a709 100644
--- a/crates/common_enums/src/transformers.rs
+++ b/crates/common_enums/src/transformers.rs
@@ -1873,6 +1873,7 @@ impl From<PaymentMethodType> for PaymentMethod {
             PaymentMethodType::FamilyMart => Self::Voucher,
             PaymentMethodType::Seicomart => Self::Voucher,
             PaymentMethodType::PayEasy => Self::Voucher,
+            PaymentMethodType::OpenBanking => Self::BankRedirect,
         }
     }
 }
diff --git a/crates/euclid/src/frontend/dir/enums.rs b/crates/euclid/src/frontend/dir/enums.rs
index 0b71f916d03..982ae4a3c43 100644
--- a/crates/euclid/src/frontend/dir/enums.rs
+++ b/crates/euclid/src/frontend/dir/enums.rs
@@ -154,6 +154,7 @@ pub enum BankRedirectType {
     OpenBankingUk,
     Przelewy24,
     Trustly,
+    OpenBanking,
 }
 #[derive(
     Clone,
diff --git a/crates/euclid/src/frontend/dir/lowering.rs b/crates/euclid/src/frontend/dir/lowering.rs
index b1f03e8dd55..d09e0cf7f7c 100644
--- a/crates/euclid/src/frontend/dir/lowering.rs
+++ b/crates/euclid/src/frontend/dir/lowering.rs
@@ -159,6 +159,7 @@ impl From<enums::BankRedirectType> for global_enums::PaymentMethodType {
             enums::BankRedirectType::OpenBankingUk => Self::OpenBankingUk,
             enums::BankRedirectType::Przelewy24 => Self::Przelewy24,
             enums::BankRedirectType::Trustly => Self::Trustly,
+            enums::BankRedirectType::OpenBanking => Self::OpenBanking,
         }
     }
 }
diff --git a/crates/euclid/src/frontend/dir/transformers.rs b/crates/euclid/src/frontend/dir/transformers.rs
index c99b39e36f4..d2f1a752734 100644
--- a/crates/euclid/src/frontend/dir/transformers.rs
+++ b/crates/euclid/src/frontend/dir/transformers.rs
@@ -164,6 +164,9 @@ impl IntoDirValue for (global_enums::PaymentMethodType, global_enums::PaymentMet
             global_enums::PaymentMethodType::CardRedirect => {
                 Ok(dirval!(CardRedirectType = CardRedirect))
             }
+            global_enums::PaymentMethodType::OpenBanking => {
+                Ok(dirval!(BankRedirectType = OpenBanking))
+            }
         }
     }
 }
diff --git a/crates/kgraph_utils/src/transformers.rs b/crates/kgraph_utils/src/transformers.rs
index 5bcb64fd875..00834f8b840 100644
--- a/crates/kgraph_utils/src/transformers.rs
+++ b/crates/kgraph_utils/src/transformers.rs
@@ -283,6 +283,9 @@ impl IntoDirValue for (api_enums::PaymentMethodType, api_enums::PaymentMethod) {
             api_enums::PaymentMethodType::CardRedirect => {
                 Ok(dirval!(CardRedirectType = CardRedirect))
             }
+            api_enums::PaymentMethodType::OpenBanking => {
+                Ok(dirval!(BankRedirectType = OpenBanking))
+            }
         }
     }
 }
diff --git a/crates/pm_auth/src/connector/plaid.rs b/crates/pm_auth/src/connector/plaid.rs
index dfcfbb7eddc..1b8568a1e7e 100644
--- a/crates/pm_auth/src/connector/plaid.rs
+++ b/crates/pm_auth/src/connector/plaid.rs
@@ -15,7 +15,9 @@ use crate::{
     types::{
         self as auth_types,
         api::{
-            auth_service::{self, BankAccountCredentials, ExchangeToken, LinkToken},
+            auth_service::{
+                self, BankAccountCredentials, ExchangeToken, LinkToken, RecipientCreate,
+            },
             ConnectorCommon, ConnectorCommonExt, ConnectorIntegration,
         },
     },
@@ -89,6 +91,8 @@ impl ConnectorCommon for Plaid {
 }
 
 impl auth_service::AuthService for Plaid {}
+impl auth_service::PaymentInitiationRecipientCreate for Plaid {}
+impl auth_service::PaymentInitiation for Plaid {}
 impl auth_service::AuthServiceLinkToken for Plaid {}
 
 impl ConnectorIntegration<LinkToken, auth_types::LinkTokenRequest, auth_types::LinkTokenResponse>
@@ -338,3 +342,89 @@ impl
         self.build_error_response(res)
     }
 }
+
+impl
+    ConnectorIntegration<
+        RecipientCreate,
+        auth_types::RecipientCreateRequest,
+        auth_types::RecipientCreateResponse,
+    > for Plaid
+{
+    fn get_headers(
+        &self,
+        req: &auth_types::RecipientCreateRouterData,
+        connectors: &auth_types::PaymentMethodAuthConnectors,
+    ) -> errors::CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
+        self.build_headers(req, connectors)
+    }
+
+    fn get_content_type(&self) -> &'static str {
+        self.common_get_content_type()
+    }
+
+    fn get_url(
+        &self,
+        _req: &auth_types::RecipientCreateRouterData,
+        connectors: &auth_types::PaymentMethodAuthConnectors,
+    ) -> errors::CustomResult<String, errors::ConnectorError> {
+        Ok(format!(
+            "{}{}",
+            self.base_url(connectors),
+            "/payment_initiation/recipient/create"
+        ))
+    }
+
+    fn get_request_body(
+        &self,
+        req: &auth_types::RecipientCreateRouterData,
+    ) -> errors::CustomResult<RequestContent, errors::ConnectorError> {
+        let req_obj = plaid::PlaidRecipientCreateRequest::try_from(req)?;
+        Ok(RequestContent::Json(Box::new(req_obj)))
+    }
+
+    fn build_request(
+        &self,
+        req: &auth_types::RecipientCreateRouterData,
+        connectors: &auth_types::PaymentMethodAuthConnectors,
+    ) -> errors::CustomResult<Option<Request>, errors::ConnectorError> {
+        Ok(Some(
+            RequestBuilder::new()
+                .method(Method::Post)
+                .url(&auth_types::PaymentInitiationRecipientCreateType::get_url(
+                    self, req, connectors,
+                )?)
+                .attach_default_headers()
+                .headers(
+                    auth_types::PaymentInitiationRecipientCreateType::get_headers(
+                        self, req, connectors,
+                    )?,
+                )
+                .set_body(
+                    auth_types::PaymentInitiationRecipientCreateType::get_request_body(self, req)?,
+                )
+                .build(),
+        ))
+    }
+
+    fn handle_response(
+        &self,
+        data: &auth_types::RecipientCreateRouterData,
+        res: auth_types::Response,
+    ) -> errors::CustomResult<auth_types::RecipientCreateRouterData, errors::ConnectorError> {
+        let response: plaid::PlaidRecipientCreateResponse = res
+            .response
+            .parse_struct("PlaidRecipientCreateResponse")
+            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
+        <auth_types::RecipientCreateRouterData>::try_from(auth_types::ResponseRouterData {
+            response,
+            data: data.clone(),
+            http_code: res.status_code,
+        })
+    }
+    fn get_error_response(
+        &self,
+        res: auth_types::Response,
+    ) -> errors::CustomResult<auth_types::ErrorResponse, errors::ConnectorError> {
+        self.build_error_response(res)
+    }
+}
diff --git a/crates/pm_auth/src/connector/plaid/transformers.rs b/crates/pm_auth/src/connector/plaid/transformers.rs
index 5e1ad67aead..c4e018663f4 100644
--- a/crates/pm_auth/src/connector/plaid/transformers.rs
+++ b/crates/pm_auth/src/connector/plaid/transformers.rs
@@ -112,6 +112,105 @@ impl TryFrom<&types::ExchangeTokenRouterData> for PlaidExchangeTokenRequest {
     }
 }
 
+#[derive(Debug, Serialize, Eq, PartialEq)]
+pub struct PlaidRecipientCreateRequest {
+    pub name: String,
+    #[serde(flatten)]
+    pub account_data: PlaidRecipientAccountData,
+    pub address: Option<PlaidRecipientCreateAddress>,
+}
+
+#[derive(Debug, Deserialize, Eq, PartialEq)]
+pub struct PlaidRecipientCreateResponse {
+    pub recipient_id: String,
+}
+
+#[derive(Debug, Serialize, Eq, PartialEq)]
+#[serde(rename_all = "lowercase")]
+pub enum PlaidRecipientAccountData {
+    Iban(Secret<String>),
+    Bacs {
+        sort_code: Secret<String>,
+        account: Secret<String>,
+    },
+}
+
+impl From<&types::RecipientAccountData> for PlaidRecipientAccountData {
+    fn from(item: &types::RecipientAccountData) -> Self {
+        match item {
+            types::RecipientAccountData::Iban(iban) => Self::Iban(iban.clone()),
+            types::RecipientAccountData::Bacs {
+                sort_code,
+                account_number,
+            } => Self::Bacs {
+                sort_code: sort_code.clone(),
+                account: account_number.clone(),
+            },
+        }
+    }
+}
+
+#[derive(Debug, Serialize, Eq, PartialEq)]
+pub struct PlaidRecipientCreateAddress {
+    pub street: String,
+    pub city: String,
+    pub postal_code: String,
+    pub country: String,
+}
+
+impl From<&types::RecipientCreateAddress> for PlaidRecipientCreateAddress {
+    fn from(item: &types::RecipientCreateAddress) -> Self {
+        Self {
+            street: item.street.clone(),
+            city: item.city.clone(),
+            postal_code: item.postal_code.clone(),
+            country: common_enums::CountryAlpha2::to_string(&item.country),
+        }
+    }
+}
+
+impl TryFrom<&types::RecipientCreateRouterData> for PlaidRecipientCreateRequest {
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(item: &types::RecipientCreateRouterData) -> Result<Self, Self::Error> {
+        Ok(Self {
+            name: item.request.name.clone(),
+            account_data: PlaidRecipientAccountData::from(&item.request.account_data),
+            address: item
+                .request
+                .address
+                .as_ref()
+                .map(PlaidRecipientCreateAddress::from),
+        })
+    }
+}
+
+impl<F, T>
+    TryFrom<
+        types::ResponseRouterData<
+            F,
+            PlaidRecipientCreateResponse,
+            T,
+            types::RecipientCreateResponse,
+        >,
+    > for types::PaymentAuthRouterData<F, T, types::RecipientCreateResponse>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        item: types::ResponseRouterData<
+            F,
+            PlaidRecipientCreateResponse,
+            T,
+            types::RecipientCreateResponse,
+        >,
+    ) -> Result<Self, Self::Error> {
+        Ok(Self {
+            response: Ok(types::RecipientCreateResponse {
+                recipient_id: item.response.recipient_id,
+            }),
+            ..item.data
+        })
+    }
+}
 #[derive(Debug, Serialize, Eq, PartialEq)]
 #[serde(rename_all = "snake_case")]
 pub struct PlaidBankAccountCredentialsRequest {
@@ -269,6 +368,7 @@ impl<F, T>
 pub struct PlaidAuthType {
     pub client_id: Secret<String>,
     pub secret: Secret<String>,
+    pub merchant_data: Option<types::MerchantRecipientData>,
 }
 
 impl TryFrom<&types::ConnectorAuthType> for PlaidAuthType {
@@ -278,6 +378,16 @@ impl TryFrom<&types::ConnectorAuthType> for PlaidAuthType {
             types::ConnectorAuthType::BodyKey { client_id, secret } => Ok(Self {
                 client_id: client_id.to_owned(),
                 secret: secret.to_owned(),
+                merchant_data: None,
+            }),
+            types::ConnectorAuthType::OpenBankingAuth {
+                api_key,
+                key1,
+                merchant_data,
+            } => Ok(Self {
+                client_id: api_key.to_owned(),
+                secret: key1.to_owned(),
+                merchant_data: Some(merchant_data.clone()),
             }),
             _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()),
         }
diff --git a/crates/pm_auth/src/types.rs b/crates/pm_auth/src/types.rs
index 6f5875247f1..71e2f543c17 100644
--- a/crates/pm_auth/src/types.rs
+++ b/crates/pm_auth/src/types.rs
@@ -2,9 +2,10 @@ pub mod api;
 
 use std::marker::PhantomData;
 
-use api::auth_service::{BankAccountCredentials, ExchangeToken, LinkToken};
-use common_enums::PaymentMethodType;
+use api::auth_service::{BankAccountCredentials, ExchangeToken, LinkToken, RecipientCreate};
+use common_enums::{CountryAlpha2, PaymentMethodType};
 use masking::Secret;
+
 #[derive(Debug, Clone)]
 pub struct PaymentAuthRouterData<F, Request, Response> {
     pub flow: PhantomData<F>,
@@ -85,6 +86,38 @@ pub type BankDetailsRouterData = PaymentAuthRouterData<
     BankAccountCredentialsResponse,
 >;
 
+#[derive(Debug, Clone)]
+pub struct RecipientCreateRequest {
+    pub name: String,
+    pub account_data: RecipientAccountData,
+    pub address: Option<RecipientCreateAddress>,
+}
+
+#[derive(Debug, Clone)]
+pub struct RecipientCreateResponse {
+    pub recipient_id: String,
+}
+
+#[derive(Debug, Clone)]
+pub enum RecipientAccountData {
+    Iban(Secret<String>),
+    Bacs {
+        sort_code: Secret<String>,
+        account_number: Secret<String>,
+    },
+}
+
+#[derive(Debug, Clone)]
+pub struct RecipientCreateAddress {
+    pub street: String,
+    pub city: String,
+    pub postal_code: String,
+    pub country: CountryAlpha2,
+}
+
+pub type RecipientCreateRouterData =
+    PaymentAuthRouterData<RecipientCreate, RecipientCreateRequest, RecipientCreateResponse>;
+
 pub type PaymentAuthLinkTokenType =
     dyn self::api::ConnectorIntegration<LinkToken, LinkTokenRequest, LinkTokenResponse>;
 
@@ -97,6 +130,12 @@ pub type PaymentAuthBankAccountDetailsType = dyn self::api::ConnectorIntegration
     BankAccountCredentialsResponse,
 >;
 
+pub type PaymentInitiationRecipientCreateType = dyn self::api::ConnectorIntegration<
+    RecipientCreate,
+    RecipientCreateRequest,
+    RecipientCreateResponse,
+>;
+
 #[derive(Clone, Debug, strum::EnumString, strum::Display)]
 #[strum(serialize_all = "snake_case")]
 pub enum PaymentMethodAuthConnectors {
@@ -129,12 +168,38 @@ impl ErrorResponse {
     }
 }
 
+#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
+pub enum MerchantAccountData {
+    Iban {
+        iban: Secret<String>,
+        name: String,
+    },
+    Bacs {
+        account_number: Secret<String>,
+        sort_code: Secret<String>,
+        name: String,
+    },
+}
+
+#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
+#[serde(rename_all = "snake_case")]
+pub enum MerchantRecipientData {
+    RecipientId(Secret<String>),
+    WalletId(Secret<String>),
+    AccountData(MerchantAccountData),
+}
+
 #[derive(Default, Debug, Clone, serde::Deserialize)]
 pub enum ConnectorAuthType {
     BodyKey {
         client_id: Secret<String>,
         secret: Secret<String>,
     },
+    OpenBankingAuth {
+        api_key: Secret<String>,
+        key1: Secret<String>,
+        merchant_data: MerchantRecipientData,
+    },
     #[default]
     NoKey,
 }
diff --git a/crates/pm_auth/src/types/api.rs b/crates/pm_auth/src/types/api.rs
index 3684e34ec05..d4edf160985 100644
--- a/crates/pm_auth/src/types/api.rs
+++ b/crates/pm_auth/src/types/api.rs
@@ -10,7 +10,10 @@ use masking::Maskable;
 
 use crate::{
     core::errors::ConnectorError,
-    types::{self as auth_types, api::auth_service::AuthService},
+    types::{
+        self as auth_types,
+        api::auth_service::{AuthService, PaymentInitiation},
+    },
 };
 
 #[async_trait::async_trait]
@@ -125,9 +128,9 @@ where
     }
 }
 
-pub trait AuthServiceConnector: AuthService + Send + Debug {}
+pub trait AuthServiceConnector: AuthService + Send + Debug + PaymentInitiation {}
 
-impl<T: Send + Debug + AuthService> AuthServiceConnector for T {}
+impl<T: Send + Debug + AuthService + PaymentInitiation> AuthServiceConnector for T {}
 
 pub type BoxedPaymentAuthConnector = Box<&'static (dyn AuthServiceConnector + Sync)>;
 
diff --git a/crates/pm_auth/src/types/api/auth_service.rs b/crates/pm_auth/src/types/api/auth_service.rs
index 35d44970d51..498b6bec40e 100644
--- a/crates/pm_auth/src/types/api/auth_service.rs
+++ b/crates/pm_auth/src/types/api/auth_service.rs
@@ -1,6 +1,7 @@
 use crate::types::{
     BankAccountCredentialsRequest, BankAccountCredentialsResponse, ExchangeTokenRequest,
-    ExchangeTokenResponse, LinkTokenRequest, LinkTokenResponse,
+    ExchangeTokenResponse, LinkTokenRequest, LinkTokenResponse, RecipientCreateRequest,
+    RecipientCreateResponse,
 };
 
 pub trait AuthService:
@@ -11,6 +12,8 @@ pub trait AuthService:
 {
 }
 
+pub trait PaymentInitiation: super::ConnectorCommon + PaymentInitiationRecipientCreate {}
+
 #[derive(Debug, Clone)]
 pub struct LinkToken;
 
@@ -38,3 +41,11 @@ pub trait AuthServiceBankAccountCredentials:
 >
 {
 }
+
+#[derive(Debug, Clone)]
+pub struct RecipientCreate;
+
+pub trait PaymentInitiationRecipientCreate:
+    super::ConnectorIntegration<RecipientCreate, RecipientCreateRequest, RecipientCreateResponse>
+{
+}
diff --git a/crates/router/src/compatibility/stripe/payment_intents/types.rs b/crates/router/src/compatibility/stripe/payment_intents/types.rs
index a74f16cee79..f76437ff97f 100644
--- a/crates/router/src/compatibility/stripe/payment_intents/types.rs
+++ b/crates/router/src/compatibility/stripe/payment_intents/types.rs
@@ -848,8 +848,18 @@ pub(crate) fn into_stripe_next_action(
             bank_transfer_steps_and_charges_details,
         },
         payments::NextActionData::ThirdPartySdkSessionToken { session_token } => {
-            StripeNextAction::ThirdPartySdkSessionToken { session_token }
+            match session_token {
+                Some(payments::SessionTokenType::Wallet(token)) => {
+                    StripeNextAction::ThirdPartySdkSessionToken {
+                        session_token: Some(token),
+                    }
+                }
+                _ => StripeNextAction::ThirdPartySdkSessionToken {
+                    session_token: None,
+                },
+            }
         }
+
         payments::NextActionData::QrCodeInformation {
             image_data_url,
             display_to_timestamp,
diff --git a/crates/router/src/compatibility/stripe/setup_intents/types.rs b/crates/router/src/compatibility/stripe/setup_intents/types.rs
index a05a8c241d0..51c83624763 100644
--- a/crates/router/src/compatibility/stripe/setup_intents/types.rs
+++ b/crates/router/src/compatibility/stripe/setup_intents/types.rs
@@ -421,7 +421,16 @@ pub(crate) fn into_stripe_next_action(
             bank_transfer_steps_and_charges_details,
         },
         payments::NextActionData::ThirdPartySdkSessionToken { session_token } => {
-            StripeNextAction::ThirdPartySdkSessionToken { session_token }
+            match session_token {
+                Some(payments::SessionTokenType::Wallet(token)) => {
+                    StripeNextAction::ThirdPartySdkSessionToken {
+                        session_token: Some(token),
+                    }
+                }
+                _ => StripeNextAction::ThirdPartySdkSessionToken {
+                    session_token: None,
+                },
+            }
         }
         payments::NextActionData::QrCodeInformation {
             image_data_url,
diff --git a/crates/router/src/configs/secrets_transformers.rs b/crates/router/src/configs/secrets_transformers.rs
index f89d1811988..b2a67712ce9 100644
--- a/crates/router/src/configs/secrets_transformers.rs
+++ b/crates/router/src/configs/secrets_transformers.rs
@@ -361,5 +361,6 @@ pub(crate) async fn fetch_raw_secrets(
         connector_onboarding,
         cors: conf.cors,
         unmasked_headers: conf.unmasked_headers,
+        locker_open_banking_connectors: conf.locker_open_banking_connectors,
     }
 }
diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs
index dc4826dfed6..89b5b81b1a4 100644
--- a/crates/router/src/configs/settings.rs
+++ b/crates/router/src/configs/settings.rs
@@ -116,6 +116,7 @@ pub struct Settings<S: SecretState> {
     #[cfg(feature = "olap")]
     pub connector_onboarding: SecretStateContainer<ConnectorOnboarding, S>,
     pub unmasked_headers: UnmaskedHeaders,
+    pub locker_open_banking_connectors: LockerBasedRecipientConnectorList,
 }
 
 #[derive(Debug, Deserialize, Clone, Default)]
@@ -511,6 +512,7 @@ pub struct Connectors {
     pub paypal: ConnectorParams,
     pub payu: ConnectorParams,
     pub placetopay: ConnectorParams,
+    pub plaid: ConnectorParams,
     pub powertranz: ConnectorParams,
     pub prophetpay: ConnectorParams,
     pub rapyd: ConnectorParams,
@@ -624,6 +626,11 @@ pub struct ApplePayDecryptConifg {
     pub apple_pay_merchant_cert_key: Secret<String>,
 }
 
+#[derive(Debug, Deserialize, Clone, Default)]
+pub struct LockerBasedRecipientConnectorList {
+    pub connector_list: HashSet<String>,
+}
+
 #[derive(Debug, Deserialize, Clone, Default)]
 pub struct ConnectorRequestReferenceIdConfig {
     pub merchant_ids_send_payment_id_as_connector_request_id: HashSet<String>,
diff --git a/crates/router/src/connector.rs b/crates/router/src/connector.rs
index eccdf3f9ddf..cd829718652 100644
--- a/crates/router/src/connector.rs
+++ b/crates/router/src/connector.rs
@@ -37,6 +37,7 @@ pub mod payme;
 pub mod paypal;
 pub mod payu;
 pub mod placetopay;
+pub mod plaid;
 pub mod powertranz;
 pub mod prophetpay;
 pub mod rapyd;
@@ -67,8 +68,8 @@ pub use self::{
     iatapay::Iatapay, klarna::Klarna, mollie::Mollie, multisafepay::Multisafepay,
     nexinets::Nexinets, nmi::Nmi, noon::Noon, nuvei::Nuvei, opayo::Opayo, opennode::Opennode,
     payeezy::Payeezy, payme::Payme, paypal::Paypal, payu::Payu, placetopay::Placetopay,
-    powertranz::Powertranz, prophetpay::Prophetpay, rapyd::Rapyd, riskified::Riskified,
-    shift4::Shift4, signifyd::Signifyd, square::Square, stax::Stax, stripe::Stripe,
-    threedsecureio::Threedsecureio, trustpay::Trustpay, tsys::Tsys, volt::Volt, wise::Wise,
-    worldline::Worldline, worldpay::Worldpay, zen::Zen,
+    plaid::Plaid, powertranz::Powertranz, prophetpay::Prophetpay, rapyd::Rapyd,
+    riskified::Riskified, shift4::Shift4, signifyd::Signifyd, square::Square, stax::Stax,
+    stripe::Stripe, threedsecureio::Threedsecureio, trustpay::Trustpay, tsys::Tsys, volt::Volt,
+    wise::Wise, worldline::Worldline, worldpay::Worldpay, zen::Zen,
 };
diff --git a/crates/router/src/connector/adyen.rs b/crates/router/src/connector/adyen.rs
index 67e319ddc22..ed1ea772898 100644
--- a/crates/router/src/connector/adyen.rs
+++ b/crates/router/src/connector/adyen.rs
@@ -210,6 +210,7 @@ impl ConnectorValidation for Adyen {
                 | PaymentMethodType::SamsungPay
                 | PaymentMethodType::Evoucher
                 | PaymentMethodType::Cashapp
+                | PaymentMethodType::OpenBanking
                 | PaymentMethodType::UpiCollect => {
                     capture_method_not_supported!(connector, capture_method, payment_method_type)
                 }
diff --git a/crates/router/src/connector/adyen/transformers.rs b/crates/router/src/connector/adyen/transformers.rs
index c44d590e2f1..1bbb336441d 100644
--- a/crates/router/src/connector/adyen/transformers.rs
+++ b/crates/router/src/connector/adyen/transformers.rs
@@ -2339,7 +2339,8 @@ impl<'a> TryFrom<(&api_models::payments::BankRedirectData, Option<bool>)>
                 Ok(AdyenPaymentMethod::Trustly)
             }
             payments::BankRedirectData::Interac { .. }
-            | payments::BankRedirectData::Przelewy24 { .. } => {
+            | payments::BankRedirectData::Przelewy24 { .. }
+            | payments::BankRedirectData::OpenBanking { .. } => {
                 Err(errors::ConnectorError::NotSupported {
                     message: utils::SELECTED_PAYMENT_METHOD.to_string(),
                     connector: "Adyen",
diff --git a/crates/router/src/connector/klarna.rs b/crates/router/src/connector/klarna.rs
index 8b7ab0da7f2..4f3aa9be9ca 100644
--- a/crates/router/src/connector/klarna.rs
+++ b/crates/router/src/connector/klarna.rs
@@ -385,6 +385,7 @@ impl
                     | api_models::enums::PaymentMethodType::PagoEfectivo
                     | api_models::enums::PaymentMethodType::PermataBankTransfer
                     | api_models::enums::PaymentMethodType::OpenBankingUk
+                    | api_models::enums::PaymentMethodType::OpenBanking
                     | api_models::enums::PaymentMethodType::PayBright
                     | api_models::enums::PaymentMethodType::Paypal
                     | api_models::enums::PaymentMethodType::Pix
diff --git a/crates/router/src/connector/nexinets/transformers.rs b/crates/router/src/connector/nexinets/transformers.rs
index 07488271aea..8ff490d265c 100644
--- a/crates/router/src/connector/nexinets/transformers.rs
+++ b/crates/router/src/connector/nexinets/transformers.rs
@@ -608,6 +608,7 @@ fn get_payment_details_and_product(
             | api_models::payments::BankRedirectData::OnlineBankingPoland { .. }
             | api_models::payments::BankRedirectData::OnlineBankingSlovakia { .. }
             | api_models::payments::BankRedirectData::OpenBankingUk { .. }
+            | api_models::payments::BankRedirectData::OpenBanking { .. }
             | api_models::payments::BankRedirectData::Przelewy24 { .. }
             | api_models::payments::BankRedirectData::Trustly { .. }
             | api_models::payments::BankRedirectData::OnlineBankingFpx { .. }
diff --git a/crates/router/src/connector/nuvei/transformers.rs b/crates/router/src/connector/nuvei/transformers.rs
index 1312eadadf7..baf511cae0b 100644
--- a/crates/router/src/connector/nuvei/transformers.rs
+++ b/crates/router/src/connector/nuvei/transformers.rs
@@ -820,6 +820,7 @@ impl<F>
                 | payments::BankRedirectData::Trustly { .. }
                 | payments::BankRedirectData::OnlineBankingFpx { .. }
                 | payments::BankRedirectData::OnlineBankingThailand { .. }
+                | payments::BankRedirectData::OpenBanking { .. }
                 | payments::BankRedirectData::OpenBankingUk { .. } => {
                     Err(errors::ConnectorError::NotImplemented(
                         utils::get_unimplemented_payment_method_error_message("nuvei"),
diff --git a/crates/router/src/connector/paypal/transformers.rs b/crates/router/src/connector/paypal/transformers.rs
index a584fe98165..46df4a0b21d 100644
--- a/crates/router/src/connector/paypal/transformers.rs
+++ b/crates/router/src/connector/paypal/transformers.rs
@@ -398,6 +398,7 @@ fn get_payment_source(
         | BankRedirectData::OnlineBankingPoland { .. }
         | BankRedirectData::OnlineBankingSlovakia { .. }
         | BankRedirectData::OpenBankingUk { .. }
+        | BankRedirectData::OpenBanking { .. }
         | BankRedirectData::Trustly { .. }
         | BankRedirectData::OnlineBankingFpx { .. }
         | BankRedirectData::OnlineBankingThailand { .. } => {
diff --git a/crates/router/src/connector/plaid.rs b/crates/router/src/connector/plaid.rs
new file mode 100644
index 00000000000..1d884a22979
--- /dev/null
+++ b/crates/router/src/connector/plaid.rs
@@ -0,0 +1,789 @@
+pub mod transformers;
+
+use std::fmt::Debug;
+
+use common_utils::ext_traits::ByteSliceExt;
+use error_stack::ResultExt;
+use transformers as plaid;
+
+use crate::{
+    configs::settings,
+    core::errors::{self, CustomResult},
+    events::connector_api_logs::ConnectorEvent,
+    headers,
+    services::{
+        self,
+        request::{self, Mask},
+        ConnectorIntegration, ConnectorValidation,
+    },
+    types::{
+        self,
+        api::{self, ConnectorCommon, ConnectorCommonExt},
+        transformers::ForeignFrom,
+        ErrorResponse, RequestContent, Response,
+    },
+    utils::BytesExt,
+};
+
+#[derive(Debug, Clone)]
+pub struct Plaid;
+
+impl api::Payment for Plaid {}
+impl api::PaymentSession for Plaid {}
+impl api::ConnectorAccessToken for Plaid {}
+impl api::MandateSetup for Plaid {}
+impl api::PaymentAuthorize for Plaid {}
+impl api::PaymentSync for Plaid {}
+impl api::PaymentCapture for Plaid {}
+impl api::PaymentVoid for Plaid {}
+impl api::Refund for Plaid {}
+impl api::RefundExecute for Plaid {}
+impl api::RefundSync for Plaid {}
+impl api::PaymentToken for Plaid {}
+impl api::PaymentsPostProcessing for Plaid {}
+impl api::ConnectorVerifyWebhookSource for Plaid {}
+
+impl
+    ConnectorIntegration<
+        api::PaymentMethodToken,
+        types::PaymentMethodTokenizationData,
+        types::PaymentsResponseData,
+    > for Plaid
+{
+    // Not Implemented (R)
+}
+
+impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Plaid
+where
+    Self: ConnectorIntegration<Flow, Request, Response>,
+{
+    fn build_headers(
+        &self,
+        req: &types::RouterData<Flow, Request, Response>,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
+        let mut header = vec![(
+            headers::CONTENT_TYPE.to_string(),
+            self.get_content_type().to_string().into(),
+        )];
+        let mut auth = self.get_auth_header(&req.connector_auth_type)?;
+        header.append(&mut auth);
+        Ok(header)
+    }
+}
+
+impl ConnectorCommon for Plaid {
+    fn id(&self) -> &'static str {
+        "plaid"
+    }
+
+    fn get_currency_unit(&self) -> api::CurrencyUnit {
+        api::CurrencyUnit::Base
+    }
+
+    fn common_get_content_type(&self) -> &'static str {
+        "application/json"
+    }
+
+    fn base_url<'a>(&self, connectors: &'a settings::Connectors) -> &'a str {
+        connectors.plaid.base_url.as_ref()
+    }
+
+    fn get_auth_header(
+        &self,
+        auth_type: &types::ConnectorAuthType,
+    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
+        let auth = plaid::PlaidAuthType::try_from(auth_type)
+            .change_context(errors::ConnectorError::FailedToObtainAuthType)?;
+        let client_id = auth.client_id.into_masked();
+        let secret = auth.secret.into_masked();
+
+        Ok(vec![
+            ("PLAID-CLIENT-ID".to_string(), client_id),
+            ("PLAID-SECRET".to_string(), secret),
+        ])
+    }
+
+    fn build_error_response(
+        &self,
+        res: Response,
+        event_builder: Option<&mut ConnectorEvent>,
+    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
+        let response: plaid::PlaidErrorResponse =
+            res.response
+                .parse_struct("PlaidErrorResponse")
+                .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
+
+        event_builder.map(|i| i.set_response_body(&response));
+        router_env::logger::info!(connector_response=?response);
+
+        Ok(ErrorResponse {
+            status_code: res.status_code,
+            code: crate::consts::NO_ERROR_CODE.to_string(),
+            message: response.error_message,
+            reason: response.display_message,
+            attempt_status: None,
+            connector_transaction_id: None,
+        })
+    }
+}
+
+impl ConnectorValidation for Plaid {
+    //TODO: implement functions when support enabled
+}
+
+impl ConnectorIntegration<api::Session, types::PaymentsSessionData, types::PaymentsResponseData>
+    for Plaid
+{
+    //TODO: implement sessions flow
+}
+
+impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, types::AccessToken>
+    for Plaid
+{
+}
+
+impl
+    ConnectorIntegration<
+        api::SetupMandate,
+        types::SetupMandateRequestData,
+        types::PaymentsResponseData,
+    > for Plaid
+{
+}
+
+impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::PaymentsResponseData>
+    for Plaid
+{
+    fn get_headers(
+        &self,
+        req: &types::PaymentsAuthorizeRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
+        self.build_headers(req, connectors)
+    }
+
+    fn get_content_type(&self) -> &'static str {
+        self.common_get_content_type()
+    }
+
+    fn get_url(
+        &self,
+        _req: &types::PaymentsAuthorizeRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<String, errors::ConnectorError> {
+        Ok(format!(
+            "{}/payment_initiation/payment/create",
+            self.base_url(connectors)
+        ))
+    }
+
+    fn get_request_body(
+        &self,
+        req: &types::PaymentsAuthorizeRouterData,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<RequestContent, errors::ConnectorError> {
+        let connector_router_data =
+            plaid::PlaidRouterData::try_from((Some(req.request.amount as f64), req))?;
+        let connector_req = plaid::PlaidPaymentsRequest::try_from(&connector_router_data)?;
+        Ok(RequestContent::Json(Box::new(connector_req)))
+    }
+
+    fn build_request(
+        &self,
+        req: &types::PaymentsAuthorizeRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
+        Ok(Some(
+            services::RequestBuilder::new()
+                .method(services::Method::Post)
+                .url(&types::PaymentsAuthorizeType::get_url(
+                    self, req, connectors,
+                )?)
+                .attach_default_headers()
+                .headers(types::PaymentsAuthorizeType::get_headers(
+                    self, req, connectors,
+                )?)
+                .set_body(types::PaymentsAuthorizeType::get_request_body(
+                    self, req, connectors,
+                )?)
+                .build(),
+        ))
+    }
+
+    fn handle_response(
+        &self,
+        data: &types::PaymentsAuthorizeRouterData,
+        event_builder: Option<&mut ConnectorEvent>,
+        res: Response,
+    ) -> CustomResult<types::PaymentsAuthorizeRouterData, errors::ConnectorError> {
+        let response: plaid::PlaidPaymentsResponse = res
+            .response
+            .parse_struct("PlaidPaymentsResponse")
+            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
+        event_builder.map(|i| i.set_response_body(&response));
+        router_env::logger::info!(connector_response=?response);
+        types::RouterData::try_from(types::ResponseRouterData {
+            response,
+            data: data.clone(),
+            http_code: res.status_code,
+        })
+    }
+
+    fn get_error_response(
+        &self,
+        res: Response,
+        event_builder: Option<&mut ConnectorEvent>,
+    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
+        self.build_error_response(res, event_builder)
+    }
+}
+
+impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>
+    for Plaid
+{
+    fn get_headers(
+        &self,
+        req: &types::PaymentsSyncRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
+        self.build_headers(req, connectors)
+    }
+
+    fn get_content_type(&self) -> &'static str {
+        self.common_get_content_type()
+    }
+
+    fn get_request_body(
+        &self,
+        req: &types::PaymentsSyncRouterData,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<RequestContent, errors::ConnectorError> {
+        let connector_router_data = plaid::PlaidRouterData::try_from((None, req))?;
+        let connector_req = plaid::PlaidSyncRequest::try_from(&connector_router_data)?;
+        Ok(RequestContent::Json(Box::new(connector_req)))
+    }
+
+    fn get_url(
+        &self,
+        req: &types::PaymentsSyncRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<String, errors::ConnectorError> {
+        let _connector_payment_id = req
+            .request
+            .connector_transaction_id
+            .get_connector_transaction_id()
+            .change_context(errors::ConnectorError::MissingConnectorTransactionID)?;
+        Ok(format!(
+            "{}/payment_initiation/payment/get",
+            self.base_url(connectors)
+        ))
+    }
+
+    fn build_request(
+        &self,
+        req: &types::PaymentsSyncRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
+        Ok(Some(
+            services::RequestBuilder::new()
+                .method(services::Method::Post)
+                .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
+                .attach_default_headers()
+                .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
+                .set_body(types::PaymentsSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
+                .build(),
+        ))
+    }
+
+    fn handle_response(
+        &self,
+        data: &types::PaymentsSyncRouterData,
+        event_builder: Option<&mut ConnectorEvent>,
+        res: Response,
+    ) -> CustomResult<types::PaymentsSyncRouterData, errors::ConnectorError> {
+        let response: plaid::PlaidSyncResponse = res
+            .response
+            .parse_struct("PlaidSyncResponse")
+            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
+        event_builder.map(|i| i.set_response_body(&response));
+        router_env::logger::info!(connector_response=?response);
+        types::RouterData::try_from(types::ResponseRouterData {
+            response,
+            data: data.clone(),
+            http_code: res.status_code,
+        })
+    }
+
+    fn get_error_response(
+        &self,
+        res: Response,
+        event_builder: Option<&mut ConnectorEvent>,
+    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
+        self.build_error_response(res, event_builder)
+    }
+}
+
+impl
+    ConnectorIntegration<
+        api::PostProcessing,
+        types::PaymentsPostProcessingData,
+        types::PaymentsResponseData,
+    > for Plaid
+{
+    fn get_headers(
+        &self,
+        req: &types::PaymentsPostProcessingRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
+        self.build_headers(req, connectors)
+    }
+
+    fn get_content_type(&self) -> &'static str {
+        self.common_get_content_type()
+    }
+
+    fn get_url(
+        &self,
+        _req: &types::PaymentsPostProcessingRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<String, errors::ConnectorError> {
+        Ok(format!("{}/link/token/create", self.base_url(connectors)))
+    }
+
+    fn get_request_body(
+        &self,
+        req: &types::PaymentsPostProcessingRouterData,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<RequestContent, errors::ConnectorError> {
+        let connector_router_data = plaid::PlaidRouterData::try_from((None, req))?;
+        let connector_req = plaid::PlaidLinkTokenRequest::try_from(&connector_router_data)?;
+        Ok(RequestContent::Json(Box::new(connector_req)))
+    }
+
+    fn build_request(
+        &self,
+        req: &types::PaymentsPostProcessingRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
+        Ok(Some(
+            services::RequestBuilder::new()
+                .method(services::Method::Post)
+                .url(&types::PaymentsPostProcessingType::get_url(
+                    self, req, connectors,
+                )?)
+                .attach_default_headers()
+                .headers(types::PaymentsPostProcessingType::get_headers(
+                    self, req, connectors,
+                )?)
+                .set_body(types::PaymentsPostProcessingType::get_request_body(
+                    self, req, connectors,
+                )?)
+                .build(),
+        ))
+    }
+
+    fn handle_response(
+        &self,
+        data: &types::PaymentsPostProcessingRouterData,
+        event_builder: Option<&mut ConnectorEvent>,
+        res: Response,
+    ) -> CustomResult<types::PaymentsPostProcessingRouterData, errors::ConnectorError> {
+        let response: plaid::PlaidLinkTokenResponse = res
+            .response
+            .parse_struct("PlaidLinkTokenResponse")
+            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
+        event_builder.map(|i| i.set_response_body(&response));
+        router_env::logger::info!(connector_response=?response);
+        types::RouterData::try_from(types::ResponseRouterData {
+            response,
+            data: data.clone(),
+            http_code: res.status_code,
+        })
+    }
+
+    fn get_error_response(
+        &self,
+        res: Response,
+        event_builder: Option<&mut ConnectorEvent>,
+    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
+        self.build_error_response(res, event_builder)
+    }
+}
+
+impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::PaymentsResponseData>
+    for Plaid
+{
+    fn get_headers(
+        &self,
+        req: &types::PaymentsCaptureRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
+        self.build_headers(req, connectors)
+    }
+
+    fn get_content_type(&self) -> &'static str {
+        self.common_get_content_type()
+    }
+
+    fn get_url(
+        &self,
+        _req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<String, errors::ConnectorError> {
+        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
+    }
+
+    fn get_request_body(
+        &self,
+        _req: &types::PaymentsCaptureRouterData,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<RequestContent, errors::ConnectorError> {
+        Err(errors::ConnectorError::NotImplemented("get_request_body method".to_string()).into())
+    }
+
+    fn build_request(
+        &self,
+        req: &types::PaymentsCaptureRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
+        Ok(Some(
+            services::RequestBuilder::new()
+                .method(services::Method::Post)
+                .url(&types::PaymentsCaptureType::get_url(self, req, connectors)?)
+                .attach_default_headers()
+                .headers(types::PaymentsCaptureType::get_headers(
+                    self, req, connectors,
+                )?)
+                .set_body(types::PaymentsCaptureType::get_request_body(
+                    self, req, connectors,
+                )?)
+                .build(),
+        ))
+    }
+
+    fn handle_response(
+        &self,
+        data: &types::PaymentsCaptureRouterData,
+        event_builder: Option<&mut ConnectorEvent>,
+        res: Response,
+    ) -> CustomResult<types::PaymentsCaptureRouterData, errors::ConnectorError> {
+        let response: plaid::PlaidPaymentsResponse = res
+            .response
+            .parse_struct("Plaid PaymentsCaptureResponse")
+            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
+        event_builder.map(|i| i.set_response_body(&response));
+        router_env::logger::info!(connector_response=?response);
+        types::RouterData::try_from(types::ResponseRouterData {
+            response,
+            data: data.clone(),
+            http_code: res.status_code,
+        })
+    }
+
+    fn get_error_response(
+        &self,
+        res: Response,
+        event_builder: Option<&mut ConnectorEvent>,
+    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
+        self.build_error_response(res, event_builder)
+    }
+}
+
+impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsResponseData>
+    for Plaid
+{
+}
+
+impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsResponseData> for Plaid {
+    fn get_headers(
+        &self,
+        req: &types::RefundsRouterData<api::Execute>,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
+        self.build_headers(req, connectors)
+    }
+
+    fn get_content_type(&self) -> &'static str {
+        self.common_get_content_type()
+    }
+
+    fn get_url(
+        &self,
+        _req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<String, errors::ConnectorError> {
+        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
+    }
+
+    fn get_request_body(
+        &self,
+        req: &types::RefundsRouterData<api::Execute>,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<RequestContent, errors::ConnectorError> {
+        let connector_router_data =
+            plaid::PlaidRouterData::try_from((Some(req.request.refund_amount as f64), req))?;
+        let connector_req = plaid::PlaidRefundRequest::try_from(&connector_router_data)?;
+        Ok(RequestContent::Json(Box::new(connector_req)))
+    }
+
+    fn build_request(
+        &self,
+        req: &types::RefundsRouterData<api::Execute>,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
+        let request = services::RequestBuilder::new()
+            .method(services::Method::Post)
+            .url(&types::RefundExecuteType::get_url(self, req, connectors)?)
+            .attach_default_headers()
+            .headers(types::RefundExecuteType::get_headers(
+                self, req, connectors,
+            )?)
+            .set_body(types::RefundExecuteType::get_request_body(
+                self, req, connectors,
+            )?)
+            .build();
+        Ok(Some(request))
+    }
+
+    fn handle_response(
+        &self,
+        data: &types::RefundsRouterData<api::Execute>,
+        event_builder: Option<&mut ConnectorEvent>,
+        res: Response,
+    ) -> CustomResult<types::RefundsRouterData<api::Execute>, errors::ConnectorError> {
+        let response: plaid::RefundResponse = res
+            .response
+            .parse_struct("plaid RefundResponse")
+            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
+        event_builder.map(|i| i.set_response_body(&response));
+        router_env::logger::info!(connector_response=?response);
+        types::RouterData::try_from(types::ResponseRouterData {
+            response,
+            data: data.clone(),
+            http_code: res.status_code,
+        })
+    }
+
+    fn get_error_response(
+        &self,
+        res: Response,
+        event_builder: Option<&mut ConnectorEvent>,
+    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
+        self.build_error_response(res, event_builder)
+    }
+}
+
+impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponseData> for Plaid {
+    fn get_headers(
+        &self,
+        req: &types::RefundSyncRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
+        self.build_headers(req, connectors)
+    }
+
+    fn get_content_type(&self) -> &'static str {
+        self.common_get_content_type()
+    }
+
+    fn get_url(
+        &self,
+        _req: &types::RefundSyncRouterData,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<String, errors::ConnectorError> {
+        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
+    }
+
+    fn build_request(
+        &self,
+        req: &types::RefundSyncRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
+        Ok(Some(
+            services::RequestBuilder::new()
+                .method(services::Method::Get)
+                .url(&types::RefundSyncType::get_url(self, req, connectors)?)
+                .attach_default_headers()
+                .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
+                .set_body(types::RefundSyncType::get_request_body(
+                    self, req, connectors,
+                )?)
+                .build(),
+        ))
+    }
+
+    fn handle_response(
+        &self,
+        data: &types::RefundSyncRouterData,
+        event_builder: Option<&mut ConnectorEvent>,
+        res: Response,
+    ) -> CustomResult<types::RefundSyncRouterData, errors::ConnectorError> {
+        let response: plaid::RefundResponse = res
+            .response
+            .parse_struct("plaid RefundSyncResponse")
+            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
+        event_builder.map(|i| i.set_response_body(&response));
+        router_env::logger::info!(connector_response=?response);
+        types::RouterData::try_from(types::ResponseRouterData {
+            response,
+            data: data.clone(),
+            http_code: res.status_code,
+        })
+    }
+
+    fn get_error_response(
+        &self,
+        res: Response,
+        event_builder: Option<&mut ConnectorEvent>,
+    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
+        self.build_error_response(res, event_builder)
+    }
+}
+
+impl
+    ConnectorIntegration<
+        api::VerifyWebhookSource,
+        types::VerifyWebhookSourceRequestData,
+        types::VerifyWebhookSourceResponseData,
+    > for Plaid
+{
+    fn get_headers(
+        &self,
+        req: &types::RouterData<
+            api::VerifyWebhookSource,
+            types::VerifyWebhookSourceRequestData,
+            types::VerifyWebhookSourceResponseData,
+        >,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
+        self.build_headers(req, connectors)
+    }
+
+    fn get_content_type(&self) -> &'static str {
+        self.common_get_content_type()
+    }
+
+    fn get_url(
+        &self,
+        _req: &types::RouterData<
+            api::VerifyWebhookSource,
+            types::VerifyWebhookSourceRequestData,
+            types::VerifyWebhookSourceResponseData,
+        >,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<String, errors::ConnectorError> {
+        Ok(format!(
+            "{}/webhook_verification_key/get",
+            self.base_url(connectors)
+        ))
+    }
+
+    fn build_request(
+        &self,
+        req: &types::VerifyWebhookSourceRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
+        let request = services::RequestBuilder::new()
+            .method(services::Method::Post)
+            .url(&types::VerifyWebhookSourceType::get_url(
+                self, req, connectors,
+            )?)
+            .headers(types::VerifyWebhookSourceType::get_headers(
+                self, req, connectors,
+            )?)
+            .set_body(types::VerifyWebhookSourceType::get_request_body(
+                self, req, connectors,
+            )?)
+            .build();
+
+        Ok(Some(request))
+    }
+
+    fn get_request_body(
+        &self,
+        req: &types::RouterData<
+            api::VerifyWebhookSource,
+            types::VerifyWebhookSourceRequestData,
+            types::VerifyWebhookSourceResponseData,
+        >,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<RequestContent, errors::ConnectorError> {
+        let connector_req = plaid::PlaidWebhookVerificationRequest::try_from(&req.request)?;
+        Ok(RequestContent::Json(Box::new(connector_req)))
+    }
+
+    fn handle_response(
+        &self,
+        data: &types::VerifyWebhookSourceRouterData,
+        event_builder: Option<&mut ConnectorEvent>,
+        res: Response,
+    ) -> CustomResult<types::VerifyWebhookSourceRouterData, errors::ConnectorError> {
+        let response: plaid::PlaidWebhookVerificationResponse = res
+            .response
+            .parse_struct("PlaidWebhookVerificationResponse")
+            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
+
+        plaid::process_plaid_jwt_header(&data.request, &response)?;
+
+        event_builder.map(|i| i.set_response_body(&response));
+        router_env::logger::info!(connector_response=?response);
+        types::RouterData::try_from(types::ResponseRouterData {
+            response,
+            data: data.clone(),
+            http_code: res.status_code,
+        })
+    }
+    fn get_error_response(
+        &self,
+        res: Response,
+        event_builder: Option<&mut ConnectorEvent>,
+    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
+        self.build_error_response(res, event_builder)
+    }
+}
+
+#[async_trait::async_trait]
+impl api::IncomingWebhook for Plaid {
+    fn get_webhook_object_reference_id(
+        &self,
+        request: &api::IncomingWebhookRequestDetails<'_>,
+    ) -> CustomResult<api::webhooks::ObjectReferenceId, errors::ConnectorError> {
+        let payload: plaid::PlaidPaymentsWebhookBody = request
+            .body
+            .parse_struct("PlaidPaymentsWebhookBody")
+            .change_context(errors::ConnectorError::WebhookReferenceIdNotFound)?;
+
+        Ok(api::ObjectReferenceId::PaymentId(
+            api::PaymentIdType::ConnectorTransactionId(payload.payment_id),
+        ))
+    }
+
+    fn get_webhook_event_type(
+        &self,
+        request: &api::IncomingWebhookRequestDetails<'_>,
+    ) -> CustomResult<api::IncomingWebhookEvent, errors::ConnectorError> {
+        let payload: plaid::PlaidPaymentsWebhookBody = request
+            .body
+            .parse_struct("PlaidPaymentsWebhookBody")
+            .change_context(errors::ConnectorError::WebhookReferenceIdNotFound)?;
+
+        Ok(api::IncomingWebhookEvent::foreign_from(
+            payload.new_payment_status,
+        ))
+    }
+
+    fn get_webhook_resource_object(
+        &self,
+        request: &api::IncomingWebhookRequestDetails<'_>,
+    ) -> CustomResult<Box<dyn masking::ErasedMaskSerialize>, errors::ConnectorError> {
+        let payload: plaid::PlaidPaymentsWebhookBody = request
+            .body
+            .parse_struct("PlaidPaymentsWebhookBody")
+            .change_context(errors::ConnectorError::WebhookResourceObjectNotFound)?;
+
+        Ok(Box::new(payload))
+    }
+}
diff --git a/crates/router/src/connector/plaid/transformers.rs b/crates/router/src/connector/plaid/transformers.rs
new file mode 100644
index 00000000000..81c0c7dde05
--- /dev/null
+++ b/crates/router/src/connector/plaid/transformers.rs
@@ -0,0 +1,678 @@
+use actix_http::header::HeaderMap;
+use common_enums::Currency;
+use error_stack::{IntoReport, ResultExt};
+use jsonwebtoken;
+use masking::{PeekInterface, Secret};
+use ring::digest;
+use serde::{Deserialize, Serialize};
+
+use crate::{
+    core::errors,
+    types::{self, api, storage::enums, transformers::ForeignFrom},
+    utils::ext_traits::OptionExt,
+};
+
+const PLAID_VERIFICATION_HEADER: &str = "Plaid-Verification";
+
+//TODO: Fill the struct with respective fields
+pub struct PlaidRouterData<T> {
+    pub amount: Option<f64>, // The type of amount that a connector accepts, for example, String, i64, f64, etc.
+    pub router_data: T,
+}
+
+impl<T> TryFrom<(Option<f64>, T)> for PlaidRouterData<T> {
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from((amount, item): (Option<f64>, T)) -> Result<Self, Self::Error> {
+        //Todo :  use utils to convert the amount to the type of amount that a connector accepts
+        Ok(Self {
+            amount,
+            router_data: item,
+        })
+    }
+}
+
+#[derive(Default, Debug, Serialize)]
+pub struct PlaidPaymentsRequest {
+    amount: PlaidAmount,
+    recipient_id: String,
+    reference: String,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    schedule: Option<PlaidSchedule>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    options: Option<PlaidOptions>,
+}
+
+#[derive(Default, Debug, Serialize, Deserialize)]
+pub struct PlaidAmount {
+    currency: Currency,
+    value: f64,
+}
+
+#[derive(Default, Debug, Serialize, Deserialize)]
+pub struct PlaidSchedule {
+    interval: String,
+    interval_execution_day: String,
+    start_date: String,
+    end_date: Option<String>,
+    adjusted_start_date: Option<String>,
+}
+
+#[derive(Default, Debug, Serialize, Deserialize)]
+pub struct PlaidOptions {
+    request_refund_details: bool,
+    iban: Option<String>,
+    bacs: Option<PlaidBacs>,
+    scheme: String,
+}
+
+#[derive(Default, Debug, Serialize, Deserialize)]
+pub struct PlaidBacs {
+    acount: Secret<String>,
+    sort_code: Secret<String>,
+}
+
+#[derive(Default, Debug, Serialize, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub struct PlaidLinkTokenRequest {
+    client_name: String,
+    country_codes: Vec<String>,
+    language: String,
+    products: Vec<String>,
+    user: User,
+    payment_initiation: PlaidPaymentInitiation,
+}
+
+#[derive(Default, Debug, Serialize, Deserialize)]
+pub struct User {
+    pub client_user_id: String,
+}
+
+#[derive(Default, Debug, Serialize, Deserialize)]
+pub struct PlaidPaymentInitiation {
+    payment_id: String,
+}
+
+impl TryFrom<&PlaidRouterData<&types::PaymentsAuthorizeRouterData>> for PlaidPaymentsRequest {
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        item: &PlaidRouterData<&types::PaymentsAuthorizeRouterData>,
+    ) -> Result<Self, Self::Error> {
+        match item.router_data.request.payment_method_data.clone() {
+            api::PaymentMethodData::BankRedirect(ref bank) => match bank {
+                api_models::payments::BankRedirectData::OpenBanking { .. } => {
+                    let amount =
+                        item.amount
+                            .ok_or(errors::ConnectorError::MissingRequiredField {
+                                field_name: "amount",
+                            })?;
+                    let currency = item.router_data.request.currency;
+                    let reference = "Some ref".to_string();
+                    let recipient_val = item
+                        .router_data
+                        .connector_meta_data
+                        .as_ref()
+                        .ok_or(errors::ConnectorError::MissingRequiredField {
+                            field_name: "connector_customer",
+                        })?
+                        .peek()
+                        .clone();
+
+                    let recipient_type =
+                        serde_json::from_value::<types::MerchantRecipientData>(recipient_val)
+                            .into_report()
+                            .change_context(errors::ConnectorError::ParsingFailed)?;
+                    let recipient_id = match recipient_type {
+                        types::MerchantRecipientData::RecipientId(id) => Ok(id.peek().to_string()),
+                        _ => Err(errors::ConnectorError::NotSupported {
+                            message: "recipient_id not found, other methods".to_string(),
+                            connector: "plaid",
+                        }),
+                    }
+                    .into_report()?;
+
+                    Ok(Self {
+                        amount: PlaidAmount {
+                            currency,
+                            value: amount,
+                        },
+                        reference,
+                        recipient_id,
+                        schedule: None,
+                        options: None,
+                    })
+                }
+                _ => Err(
+                    errors::ConnectorError::NotImplemented("Payment method type".to_string())
+                        .into(),
+                ),
+            },
+            _ => Err(errors::ConnectorError::NotImplemented("Payment methods".to_string()).into()),
+        }
+    }
+}
+
+impl TryFrom<&PlaidRouterData<&types::PaymentsSyncRouterData>> for PlaidSyncRequest {
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        item: &PlaidRouterData<&types::PaymentsSyncRouterData>,
+    ) -> Result<Self, Self::Error> {
+        match item.router_data.request.connector_transaction_id {
+            types::ResponseId::ConnectorTransactionId(ref id) => Ok(Self {
+                payment_id: id.clone(),
+            }),
+            _ => Err(
+                errors::ConnectorError::NotImplemented("ResponseId for Plaid".to_string()).into(),
+            ),
+        }
+    }
+}
+
+impl TryFrom<&PlaidRouterData<&types::PaymentsPostProcessingRouterData>> for PlaidLinkTokenRequest {
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        item: &PlaidRouterData<&types::PaymentsPostProcessingRouterData>,
+    ) -> Result<Self, Self::Error> {
+        match item.router_data.request.payment_method_data.clone() {
+            api::PaymentMethodData::BankRedirect(ref bank) => match bank {
+                api_models::payments::BankRedirectData::OpenBanking { .. } => Ok(Self {
+                    // discuss this with folks
+                    client_name: "Hyperswitch".to_string(),
+                    country_codes: vec!["GB".to_string()],
+                    language: "en".to_string(),
+                    products: vec!["payment_initiation".to_string()],
+                    user: User {
+                        client_user_id: item
+                            .router_data
+                            .request
+                            .customer_id
+                            .clone()
+                            .unwrap_or("default cust".to_string()),
+                    },
+                    payment_initiation: PlaidPaymentInitiation {
+                        payment_id: item
+                            .router_data
+                            .request
+                            .connector_transaction_id
+                            .clone()
+                            .ok_or(errors::ConnectorError::MissingRequiredField {
+                                field_name: "connector_transaction_id",
+                            })?,
+                    },
+                }),
+                _ => Err(
+                    errors::ConnectorError::NotImplemented("Payment method type".to_string())
+                        .into(),
+                ),
+            },
+            _ => Err(errors::ConnectorError::NotImplemented("Payment methods".to_string()).into()),
+        }
+    }
+}
+
+//TODO: Fill the struct with respective fields
+// Auth Struct
+pub struct PlaidAuthType {
+    pub client_id: Secret<String>,
+    pub secret: Secret<String>,
+}
+
+impl TryFrom<&types::ConnectorAuthType> for PlaidAuthType {
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(auth_type: &types::ConnectorAuthType) -> Result<Self, Self::Error> {
+        match auth_type {
+            types::ConnectorAuthType::OpenBankingAuth {
+                api_key,
+                key1,
+                ..
+            } => Ok(Self {
+                client_id: api_key.to_owned(),
+                secret: key1.to_owned(),
+            }),
+            _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()),
+        }
+    }
+}
+// PaymentsResponse
+//TODO: Append the remaining status flags
+#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
+#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
+#[derive(strum::Display)]
+pub enum PlaidPaymentStatus {
+    PaymentStatusInputNeeded,
+    PaymentStatusInitiated,
+    PaymentStatusInsuficientFunds,
+    PaymentStatusFailed,
+    PaymentStatusBlcoked,
+    PaymentStatusCancelled,
+    PaymentStatusExecuted,
+    PaymentStatusSettled,
+    PaymentStatusEstablished,
+    PaymentStatusRejected,
+    #[default]
+    PaymentStatusAuthorising,
+}
+
+impl From<PlaidPaymentStatus> for enums::AttemptStatus {
+    fn from(item: PlaidPaymentStatus) -> Self {
+        match item {
+            // Double check these with someone
+            PlaidPaymentStatus::PaymentStatusAuthorising => Self::Authorizing,
+            PlaidPaymentStatus::PaymentStatusBlcoked => Self::AuthorizationFailed,
+            PlaidPaymentStatus::PaymentStatusCancelled => Self::Voided,
+            PlaidPaymentStatus::PaymentStatusEstablished => Self::Authorized,
+            PlaidPaymentStatus::PaymentStatusExecuted => Self::Authorized,
+            PlaidPaymentStatus::PaymentStatusFailed => Self::Failure,
+            PlaidPaymentStatus::PaymentStatusInitiated => Self::AuthenticationPending,
+            PlaidPaymentStatus::PaymentStatusInputNeeded => Self::AuthenticationPending,
+            PlaidPaymentStatus::PaymentStatusInsuficientFunds => Self::AuthorizationFailed,
+            PlaidPaymentStatus::PaymentStatusRejected => Self::AuthorizationFailed,
+            PlaidPaymentStatus::PaymentStatusSettled => Self::Charged,
+        }
+    }
+}
+
+//TODO: Fill the struct with respective fields
+#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
+pub struct PlaidPaymentsResponse {
+    status: PlaidPaymentStatus,
+    payment_id: String,
+}
+
+impl<F, T>
+    TryFrom<types::ResponseRouterData<F, PlaidPaymentsResponse, T, types::PaymentsResponseData>>
+    for types::RouterData<F, T, types::PaymentsResponseData>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        item: types::ResponseRouterData<F, PlaidPaymentsResponse, T, types::PaymentsResponseData>,
+    ) -> Result<Self, Self::Error> {
+        Ok(Self {
+            status: enums::AttemptStatus::from(item.response.status),
+            response: Ok(types::PaymentsResponseData::TransactionResponse {
+                resource_id: types::ResponseId::ConnectorTransactionId(
+                    item.response.payment_id.clone(),
+                ),
+                redirection_data: None,
+                mandate_reference: None,
+                connector_metadata: None,
+                network_txn_id: None,
+                connector_response_reference_id: Some(item.response.payment_id),
+                incremental_authorization_allowed: None,
+            }),
+            ..item.data
+        })
+    }
+}
+
+#[derive(Default, Debug, Serialize, Deserialize)]
+pub struct PlaidLinkTokenResponse {
+    link_token: String,
+}
+
+impl<F, T>
+    TryFrom<types::ResponseRouterData<F, PlaidLinkTokenResponse, T, types::PaymentsResponseData>>
+    for types::RouterData<F, T, types::PaymentsResponseData>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        item: types::ResponseRouterData<F, PlaidLinkTokenResponse, T, types::PaymentsResponseData>,
+    ) -> Result<Self, Self::Error> {
+        let session_token = Some(api::OpenBankingSessionToken {
+            open_banking_session_token: item.response.link_token,
+        });
+
+        Ok(Self {
+            status: enums::AttemptStatus::AuthenticationPending,
+            response: Ok(types::PaymentsResponseData::PostProcessingResponse { session_token }),
+            ..item.data
+        })
+    }
+}
+
+#[derive(Default, Debug, Serialize, Deserialize)]
+pub struct PlaidSyncRequest {
+    payment_id: String,
+}
+
+#[derive(Default, Debug, Serialize, Deserialize)]
+pub struct PlaidSyncResponse {
+    payment_id: String,
+    amount: PlaidAmount,
+    status: PlaidPaymentStatus,
+    recipient_id: String,
+    reference: String,
+    last_status_update: String,
+    adjusted_reference: Option<String>,
+    schedule: Option<PlaidSchedule>,
+    iban: Option<String>,
+    bacs: Option<PlaidBacs>,
+    scheme: Option<String>,
+    adjusted_scheme: Option<String>,
+    request_id: String,
+    // TODO: add refund related objects
+}
+
+impl<F, T> TryFrom<types::ResponseRouterData<F, PlaidSyncResponse, T, types::PaymentsResponseData>>
+    for types::RouterData<F, T, types::PaymentsResponseData>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        item: types::ResponseRouterData<F, PlaidSyncResponse, T, types::PaymentsResponseData>,
+    ) -> Result<Self, Self::Error> {
+        let status = enums::AttemptStatus::from(item.response.status.clone());
+        Ok(Self {
+            status,
+            response: if is_payment_failure(status) {
+                Err(types::ErrorResponse {
+                    code: item.response.status.clone().to_string(),
+                    message: item.response.status.clone().to_string(),
+                    reason: Some(item.response.status.to_string()),
+                    status_code: item.http_code,
+                    attempt_status: None,
+                    connector_transaction_id: Some(item.response.payment_id),
+                })
+            } else {
+                Ok(types::PaymentsResponseData::TransactionResponse {
+                    resource_id: types::ResponseId::ConnectorTransactionId(
+                        item.response.payment_id.clone(),
+                    ),
+                    redirection_data: None,
+                    mandate_reference: None,
+                    connector_metadata: None,
+                    network_txn_id: None,
+                    connector_response_reference_id: Some(item.response.payment_id),
+                    incremental_authorization_allowed: None,
+                })
+            },
+            ..item.data
+        })
+    }
+}
+
+// TODO: Fill the struct with respective fields
+// REFUND :
+// Type definition for RefundRequest
+#[derive(Default, Debug, Serialize)]
+pub struct PlaidRefundRequest {
+    pub amount: f64,
+}
+
+impl<F> TryFrom<&PlaidRouterData<&types::RefundsRouterData<F>>> for PlaidRefundRequest {
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(item: &PlaidRouterData<&types::RefundsRouterData<F>>) -> Result<Self, Self::Error> {
+        Ok(Self {
+            amount: item
+                .amount
+                .ok_or(errors::ConnectorError::MissingRequiredField {
+                    field_name: "amount",
+                })?,
+        })
+    }
+}
+
+// Type definition for Refund Response
+
+#[allow(dead_code)]
+#[derive(Debug, Serialize, Default, Deserialize, Clone)]
+pub enum RefundStatus {
+    Succeeded,
+    Failed,
+    #[default]
+    Processing,
+}
+
+impl From<RefundStatus> for enums::RefundStatus {
+    fn from(item: RefundStatus) -> Self {
+        match item {
+            RefundStatus::Succeeded => Self::Success,
+            RefundStatus::Failed => Self::Failure,
+            RefundStatus::Processing => Self::Pending,
+            //TODO: Review mapping
+        }
+    }
+}
+
+//TODO: Fill the struct with respective fields
+#[derive(Default, Debug, Clone, Serialize, Deserialize)]
+pub struct RefundResponse {
+    id: String,
+    status: RefundStatus,
+}
+
+impl TryFrom<types::RefundsResponseRouterData<api::Execute, RefundResponse>>
+    for types::RefundsRouterData<api::Execute>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        item: types::RefundsResponseRouterData<api::Execute, RefundResponse>,
+    ) -> Result<Self, Self::Error> {
+        Ok(Self {
+            response: Ok(types::RefundsResponseData {
+                connector_refund_id: item.response.id.to_string(),
+                refund_status: enums::RefundStatus::from(item.response.status),
+            }),
+            ..item.data
+        })
+    }
+}
+
+impl TryFrom<types::RefundsResponseRouterData<api::RSync, RefundResponse>>
+    for types::RefundsRouterData<api::RSync>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        item: types::RefundsResponseRouterData<api::RSync, RefundResponse>,
+    ) -> Result<Self, Self::Error> {
+        Ok(Self {
+            response: Ok(types::RefundsResponseData {
+                connector_refund_id: item.response.id.to_string(),
+                refund_status: enums::RefundStatus::from(item.response.status),
+            }),
+            ..item.data
+        })
+    }
+}
+
+#[derive(Default, Debug, Serialize, Deserialize)]
+pub struct PlaidPaymentsWebhookBody {
+    pub webhook_type: String,
+    pub webhook_code: String,
+    pub payment_id: String,
+    pub new_payment_status: PlaidPaymentStatus,
+    pub old_payment_status: PlaidPaymentStatus,
+    pub original_reference: String,
+    pub adjusted_reference: String,
+    pub original_start_date: String,
+    pub adjusted_start_date: String,
+    pub timestamp: String,
+    pub environment: String,
+}
+
+impl ForeignFrom<PlaidPaymentStatus> for api::IncomingWebhookEvent {
+    fn foreign_from(status: PlaidPaymentStatus) -> Self {
+        match status {
+            // Double check these with someone
+            PlaidPaymentStatus::PaymentStatusAuthorising => Self::PaymentIntentProcessing,
+            PlaidPaymentStatus::PaymentStatusBlcoked => Self::PaymentIntentAuthorizationFailure,
+            PlaidPaymentStatus::PaymentStatusCancelled => Self::PaymentIntentCancelled,
+            PlaidPaymentStatus::PaymentStatusEstablished => Self::PaymentIntentAuthorizationSuccess,
+            PlaidPaymentStatus::PaymentStatusExecuted => Self::PaymentIntentSuccess,
+            PlaidPaymentStatus::PaymentStatusFailed => Self::PaymentIntentFailure,
+            PlaidPaymentStatus::PaymentStatusInitiated => Self::PaymentIntentAuthorizationSuccess,
+            PlaidPaymentStatus::PaymentStatusInputNeeded => Self::PaymentActionRequired,
+            PlaidPaymentStatus::PaymentStatusInsuficientFunds => Self::PaymentIntentFailure,
+            PlaidPaymentStatus::PaymentStatusRejected => Self::PaymentIntentFailure,
+            PlaidPaymentStatus::PaymentStatusSettled => Self::PaymentIntentSuccess,
+        }
+    }
+}
+
+#[derive(Default, Debug, Serialize, Deserialize)]
+pub struct PlaidWebhookVerificationRequest {
+    pub key_id: String,
+}
+
+#[derive(Default, Debug, Serialize, Deserialize)]
+pub struct PlaidJWK {
+    kid: String,
+    alg: String,
+    created_at: i64,
+    expired_at: Option<i64>,
+    pub x: String,
+    pub y: String,
+    #[serde(rename = "use")]
+    _use: String,
+    kty: String,
+    crv: String,
+}
+
+#[derive(Default, Debug, Serialize, Deserialize)]
+pub struct PlaidWebhookVerificationResponse {
+    key: PlaidJWK,
+}
+
+#[derive(Default, Debug, Serialize, Deserialize)]
+struct PlaidJWTPayload {
+    iat: i64,
+    request_body_sha256: String,
+}
+
+impl TryFrom<&types::VerifyWebhookSourceRequestData> for PlaidWebhookVerificationRequest {
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(req: &types::VerifyWebhookSourceRequestData) -> Result<Self, Self::Error> {
+        let kid = get_data_from_verification_header(&req.webhook_headers)?;
+
+        Ok(Self { key_id: kid })
+    }
+}
+
+impl
+    TryFrom<
+        types::ResponseRouterData<
+            api::VerifyWebhookSource,
+            PlaidWebhookVerificationResponse,
+            types::VerifyWebhookSourceRequestData,
+            types::VerifyWebhookSourceResponseData,
+        >,
+    > for types::VerifyWebhookSourceRouterData
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        item: types::ResponseRouterData<
+            api::VerifyWebhookSource,
+            PlaidWebhookVerificationResponse,
+            types::VerifyWebhookSourceRequestData,
+            types::VerifyWebhookSourceResponseData,
+        >,
+    ) -> Result<Self, Self::Error> {
+        Ok(Self {
+            response: Ok(types::VerifyWebhookSourceResponseData {
+                verify_webhook_status: types::VerifyWebhookStatus::SourceVerified,
+            }),
+            ..item.data
+        })
+    }
+}
+#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
+#[serde(rename_all = "snake_case")]
+pub struct PlaidErrorResponse {
+    pub display_message: Option<String>,
+    pub error_code: Option<String>,
+    pub error_message: String,
+    pub error_type: Option<String>,
+}
+
+fn is_payment_failure(status: enums::AttemptStatus) -> bool {
+    match status {
+        common_enums::AttemptStatus::AuthenticationFailed
+        | common_enums::AttemptStatus::AuthorizationFailed
+        | common_enums::AttemptStatus::CaptureFailed
+        | common_enums::AttemptStatus::VoidFailed
+        | common_enums::AttemptStatus::Failure => true,
+        common_enums::AttemptStatus::Started
+        | common_enums::AttemptStatus::RouterDeclined
+        | common_enums::AttemptStatus::AuthenticationPending
+        | common_enums::AttemptStatus::AuthenticationSuccessful
+        | common_enums::AttemptStatus::Authorized
+        | common_enums::AttemptStatus::Charged
+        | common_enums::AttemptStatus::Authorizing
+        | common_enums::AttemptStatus::CodInitiated
+        | common_enums::AttemptStatus::Voided
+        | common_enums::AttemptStatus::VoidInitiated
+        | common_enums::AttemptStatus::CaptureInitiated
+        | common_enums::AttemptStatus::AutoRefunded
+        | common_enums::AttemptStatus::PartialCharged
+        | common_enums::AttemptStatus::PartialChargedAndChargeable
+        | common_enums::AttemptStatus::Unresolved
+        | common_enums::AttemptStatus::Pending
+        | common_enums::AttemptStatus::PaymentMethodAwaited
+        | common_enums::AttemptStatus::ConfirmationAwaited
+        | common_enums::AttemptStatus::DeviceDataCollectionPending => false,
+    }
+}
+
+fn get_data_from_verification_header(
+    headers: &HeaderMap,
+) -> Result<String, error_stack::Report<errors::ConnectorError>> {
+    let plaid_header = headers
+        .get(PLAID_VERIFICATION_HEADER)
+        .get_required_value(PLAID_VERIFICATION_HEADER)
+        .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)?
+        .to_str()
+        .into_report()
+        .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)
+        .attach_printable("Failed to convert JWT token to string")?;
+
+    let jwt_header = jsonwebtoken::decode_header(plaid_header)
+        .into_report()
+        .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)
+        .attach_printable("Failed to get JWT Header for Plaid")?;
+
+    jwt_header
+        .kid
+        .ok_or(errors::ConnectorError::WebhookSourceVerificationFailed)
+        .into_report()
+        .attach_printable("Failed to get kid from JWT Header for Plaid")
+}
+
+pub fn process_plaid_jwt_header(
+    req: &types::VerifyWebhookSourceRequestData,
+    res: &PlaidWebhookVerificationResponse,
+) -> Result<(), error_stack::Report<errors::ConnectorError>> {
+    let plaid_header = req
+        .webhook_headers
+        .get(PLAID_VERIFICATION_HEADER)
+        .get_required_value(PLAID_VERIFICATION_HEADER)
+        .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)?
+        .to_str()
+        .into_report()
+        .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)
+        .attach_printable("Failed to convert JWT token to string")?;
+
+    let key = jsonwebtoken::DecodingKey::from_ec_components(&res.key.x, &res.key.y)
+        .into_report()
+        .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)
+        .attach_printable("Failed to from Decoding key for JWT token")?;
+
+    let decoded = jsonwebtoken::decode::<PlaidJWTPayload>(
+        plaid_header,
+        &key,
+        &jsonwebtoken::Validation::new(jsonwebtoken::Algorithm::ES256),
+    )
+    .into_report()
+    .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)
+    .attach_printable("Failed to validate JWT token")?;
+
+    let body_value = hex::decode(decoded.claims.request_body_sha256)
+        .into_report()
+        .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)
+        .attach_printable("Failed to hex-decode plaid webhook request_body_sha256")?;
+
+    let payload_digest = digest::digest(&digest::SHA256, req.webhook_body.as_slice());
+
+    if payload_digest.as_ref() != body_value.as_slice() {
+        return Err(errors::ConnectorError::WebhookSourceVerificationFailed.into());
+    }
+
+    Ok(())
+}
diff --git a/crates/router/src/connector/shift4/transformers.rs b/crates/router/src/connector/shift4/transformers.rs
index 97c19c49af8..7d4ee582485 100644
--- a/crates/router/src/connector/shift4/transformers.rs
+++ b/crates/router/src/connector/shift4/transformers.rs
@@ -411,6 +411,7 @@ impl TryFrom<&payments::BankRedirectData> for PaymentMethodType {
             | payments::BankRedirectData::OnlineBankingPoland { .. }
             | payments::BankRedirectData::OnlineBankingSlovakia { .. }
             | payments::BankRedirectData::OpenBankingUk { .. }
+            | payments::BankRedirectData::OpenBanking { .. }
             | payments::BankRedirectData::OnlineBankingFpx { .. }
             | payments::BankRedirectData::OnlineBankingThailand { .. } => {
                 Err(errors::ConnectorError::NotImplemented(
diff --git a/crates/router/src/connector/square/transformers.rs b/crates/router/src/connector/square/transformers.rs
index 1e5501575ad..dfa5c509cc3 100644
--- a/crates/router/src/connector/square/transformers.rs
+++ b/crates/router/src/connector/square/transformers.rs
@@ -305,15 +305,7 @@ impl TryFrom<&types::ConnectorAuthType> for SquareAuthType {
                 api_key: api_key.to_owned(),
                 key1: key1.to_owned(),
             }),
-
-            types::ConnectorAuthType::HeaderKey { .. }
-            | types::ConnectorAuthType::SignatureKey { .. }
-            | types::ConnectorAuthType::MultiAuthKey { .. }
-            | types::ConnectorAuthType::CurrencyAuthKey { .. }
-            | types::ConnectorAuthType::TemporaryAuth { .. }
-            | types::ConnectorAuthType::NoKey { .. } => {
-                Err(errors::ConnectorError::FailedToObtainAuthType.into())
-            }
+            _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()),
         }
     }
 }
diff --git a/crates/router/src/connector/stripe/transformers.rs b/crates/router/src/connector/stripe/transformers.rs
index d08f28d1a84..d5a1a58ec0f 100644
--- a/crates/router/src/connector/stripe/transformers.rs
+++ b/crates/router/src/connector/stripe/transformers.rs
@@ -654,6 +654,7 @@ impl TryFrom<enums::PaymentMethodType> for StripePaymentMethodType {
             | enums::PaymentMethodType::OnlineBankingPoland
             | enums::PaymentMethodType::OnlineBankingSlovakia
             | enums::PaymentMethodType::OpenBankingUk
+            | enums::PaymentMethodType::OpenBanking
             | enums::PaymentMethodType::PagoEfectivo
             | enums::PaymentMethodType::PayBright
             | enums::PaymentMethodType::Pse
@@ -952,6 +953,7 @@ impl TryFrom<&payments::BankRedirectData> for StripePaymentMethodType {
             | payments::BankRedirectData::OnlineBankingSlovakia { .. }
             | payments::BankRedirectData::OnlineBankingThailand { .. }
             | payments::BankRedirectData::OpenBankingUk { .. }
+            | payments::BankRedirectData::OpenBanking { .. }
             | payments::BankRedirectData::Trustly { .. } => {
                 Err(errors::ConnectorError::NotSupported {
                     message: connector_util::SELECTED_PAYMENT_METHOD.to_string(),
@@ -1183,6 +1185,7 @@ impl TryFrom<(&payments::BankRedirectData, Option<bool>)> for StripeBillingAddre
             | payments::BankRedirectData::Trustly { .. }
             | payments::BankRedirectData::OnlineBankingFpx { .. }
             | payments::BankRedirectData::OnlineBankingThailand { .. }
+            | payments::BankRedirectData::OpenBanking { .. }
             | payments::BankRedirectData::OpenBankingUk { .. } => Ok(Self::default()),
         }
     }
@@ -1680,6 +1683,7 @@ impl TryFrom<&payments::BankRedirectData> for StripePaymentMethodData {
             | payments::BankRedirectData::OnlineBankingSlovakia { .. }
             | payments::BankRedirectData::OnlineBankingThailand { .. }
             | payments::BankRedirectData::OpenBankingUk { .. }
+            | payments::BankRedirectData::OpenBanking { .. }
             | payments::BankRedirectData::Trustly { .. } => {
                 Err(errors::ConnectorError::NotSupported {
                     message: connector_util::SELECTED_PAYMENT_METHOD.to_string(),
diff --git a/crates/router/src/connector/trustpay/transformers.rs b/crates/router/src/connector/trustpay/transformers.rs
index 79850decb69..1fa9a4aebe3 100644
--- a/crates/router/src/connector/trustpay/transformers.rs
+++ b/crates/router/src/connector/trustpay/transformers.rs
@@ -17,6 +17,7 @@ use crate::{
     },
     consts,
     core::errors,
+    headers::NONCE,
     services,
     types::{self, api, storage::enums, BrowserInformation},
 };
@@ -246,6 +247,7 @@ impl TryFrom<&BankRedirectData> for TrustpayPaymentMethod {
             | api_models::payments::BankRedirectData::OnlineBankingPoland { .. }
             | api_models::payments::BankRedirectData::OnlineBankingSlovakia { .. }
             | api_models::payments::BankRedirectData::OpenBankingUk { .. }
+            | api_models::payments::BankRedirectData::OpenBanking { .. }
             | api_models::payments::BankRedirectData::Przelewy24 { .. }
             | api_models::payments::BankRedirectData::Trustly { .. }
             | api_models::payments::BankRedirectData::OnlineBankingFpx { .. }
diff --git a/crates/router/src/connector/volt/transformers.rs b/crates/router/src/connector/volt/transformers.rs
index b7c9a6826ce..c1eb52a1a19 100644
--- a/crates/router/src/connector/volt/transformers.rs
+++ b/crates/router/src/connector/volt/transformers.rs
@@ -133,6 +133,7 @@ impl TryFrom<&VoltRouterData<&types::PaymentsAuthorizeRouterData>> for VoltPayme
                 | api_models::payments::BankRedirectData::Sofort { .. }
                 | api_models::payments::BankRedirectData::Trustly { .. }
                 | api_models::payments::BankRedirectData::OnlineBankingFpx { .. }
+                | api_models::payments::BankRedirectData::OpenBanking { .. }
                 | api_models::payments::BankRedirectData::OnlineBankingThailand { .. } => {
                     Err(errors::ConnectorError::NotImplemented(
                         utils::get_unimplemented_payment_method_error_message("Volt"),
diff --git a/crates/router/src/connector/worldline/transformers.rs b/crates/router/src/connector/worldline/transformers.rs
index 1eb22fc52d2..caca9a41770 100644
--- a/crates/router/src/connector/worldline/transformers.rs
+++ b/crates/router/src/connector/worldline/transformers.rs
@@ -417,6 +417,7 @@ fn make_bank_redirect_request(
         | payments::BankRedirectData::OnlineBankingPoland { .. }
         | payments::BankRedirectData::OnlineBankingSlovakia { .. }
         | payments::BankRedirectData::OpenBankingUk { .. }
+        | payments::BankRedirectData::OpenBanking { .. }
         | payments::BankRedirectData::Przelewy24 { .. }
         | payments::BankRedirectData::Sofort { .. }
         | payments::BankRedirectData::Trustly { .. }
diff --git a/crates/router/src/connector/zen/transformers.rs b/crates/router/src/connector/zen/transformers.rs
index ebea61304a1..5497969ccc1 100644
--- a/crates/router/src/connector/zen/transformers.rs
+++ b/crates/router/src/connector/zen/transformers.rs
@@ -737,6 +737,7 @@ impl TryFrom<&api_models::payments::BankRedirectData> for ZenPaymentsRequest {
             | api_models::payments::BankRedirectData::OnlineBankingPoland { .. }
             | api_models::payments::BankRedirectData::OnlineBankingSlovakia { .. }
             | api_models::payments::BankRedirectData::OpenBankingUk { .. }
+            | api_models::payments::BankRedirectData::OpenBanking { .. }
             | api_models::payments::BankRedirectData::OnlineBankingFpx { .. }
             | api_models::payments::BankRedirectData::OnlineBankingThailand { .. } => {
                 Err(errors::ConnectorError::NotImplemented(
diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs
index 0eaabf8652c..87397879dde 100644
--- a/crates/router/src/core/admin.rs
+++ b/crates/router/src/core/admin.rs
@@ -10,24 +10,28 @@ use common_utils::{
     ext_traits::{AsyncExt, ConfigExt, Encode, ValueExt},
     pii,
 };
-use diesel_models::configs;
+use diesel_models::{configs, encryption};
 use error_stack::{report, FutureExt, IntoReport, ResultExt};
 use futures::future::try_join_all;
 use masking::{PeekInterface, Secret};
-use pm_auth::connector::plaid::transformers::PlaidAuthType;
+use pm_auth::{connector::plaid::transformers::PlaidAuthType, types as pm_auth_types};
+use regex::Regex;
+use serde_json;
 use uuid::Uuid;
 
 use crate::{
     consts,
     core::{
         errors::{self, RouterResponse, RouterResult, StorageErrorExt},
+        payment_methods::{cards, transformers},
         payments::helpers,
+        pm_auth::helpers::PaymentAuthConnectorDataExt,
         routing::helpers as routing_helpers,
         utils as core_utils,
     },
     db::StorageInterface,
     routes::{metrics, AppState},
-    services::{self, api as service_api},
+    services::{self, api as service_api, pm_auth as payment_initiation_service},
     types::{
         self, api,
         domain::{
@@ -786,7 +790,9 @@ pub async fn create_payment_connector(
         api_enums::convert_authentication_connector(req.connector_name.to_string().as_str());
 
     if pm_auth_connector.is_some() {
-        if req.connector_type != api_enums::ConnectorType::PaymentMethodAuth {
+        if req.connector_type != api_enums::ConnectorType::PaymentMethodAuth
+            && req.connector_type != api_enums::ConnectorType::PaymentProcessor
+        {
             return Err(errors::ApiErrorResponse::InvalidRequestData {
                 message: "Invalid connector type given".to_string(),
             })
@@ -852,6 +858,16 @@ pub async fn create_payment_connector(
             expected_format: "auth_type and api_key".to_string(),
         })?;
 
+    let auth = process_open_banking_connectors(
+        &state,
+        merchant_id.as_str(),
+        &key_store,
+        auth,
+        &req.connector_type,
+        &req.connector_name,
+    )
+    .await?;
+
     validate_auth_and_metadata_type(req.connector_name, &auth, &req.metadata).map_err(|err| {
         match *err.current_context() {
             errors::ConnectorError::InvalidConnectorName => {
@@ -892,7 +908,7 @@ pub async fn create_payment_connector(
     let (connector_status, disabled) = validate_status_and_disabled(
         req.status,
         req.disabled,
-        auth,
+        auth.clone(),
         // The validate_status_and_disabled function will use this value only
         // when the status can be active. So we are passing this as fallback.
         api_enums::ConnectorStatus::Active,
@@ -912,17 +928,19 @@ pub async fn create_payment_connector(
         }
     }
 
+    let connector_auth = serde_json::to_value(auth)
+        .into_report()
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Failed while encoding to serde_json::Value, ConnectorAuthType")?;
+    let conn_auth = Secret::new(connector_auth);
+
     let merchant_connector_account = domain::MerchantConnectorAccount {
         merchant_id: merchant_id.to_string(),
         connector_type: req.connector_type,
         connector_name: req.connector_name.to_string(),
         merchant_connector_id: utils::generate_id(consts::ID_LENGTH, "mca"),
         connector_account_details: domain_types::encrypt(
-            req.connector_account_details.ok_or(
-                errors::ApiErrorResponse::MissingRequiredField {
-                    field_name: "connector_account_details",
-                },
-            )?,
+            conn_auth,
             key_store.key.peek(),
         )
         .await
@@ -1987,3 +2005,288 @@ pub fn validate_status_and_disabled(
 
     Ok((connector_status, disabled))
 }
+
+async fn process_open_banking_connectors(
+    state: &AppState,
+    merchant_id: &str,
+    key_store: &domain::MerchantKeyStore,
+    auth: types::ConnectorAuthType,
+    connector_type: &api_enums::ConnectorType,
+    connector: &api_enums::Connector,
+) -> RouterResult<types::ConnectorAuthType> {
+    match &auth {
+        types::ConnectorAuthType::OpenBankingAuth {
+            api_key,
+            key1,
+            merchant_data,
+        } => {
+            // incorporate a connector check as well
+            if connector_type != &api_enums::ConnectorType::PaymentProcessor {
+                return Err(errors::ApiErrorResponse::InvalidConnectorConfiguration {
+                    config: "OpenBankingAuth type needs to be coupled with a payment connector"
+                        .to_string(),
+                }
+                .into());
+            }
+
+            let new_auth = match merchant_data {
+                types::MerchantRecipientData::AccountData(acc_data) => {
+                    validate_bank_account_data(acc_data)?;
+
+                    let connector_name = api_enums::Connector::to_string(connector);
+
+                    let locker_based_connector_list =
+                        state.conf.locker_open_banking_connectors.clone();
+                    let contains = locker_based_connector_list
+                        .connector_list
+                        .get(connector_name.as_str());
+
+                    let recipient_id = if let Some(_conn) = contains {
+                        locker_recipient_create_call(state, merchant_id, key_store, acc_data).await
+                    } else {
+                        connector_recipient_create_call(
+                            state,
+                            merchant_id,
+                            connector_name,
+                            &auth,
+                            acc_data,
+                        )
+                        .await
+                    }
+                    .change_context(errors::ApiErrorResponse::InternalServerError)
+                    .attach_printable("failed to get recipient_id")?;
+
+                    // data.merchant_data = api_models::admin::MerchantRecipientData::RecipientID(
+                    //     Secret::new(recipient_id),
+                    // );
+
+                    types::ConnectorAuthType::OpenBankingAuth {
+                        api_key: api_key.clone(),
+                        key1: key1.clone(),
+                        merchant_data: types::MerchantRecipientData::RecipientId(Secret::new(
+                            recipient_id,
+                        )),
+                    }
+                }
+                _ => auth.clone(),
+            };
+
+            Ok(new_auth)
+        }
+        _ => Ok(auth.clone()),
+    }
+}
+
+fn validate_bank_account_data(data: &types::MerchantAccountData) -> RouterResult<()> {
+    match data {
+        types::MerchantAccountData::Iban { iban, .. } => {
+            if iban.peek().len() > 34 {
+                return Err(errors::ApiErrorResponse::InvalidRequestData {
+                    message: "IBAN length must be up to 34 characters".to_string(),
+                }
+                .into());
+            }
+            let pattern = Regex::new(r"^[A-Z0-9]*$")
+                .into_report()
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("failed to create regex pattern")?;
+
+            let mut iban = iban.peek().to_string();
+
+            if !pattern.is_match(iban.as_str()) {
+                return Err(errors::ApiErrorResponse::InvalidRequestData {
+                    message: "IBAN data must be alphanumeric".to_string(),
+                }
+                .into());
+            }
+
+            // MOD check
+            let first_4 = iban.chars().take(4).collect::<String>();
+            iban.push_str(first_4.as_str());
+            let len = iban.len();
+
+            let rearranged_iban = iban
+                .chars()
+                .rev()
+                .take(len - 4)
+                .collect::<String>()
+                .chars()
+                .rev()
+                .collect::<String>();
+
+            let mut result = String::new();
+
+            for c in rearranged_iban.chars() {
+                match c {
+                    'A'..='Z' => {
+                        let digit = (c as u8 - b'A') + 10;
+                        result.push_str(&format!("{:02}", digit));
+                    }
+                    _ => result.push(c),
+                }
+            }
+
+            let num = result
+                .parse::<u128>()
+                .into_report()
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("failed to validate IBAN")?;
+
+            if num % 97 != 1 {
+                return Err(errors::ApiErrorResponse::InvalidRequestData {
+                    message: "Invalid IBAN".to_string(),
+                }
+                .into());
+            }
+
+            Ok(())
+        }
+        types::MerchantAccountData::Bacs {
+            account_number,
+            sort_code,
+            ..
+        } => {
+            if account_number.peek().len() > 8 || sort_code.peek().len() != 6 {
+                return Err(errors::ApiErrorResponse::InvalidRequestData {
+                    message: "Invalid BACS numbers".to_string(),
+                }
+                .into());
+            }
+
+            Ok(())
+        }
+    }
+}
+
+async fn connector_recipient_create_call(
+    state: &AppState,
+    merchant_id: &str,
+    connector_name: String,
+    auth: &types::ConnectorAuthType,
+    data: &types::MerchantAccountData,
+) -> RouterResult<String> {
+    let connector = pm_auth_types::api::PaymentAuthConnectorData::get_connector_by_name(
+        connector_name.as_str(),
+    )?;
+
+    let auth = pm_auth_types::ConnectorAuthType::foreign_try_from(auth.clone())
+        .into_report()
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Failed while converting ConnectorAuthType")?;
+
+    let connector_integration: pm_auth_types::api::BoxedConnectorIntegration<
+        '_,
+        pm_auth_types::api::auth_service::RecipientCreate,
+        pm_auth_types::RecipientCreateRequest,
+        pm_auth_types::RecipientCreateResponse,
+    > = connector.connector.get_connector_integration();
+
+    let req = match data {
+        types::MerchantAccountData::Iban { iban, name } => pm_auth_types::RecipientCreateRequest {
+            name: name.clone(),
+            account_data: pm_auth_types::RecipientAccountData::Iban(iban.clone()),
+            address: None,
+        },
+        types::MerchantAccountData::Bacs {
+            account_number,
+            sort_code,
+            name,
+        } => pm_auth_types::RecipientCreateRequest {
+            name: name.clone(),
+            account_data: pm_auth_types::RecipientAccountData::Bacs {
+                sort_code: sort_code.clone(),
+                account_number: account_number.clone(),
+            },
+            address: None,
+        },
+    };
+
+    let router_data = pm_auth_types::RecipientCreateRouterData {
+        flow: std::marker::PhantomData,
+        merchant_id: Some(merchant_id.to_owned()),
+        connector: Some(connector_name),
+        request: req,
+        response: Ok(pm_auth_types::RecipientCreateResponse {
+            recipient_id: "".to_string(),
+        }),
+        connector_http_status_code: None,
+        connector_auth_type: auth,
+    };
+
+    let resp = payment_initiation_service::execute_connector_processing_step(
+        state,
+        connector_integration,
+        &router_data,
+        &connector.connector_name,
+    )
+    .await
+    .change_context(errors::ApiErrorResponse::InternalServerError)
+    .attach_printable("Failed while calling recipient create connector api")?;
+
+    let recipient_create_resp =
+        resp.response
+            .map_err(|err| errors::ApiErrorResponse::ExternalConnectorError {
+                code: err.code,
+                message: err.message,
+                connector: connector.connector_name.to_string(),
+                status_code: err.status_code,
+                reason: err.reason,
+            })?;
+
+    let recipient_id = recipient_create_resp.recipient_id;
+
+    Ok(recipient_id)
+}
+
+async fn locker_recipient_create_call(
+    state: &AppState,
+    merchant_id: &str,
+    key_store: &domain::MerchantKeyStore,
+    data: &types::MerchantAccountData,
+) -> RouterResult<String> {
+    let key = key_store.key.get_inner().peek();
+
+    let enc_data = async {
+        serde_json::to_value(data.to_owned())
+            .map_err(|err| {
+                crate::logger::error!("Error while encoding merchant bank account data: {}", err);
+                errors::VaultError::SavePaymentMethodFailed
+            })
+            .into_report()
+            .change_context(errors::VaultError::SavePaymentMethodFailed)
+            .attach_printable("Unable to encode merchant bank account data")
+            .ok()
+            .map(|v| {
+                let secret: Secret<String> = Secret::new(v.to_string());
+                secret
+            })
+            .async_lift(|inner| domain_types::encrypt_optional(inner, key))
+            .await
+    }
+    .await
+    .change_context(errors::ApiErrorResponse::InternalServerError)
+    .attach_printable("Failed to encrypt merchant bank account data")?
+    .map(encryption::Encryption::from)
+    .map(|e| e.into_inner())
+    .map_or(Err(errors::ApiErrorResponse::InternalServerError), |e| {
+        Ok(hex::encode(e.peek()))
+    })?;
+
+    let payload = transformers::StoreLockerReq::LockerGeneric(transformers::StoreGenericReq {
+        merchant_id,
+        merchant_customer_id: merchant_id.to_string(),
+        enc_data,
+    });
+
+    let store_resp = cards::call_to_locker_hs(
+        state,
+        &payload,
+        merchant_id,
+        api_enums::LockerChoice::HyperswitchCardVault,
+    )
+    .await
+    .change_context(errors::ApiErrorResponse::InternalServerError)
+    .attach_printable("Failed to encrypt merchant bank account data")?;
+
+    Ok(store_resp.card_reference)
+}
diff --git a/crates/router/src/core/fraud_check.rs b/crates/router/src/core/fraud_check.rs
index 0e3f67c051b..bdf34f095e7 100644
--- a/crates/router/src/core/fraud_check.rs
+++ b/crates/router/src/core/fraud_check.rs
@@ -90,6 +90,7 @@ where
             key_store,
             customer,
             &merchant_connector_account,
+            None,
         )
         .await?;
 
diff --git a/crates/router/src/core/fraud_check/flows/checkout_flow.rs b/crates/router/src/core/fraud_check/flows/checkout_flow.rs
index 8b3eed45f9e..3b904e3dd1a 100644
--- a/crates/router/src/core/fraud_check/flows/checkout_flow.rs
+++ b/crates/router/src/core/fraud_check/flows/checkout_flow.rs
@@ -17,7 +17,7 @@ use crate::{
         domain,
         fraud_check::{FraudCheckCheckoutData, FraudCheckResponseData, FrmCheckoutRouterData},
         storage::enums as storage_enums,
-        BrowserInformation, ConnectorAuthType, ResponseId, RouterData,
+        BrowserInformation, ConnectorAuthType, MerchantRecipientData, ResponseId, RouterData,
     },
     AppState,
 };
@@ -34,6 +34,7 @@ impl ConstructFlowSpecificData<frm_api::Checkout, FraudCheckCheckoutData, FraudC
         _key_store: &domain::MerchantKeyStore,
         customer: &Option<domain::Customer>,
         merchant_connector_account: &helpers::MerchantConnectorAccountType,
+        _merchant_recipient_data: Option<MerchantRecipientData>,
     ) -> RouterResult<RouterData<frm_api::Checkout, FraudCheckCheckoutData, FraudCheckResponseData>>
     {
         let status = storage_enums::AttemptStatus::Pending;
diff --git a/crates/router/src/core/fraud_check/flows/record_return.rs b/crates/router/src/core/fraud_check/flows/record_return.rs
index 2de6aaab7c7..a947c81ca17 100644
--- a/crates/router/src/core/fraud_check/flows/record_return.rs
+++ b/crates/router/src/core/fraud_check/flows/record_return.rs
@@ -17,7 +17,7 @@ use crate::{
             FraudCheckRecordReturnData, FraudCheckResponseData, FrmRecordReturnRouterData,
         },
         storage::enums as storage_enums,
-        ConnectorAuthType, ResponseId, RouterData,
+        ConnectorAuthType, MerchantRecipientData, ResponseId, RouterData,
     },
     utils, AppState,
 };
@@ -34,6 +34,7 @@ impl ConstructFlowSpecificData<RecordReturn, FraudCheckRecordReturnData, FraudCh
         _key_store: &domain::MerchantKeyStore,
         customer: &Option<domain::Customer>,
         merchant_connector_account: &helpers::MerchantConnectorAccountType,
+        _merchant_recipient_data: Option<MerchantRecipientData>,
     ) -> RouterResult<RouterData<RecordReturn, FraudCheckRecordReturnData, FraudCheckResponseData>>
     {
         let status = storage_enums::AttemptStatus::Pending;
diff --git a/crates/router/src/core/fraud_check/flows/sale_flow.rs b/crates/router/src/core/fraud_check/flows/sale_flow.rs
index dfe70570047..b9a7cb87e98 100644
--- a/crates/router/src/core/fraud_check/flows/sale_flow.rs
+++ b/crates/router/src/core/fraud_check/flows/sale_flow.rs
@@ -14,7 +14,7 @@ use crate::{
         domain,
         fraud_check::{FraudCheckResponseData, FraudCheckSaleData, FrmSaleRouterData},
         storage::enums as storage_enums,
-        ConnectorAuthType, ResponseId, RouterData,
+        ConnectorAuthType, MerchantRecipientData, ResponseId, RouterData,
     },
     AppState,
 };
@@ -31,6 +31,7 @@ impl ConstructFlowSpecificData<frm_api::Sale, FraudCheckSaleData, FraudCheckResp
         _key_store: &domain::MerchantKeyStore,
         customer: &Option<domain::Customer>,
         merchant_connector_account: &helpers::MerchantConnectorAccountType,
+        _merchant_recipient_data: Option<MerchantRecipientData>,
     ) -> RouterResult<RouterData<frm_api::Sale, FraudCheckSaleData, FraudCheckResponseData>> {
         let status = storage_enums::AttemptStatus::Pending;
 
diff --git a/crates/router/src/core/fraud_check/flows/transaction_flow.rs b/crates/router/src/core/fraud_check/flows/transaction_flow.rs
index a84d9a771b4..f9aed084663 100644
--- a/crates/router/src/core/fraud_check/flows/transaction_flow.rs
+++ b/crates/router/src/core/fraud_check/flows/transaction_flow.rs
@@ -16,7 +16,7 @@ use crate::{
             FraudCheckResponseData, FraudCheckTransactionData, FrmTransactionRouterData,
         },
         storage::enums as storage_enums,
-        ConnectorAuthType, ResponseId, RouterData,
+        ConnectorAuthType, MerchantRecipientData, ResponseId, RouterData,
     },
     AppState,
 };
@@ -37,6 +37,7 @@ impl
         _key_store: &domain::MerchantKeyStore,
         customer: &Option<domain::Customer>,
         merchant_connector_account: &helpers::MerchantConnectorAccountType,
+        _merchant_recipient_data: Option<MerchantRecipientData>,
     ) -> RouterResult<
         RouterData<frm_api::Transaction, FraudCheckTransactionData, FraudCheckResponseData>,
     > {
diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs
index 52240bbf39b..f8aa2608261 100644
--- a/crates/router/src/core/payments.rs
+++ b/crates/router/src/core/payments.rs
@@ -14,13 +14,17 @@ pub mod types;
 use std::{fmt::Debug, marker::PhantomData, ops::Deref, time::Instant, vec::IntoIter};
 
 use api_models::{self, enums, payments::HeaderPayload};
-use common_utils::{ext_traits::AsyncExt, pii, types::Surcharge};
+use common_utils::{
+    ext_traits::{AsyncExt, StringExt},
+    pii,
+    types::Surcharge,
+};
 use data_models::mandates::{CustomerAcceptance, MandateData};
 use diesel_models::{ephemeral_key, fraud_check::FraudCheck};
 use error_stack::{IntoReport, ResultExt};
 use futures::future::join_all;
 use helpers::ApplePayData;
-use masking::Secret;
+use masking::{PeekInterface, Secret};
 use redis_interface::errors::RedisError;
 use router_env::{instrument, tracing};
 #[cfg(feature = "olap")]
@@ -51,7 +55,7 @@ use crate::{
     core::{
         authentication as authentication_core,
         errors::{self, CustomResult, RouterResponse, RouterResult},
-        payment_methods::PaymentMethodRetrieve,
+        payment_methods::{self, PaymentMethodRetrieve},
         utils,
     },
     db::StorageInterface,
@@ -176,6 +180,10 @@ where
     )
     .await?;
 
+    let op_ref = &operation;
+    let should_trigger_post_processing_flows =
+        matches!(format!("{op_ref:?}").as_str(), "PaymentConfirm");
+
     let mut connector_http_status_code = None;
     let mut external_latency = None;
     if let Some(connector_details) = connector {
@@ -243,11 +251,11 @@ where
                     } else {
                         None
                     };
-                    let router_data = call_connector_service(
+                    let (router_data, mca) = call_connector_service(
                         state,
                         &merchant_account,
                         &key_store,
-                        connector,
+                        connector.clone(),
                         &operation,
                         &mut payment_data,
                         &customer,
@@ -267,7 +275,7 @@ where
                     external_latency = router_data.external_latency;
                     //add connector http status code metrics
                     add_connector_http_status_code_metrics(connector_http_status_code);
-                    operation
+                    payment_data = operation
                         .to_post_update_tracker()?
                         .update_tracker(
                             state,
@@ -276,7 +284,23 @@ where
                             router_data,
                             merchant_account.storage_scheme,
                         )
-                        .await?
+                        .await?;
+
+                    if should_trigger_post_processing_flows {
+                        complete_postprocessing_steps_if_required(
+                            state,
+                            &merchant_account,
+                            &key_store,
+                            &customer,
+                            &mca,
+                            &connector,
+                            &mut payment_data,
+                            op_ref,
+                        )
+                        .await?;
+                    }
+
+                    payment_data
                 }
 
                 api::ConnectorCallType::Retryable(connectors) => {
@@ -298,7 +322,7 @@ where
                     } else {
                         None
                     };
-                    let router_data = call_connector_service(
+                    let (router_data, mca) = call_connector_service(
                         state,
                         &merchant_account,
                         &key_store,
@@ -333,7 +357,7 @@ where
                                 state,
                                 &mut payment_data,
                                 connectors,
-                                connector_data,
+                                connector_data.clone(),
                                 router_data,
                                 &merchant_account,
                                 &key_store,
@@ -355,7 +379,7 @@ where
                     external_latency = router_data.external_latency;
                     //add connector http status code metrics
                     add_connector_http_status_code_metrics(connector_http_status_code);
-                    operation
+                    payment_data = operation
                         .to_post_update_tracker()?
                         .update_tracker(
                             state,
@@ -364,7 +388,23 @@ where
                             router_data,
                             merchant_account.storage_scheme,
                         )
-                        .await?
+                        .await?;
+
+                    if should_trigger_post_processing_flows {
+                        complete_postprocessing_steps_if_required(
+                            state,
+                            &merchant_account,
+                            &key_store,
+                            &customer,
+                            &mca,
+                            &connector_data,
+                            &mut payment_data,
+                            op_ref,
+                        )
+                        .await?;
+                    }
+
+                    payment_data
                 }
 
                 api::ConnectorCallType::SessionMultiple(connectors) => {
@@ -669,7 +709,7 @@ pub async fn payments_core<F, Res, Req, Op, FData, Ctx>(
 ) -> RouterResponse<Res>
 where
     F: Send + Clone + Sync,
-    FData: Send + Sync,
+    FData: Send + Sync + Clone,
     Op: Operation<F, Req, Ctx> + Send + Sync + Clone,
     Req: Debug + Authenticate + Clone,
     Res: transformers::ToResponse<Req, PaymentData<F>, Op>,
@@ -1026,7 +1066,10 @@ pub async fn call_connector_service<F, RouterDReq, ApiRequest, Ctx>(
     schedule_time: Option<time::PrimitiveDateTime>,
     header_payload: HeaderPayload,
     frm_suggestion: Option<storage_enums::FrmSuggestion>,
-) -> RouterResult<router_types::RouterData<F, RouterDReq, router_types::PaymentsResponseData>>
+) -> RouterResult<(
+    router_types::RouterData<F, RouterDReq, router_types::PaymentsResponseData>,
+    helpers::MerchantConnectorAccountType,
+)>
 where
     F: Send + Clone + Sync,
     RouterDReq: Send + Sync,
@@ -1089,6 +1132,15 @@ where
     )
     .await?;
 
+    let merchant_recipient_data = get_merchant_bank_data_for_open_banking_connectors(
+        &merchant_connector_account,
+        key_store,
+        &connector,
+        state,
+        merchant_account,
+    )
+    .await?;
+
     let mut router_data = payment_data
         .construct_router_data(
             state,
@@ -1097,6 +1149,7 @@ where
             key_store,
             customer,
             &merchant_connector_account,
+            merchant_recipient_data,
         )
         .await?;
 
@@ -1165,7 +1218,9 @@ where
         ..
     }) = router_data.response.to_owned()
     {
-        payment_data.sessions_token.push(session_token);
+        payment_data
+            .sessions_token
+            .push(api::SessionTokenType::Wallet(session_token));
     };
 
     // In case of authorize flow, pre-task and post-tasks are being called in build request
@@ -1210,7 +1265,7 @@ where
         )
         .await?;
 
-    let router_data_res = if should_continue_further {
+    let router_data = if should_continue_further {
         // The status of payment_attempt and intent will be updated in the previous step
         // update this in router_data.
         // This is added because few connector integrations do not update the status,
@@ -1229,13 +1284,63 @@ where
             .await
     } else {
         Ok(router_data)
-    };
+    }?;
 
     let etime_connector = Instant::now();
     let duration_connector = etime_connector.saturating_duration_since(stime_connector);
     tracing::info!(duration = format!("Duration taken: {}", duration_connector.as_millis()));
 
-    router_data_res
+    Ok((router_data, merchant_connector_account))
+}
+
+async fn get_merchant_bank_data_for_open_banking_connectors(
+    merchant_connector_account: &helpers::MerchantConnectorAccountType,
+    key_store: &domain::MerchantKeyStore,
+    connector: &api::ConnectorData,
+    state: &AppState,
+    merchant_account: &domain::MerchantAccount,
+) -> RouterResult<Option<router_types::MerchantRecipientData>> {
+    let auth_type: router_types::ConnectorAuthType = merchant_connector_account
+        .get_connector_account_details()
+        .parse_value("ConnectorAuthType")
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Failed while parsing value for ConnectorAuthType")?;
+    let connector_name = enums::Connector::to_string(&connector.connector_name);
+    let locker_based_connector_list = state.conf.locker_open_banking_connectors.clone();
+    let contains = locker_based_connector_list
+        .connector_list
+        .get(connector_name.as_str());
+    let recipient_id = helpers::get_recipient_id_from_open_banking_auth(&auth_type)?;
+    let final_recipient_data = if let Some(id) = recipient_id {
+        if let Some(_con) = contains {
+            let resp = payment_methods::cards::get_payment_method_from_hs_locker(
+                state,
+                key_store,
+                merchant_account.merchant_id.as_str(),
+                merchant_account.merchant_id.as_str(),
+                id.as_str(),
+                Some(enums::LockerChoice::HyperswitchCardVault),
+            )
+            .await
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("Merchant bank account data could not be fetched from locker")?;
+
+            let parsed: router_types::MerchantAccountData = resp
+                .peek()
+                .to_string()
+                .parse_struct("MerchantAccountData")
+                .change_context(errors::ApiErrorResponse::InternalServerError)?;
+
+            Some(router_types::MerchantRecipientData::AccountData(parsed))
+        } else {
+            Some(router_types::MerchantRecipientData::RecipientId(
+                Secret::new(id),
+            ))
+        }
+    } else {
+        None
+    };
+    Ok(final_recipient_data)
 }
 
 async fn blocklist_guard<F, ApiRequest, Ctx>(
@@ -1342,6 +1447,7 @@ where
                 key_store,
                 customer,
                 &merchant_connector_account,
+                None,
             )
             .await?;
 
@@ -1375,7 +1481,9 @@ where
                         session_token,
                         api_models::payments::SessionToken::NoSessionTokenReceived,
                     ) {
-                        payment_data.sessions_token.push(session_token);
+                        payment_data
+                            .sessions_token
+                            .push(api::SessionTokenType::Wallet(session_token));
                     }
                 }
             }
@@ -1472,6 +1580,7 @@ where
                         key_store,
                         customer,
                         merchant_connector_account,
+                        None,
                     )
                     .await?;
 
@@ -1603,6 +1712,17 @@ where
                 (router_data, should_continue_payment)
             }
         }
+        Some(api_models::payments::PaymentMethodData::BankRedirect(data)) => match data {
+            api_models::payments::BankRedirectData::OpenBanking { .. } => {
+                if connector.connector_name == router_types::Connector::Plaid {
+                    router_data = router_data.preprocessing_steps(state, connector).await?;
+                    (router_data, true)
+                } else {
+                    (router_data, should_continue_payment)
+                }
+            }
+            _ => (router_data, should_continue_payment),
+        },
         _ => {
             // 3DS validation for paypal cards after verification (authorize call)
             if connector.connector_name == router_types::Connector::Paypal
@@ -1623,6 +1743,71 @@ where
     Ok(router_data_and_should_continue_payment)
 }
 
+#[allow(clippy::too_many_arguments)]
+async fn complete_postprocessing_steps_if_required<F, Q, Ctx, RouterDReq>(
+    state: &AppState,
+    merchant_account: &domain::MerchantAccount,
+    key_store: &domain::MerchantKeyStore,
+    customer: &Option<domain::Customer>,
+    merchant_conn_account: &helpers::MerchantConnectorAccountType,
+    connector: &api::ConnectorData,
+    payment_data: &mut PaymentData<F>,
+    _operation: &BoxedOperation<'_, F, Q, Ctx>,
+) -> RouterResult<router_types::RouterData<F, RouterDReq, router_types::PaymentsResponseData>>
+where
+    F: Send + Clone + Sync,
+    RouterDReq: Send + Sync,
+
+    router_types::RouterData<F, RouterDReq, router_types::PaymentsResponseData>:
+        Feature<F, RouterDReq> + Send,
+    dyn api::Connector:
+        services::api::ConnectorIntegration<F, RouterDReq, router_types::PaymentsResponseData>,
+    PaymentData<F>: ConstructFlowSpecificData<F, RouterDReq, router_types::PaymentsResponseData>,
+{
+    let mut router_data = payment_data
+        .construct_router_data(
+            state,
+            connector.connector.id(),
+            merchant_account,
+            key_store,
+            customer,
+            merchant_conn_account,
+            None,
+        )
+        .await?;
+
+    match payment_data.payment_method_data.clone() {
+        Some(api_models::payments::PaymentMethodData::BankRedirect(data)) => match data {
+            api_models::payments::BankRedirectData::OpenBanking { .. } => {
+                if connector.connector_name == router_types::Connector::Plaid {
+                    router_data = router_data.postprocessing_steps(state, connector).await?;
+                    let token = if let Ok(ref res) = router_data.response {
+                        match res {
+                            router_types::PaymentsResponseData::PostProcessingResponse {
+                                session_token,
+                            } => session_token
+                                .as_ref()
+                                .map(|token| api::SessionTokenType::OpenBanking(token.clone())),
+                            _ => None,
+                        }
+                    } else {
+                        None
+                    };
+                    if let Some(t) = token {
+                        payment_data.sessions_token.push(t);
+                    }
+
+                    Ok(router_data)
+                } else {
+                    Ok(router_data)
+                }
+            }
+            _ => Ok(router_data),
+        },
+        _ => Ok(router_data),
+    }
+}
+
 pub fn is_preprocessing_required_for_wallets(connector_name: String) -> bool {
     connector_name == *"trustpay" || connector_name == *"payme"
 }
@@ -2062,7 +2247,7 @@ where
     pub refunds: Vec<storage::Refund>,
     pub disputes: Vec<storage::Dispute>,
     pub attempts: Option<Vec<storage::PaymentAttempt>>,
-    pub sessions_token: Vec<api::SessionToken>,
+    pub sessions_token: Vec<api::SessionTokenType>,
     pub card_cvc: Option<Secret<String>>,
     pub email: Option<pii::Email>,
     pub creds_identifier: Option<String>,
diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs
index fe4a504861d..bdca658a89f 100644
--- a/crates/router/src/core/payments/flows.rs
+++ b/crates/router/src/core/payments/flows.rs
@@ -25,6 +25,7 @@ use crate::{
 };
 
 #[async_trait]
+#[allow(clippy::too_many_arguments)]
 pub trait ConstructFlowSpecificData<F, Req, Res> {
     async fn construct_router_data<'a>(
         &self,
@@ -34,6 +35,7 @@ pub trait ConstructFlowSpecificData<F, Req, Res> {
         key_store: &domain::MerchantKeyStore,
         customer: &Option<domain::Customer>,
         merchant_connector_account: &helpers::MerchantConnectorAccountType,
+        merchant_recipient_data: Option<types::MerchantRecipientData>,
     ) -> RouterResult<types::RouterData<F, Req, Res>>;
 }
 
@@ -93,6 +95,19 @@ pub trait Feature<F, T> {
         Ok(self)
     }
 
+    async fn postprocessing_steps<'a>(
+        self,
+        _state: &AppState,
+        _connector: &api::ConnectorData,
+    ) -> RouterResult<Self>
+    where
+        F: Clone,
+        Self: Sized,
+        dyn api::Connector: services::ConnectorIntegration<F, T, types::PaymentsResponseData>,
+    {
+        Ok(self)
+    }
+
     async fn create_connector_customer<'a>(
         &self,
         _state: &AppState,
@@ -146,6 +161,7 @@ impl<const T: u8>
 
 default_imp_for_complete_authorize!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Adyen,
     connector::Bitpay,
@@ -295,6 +311,7 @@ impl<const T: u8>
 
 default_imp_for_create_customer!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Adyen,
     connector::Airwallex,
@@ -378,6 +395,7 @@ impl<const T: u8> services::ConnectorRedirectResponse for connector::DummyConnec
 
 default_imp_for_connector_redirect_response!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Adyen,
     connector::Bitpay,
@@ -430,6 +448,7 @@ impl<const T: u8> api::ConnectorTransactionId for connector::DummyConnector<T> {
 
 default_imp_for_connector_request_id!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Adyen,
     connector::Airwallex,
@@ -515,6 +534,7 @@ impl<const T: u8>
 
 default_imp_for_accept_dispute!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Adyen,
     connector::Airwallex,
@@ -620,6 +640,7 @@ impl<const T: u8>
 
 default_imp_for_file_upload!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Adyen,
     connector::Airwallex,
@@ -702,6 +723,7 @@ impl<const T: u8>
 
 default_imp_for_submit_evidence!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Adyen,
     connector::Airwallex,
@@ -784,6 +806,7 @@ impl<const T: u8>
 
 default_imp_for_defend_dispute!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Adyen,
     connector::Airwallex,
@@ -853,6 +876,21 @@ macro_rules! default_imp_for_pre_processing_steps{
     };
 }
 
+macro_rules! default_imp_for_post_processing_steps{
+    ($($path:ident::$connector:ident),*)=> {
+        $(
+            impl api::PaymentsPostProcessing for $path::$connector {}
+            impl
+            services::ConnectorIntegration<
+            api::PostProcessing,
+            types::PaymentsPostProcessingData,
+            types::PaymentsResponseData,
+        > for $path::$connector
+        {}
+    )*
+    };
+}
+
 #[cfg(feature = "dummy_connector")]
 impl<const T: u8> api::PaymentsPreProcessing for connector::DummyConnector<T> {}
 #[cfg(feature = "dummy_connector")]
@@ -867,6 +905,7 @@ impl<const T: u8>
 
 default_imp_for_pre_processing_steps!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Airwallex,
     connector::Authorizedotnet,
@@ -913,6 +952,75 @@ default_imp_for_pre_processing_steps!(
     connector::Zen
 );
 
+#[cfg(feature = "dummy_connector")]
+impl<const T: u8> api::PaymentsPostProcessing for connector::DummyConnector<T> {}
+#[cfg(feature = "dummy_connector")]
+impl<const T: u8>
+    services::ConnectorIntegration<
+        api::PostProcessing,
+        types::PaymentsPostProcessingData,
+        types::PaymentsResponseData,
+    > for connector::DummyConnector<T>
+{
+}
+
+default_imp_for_post_processing_steps!(
+    connector::Aci,
+    connector::Airwallex,
+    connector::Authorizedotnet,
+    connector::Bambora,
+    connector::Bitpay,
+    connector::Bluesnap,
+    connector::Boku,
+    connector::Braintree,
+    connector::Cashtocode,
+    connector::Checkout,
+    connector::Coinbase,
+    connector::Cryptopay,
+    connector::Dlocal,
+    connector::Iatapay,
+    connector::Fiserv,
+    connector::Forte,
+    connector::Globalpay,
+    connector::Globepay,
+    connector::Helcim,
+    connector::Klarna,
+    connector::Mollie,
+    connector::Multisafepay,
+    connector::Nexinets,
+    connector::Noon,
+    connector::Nuvei,
+    connector::Opayo,
+    connector::Opennode,
+    connector::Payeezy,
+    connector::Payu,
+    connector::Placetopay,
+    connector::Powertranz,
+    connector::Prophetpay,
+    connector::Rapyd,
+    connector::Riskified,
+    connector::Shift4,
+    connector::Signifyd,
+    connector::Square,
+    connector::Stax,
+    connector::Tsys,
+    connector::Volt,
+    connector::Wise,
+    connector::Worldline,
+    connector::Worldpay,
+    connector::Zen,
+    connector::Adyen,
+    connector::Bankofamerica,
+    connector::Cybersource,
+    connector::Gocardless,
+    connector::Nmi,
+    connector::Payme,
+    connector::Paypal,
+    connector::Stripe,
+    connector::Trustpay,
+    connector::Threedsecureio
+);
+
 macro_rules! default_imp_for_payouts {
     ($($path:ident::$connector:ident),*) => {
         $(
@@ -926,6 +1034,7 @@ impl<const T: u8> api::Payouts for connector::DummyConnector<T> {}
 
 default_imp_for_payouts!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Airwallex,
     connector::Authorizedotnet,
@@ -1009,6 +1118,7 @@ impl<const T: u8>
 #[cfg(feature = "payouts")]
 default_imp_for_payouts_create!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Airwallex,
     connector::Authorizedotnet,
@@ -1095,6 +1205,7 @@ impl<const T: u8>
 #[cfg(feature = "payouts")]
 default_imp_for_payouts_eligibility!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Airwallex,
     connector::Authorizedotnet,
@@ -1178,6 +1289,7 @@ impl<const T: u8>
 #[cfg(feature = "payouts")]
 default_imp_for_payouts_fulfill!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Airwallex,
     connector::Authorizedotnet,
@@ -1261,6 +1373,7 @@ impl<const T: u8>
 #[cfg(feature = "payouts")]
 default_imp_for_payouts_cancel!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Airwallex,
     connector::Authorizedotnet,
@@ -1344,6 +1457,7 @@ impl<const T: u8>
 #[cfg(feature = "payouts")]
 default_imp_for_payouts_quote!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Adyen,
     connector::Airwallex,
@@ -1428,6 +1542,7 @@ impl<const T: u8>
 #[cfg(feature = "payouts")]
 default_imp_for_payouts_recipient!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Adyen,
     connector::Airwallex,
@@ -1511,6 +1626,7 @@ impl<const T: u8>
 
 default_imp_for_approve!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Adyen,
     connector::Airwallex,
@@ -1595,6 +1711,7 @@ impl<const T: u8>
 
 default_imp_for_reject!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Adyen,
     connector::Airwallex,
@@ -1663,6 +1780,7 @@ impl<const T: u8> api::FraudCheck for connector::DummyConnector<T> {}
 
 default_imp_for_fraud_check!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Adyen,
     connector::Airwallex,
@@ -1747,6 +1865,7 @@ impl<const T: u8>
 #[cfg(feature = "frm")]
 default_imp_for_frm_sale!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Adyen,
     connector::Airwallex,
@@ -1831,6 +1950,7 @@ impl<const T: u8>
 #[cfg(feature = "frm")]
 default_imp_for_frm_checkout!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Adyen,
     connector::Airwallex,
@@ -1915,6 +2035,7 @@ impl<const T: u8>
 #[cfg(feature = "frm")]
 default_imp_for_frm_transaction!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Adyen,
     connector::Airwallex,
@@ -1999,6 +2120,7 @@ impl<const T: u8>
 #[cfg(feature = "frm")]
 default_imp_for_frm_fulfillment!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Adyen,
     connector::Airwallex,
@@ -2083,6 +2205,7 @@ impl<const T: u8>
 #[cfg(feature = "frm")]
 default_imp_for_frm_record_return!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Adyen,
     connector::Airwallex,
@@ -2165,6 +2288,7 @@ impl<const T: u8>
 
 default_imp_for_incremental_authorization!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Adyen,
     connector::Airwallex,
@@ -2246,6 +2370,7 @@ impl<const T: u8>
 }
 default_imp_for_revoking_mandates!(
     connector::Threedsecureio,
+    connector::Plaid,
     connector::Aci,
     connector::Adyen,
     connector::Airwallex,
@@ -2419,5 +2544,6 @@ default_imp_for_connector_authentication!(
     connector::Wise,
     connector::Worldline,
     connector::Worldpay,
-    connector::Zen
+    connector::Zen,
+    connector::Plaid
 );
diff --git a/crates/router/src/core/payments/flows/approve_flow.rs b/crates/router/src/core/payments/flows/approve_flow.rs
index 14b710de914..43f2f3877ce 100644
--- a/crates/router/src/core/payments/flows/approve_flow.rs
+++ b/crates/router/src/core/payments/flows/approve_flow.rs
@@ -24,6 +24,7 @@ impl
         key_store: &domain::MerchantKeyStore,
         customer: &Option<domain::Customer>,
         merchant_connector_account: &helpers::MerchantConnectorAccountType,
+        merchant_recipient_data: Option<types::MerchantRecipientData>,
     ) -> RouterResult<types::PaymentsApproveRouterData> {
         Box::pin(transformers::construct_payment_router_data::<
             api::Approve,
@@ -36,6 +37,7 @@ impl
             key_store,
             customer,
             merchant_connector_account,
+            merchant_recipient_data,
         ))
         .await
     }
diff --git a/crates/router/src/core/payments/flows/authorize_flow.rs b/crates/router/src/core/payments/flows/authorize_flow.rs
index cc2540aa221..489b3b87eaa 100644
--- a/crates/router/src/core/payments/flows/authorize_flow.rs
+++ b/crates/router/src/core/payments/flows/authorize_flow.rs
@@ -32,6 +32,7 @@ impl
         key_store: &domain::MerchantKeyStore,
         customer: &Option<domain::Customer>,
         merchant_connector_account: &helpers::MerchantConnectorAccountType,
+        merchant_recipient_data: Option<types::MerchantRecipientData>,
     ) -> RouterResult<
         types::RouterData<
             api::Authorize,
@@ -50,6 +51,7 @@ impl
             key_store,
             customer,
             merchant_connector_account,
+            merchant_recipient_data,
         ))
         .await
     }
@@ -179,6 +181,14 @@ impl Feature<api::Authorize, types::PaymentsAuthorizeData> for types::PaymentsAu
         authorize_preprocessing_steps(state, &self, true, connector).await
     }
 
+    async fn postprocessing_steps<'a>(
+        self,
+        state: &AppState,
+        connector: &api::ConnectorData,
+    ) -> RouterResult<Self> {
+        authorize_postprocessing_steps(state, &self, true, connector).await
+    }
+
     async fn create_connector_customer<'a>(
         &self,
         state: &AppState,
@@ -368,6 +378,58 @@ pub async fn authorize_preprocessing_steps<F: Clone>(
     }
 }
 
+pub async fn authorize_postprocessing_steps<F: Clone>(
+    state: &AppState,
+    router_data: &types::RouterData<F, types::PaymentsAuthorizeData, types::PaymentsResponseData>,
+    confirm: bool,
+    connector: &api::ConnectorData,
+) -> RouterResult<types::RouterData<F, types::PaymentsAuthorizeData, types::PaymentsResponseData>> {
+    if confirm {
+        let connector_integration: services::BoxedConnectorIntegration<
+            '_,
+            api::PostProcessing,
+            types::PaymentsPostProcessingData,
+            types::PaymentsResponseData,
+        > = connector.connector.get_connector_integration();
+
+        let postprocessing_request_data =
+            types::PaymentsPostProcessingData::try_from(router_data.request.to_owned())?;
+
+        let postprocessing_response_data: Result<
+            types::PaymentsResponseData,
+            types::ErrorResponse,
+        > = Err(types::ErrorResponse::default());
+
+        let postprocessing_router_data =
+            payments::helpers::router_data_type_conversion::<_, api::PostProcessing, _, _, _, _>(
+                router_data.clone(),
+                postprocessing_request_data,
+                postprocessing_response_data,
+            );
+
+        let resp = services::execute_connector_processing_step(
+            state,
+            connector_integration,
+            &postprocessing_router_data,
+            payments::CallConnectorAction::Trigger,
+            None,
+        )
+        .await
+        .to_payment_failed_response()?;
+
+        let authorize_router_data =
+            payments::helpers::router_data_type_conversion::<_, F, _, _, _, _>(
+                resp.clone(),
+                router_data.request.to_owned(),
+                resp.response,
+            );
+
+        Ok(authorize_router_data)
+    } else {
+        Ok(router_data.clone())
+    }
+}
+
 impl<F> TryFrom<&types::RouterData<F, types::PaymentsAuthorizeData, types::PaymentsResponseData>>
     for types::ConnectorCustomerData
 {
@@ -424,6 +486,29 @@ impl TryFrom<types::PaymentsAuthorizeData> for types::PaymentsPreProcessingData
     }
 }
 
+impl TryFrom<types::PaymentsAuthorizeData> for types::PaymentsPostProcessingData {
+    type Error = error_stack::Report<errors::ApiErrorResponse>;
+
+    fn try_from(data: types::PaymentsAuthorizeData) -> Result<Self, Self::Error> {
+        Ok(Self {
+            payment_method_data: data.payment_method_data,
+            amount: data.amount,
+            email: data.email,
+            currency: data.currency,
+            payment_method_type: data.payment_method_type,
+            setup_mandate_details: data.setup_mandate_details,
+            capture_method: data.capture_method,
+            order_details: data.order_details,
+            router_return_url: data.router_return_url,
+            webhook_url: data.webhook_url,
+            complete_authorize_url: data.complete_authorize_url,
+            browser_info: data.browser_info,
+            connector_transaction_id: data.related_transaction_id,
+            customer_id: data.customer_id,
+        })
+    }
+}
+
 impl TryFrom<types::CompleteAuthorizeData> for types::PaymentsPreProcessingData {
     type Error = error_stack::Report<errors::ApiErrorResponse>;
 
diff --git a/crates/router/src/core/payments/flows/cancel_flow.rs b/crates/router/src/core/payments/flows/cancel_flow.rs
index 5918380ee0b..0a6abda11ef 100644
--- a/crates/router/src/core/payments/flows/cancel_flow.rs
+++ b/crates/router/src/core/payments/flows/cancel_flow.rs
@@ -23,6 +23,7 @@ impl ConstructFlowSpecificData<api::Void, types::PaymentsCancelData, types::Paym
         key_store: &domain::MerchantKeyStore,
         customer: &Option<domain::Customer>,
         merchant_connector_account: &helpers::MerchantConnectorAccountType,
+        merchant_recipient_data: Option<types::MerchantRecipientData>,
     ) -> RouterResult<types::PaymentsCancelRouterData> {
         Box::pin(transformers::construct_payment_router_data::<
             api::Void,
@@ -35,6 +36,7 @@ impl ConstructFlowSpecificData<api::Void, types::PaymentsCancelData, types::Paym
             key_store,
             customer,
             merchant_connector_account,
+            merchant_recipient_data,
         ))
         .await
     }
diff --git a/crates/router/src/core/payments/flows/capture_flow.rs b/crates/router/src/core/payments/flows/capture_flow.rs
index d2b7c8e91bd..4d14a188922 100644
--- a/crates/router/src/core/payments/flows/capture_flow.rs
+++ b/crates/router/src/core/payments/flows/capture_flow.rs
@@ -24,6 +24,7 @@ impl
         key_store: &domain::MerchantKeyStore,
         customer: &Option<domain::Customer>,
         merchant_connector_account: &helpers::MerchantConnectorAccountType,
+        merchant_recipient_data: Option<types::MerchantRecipientData>,
     ) -> RouterResult<types::PaymentsCaptureRouterData> {
         Box::pin(transformers::construct_payment_router_data::<
             api::Capture,
@@ -36,6 +37,7 @@ impl
             key_store,
             customer,
             merchant_connector_account,
+            merchant_recipient_data,
         ))
         .await
     }
diff --git a/crates/router/src/core/payments/flows/complete_authorize_flow.rs b/crates/router/src/core/payments/flows/complete_authorize_flow.rs
index 68d0ee8d475..c2c21569703 100644
--- a/crates/router/src/core/payments/flows/complete_authorize_flow.rs
+++ b/crates/router/src/core/payments/flows/complete_authorize_flow.rs
@@ -28,6 +28,7 @@ impl
         key_store: &domain::MerchantKeyStore,
         customer: &Option<domain::Customer>,
         merchant_connector_account: &helpers::MerchantConnectorAccountType,
+        merchant_recipient_data: Option<types::MerchantRecipientData>,
     ) -> RouterResult<
         types::RouterData<
             api::CompleteAuthorize,
@@ -46,6 +47,7 @@ impl
             key_store,
             customer,
             merchant_connector_account,
+            merchant_recipient_data,
         ))
         .await
     }
diff --git a/crates/router/src/core/payments/flows/incremental_authorization_flow.rs b/crates/router/src/core/payments/flows/incremental_authorization_flow.rs
index 387916bab7c..6ab6d37a3fb 100644
--- a/crates/router/src/core/payments/flows/incremental_authorization_flow.rs
+++ b/crates/router/src/core/payments/flows/incremental_authorization_flow.rs
@@ -27,6 +27,7 @@ impl
         key_store: &domain::MerchantKeyStore,
         customer: &Option<domain::Customer>,
         merchant_connector_account: &helpers::MerchantConnectorAccountType,
+        merchant_recipient_data: Option<types::MerchantRecipientData>,
     ) -> RouterResult<types::PaymentsIncrementalAuthorizationRouterData> {
         Box::pin(transformers::construct_payment_router_data::<
             api::IncrementalAuthorization,
@@ -39,6 +40,7 @@ impl
             key_store,
             customer,
             merchant_connector_account,
+            merchant_recipient_data,
         ))
         .await
     }
diff --git a/crates/router/src/core/payments/flows/psync_flow.rs b/crates/router/src/core/payments/flows/psync_flow.rs
index cb7a764985d..1f519f14dfc 100644
--- a/crates/router/src/core/payments/flows/psync_flow.rs
+++ b/crates/router/src/core/payments/flows/psync_flow.rs
@@ -25,6 +25,7 @@ impl ConstructFlowSpecificData<api::PSync, types::PaymentsSyncData, types::Payme
         key_store: &domain::MerchantKeyStore,
         customer: &Option<domain::Customer>,
         merchant_connector_account: &helpers::MerchantConnectorAccountType,
+        merchant_recipient_data: Option<types::MerchantRecipientData>,
     ) -> RouterResult<
         types::RouterData<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>,
     > {
@@ -39,6 +40,7 @@ impl ConstructFlowSpecificData<api::PSync, types::PaymentsSyncData, types::Payme
             key_store,
             customer,
             merchant_connector_account,
+            merchant_recipient_data,
         ))
         .await
     }
diff --git a/crates/router/src/core/payments/flows/reject_flow.rs b/crates/router/src/core/payments/flows/reject_flow.rs
index 910cc955e63..679b7f398bd 100644
--- a/crates/router/src/core/payments/flows/reject_flow.rs
+++ b/crates/router/src/core/payments/flows/reject_flow.rs
@@ -23,6 +23,7 @@ impl ConstructFlowSpecificData<api::Reject, types::PaymentsRejectData, types::Pa
         key_store: &domain::MerchantKeyStore,
         customer: &Option<domain::Customer>,
         merchant_connector_account: &helpers::MerchantConnectorAccountType,
+        merchant_recipient_data: Option<types::MerchantRecipientData>,
     ) -> RouterResult<types::PaymentsRejectRouterData> {
         Box::pin(transformers::construct_payment_router_data::<
             api::Reject,
@@ -35,6 +36,7 @@ impl ConstructFlowSpecificData<api::Reject, types::PaymentsRejectData, types::Pa
             key_store,
             customer,
             merchant_connector_account,
+            merchant_recipient_data,
         ))
         .await
     }
diff --git a/crates/router/src/core/payments/flows/session_flow.rs b/crates/router/src/core/payments/flows/session_flow.rs
index e29b66ea0ca..8a54a2a8b79 100644
--- a/crates/router/src/core/payments/flows/session_flow.rs
+++ b/crates/router/src/core/payments/flows/session_flow.rs
@@ -30,6 +30,7 @@ impl
         key_store: &domain::MerchantKeyStore,
         customer: &Option<domain::Customer>,
         merchant_connector_account: &helpers::MerchantConnectorAccountType,
+        merchant_recipient_data: Option<types::MerchantRecipientData>,
     ) -> RouterResult<types::PaymentsSessionRouterData> {
         Box::pin(transformers::construct_payment_router_data::<
             api::Session,
@@ -42,6 +43,7 @@ impl
             key_store,
             customer,
             merchant_connector_account,
+            merchant_recipient_data,
         ))
         .await
     }
diff --git a/crates/router/src/core/payments/flows/setup_mandate_flow.rs b/crates/router/src/core/payments/flows/setup_mandate_flow.rs
index 71d43989336..a3757975186 100644
--- a/crates/router/src/core/payments/flows/setup_mandate_flow.rs
+++ b/crates/router/src/core/payments/flows/setup_mandate_flow.rs
@@ -34,6 +34,7 @@ impl
         key_store: &domain::MerchantKeyStore,
         customer: &Option<domain::Customer>,
         merchant_connector_account: &helpers::MerchantConnectorAccountType,
+        merchant_recipient_data: Option<types::MerchantRecipientData>,
     ) -> RouterResult<types::SetupMandateRouterData> {
         Box::pin(transformers::construct_payment_router_data::<
             api::SetupMandate,
@@ -46,6 +47,7 @@ impl
             key_store,
             customer,
             merchant_connector_account,
+            merchant_recipient_data,
         ))
         .await
     }
diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs
index a60fae4f579..f8917d37c4e 100644
--- a/crates/router/src/core/payments/helpers.rs
+++ b/crates/router/src/core/payments/helpers.rs
@@ -49,7 +49,7 @@ use crate::{
         },
         storage::{self, enums as storage_enums, ephemeral_key, CustomerUpdate::Update},
         transformers::{ForeignFrom, ForeignTryFrom},
-        ErrorResponse, MandateReference, RouterData,
+        ConnectorAuthType, ErrorResponse, MandateReference, MerchantRecipientData, RouterData,
     },
     utils::{
         self,
@@ -2021,6 +2021,7 @@ pub fn validate_payment_method_type_against_payment_method(
                 | api_enums::PaymentMethodType::Bizum
                 | api_enums::PaymentMethodType::Interac
                 | api_enums::PaymentMethodType::OpenBankingUk
+                | api_enums::PaymentMethodType::OpenBanking
         ),
         api_enums::PaymentMethod::BankTransfer => matches!(
             payment_method_type,
@@ -4007,3 +4008,19 @@ pub fn validate_mandate_data_and_future_usage(
         Ok(())
     }
 }
+
+pub fn get_recipient_id_from_open_banking_auth(
+    auth: &ConnectorAuthType,
+) -> Result<Option<String>, errors::ApiErrorResponse> {
+    match auth {
+        ConnectorAuthType::OpenBankingAuth {
+            api_key: _,
+            key1: _,
+            merchant_data,
+        } => match merchant_data {
+            MerchantRecipientData::RecipientId(id) => Ok(Some(id.peek().to_string())),
+            _ => Err(errors::ApiErrorResponse::InternalServerError),
+        },
+        _ => Ok(None),
+    }
+}
diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs
index 33e8ff26edc..eae82e94d32 100644
--- a/crates/router/src/core/payments/operations/payment_response.rs
+++ b/crates/router/src/core/payments/operations/payment_response.rs
@@ -703,6 +703,7 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
                 types::PaymentsResponseData::IncrementalAuthorizationResponse { .. } => {
                     (None, None)
                 }
+                types::PaymentsResponseData::PostProcessingResponse { .. } => (None, None),
                 types::PaymentsResponseData::MultipleCaptureResponse {
                     capture_sync_response_list,
                 } => match payment_data.multiple_capture_data {
diff --git a/crates/router/src/core/payments/retry.rs b/crates/router/src/core/payments/retry.rs
index 91b6061c111..87bb22f454f 100644
--- a/crates/router/src/core/payments/retry.rs
+++ b/crates/router/src/core/payments/retry.rs
@@ -302,7 +302,7 @@ where
     )
     .await?;
 
-    payments::call_connector_service(
+    let (router_data, _mca) = payments::call_connector_service(
         state,
         merchant_account,
         key_store,
@@ -316,7 +316,9 @@ where
         api::HeaderPayload::default(),
         frm_suggestion,
     )
-    .await
+    .await?;
+
+    Ok(router_data)
 }
 
 #[instrument(skip_all)]
diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs
index 9dd7df66fa6..8e15e6ba61e 100644
--- a/crates/router/src/core/payments/transformers.rs
+++ b/crates/router/src/core/payments/transformers.rs
@@ -29,6 +29,7 @@ use crate::{
 };
 
 #[instrument(skip_all)]
+#[allow(clippy::too_many_arguments)]
 pub async fn construct_payment_router_data<'a, F, T>(
     state: &'a AppState,
     payment_data: PaymentData<F>,
@@ -37,6 +38,7 @@ pub async fn construct_payment_router_data<'a, F, T>(
     _key_store: &domain::MerchantKeyStore,
     customer: &'a Option<domain::Customer>,
     merchant_connector_account: &helpers::MerchantConnectorAccountType,
+    merchant_recipient_data: Option<types::MerchantRecipientData>,
 ) -> RouterResult<types::RouterData<F, T, types::PaymentsResponseData>>
 where
     T: TryFrom<PaymentAdditionalData<'a, F>>,
@@ -141,7 +143,15 @@ where
             .payment_attempt
             .authentication_type
             .unwrap_or_default(),
-        connector_meta_data: merchant_connector_account.get_metadata(),
+        connector_meta_data: if let Some(data) = merchant_recipient_data {
+            let val = serde_json::to_value(data)
+                .into_report()
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("Failed while encoding MerchantRecipientDatas")?;
+            Some(masking::Secret::new(val))
+        } else {
+            merchant_connector_account.get_metadata()
+        },
         request: T::try_from(additional_data)?,
         response,
         amount_captured: payment_data.payment_intent.amount_captured,
@@ -820,7 +830,7 @@ where
 {
     // If the operation is confirm, we will send session token response in next action
     if format!("{operation:?}").eq("PaymentConfirm") {
-        payment_attempt
+        let condition1 = payment_attempt
             .connector
             .as_ref()
             .map(|connector| {
@@ -835,7 +845,35 @@ where
                     Some(false)
                 }
             })
-            .unwrap_or(false)
+            .unwrap_or(false);
+
+        let condition2 = payment_attempt
+            .connector
+            .as_ref()
+            .map(|connector| matches!(connector.as_str(), "plaid"))
+            .and_then(|is_connector_supports_third_party_sdk| {
+                if is_connector_supports_third_party_sdk {
+                    payment_attempt
+                        .payment_method
+                        .map(|pm| matches!(pm, diesel_models::enums::PaymentMethod::BankRedirect))
+                        .and_then(|first_match| {
+                            payment_attempt
+                                .payment_method_type
+                                .map(|pmt| {
+                                    matches!(
+                                        pmt,
+                                        diesel_models::enums::PaymentMethodType::OpenBanking
+                                    )
+                                })
+                                .map(|second_match| first_match && second_match)
+                        })
+                } else {
+                    Some(false)
+                }
+            })
+            .unwrap_or(false);
+
+        condition1 || condition2
     } else {
         false
     }
@@ -1112,6 +1150,13 @@ impl<F: Clone> TryFrom<PaymentAdditionalData<'_, F>> for types::PaymentsAuthoriz
                     .map(|customer| customer.clone().into_inner())
             });
 
+        let customer_id = additional_data
+            .customer_data
+            .as_ref()
+            .map(|data| data.customer_id.clone());
+
+        let conn_transaction_id = payment_data.payment_attempt.connector_transaction_id;
+
         Ok(Self {
             payment_method_data: payment_method_data.get_required_value("payment_method_data")?,
             setup_future_usage: payment_data.payment_intent.setup_future_usage,
@@ -1132,12 +1177,12 @@ impl<F: Clone> TryFrom<PaymentAdditionalData<'_, F>> for types::PaymentsAuthoriz
             order_category,
             session_token: None,
             enrolled_for_3ds: true,
-            related_transaction_id: None,
+            related_transaction_id: conn_transaction_id,
             payment_method_type: payment_data.payment_attempt.payment_method_type,
             router_return_url,
             webhook_url,
             complete_authorize_url,
-            customer_id: None,
+            customer_id,
             surcharge_details: payment_data.surcharge_details,
             request_incremental_authorization: matches!(
                 payment_data
diff --git a/crates/router/src/core/pm_auth.rs b/crates/router/src/core/pm_auth.rs
index 21ba27eac17..125f4b294a5 100644
--- a/crates/router/src/core/pm_auth.rs
+++ b/crates/router/src/core/pm_auth.rs
@@ -197,8 +197,18 @@ impl ForeignTryFrom<&types::ConnectorAuthType> for PlaidAuthType {
                 Ok::<Self, errors::ConnectorError>(Self {
                     client_id: api_key.to_owned(),
                     secret: key1.to_owned(),
+                    merchant_data: None,
                 })
             }
+            types::ConnectorAuthType::OpenBankingAuth {
+                api_key,
+                key1,
+                merchant_data,
+            } => Ok::<Self, errors::ConnectorError>(Self {
+                client_id: api_key.to_owned(),
+                secret: key1.to_owned(),
+                merchant_data: Some(merchant_data.clone().into()),
+            }),
             _ => Err(errors::ConnectorError::FailedToObtainAuthType),
         }
     }
diff --git a/crates/router/src/core/pm_auth/transformers.rs b/crates/router/src/core/pm_auth/transformers.rs
index 8a1369c2e02..3209ec95353 100644
--- a/crates/router/src/core/pm_auth/transformers.rs
+++ b/crates/router/src/core/pm_auth/transformers.rs
@@ -2,6 +2,33 @@ use pm_auth::types::{self as pm_auth_types};
 
 use crate::{core::errors, types, types::transformers::ForeignTryFrom};
 
+impl From<types::MerchantAccountData> for pm_auth_types::MerchantAccountData {
+    fn from(from: types::MerchantAccountData) -> Self {
+        match from {
+            types::MerchantAccountData::Iban { iban, name } => Self::Iban { iban, name },
+            types::MerchantAccountData::Bacs {
+                account_number,
+                sort_code,
+                name,
+            } => Self::Bacs {
+                account_number,
+                sort_code,
+                name,
+            },
+        }
+    }
+}
+
+impl From<types::MerchantRecipientData> for pm_auth_types::MerchantRecipientData {
+    fn from(value: types::MerchantRecipientData) -> Self {
+        match value {
+            types::MerchantRecipientData::RecipientId(id) => Self::RecipientId(id),
+            types::MerchantRecipientData::WalletId(id) => Self::WalletId(id),
+            types::MerchantRecipientData::AccountData(data) => Self::AccountData(data.into()),
+        }
+    }
+}
+
 impl ForeignTryFrom<types::ConnectorAuthType> for pm_auth_types::ConnectorAuthType {
     type Error = errors::ConnectorError;
     fn foreign_try_from(auth_type: types::ConnectorAuthType) -> Result<Self, Self::Error> {
@@ -12,6 +39,15 @@ impl ForeignTryFrom<types::ConnectorAuthType> for pm_auth_types::ConnectorAuthTy
                     secret: key1.to_owned(),
                 })
             }
+            types::ConnectorAuthType::OpenBankingAuth {
+                api_key,
+                key1,
+                merchant_data,
+            } => Ok::<Self, errors::ConnectorError>(Self::OpenBankingAuth {
+                api_key,
+                key1,
+                merchant_data: merchant_data.into(),
+            }),
             _ => Err(errors::ConnectorError::FailedToObtainAuthType),
         }
     }
diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs
index 5b609b072c1..76147753366 100644
--- a/crates/router/src/types.rs
+++ b/crates/router/src/types.rs
@@ -49,6 +49,8 @@ pub type PaymentsAuthorizeRouterData =
     RouterData<api::Authorize, PaymentsAuthorizeData, PaymentsResponseData>;
 pub type PaymentsPreProcessingRouterData =
     RouterData<api::PreProcessing, PaymentsPreProcessingData, PaymentsResponseData>;
+pub type PaymentsPostProcessingRouterData =
+    RouterData<api::PostProcessing, PaymentsPostProcessingData, PaymentsResponseData>;
 pub type PaymentsAuthorizeSessionTokenRouterData =
     RouterData<api::AuthorizeSessionToken, AuthorizeSessionTokenData, PaymentsResponseData>;
 pub type PaymentsCompleteAuthorizeRouterData =
@@ -130,6 +132,11 @@ pub type PaymentsPreProcessingType = dyn services::ConnectorIntegration<
     PaymentsPreProcessingData,
     PaymentsResponseData,
 >;
+pub type PaymentsPostProcessingType = dyn services::ConnectorIntegration<
+    api::PostProcessing,
+    PaymentsPostProcessingData,
+    PaymentsResponseData,
+>;
 pub type PaymentsCompleteAuthorizeType = dyn services::ConnectorIntegration<
     api::CompleteAuthorize,
     CompleteAuthorizeData,
@@ -501,6 +508,24 @@ pub struct PaymentsPreProcessingData {
     pub redirect_response: Option<CompleteAuthorizeRedirectResponse>,
 }
 
+#[derive(Debug, Clone)]
+pub struct PaymentsPostProcessingData {
+    pub payment_method_data: payments::PaymentMethodData,
+    pub amount: i64,
+    pub email: Option<Email>,
+    pub customer_id: Option<String>,
+    pub currency: storage_enums::Currency,
+    pub payment_method_type: Option<storage_enums::PaymentMethodType>,
+    pub setup_mandate_details: Option<MandateData>,
+    pub capture_method: Option<storage_enums::CaptureMethod>,
+    pub order_details: Option<Vec<api_models::payments::OrderDetailsWithAmount>>,
+    pub router_return_url: Option<String>,
+    pub webhook_url: Option<String>,
+    pub complete_authorize_url: Option<String>,
+    pub browser_info: Option<BrowserInformation>,
+    pub connector_transaction_id: Option<String>,
+}
+
 #[derive(Debug, Clone)]
 pub struct CompleteAuthorizeData {
     pub payment_method_data: Option<payments::PaymentMethodData>,
@@ -931,6 +956,9 @@ pub enum PaymentsResponseData {
         error_code: Option<String>,
         error_message: Option<String>,
     },
+    PostProcessingResponse {
+        session_token: Option<api::OpenBankingSessionToken>,
+    },
 }
 
 #[derive(Debug, Clone)]
@@ -1150,6 +1178,88 @@ pub struct MandateRevokeResponseData {
     pub mandate_status: MandateStatus,
 }
 
+#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
+#[serde(rename_all = "snake_case")]
+pub enum MerchantAccountData {
+    Iban {
+        iban: Secret<String>,
+        name: String,
+    },
+    Bacs {
+        account_number: Secret<String>,
+        sort_code: Secret<String>,
+        name: String,
+    },
+}
+
+impl ForeignFrom<MerchantAccountData> for api_models::admin::MerchantAccountData {
+    fn foreign_from(from: MerchantAccountData) -> Self {
+        match from {
+            MerchantAccountData::Iban { iban, name } => Self::Iban { iban, name },
+            MerchantAccountData::Bacs {
+                account_number,
+                sort_code,
+                name,
+            } => Self::Bacs {
+                account_number,
+                sort_code,
+                name,
+            },
+        }
+    }
+}
+
+impl From<api_models::admin::MerchantAccountData> for MerchantAccountData {
+    fn from(from: api_models::admin::MerchantAccountData) -> Self {
+        match from {
+            api_models::admin::MerchantAccountData::Iban { iban, name } => {
+                Self::Iban { iban, name }
+            }
+            api_models::admin::MerchantAccountData::Bacs {
+                account_number,
+                sort_code,
+                name,
+            } => Self::Bacs {
+                account_number,
+                sort_code,
+                name,
+            },
+        }
+    }
+}
+
+#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
+#[serde(rename_all = "snake_case")]
+pub enum MerchantRecipientData {
+    RecipientId(Secret<String>),
+    WalletId(Secret<String>),
+    AccountData(MerchantAccountData),
+}
+
+impl ForeignFrom<MerchantRecipientData> for api_models::admin::MerchantRecipientData {
+    fn foreign_from(value: MerchantRecipientData) -> Self {
+        match value {
+            MerchantRecipientData::RecipientId(id) => Self::RecipientId(id),
+            MerchantRecipientData::WalletId(id) => Self::WalletId(id),
+            MerchantRecipientData::AccountData(data) => {
+                Self::AccountData(api_models::admin::MerchantAccountData::foreign_from(data))
+            }
+        }
+    }
+}
+
+impl From<api_models::admin::MerchantRecipientData> for MerchantRecipientData {
+    fn from(value: api_models::admin::MerchantRecipientData) -> Self {
+        match value {
+            api_models::admin::MerchantRecipientData::RecipientId(id) => Self::RecipientId(id),
+            api_models::admin::MerchantRecipientData::WalletId(id) => Self::WalletId(id),
+            api_models::admin::MerchantRecipientData::AccountData(data) => {
+                Self::AccountData(data.into())
+            }
+        }
+    }
+}
+
 // Different patterns of authentication.
 #[derive(Default, Debug, Clone, serde::Deserialize, serde::Serialize)]
 #[serde(tag = "auth_type")]
@@ -1176,6 +1286,11 @@ pub enum ConnectorAuthType {
     CurrencyAuthKey {
         auth_key_map: HashMap<storage_enums::Currency, pii::SecretSerdeValue>,
     },
+    OpenBankingAuth {
+        api_key: Secret<String>,
+        key1: Secret<String>,
+        merchant_data: MerchantRecipientData,
+    },
     #[default]
     NoKey,
 }
@@ -1214,6 +1329,15 @@ impl From<api_models::admin::ConnectorAuthType> for ConnectorAuthType {
                 Self::CurrencyAuthKey { auth_key_map }
             }
             api_models::admin::ConnectorAuthType::NoKey => Self::NoKey,
+            api_models::admin::ConnectorAuthType::OpenBankingAuth {
+                api_key,
+                key1,
+                merchant_data,
+            } => Self::OpenBankingAuth {
+                api_key,
+                key1,
+                merchant_data: merchant_data.into(),
+            },
         }
     }
 }
@@ -1248,6 +1372,17 @@ impl ForeignFrom<ConnectorAuthType> for api_models::admin::ConnectorAuthType {
                 Self::CurrencyAuthKey { auth_key_map }
             }
             ConnectorAuthType::NoKey => Self::NoKey,
+            ConnectorAuthType::OpenBankingAuth {
+                api_key,
+                key1,
+                merchant_data,
+            } => Self::OpenBankingAuth {
+                api_key,
+                key1,
+                merchant_data: api_models::admin::MerchantRecipientData::foreign_from(
+                    merchant_data,
+                ),
+            },
         }
     }
 }
diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs
index 50d256b034b..786228ba484 100644
--- a/crates/router/src/types/api.rs
+++ b/crates/router/src/types/api.rs
@@ -363,6 +363,7 @@ impl ConnectorData {
                 enums::Connector::Payme => Ok(Box::new(&connector::Payme)),
                 enums::Connector::Payu => Ok(Box::new(&connector::Payu)),
                 enums::Connector::Placetopay => Ok(Box::new(&connector::Placetopay)),
+                enums::Connector::Plaid => Ok(Box::new(&connector::Plaid)),
                 enums::Connector::Powertranz => Ok(Box::new(&connector::Powertranz)),
                 enums::Connector::Prophetpay => Ok(Box::new(&connector::Prophetpay)),
                 enums::Connector::Rapyd => Ok(Box::new(&connector::Rapyd)),
@@ -381,7 +382,6 @@ impl ConnectorData {
                 enums::Connector::Volt => Ok(Box::new(&connector::Volt)),
                 enums::Connector::Zen => Ok(Box::new(&connector::Zen)),
                 enums::Connector::Signifyd
-                | enums::Connector::Plaid
                 | enums::Connector::Riskified
                 | enums::Connector::Threedsecureio => {
                     Err(report!(errors::ConnectorError::InvalidConnectorName)
diff --git a/crates/router/src/types/api/payments.rs b/crates/router/src/types/api/payments.rs
index 8e13f6c9935..48164e94000 100644
--- a/crates/router/src/types/api/payments.rs
+++ b/crates/router/src/types/api/payments.rs
@@ -2,16 +2,16 @@ pub use api_models::payments::{
     AcceptanceType, Address, AddressDetails, Amount, AuthenticationForStartResponse, Card,
     CryptoData, CustomerAcceptance, HeaderPayload, MandateAmountData, MandateData,
     MandateTransactionType, MandateType, MandateValidationFields, NextActionType, OnlineMandate,
-    PayLaterData, PaymentIdType, PaymentListConstraints, PaymentListFilterConstraints,
-    PaymentListFilters, PaymentListResponse, PaymentListResponseV2, PaymentMethodData,
-    PaymentMethodDataRequest, PaymentMethodDataResponse, PaymentOp, PaymentRetrieveBody,
-    PaymentRetrieveBodyWithCredentials, PaymentsApproveRequest, PaymentsCancelRequest,
-    PaymentsCaptureRequest, PaymentsExternalAuthenticationRequest,
+    OpenBankingSessionToken, PayLaterData, PaymentIdType, PaymentListConstraints,
+    PaymentListFilterConstraints, PaymentListFilters, PaymentListResponse, PaymentListResponseV2,
+    PaymentMethodData, PaymentMethodDataRequest, PaymentMethodDataResponse, PaymentOp,
+    PaymentRetrieveBody, PaymentRetrieveBodyWithCredentials, PaymentsApproveRequest,
+    PaymentsCancelRequest, PaymentsCaptureRequest, PaymentsExternalAuthenticationRequest,
     PaymentsIncrementalAuthorizationRequest, PaymentsRedirectRequest, PaymentsRedirectionResponse,
     PaymentsRejectRequest, PaymentsRequest, PaymentsResponse, PaymentsResponseForm,
     PaymentsRetrieveRequest, PaymentsSessionRequest, PaymentsSessionResponse, PaymentsStartRequest,
-    PgRedirectResponse, PhoneDetails, RedirectionResponse, SessionToken, TimeRange, UrlDetails,
-    VerifyRequest, VerifyResponse, WalletData,
+    PgRedirectResponse, PhoneDetails, RedirectionResponse, SessionToken, SessionTokenType,
+    TimeRange, UrlDetails, VerifyRequest, VerifyResponse, WalletData,
 };
 use error_stack::{IntoReport, ResultExt};
 
@@ -83,6 +83,9 @@ pub struct SetupMandate;
 #[derive(Debug, Clone)]
 pub struct PreProcessing;
 
+#[derive(Debug, Clone)]
+pub struct PostProcessing;
+
 #[derive(Debug, Clone)]
 pub struct IncrementalAuthorization;
 
@@ -214,6 +217,15 @@ pub trait PaymentsPreProcessing:
 {
 }
 
+pub trait PaymentsPostProcessing:
+    api::ConnectorIntegration<
+    PostProcessing,
+    types::PaymentsPostProcessingData,
+    types::PaymentsResponseData,
+>
+{
+}
+
 pub trait Payment:
     api_types::ConnectorCommon
     + api_types::ConnectorValidation
@@ -228,6 +240,7 @@ pub trait Payment:
     + PaymentSession
     + PaymentToken
     + PaymentsPreProcessing
+    + PaymentsPostProcessing
     + ConnectorCustomer
     + PaymentIncrementalAuthorization
 {
diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs
index 29f924fc65b..3c0b424c94c 100644
--- a/crates/router/src/types/transformers.rs
+++ b/crates/router/src/types/transformers.rs
@@ -216,12 +216,7 @@ impl ForeignTryFrom<api_enums::Connector> for common_enums::RoutableConnectors {
             api_enums::Connector::Paypal => Self::Paypal,
             api_enums::Connector::Payu => Self::Payu,
             api_models::enums::Connector::Placetopay => Self::Placetopay,
-            api_enums::Connector::Plaid => {
-                Err(common_utils::errors::ValidationError::InvalidValue {
-                    message: "plaid is not a routable connector".to_string(),
-                })
-                .into_report()?
-            }
+            api_enums::Connector::Plaid => Self::Plaid,
             api_enums::Connector::Powertranz => Self::Powertranz,
             api_enums::Connector::Prophetpay => Self::Prophetpay,
             api_enums::Connector::Rapyd => Self::Rapyd,
@@ -417,6 +412,7 @@ impl ForeignFrom<api_enums::PaymentMethodType> for api_enums::PaymentMethod {
             | api_enums::PaymentMethodType::OnlineBankingPoland
             | api_enums::PaymentMethodType::OnlineBankingSlovakia
             | api_enums::PaymentMethodType::OpenBankingUk
+            | api_enums::PaymentMethodType::OpenBanking
             | api_enums::PaymentMethodType::Przelewy24
             | api_enums::PaymentMethodType::Trustly
             | api_enums::PaymentMethodType::Bizum
diff --git a/crates/router/tests/connectors/main.rs b/crates/router/tests/connectors/main.rs
index 8db743d6098..c69158bc293 100644
--- a/crates/router/tests/connectors/main.rs
+++ b/crates/router/tests/connectors/main.rs
@@ -46,6 +46,7 @@ mod payme;
 mod paypal;
 mod payu;
 mod placetopay;
+mod plaid;
 mod powertranz;
 #[cfg(feature = "dummy_connector")]
 mod prophetpay;
diff --git a/crates/router/tests/connectors/plaid.rs b/crates/router/tests/connectors/plaid.rs
new file mode 100644
index 00000000000..d54d3cd6772
--- /dev/null
+++ b/crates/router/tests/connectors/plaid.rs
@@ -0,0 +1,423 @@
+use masking::Secret;
+use router::{
+    core::utils as core_utils,
+    types::{self, api, storage::enums},
+};
+use test_utils::connector_auth;
+
+use crate::utils::{self, ConnectorActions};
+
+#[derive(Clone, Copy)]
+struct PlaidTest;
+impl ConnectorActions for PlaidTest {}
+impl utils::Connector for PlaidTest {
+    fn get_data(&self) -> types::api::ConnectorData {
+        use router::connector::Plaid;
+        types::api::ConnectorData {
+            connector: Box::new(&Plaid),
+            connector_name: types::Connector::Plaid,
+            get_token: types::api::GetToken::Connector,
+            merchant_connector_id: None,
+        }
+    }
+
+    fn get_auth_token(&self) -> types::ConnectorAuthType {
+        utils::to_connector_auth_type(
+            connector_auth::ConnectorAuthentication::new()
+                .plaid
+                .expect("Missing connector authentication configuration")
+                .into(),
+        )
+    }
+
+    fn get_name(&self) -> String {
+        "plaid".to_string()
+    }
+}
+
+static CONNECTOR: PlaidTest = PlaidTest {};
+
+fn get_default_payment_info() -> Option<utils::PaymentInfo> {
+    None
+}
+
+fn payment_method_details() -> Option<types::PaymentsAuthorizeData> {
+    None
+}
+
+// Cards Positive Tests
+// Creates a payment using the manual capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_only_authorize_payment() {
+    let response = CONNECTOR
+        .authorize_payment(payment_method_details(), get_default_payment_info())
+        .await
+        .expect("Authorize payment response");
+    assert_eq!(response.status, enums::AttemptStatus::Authorized);
+}
+
+// Captures a payment using the manual capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_capture_authorized_payment() {
+    let response = CONNECTOR
+        .authorize_and_capture_payment(payment_method_details(), None, get_default_payment_info())
+        .await
+        .expect("Capture payment response");
+    assert_eq!(response.status, enums::AttemptStatus::Charged);
+}
+
+// Partially captures a payment using the manual capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_partially_capture_authorized_payment() {
+    let response = CONNECTOR
+        .authorize_and_capture_payment(
+            payment_method_details(),
+            Some(types::PaymentsCaptureData {
+                amount_to_capture: 50,
+                ..utils::PaymentCaptureType::default().0
+            }),
+            get_default_payment_info(),
+        )
+        .await
+        .expect("Capture payment response");
+    assert_eq!(response.status, enums::AttemptStatus::Charged);
+}
+
+// Synchronizes a payment using the manual capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_sync_authorized_payment() {
+    let authorize_response = CONNECTOR
+        .authorize_payment(payment_method_details(), get_default_payment_info())
+        .await
+        .expect("Authorize payment response");
+    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
+    let response = CONNECTOR
+        .psync_retry_till_status_matches(
+            enums::AttemptStatus::Authorized,
+            Some(types::PaymentsSyncData {
+                connector_transaction_id: router::types::ResponseId::ConnectorTransactionId(
+                    txn_id.unwrap(),
+                ),
+                ..Default::default()
+            }),
+            get_default_payment_info(),
+        )
+        .await
+        .expect("PSync response");
+    assert_eq!(response.status, enums::AttemptStatus::Authorized,);
+}
+
+// Voids a payment using the manual capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_void_authorized_payment() {
+    let response = CONNECTOR
+        .authorize_and_void_payment(
+            payment_method_details(),
+            Some(types::PaymentsCancelData {
+                connector_transaction_id: String::from(""),
+                cancellation_reason: Some("requested_by_customer".to_string()),
+                ..Default::default()
+            }),
+            get_default_payment_info(),
+        )
+        .await
+        .expect("Void payment response");
+    assert_eq!(response.status, enums::AttemptStatus::Voided);
+}
+
+// Refunds a payment using the manual capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_refund_manually_captured_payment() {
+    let response = CONNECTOR
+        .capture_payment_and_refund(
+            payment_method_details(),
+            None,
+            None,
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap().refund_status,
+        enums::RefundStatus::Success,
+    );
+}
+
+// Partially refunds a payment using the manual capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_partially_refund_manually_captured_payment() {
+    let response = CONNECTOR
+        .capture_payment_and_refund(
+            payment_method_details(),
+            None,
+            Some(types::RefundsData {
+                refund_amount: 50,
+                ..utils::PaymentRefundType::default().0
+            }),
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap().refund_status,
+        enums::RefundStatus::Success,
+    );
+}
+
+// Synchronizes a refund using the manual capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_sync_manually_captured_refund() {
+    let refund_response = CONNECTOR
+        .capture_payment_and_refund(
+            payment_method_details(),
+            None,
+            None,
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    let response = CONNECTOR
+        .rsync_retry_till_status_matches(
+            enums::RefundStatus::Success,
+            refund_response.response.unwrap().connector_refund_id,
+            None,
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap().refund_status,
+        enums::RefundStatus::Success,
+    );
+}
+
+// Creates a payment using the automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_make_payment() {
+    let authorize_response = CONNECTOR
+        .make_payment(payment_method_details(), get_default_payment_info())
+        .await
+        .unwrap();
+    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
+}
+
+// Synchronizes a payment using the automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_sync_auto_captured_payment() {
+    let authorize_response = CONNECTOR
+        .make_payment(payment_method_details(), get_default_payment_info())
+        .await
+        .unwrap();
+    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
+    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
+    assert_ne!(txn_id, None, "Empty connector transaction id");
+    let response = CONNECTOR
+        .psync_retry_till_status_matches(
+            enums::AttemptStatus::Charged,
+            Some(types::PaymentsSyncData {
+                connector_transaction_id: router::types::ResponseId::ConnectorTransactionId(
+                    txn_id.unwrap(),
+                ),
+                capture_method: Some(enums::CaptureMethod::Automatic),
+                ..Default::default()
+            }),
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    assert_eq!(response.status, enums::AttemptStatus::Charged,);
+}
+
+// Refunds a payment using the automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_refund_auto_captured_payment() {
+    let response = CONNECTOR
+        .make_payment_and_refund(payment_method_details(), None, get_default_payment_info())
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap().refund_status,
+        enums::RefundStatus::Success,
+    );
+}
+
+// Partially refunds a payment using the automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_partially_refund_succeeded_payment() {
+    let refund_response = CONNECTOR
+        .make_payment_and_refund(
+            payment_method_details(),
+            Some(types::RefundsData {
+                refund_amount: 50,
+                ..utils::PaymentRefundType::default().0
+            }),
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        refund_response.response.unwrap().refund_status,
+        enums::RefundStatus::Success,
+    );
+}
+
+// Creates multiple refunds against a payment using the automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_refund_succeeded_payment_multiple_times() {
+    CONNECTOR
+        .make_payment_and_multiple_refund(
+            payment_method_details(),
+            Some(types::RefundsData {
+                refund_amount: 50,
+                ..utils::PaymentRefundType::default().0
+            }),
+            get_default_payment_info(),
+        )
+        .await;
+}
+
+// Synchronizes a refund using the automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_sync_refund() {
+    let refund_response = CONNECTOR
+        .make_payment_and_refund(payment_method_details(), None, get_default_payment_info())
+        .await
+        .unwrap();
+    let response = CONNECTOR
+        .rsync_retry_till_status_matches(
+            enums::RefundStatus::Success,
+            refund_response.response.unwrap().connector_refund_id,
+            None,
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap().refund_status,
+        enums::RefundStatus::Success,
+    );
+}
+
+// Cards Negative scenerios
+// Creates a payment with incorrect CVC.
+#[actix_web::test]
+async fn should_fail_payment_for_incorrect_cvc() {
+    let response = CONNECTOR
+        .make_payment(
+            Some(types::PaymentsAuthorizeData {
+                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
+                    card_cvc: Secret::new("12345".to_string()),
+                    ..utils::CCardType::default().0
+                }),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap_err().message,
+        "Your card's security code is invalid.".to_string(),
+    );
+}
+
+// Creates a payment with incorrect expiry month.
+#[actix_web::test]
+async fn should_fail_payment_for_invalid_exp_month() {
+    let response = CONNECTOR
+        .make_payment(
+            Some(types::PaymentsAuthorizeData {
+                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
+                    card_exp_month: Secret::new("20".to_string()),
+                    ..utils::CCardType::default().0
+                }),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap_err().message,
+        "Your card's expiration month is invalid.".to_string(),
+    );
+}
+
+// Creates a payment with incorrect expiry year.
+#[actix_web::test]
+async fn should_fail_payment_for_incorrect_expiry_year() {
+    let response = CONNECTOR
+        .make_payment(
+            Some(types::PaymentsAuthorizeData {
+                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
+                    card_exp_year: Secret::new("2000".to_string()),
+                    ..utils::CCardType::default().0
+                }),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap_err().message,
+        "Your card's expiration year is invalid.".to_string(),
+    );
+}
+
+// Voids a payment using automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_fail_void_payment_for_auto_capture() {
+    let authorize_response = CONNECTOR
+        .make_payment(payment_method_details(), get_default_payment_info())
+        .await
+        .unwrap();
+    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
+    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
+    assert_ne!(txn_id, None, "Empty connector transaction id");
+    let void_response = CONNECTOR
+        .void_payment(txn_id.unwrap(), None, get_default_payment_info())
+        .await
+        .unwrap();
+    assert_eq!(
+        void_response.response.unwrap_err().message,
+        "You cannot cancel this PaymentIntent because it has a status of succeeded."
+    );
+}
+
+// Captures a payment using invalid connector payment id.
+#[actix_web::test]
+async fn should_fail_capture_for_invalid_payment() {
+    let capture_response = CONNECTOR
+        .capture_payment("123456789".to_string(), None, get_default_payment_info())
+        .await
+        .unwrap();
+    assert_eq!(
+        capture_response.response.unwrap_err().message,
+        String::from("No such payment_intent: '123456789'")
+    );
+}
+
+// Refunds a payment with refund amount higher than payment amount.
+#[actix_web::test]
+async fn should_fail_for_refund_amount_higher_than_payment_amount() {
+    let response = CONNECTOR
+        .make_payment_and_refund(
+            payment_method_details(),
+            Some(types::RefundsData {
+                refund_amount: 150,
+                ..utils::PaymentRefundType::default().0
+            }),
+            get_default_payment_info(),
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap_err().message,
+        "Refund amount (₹1.50) is greater than charge amount (₹1.00)",
+    );
+}
+
+// Connector dependent test cases goes here
+
+// [#478]: add unit tests for non 3DS, wallets & webhooks in connector tests
diff --git a/crates/router/tests/connectors/sample_auth.toml b/crates/router/tests/connectors/sample_auth.toml
index 3f78ff7f491..5e00249dc10 100644
--- a/crates/router/tests/connectors/sample_auth.toml
+++ b/crates/router/tests/connectors/sample_auth.toml
@@ -119,38 +119,38 @@ api_secret = "Application Identifier"
 key1 = "Business Identifier"
 
 [opayo]
-api_key="API Key"
+api_key = "API Key"
 
 [wise]
 api_key = "API Key"
 key1 = "Profile ID"
 
 [automation_configs]
-hs_base_url="http://localhost:8080"
-hs_test_browser="firefox"
-chrome_profile_path=""
-firefox_profile_path=""
-pypl_email=""
-pypl_pass=""
-gmail_email=""
-gmail_pass=""
+hs_base_url = "http://localhost:8080"
+hs_test_browser = "firefox"
+chrome_profile_path = ""
+firefox_profile_path = ""
+pypl_email = ""
+pypl_pass = ""
+gmail_email = ""
+gmail_pass = ""
 
 [payme]
 # Open api key
-api_key="seller payme id"
-key1="payme client key"
+api_key = "seller payme id"
+key1 = "payme client key"
 
 [cryptopay]
 api_key = "api_key"
 key1 = "key1"
 
 [cashtocode]
-api_key="Classic PMT API Key"
+api_key = "Classic PMT API Key"
 key1 = "Evoucher PMT API Key"
 
 
 [tsys]
-api_key="device id"
+api_key = "device id"
 key1 = "transaction key"
 api_secret = "developer id"
 
@@ -159,31 +159,31 @@ api_key = "Partner code"
 key1 = "Credential code"
 
 [powertranz]
-api_key="PowerTranz-PowerTranzPassword"
+api_key = "PowerTranz-PowerTranzPassword"
 key1 = "PowerTranz-PowerTranzId"
 
 [stax]
-api_key="API Key"
+api_key = "API Key"
 
 [boku]
-api_key="API Key"
+api_key = "API Key"
 key1 = "transaction key"
 
 [square]
-api_key="API Key"
+api_key = "API Key"
 key1 = "transaction key"
 
 [helcim]
-api_key="API Key"
+api_key = "API Key"
 
 [gocardless]
-api_key="API Key"
+api_key = "API Key"
 
 [volt]
-api_key="API Key"
+api_key = "API Key"
 
 [prophetpay]
-api_key="API Key"
+api_key = "API Key"
 
 [bankofamerica]
 api_key = "MyApiKey"
@@ -191,10 +191,12 @@ key1 = "Merchant id"
 api_secret = "Secret key"
 
 [placetopay]
-api_key= "Login"
-key1= "Trankey"
+api_key = "Login"
+key1 = "Trankey"
 
 
 [threedsecureio]
-api_key="API Key"
+api_key = "API Key"
 
+[plaid]
+api_key = "API Key"
diff --git a/crates/test_utils/src/connector_auth.rs b/crates/test_utils/src/connector_auth.rs
index a2753a2c517..c91a50fce33 100644
--- a/crates/test_utils/src/connector_auth.rs
+++ b/crates/test_utils/src/connector_auth.rs
@@ -49,6 +49,7 @@ pub struct ConnectorAuthentication {
     pub paypal: Option<BodyKey>,
     pub payu: Option<BodyKey>,
     pub placetopay: Option<BodyKey>,
+    pub plaid: Option<HeaderKey>,
     pub powertranz: Option<BodyKey>,
     pub prophetpay: Option<HeaderKey>,
     pub rapyd: Option<BodyKey>,
diff --git a/loadtest/config/development.toml b/loadtest/config/development.toml
index 98a2613f3f2..4c102aad709 100644
--- a/loadtest/config/development.toml
+++ b/loadtest/config/development.toml
@@ -107,6 +107,7 @@ payme.base_url = "https://sandbox.payme.io/"
 paypal.base_url = "https://api-m.sandbox.paypal.com/"
 payu.base_url = "https://secure.snd.payu.com/"
 placetopay.base_url = "https://test.placetopay.com/rest/gateway"
+plaid.base_url = "https://sandbox.plaid.com"
 powertranz.base_url = "https://staging.ptranz.com/api/"
 prophetpay.base_url = "https://ccm-thirdparty.cps.golf/"
 rapyd.base_url = "https://sandboxapi.rapyd.net"
@@ -172,6 +173,7 @@ cards = [
     "paypal",
     "payu",
     "placetopay",
+    "plaid",
     "powertranz",
     "prophetpay",
     "shift4",
diff --git a/openapi/openapi_spec.json b/openapi/openapi_spec.json
index 4f6a4410cb8..251a0de4e81 100644
--- a/openapi/openapi_spec.json
+++ b/openapi/openapi_spec.json
@@ -16067,7 +16067,8 @@
           "wise",
           "worldline",
           "worldpay",
-          "zen"
+          "zen",
+          "plaid"
         ]
       },
       "RoutingAlgorithm": {
diff --git a/scripts/add_connector.sh b/scripts/add_connector.sh
index 2be49d123b0..9ec7c031406 100755
--- a/scripts/add_connector.sh
+++ b/scripts/add_connector.sh
@@ -6,7 +6,7 @@ function find_prev_connector() {
     git checkout $self
     cp $self $self.tmp
     # Add new connector to existing list and sort it
-    connectors=(aci adyen airwallex applepay authorizedotnet bambora bankofamerica bitpay bluesnap boku braintree cashtocode checkout coinbase cryptopay cybersource dlocal dummyconnector fiserv forte globalpay globepay gocardless helcim iatapay klarna mollie multisafepay nexinets noon nuvei opayo opennode payeezy payme paypal payu placetopay powertranz prophetpay rapyd shift4 square stax stripe threedsecureio trustpay tsys volt wise worldline worldpay "$1")
+    connectors=(aci adyen airwallex applepay authorizedotnet bambora bankofamerica bitpay bluesnap boku braintree cashtocode checkout coinbase cryptopay cybersource dlocal dummyconnector fiserv forte globalpay globepay gocardless helcim iatapay klarna mollie multisafepay nexinets noon nuvei opayo opennode payeezy payme paypal payu placetopay plaid powertranz prophetpay rapyd shift4 square stax stripe threedsecureio trustpay tsys volt wise worldline worldpay "$1")
     IFS=$'\n' sorted=($(sort <<<"${connectors[*]}")); unset IFS
     res=`echo ${sorted[@]}`
     sed -i'' -e "s/^    connectors=.*/    connectors=($res \"\$1\")/" $self.tmp

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

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

## Description
<!-- Describe your changes in detail -->
Webhook Implementation for Plaid


### Additional Changes

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

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

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


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

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


## How did you test it?
<!--
Did you write an integration/unit/API test to verify the code changes?
Or did you test this change manually (provide relevant screenshots)?
-->


## 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`
- [ ] I reviewed the submitted code
- [ ] I added unit tests for my changes where possible
- [ ] I added a [CHANGELOG](/CHANGELOG.md) entry if applicable
