Bug: [FEATURE] Integrate AdyenPlatform for processing payouts



### Feature Description

Adyen for Platforms is a marketplace solution which also provides paying out to third parties. This needs to be integrated in HyperSwitch as a payout processor for now. 

### Possible Implementation

Integrate Adyen's "Payout to third parties" 

ref - https://docs.adyen.com/payouts/payout-service/payout-to-users/

### 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/CHANGELOG.md b/CHANGELOG.md
index 8f6fb64a4a4..312544c05a0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,72 @@
+# 0.5.0 (2023-03-21)
+
+## Build System / Dependencies
+
+* **deps:**  update deps (#734) (16bc886c)
+
+## Chores
+
+* **merchant_account:**  remove `api_key` field (#713) (230fcdd4)
+* **config:**  move connector base URLs under the `[connectors]` table (#723) (df8c8b5a)
+*  address Rust 1.68 clippy lints (#728) (1ffabb40)
+
+## Continuous Integration
+
+* **release:**  specify `fetch-depth` for code checkout and use official Docker GitHub actions (#722) (c451368f)
+
+## Documentation Changes
+
+*  Update naming conventions and added examples (#709) (98415193)
+* **openapi:**  document path parameters for API keys endpoints (#702) (9062dc80)
+
+## New Features
+
+* **connector:**
+  *  [Mollie]: add authorize, void, refund, psync, rsync support for mollie connector (#740) (168fa32)
+  *  [worldline] add webhook support for connector (#721) (13a8ce8e)
+  *  [Trustpay] add authorize (cards 3ds, no3ds and bank redirects), refund, psync, rsync (#717) (e102cae7)
+  *  [Fiserv] add Refunds, Cancel and Wallets flow along with Unit Tests (#593) (cd1c5409)
+  *  Add support for complete authorize payment after 3DS redirection (#741) (ec2b1b18)
+*  removing unnecessary logs from console (#753) (1021d1ae)
+*  Time based deletion of temp card (#729) (db3d3164)
+*  populate fields from payment attempt in payment list (#736) (b5b3d57c)
+*  add generic in-memory cache interface (#737) (7f5e5d86)
+*  Add HSTS headers to response (#725) (7ed665ec)
+*  cache reverse lookup fetches on redis (#719) (1a27faca)
+* **compatibility:**  add webhook support for stripe compatibility (#710) (79160504)
+
+## Bug Fixes
+
+* **docker-compose:**  remove port for hyperswitch-server-init in docker-compose.yml (#763) (20b93276)
+*  fixing docker compose setup & adding redisinsight (#748) (5c9bec9f)
+* **kms:**  log KMS SDK errors using the `Debug` impl (#720) (468aa87f)
+* **errors:**
+  *  Replace PaymentMethod with PaymentModethodData in test.rs (#716) (763ee094)
+  *  use `Debug` impl instead of `Display` for error types wrapping `error_stack::Report` (#714) (45484752)
+
+## Other Changes
+
+*  card_fingerprint not sent by basilisk_hs (#754) (5ae2f63f)
+
+## Refactors
+
+* **merchant_account:**  add back `api_key` field for backward compatibility (#761) (661dd48a)
+* **connector:**  update add_connector script (#762) (78794ed6)
+* **metrics:**  use macros for constructing counter and histogram metrics (#755) (58106d91)
+* **kms:**  share a KMS client for all KMS operations (#744) (a3ff2e8d)
+*  Basilisk hs integration (#704) (585618e5)
+*  Add service_name to get and delete request (#738) (8b7ae9c3)
+*  Add secret to metadata (#706) (d36afbed)
+* **client:**
+  *  simplify HTTP client construction (#731) (1756d1c4)
+  *  remove dependence on `ROUTER_HTTP_PROXY` and `ROUTER_HTTPS_PROXY` env vars (#730) (c085e460)
+* **authentication:**  authenticate merchant by API keys from API keys table (#712) (afd08d42)
+* **api_keys:**  use a KMS encrypted API key hashing key and remove key ID prefix from plaintext API keys (#639) (3a3b33ac)
+
+## Tests
+
+* **masking:**  add suitable feature gates for basic tests (#745) (4859b6e4)
+
 # 0.3.0 (2023-03-05)
 
 ## Chores
diff --git a/config/Development.toml b/config/Development.toml
index 94bb5c0ad23..4a74b768959 100644
--- a/config/Development.toml
+++ b/config/Development.toml
@@ -17,6 +17,7 @@ host = "localhost"
 port = 5432
 dbname = "hyperswitch_db"
 pool_size = 5
+connection_timeout = 10
 
 [replica_database]
 username = "replica_user"
@@ -79,71 +80,29 @@ validity = 1
 [api_keys]
 hash_key = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
 
-[connectors.aci]
-base_url = "https://eu-test.oppwa.com/"
-
-[connectors.adyen]
-base_url = "https://checkout-test.adyen.com/"
-
-[connectors.authorizedotnet]
-base_url = "https://apitest.authorize.net/xml/v1/request.api"
-
-[connectors.checkout]
-base_url = "https://api.sandbox.checkout.com/"
-
-[connectors.stripe]
-base_url = "https://api.stripe.com/"
-
-[connectors.braintree]
-base_url = "https://api.sandbox.braintreegateway.com/"
-
-[connectors.klarna]
-base_url = "https://api-na.playground.klarna.com/"
-
-[connectors.applepay]
-base_url = "https://apple-pay-gateway.apple.com/"
-
-[connectors.cybersource]
-base_url = "https://apitest.cybersource.com/"
-
-[connectors.shift4]
-base_url = "https://api.shift4.com/"
-
-[connectors.rapyd]
-base_url = "https://sandboxapi.rapyd.net"
-
-[connectors.fiserv]
-base_url = "https://cert.api.fiservapps.com/"
-
-[connectors.worldpay]
-base_url = "https://try.access.worldpay.com/"
-
-[connectors.payu]
-base_url = "https://secure.snd.payu.com/"
-
-[connectors.globalpay]
-base_url = "https://apis.sandbox.globalpay.com/ucp/"
-
-[connectors.worldline]
-base_url = "https://eu.sandbox.api-ingenico.com/"
-
-[connectors.bluesnap]
-base_url = "https://sandbox.bluesnap.com/"
-
-[connectors.nuvei]
-base_url = "https://ppp-test.nuvei.com/"
-
-[connectors.airwallex]
-base_url = "https://api-demo.airwallex.com/"
-
-[connectors.multisafepay]
-base_url = "https://testapi.multisafepay.com/"
-
-[connectors.dlocal]
-base_url = "https://sandbox.dlocal.com/"
-
-[connectors.bambora]
-base_url = "https://api.na.bambora.com"
+[connectors]
+aci.base_url = "https://eu-test.oppwa.com/"
+adyen.base_url = "https://checkout-test.adyen.com/"
+airwallex.base_url = "https://api-demo.airwallex.com/"
+applepay.base_url = "https://apple-pay-gateway.apple.com/"
+authorizedotnet.base_url = "https://apitest.authorize.net/xml/v1/request.api"
+bambora.base_url = "https://api.na.bambora.com"
+bluesnap.base_url = "https://sandbox.bluesnap.com/"
+braintree.base_url = "https://api.sandbox.braintreegateway.com/"
+checkout.base_url = "https://api.sandbox.checkout.com/"
+cybersource.base_url = "https://apitest.cybersource.com/"
+dlocal.base_url = "https://sandbox.dlocal.com/"
+fiserv.base_url = "https://cert.api.fiservapps.com/"
+globalpay.base_url = "https://apis.sandbox.globalpay.com/ucp/"
+klarna.base_url = "https://api-na.playground.klarna.com/"
+multisafepay.base_url = "https://testapi.multisafepay.com/"
+nuvei.base_url = "https://ppp-test.nuvei.com/"
+payu.base_url = "https://secure.snd.payu.com/"
+rapyd.base_url = "https://sandboxapi.rapyd.net"
+shift4.base_url = "https://api.shift4.com/"
+stripe.base_url = "https://api.stripe.com/"
+worldline.base_url = "https://eu.sandbox.api-ingenico.com/"
+worldpay.base_url = "https://try.access.worldpay.com/"
 
 [scheduler]
 stream = "SCHEDULER_STREAM"
@@ -153,12 +112,12 @@ disabled = false
 consumer_group = "SCHEDULER_GROUP"
 
 [bank_config.eps]
-stripe = {banks = "arzte_und_apotheker_bank,austrian_anadi_bank_ag,bank_austria,bankhaus_carl_spangler,bankhaus_schelhammer_und_schattera_ag,bawag_psk_ag,bks_bank_ag,brull_kallmus_bank_ag,btv_vier_lander_bank,capital_bank_grawe_gruppe_ag,dolomitenbank,easybank_ag,erste_bank_und_sparkassen,hypo_alpeadriabank_international_ag,hypo_noe_lb_fur_niederosterreich_u_wien,hypo_oberosterreich_salzburg_steiermark,hypo_tirol_bank_ag,hypo_vorarlberg_bank_ag,hypo_bank_burgenland_aktiengesellschaft,marchfelder_bank,oberbank_ag,raiffeisen_bankengruppe_osterreich,schoellerbank_ag,sparda_bank_wien,volksbank_gruppe,volkskreditbank_ag,vr_bank_braunau"}
-adyen = {banks = "bank_austria,bawag_psk_ag,dolomitenbank,easybank_ag,erste_bank_und_sparkassen,hypo_tirol_bank_ag,posojilnica_bank_e_gen,raiffeisen_bankengruppe_osterreich,schoellerbank_ag,sparda_bank_wien,volksbank_gruppe,volkskreditbank_ag"}
+stripe = { banks = "arzte_und_apotheker_bank,austrian_anadi_bank_ag,bank_austria,bankhaus_carl_spangler,bankhaus_schelhammer_und_schattera_ag,bawag_psk_ag,bks_bank_ag,brull_kallmus_bank_ag,btv_vier_lander_bank,capital_bank_grawe_gruppe_ag,dolomitenbank,easybank_ag,erste_bank_und_sparkassen,hypo_alpeadriabank_international_ag,hypo_noe_lb_fur_niederosterreich_u_wien,hypo_oberosterreich_salzburg_steiermark,hypo_tirol_bank_ag,hypo_vorarlberg_bank_ag,hypo_bank_burgenland_aktiengesellschaft,marchfelder_bank,oberbank_ag,raiffeisen_bankengruppe_osterreich,schoellerbank_ag,sparda_bank_wien,volksbank_gruppe,volkskreditbank_ag,vr_bank_braunau" }
+adyen = { banks = "bank_austria,bawag_psk_ag,dolomitenbank,easybank_ag,erste_bank_und_sparkassen,hypo_tirol_bank_ag,posojilnica_bank_e_gen,raiffeisen_bankengruppe_osterreich,schoellerbank_ag,sparda_bank_wien,volksbank_gruppe,volkskreditbank_ag" }
 
 [bank_config.ideal]
-stripe = {banks = "abn_amro,asn_bank,bunq,handelsbanken,ing,knab,moneyou,rabobank,regiobank,revolut,sns_bank,triodos_bank,van_lanschot"}
-adyen = {banks = "abn_amro,asn_bank,bunq,handelsbanken,ing,knab,moneyou,rabobank,regiobank,revolut,sns_bank,triodos_bank,van_lanschot"}
+stripe = { banks = "abn_amro,asn_bank,bunq,handelsbanken,ing,knab,moneyou,rabobank,regiobank,revolut,sns_bank,triodos_bank,van_lanschot" }
+adyen = { banks = "abn_amro,asn_bank,bunq,handelsbanken,ing,knab,moneyou,rabobank,regiobank,revolut,sns_bank,triodos_bank,van_lanschot" }
 
 [pm_filters.stripe]
 google_pay = { country = "AL,DZ,AS,AO,AG,AR,AU,AT,AZ,BH,BY,BE,BR,BG,CA,CL,CO,HR,CZ,DK,DO,EG,EE,FI,FR,DE,GR,HK,HU,IN,ID,IE,IL,IT,JP,JO,KZ,KE,KW,LV,LB,LT,LU,MY,MX,NL,NZ,NO,OM,PK,PA,PE,PH,PL,PT,QA,RO,RU,SA,SG,SK,ZA,ES,LK,SE,CH,TW,TH,TR,UA,AE,GB,US,UY,VN" }
diff --git a/config/config.example.toml b/config/config.example.toml
index 176a309e067..60f9bdcc5d9 100644
--- a/config/config.example.toml
+++ b/config/config.example.toml
@@ -121,67 +121,31 @@ hash_key = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
 # Examples provided here are sandbox/test base urls, can be replaced by live or mock
 # base urls based on your need.
 # Note: These are not optional attributes. hyperswitch request can fail due to invalid/empty values.
-[connectors.aci]
-base_url = "https://eu-test.oppwa.com/"
-
-[connectors.adyen]
-base_url = "https://checkout-test.adyen.com/"
-
-[connectors.authorizedotnet]
-base_url = "https://apitest.authorize.net/xml/v1/request.api"
-
-[connectors.checkout]
-base_url = "https://api.sandbox.checkout.com/"
-
-[connectors.stripe]
-base_url = "https://api.stripe.com/"
-
-[connectors.braintree]
-base_url = "https://api.sandbox.braintreegateway.com/"
-
-[connectors.klarna]
-base_url = "https://api-na.playground.klarna.com/"
-
-[connectors.applepay]
-base_url = "https://apple-pay-gateway.apple.com/"
-
-[connectors.cybersource]
-base_url = "https://apitest.cybersource.com/"
-
-[connectors.shift4]
-base_url = "https://api.shift4.com/"
-
-[connectors.rapyd]
-base_url = "https://sandboxapi.rapyd.net"
-
-[connectors.fiserv]
-base_url = "https://cert.api.fiservapps.com/"
-
-[connectors.worldpay]
-base_url = "https://try.access.worldpay.com/"
-
-[connectors.globalpay]
-base_url = "https://apis.sandbox.globalpay.com/ucp/"
-
-[connectors.bluesnap]
-base_url = "https://sandbox.bluesnap.com/"
-
-[connectors.nuvei]
-base_url = "https://ppp-test.nuvei.com/"
-
-[connectors.airwallex]
-base_url = "https://api-demo.airwallex.com/"
-
-[connectors.multisafepay]
-base_url = "https://testapi.multisafepay.com/"
-
-[connectors.dlocal]
-base_url = "https://sandbox.dlocal.com/"
+[connectors]
+aci.base_url = "https://eu-test.oppwa.com/"
+adyen.base_url = "https://checkout-test.adyen.com/"
+airwallex.base_url = "https://api-demo.airwallex.com/"
+applepay.base_url = "https://apple-pay-gateway.apple.com/"
+authorizedotnet.base_url = "https://apitest.authorize.net/xml/v1/request.api"
+bambora.base_url = "https://api.na.bambora.com"
+bluesnap.base_url = "https://sandbox.bluesnap.com/"
+braintree.base_url = "https://api.sandbox.braintreegateway.com/"
+checkout.base_url = "https://api.sandbox.checkout.com/"
+cybersource.base_url = "https://apitest.cybersource.com/"
+dlocal.base_url = "https://sandbox.dlocal.com/"
+fiserv.base_url = "https://cert.api.fiservapps.com/"
+globalpay.base_url = "https://apis.sandbox.globalpay.com/ucp/"
+klarna.base_url = "https://api-na.playground.klarna.com/"
+multisafepay.base_url = "https://testapi.multisafepay.com/"
+nuvei.base_url = "https://ppp-test.nuvei.com/"
+payu.base_url = "https://secure.snd.payu.com/"
+rapyd.base_url = "https://sandboxapi.rapyd.net"
+shift4.base_url = "https://api.shift4.com/"
+stripe.base_url = "https://api.stripe.com/"
+worldline.base_url = "https://eu.sandbox.api-ingenico.com/"
+worldpay.base_url = "https://try.access.worldpay.com/"
 
 # This data is used to call respective connectors for wallets and cards
-[connectors.bambora]
-base_url = "https://api.na.bambora.com"
-
 [connectors.supported]
 wallets = ["klarna", "braintree", "applepay"]
 cards = [
diff --git a/config/docker_compose.toml b/config/docker_compose.toml
index a0da848ddcf..e7128d3d6b3 100644
--- a/config/docker_compose.toml
+++ b/config/docker_compose.toml
@@ -66,69 +66,34 @@ max_age = 365
 [api_keys]
 hash_key = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
 
-[connectors.aci]
-base_url = "https://eu-test.oppwa.com/"
-
-[connectors.adyen]
-base_url = "https://checkout-test.adyen.com/"
-
-[connectors.authorizedotnet]
-base_url = "https://apitest.authorize.net/xml/v1/request.api"
-
-[connectors.checkout]
-base_url = "https://api.sandbox.checkout.com/"
-
-[connectors.stripe]
-base_url = "https://api.stripe.com/"
-
-[connectors.braintree]
-base_url = "https://api.sandbox.braintreegateway.com/"
-
-[connectors.klarna]
-base_url = "https://api-na.playground.klarna.com/"
-
-[connectors.applepay]
-base_url = "https://apple-pay-gateway.apple.com/"
-
-[connectors.cybersource]
-base_url = "https://apitest.cybersource.com/"
-
-[connectors.shift4]
-base_url = "https://api.shift4.com/"
-
-[connectors.rapyd]
-base_url = "https://sandboxapi.rapyd.net"
-
-[connectors.fiserv]
-base_url = "https://cert.api.fiservapps.com/"
-
-[connectors.worldpay]
-base_url = "https://try.access.worldpay.com/"
-
-[connectors.globalpay]
-base_url = "https://apis.sandbox.globalpay.com/ucp/"
-
-[connectors.bluesnap]
-base_url = "https://sandbox.bluesnap.com/"
-
-[connectors.nuvei]
-base_url = "https://ppp-test.nuvei.com/"
-
-[connectors.airwallex]
-base_url = "https://api-demo.airwallex.com/"
-
-[connectors.multisafepay]
-base_url = "https://testapi.multisafepay.com/"
-
-[connectors.dlocal]
-base_url = "https://sandbox.dlocal.com/"
-
-[connectors.bambora]
-base_url = "https://api.na.bambora.com"
+[connectors]
+aci.base_url = "https://eu-test.oppwa.com/"
+adyen.base_url = "https://checkout-test.adyen.com/"
+airwallex.base_url = "https://api-demo.airwallex.com/"
+applepay.base_url = "https://apple-pay-gateway.apple.com/"
+authorizedotnet.base_url = "https://apitest.authorize.net/xml/v1/request.api"
+bambora.base_url = "https://api.na.bambora.com"
+bluesnap.base_url = "https://sandbox.bluesnap.com/"
+braintree.base_url = "https://api.sandbox.braintreegateway.com/"
+checkout.base_url = "https://api.sandbox.checkout.com/"
+cybersource.base_url = "https://apitest.cybersource.com/"
+dlocal.base_url = "https://sandbox.dlocal.com/"
+fiserv.base_url = "https://cert.api.fiservapps.com/"
+globalpay.base_url = "https://apis.sandbox.globalpay.com/ucp/"
+klarna.base_url = "https://api-na.playground.klarna.com/"
+multisafepay.base_url = "https://testapi.multisafepay.com/"
+nuvei.base_url = "https://ppp-test.nuvei.com/"
+payu.base_url = "https://secure.snd.payu.com/"
+rapyd.base_url = "https://sandboxapi.rapyd.net"
+shift4.base_url = "https://api.shift4.com/"
+stripe.base_url = "https://api.stripe.com/"
+worldline.base_url = "https://eu.sandbox.api-ingenico.com/"
+worldpay.base_url = "https://try.access.worldpay.com/"
 
 [connectors.supported]
 wallets = ["klarna", "braintree", "applepay"]
 cards = [
+    "aci",
     "adyen",
     "airwallex",
     "authorizedotnet",
diff --git a/crates/api_models/src/admin.rs b/crates/api_models/src/admin.rs
index 92a8bd773fe..f3ed6ff2681 100644
--- a/crates/api_models/src/admin.rs
+++ b/crates/api_models/src/admin.rs
@@ -66,6 +66,10 @@ pub struct MerchantAccountCreate {
     /// An identifier for the vault used to store payment method information.
     #[schema(example = "locker_abc123")]
     pub locker_id: Option<String>,
+
+    ///Default business details for connector routing
+    #[schema(value_type = Option<PrimaryBusinessDetails>)]
+    pub primary_business_details: Option<serde_json::Value>,
 }
 
 #[derive(Clone, Debug, Deserialize, ToSchema)]
@@ -127,6 +131,9 @@ pub struct MerchantAccountUpdate {
     /// An identifier for the vault used to store payment method information.
     #[schema(example = "locker_abc123")]
     pub locker_id: Option<String>,
+
+    ///Default business details for connector routing
+    pub primary_business_details: Option<PrimaryBusinessDetails>,
 }
 
 #[derive(Clone, Debug, ToSchema, Serialize)]
@@ -190,6 +197,10 @@ pub struct MerchantAccountResponse {
     /// An identifier for the vault used to store payment method information.
     #[schema(example = "locker_abc123")]
     pub locker_id: Option<String>,
+
+    ///Default business details for connector routing
+    #[schema(value_type = Option<PrimaryBusinessDetails>)]
+    pub primary_business_details: Option<serde_json::Value>,
 }
 
 #[derive(Clone, Debug, Deserialize, ToSchema, Serialize)]
@@ -240,6 +251,13 @@ pub enum RoutingAlgorithm {
     Single(api_enums::RoutableConnectors),
 }
 
+#[derive(Clone, Debug, Deserialize, ToSchema, Serialize)]
+#[serde(deny_unknown_fields)]
+pub struct PrimaryBusinessDetails {
+    country: String,
+    business: String,
+}
+
 #[derive(Clone, Debug, Deserialize, ToSchema, Serialize)]
 #[serde(deny_unknown_fields)]
 pub struct WebhookDetails {
@@ -303,6 +321,15 @@ pub struct MerchantConnector {
     /// Name of the Connector
     #[schema(example = "stripe")]
     pub connector_name: String,
+    /// Connector label for specific country and Business
+    #[schema(example = "stripe_US_travel")]
+    pub connector_label: String,
+    /// Country through which payment should be processed
+    #[schema(example = "US")]
+    pub business_country: String,
+    ///Business Type of the merchant
+    #[schema(example = "travel")]
+    pub business_label: String,
     /// Unique ID of the connector
     #[schema(example = "mca_5apGeP94tMts6rg3U3kR")]
     pub merchant_connector_id: Option<String>,
diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs
index 0cfb48650b5..3b7c256614d 100644
--- a/crates/router/src/core/admin.rs
+++ b/crates/router/src/core/admin.rs
@@ -34,19 +34,38 @@ pub async fn create_merchant_account(
 
     let api_key = Some(create_merchant_api_key().into());
 
-    let merchant_details = Some(
-        utils::Encode::<api::MerchantDetails>::encode_to_value(&req.merchant_details)
-            .change_context(errors::ApiErrorResponse::InvalidDataValue {
-                field_name: "merchant_details",
-            })?,
-    );
-
-    let webhook_details = Some(
-        utils::Encode::<api::WebhookDetails>::encode_to_value(&req.webhook_details)
-            .change_context(errors::ApiErrorResponse::InvalidDataValue {
-                field_name: "webhook details",
-            })?,
-    );
+    let merchant_details = req
+        .merchant_details
+        .map(|md| {
+            utils::Encode::<api::MerchantDetails>::encode_to_value(&md).change_context(
+                errors::ApiErrorResponse::InvalidDataValue {
+                    field_name: "merchant_details",
+                },
+            )
+        })
+        .transpose()?;
+
+    let webhook_details = req
+        .webhook_details
+        .map(|wd| {
+            utils::Encode::<api::WebhookDetails>::encode_to_value(&wd).change_context(
+                errors::ApiErrorResponse::InvalidDataValue {
+                    field_name: "webhook details",
+                },
+            )
+        })
+        .transpose()?;
+
+    let primary_business_details = req
+        .primary_business_details
+        .map(|pbd| {
+            utils::Encode::<api::PrimaryBusinessDetails>::encode_to_value(&pbd).change_context(
+                errors::ApiErrorResponse::InvalidDataValue {
+                    field_name: "default business details",
+                },
+            )
+        })
+        .transpose()?;
 
     if let Some(ref routing_algorithm) = req.routing_algorithm {
         let _: api::RoutingAlgorithm = routing_algorithm
@@ -79,6 +98,7 @@ pub async fn create_merchant_account(
         publishable_key,
         locker_id: req.locker_id,
         metadata: req.metadata,
+        primary_business_details,
     };
 
     let merchant_account = db
@@ -171,6 +191,12 @@ pub async fn merchant_account_update(
         metadata: req.metadata,
         api_key: None,
         publishable_key: None,
+        primary_business_details: req
+            .primary_business_details
+            .as_ref()
+            .map(utils::Encode::<api::PrimaryBusinessDetails>::encode_to_value)
+            .transpose()
+            .change_context(errors::ApiErrorResponse::InternalServerError)?,
     };
 
     let response = db
@@ -292,6 +318,9 @@ pub async fn create_payment_connector(
         test_mode: req.test_mode,
         disabled: req.disabled,
         metadata: req.metadata,
+        connector_label: Some(req.connector_label),
+        business_country: Some(req.business_country),
+        business_label: Some(req.business_label),
     };
 
     let mca = store
@@ -402,6 +431,9 @@ pub async fn update_payment_connector(
         test_mode: req.test_mode,
         disabled: req.disabled,
         metadata: req.metadata,
+        connector_label: Some(req.connector_label),
+        business_country: Some(req.business_country),
+        business_label: Some(req.business_label),
     };
 
     let updated_mca = db
@@ -432,6 +464,9 @@ pub async fn update_payment_connector(
         disabled: updated_mca.disabled,
         payment_methods_enabled: updated_pm_enabled,
         metadata: updated_mca.metadata,
+        connector_label: updated_mca.connector_label,
+        business_country: updated_mca.business_country,
+        business_label: updated_mca.business_label,
     };
     Ok(service_api::ApplicationResponse::Json(response))
 }
diff --git a/crates/router/src/core/api_keys.rs b/crates/router/src/core/api_keys.rs
index de1d0d71f74..9cda9e9562f 100644
--- a/crates/router/src/core/api_keys.rs
+++ b/crates/router/src/core/api_keys.rs
@@ -1,10 +1,8 @@
-use common_utils::{date_time, errors::CustomResult, fp_utils};
+use common_utils::date_time;
 use error_stack::{report, IntoReport, ResultExt};
-use masking::{PeekInterface, Secret, StrongSecret};
+use masking::{PeekInterface, StrongSecret};
 use router_env::{instrument, tracing};
 
-#[cfg(feature = "kms")]
-use crate::services::kms;
 use crate::{
     configs::settings,
     consts,
@@ -14,6 +12,8 @@ use crate::{
     types::{api, storage, transformers::ForeignInto},
     utils,
 };
+#[cfg(feature = "kms")]
+use crate::{routes::metrics, services::kms};
 
 pub static HASH_KEY: tokio::sync::OnceCell<StrongSecret<[u8; PlaintextApiKey::HASH_KEY_LEN]>> =
     tokio::sync::OnceCell::const_new();
@@ -28,6 +28,10 @@ pub async fn get_hash_key(
         api_key_config.kms_encrypted_hash_key.clone(),
     )
     .await
+    .map_err(|error| {
+        metrics::AWS_KMS_FAILURES.add(&metrics::CONTEXT, 1, &[]);
+        error
+    })
     .change_context(errors::ApiErrorResponse::InternalServerError)
     .attach_printable("Failed to KMS decrypt API key hashing key")?;
 
@@ -49,11 +53,13 @@ pub async fn get_hash_key(
 
 // Defining new types `PlaintextApiKey` and `HashedApiKey` in the hopes of reducing the possibility
 // of plaintext API key being stored in the data store.
-pub struct PlaintextApiKey(Secret<String>);
+pub struct PlaintextApiKey(StrongSecret<String>);
+
+#[derive(Debug, PartialEq, Eq)]
 pub struct HashedApiKey(String);
 
 impl PlaintextApiKey {
-    pub const HASH_KEY_LEN: usize = 32;
+    const HASH_KEY_LEN: usize = 32;
 
     const PREFIX_LEN: usize = 12;
 
@@ -107,22 +113,6 @@ impl PlaintextApiKey {
                 .to_string(),
         )
     }
-
-    pub fn verify_hash(
-        &self,
-        key: &[u8; Self::HASH_KEY_LEN],
-        stored_api_key: &HashedApiKey,
-    ) -> CustomResult<(), errors::ApiKeyError> {
-        // Converting both hashes to `blake3::Hash` since it provides constant-time equality checks
-        let provided_api_key_hash = blake3::keyed_hash(key, self.0.peek().as_bytes());
-        let stored_api_key_hash = blake3::Hash::from_hex(&stored_api_key.0)
-            .into_report()
-            .change_context(errors::ApiKeyError::FailedToReadHashFromHex)?;
-
-        fp_utils::when(provided_api_key_hash != stored_api_key_hash, || {
-            Err(errors::ApiKeyError::HashVerificationFailed).into_report()
-        })
-    }
 }
 
 #[instrument(skip_all)]
@@ -165,7 +155,7 @@ pub async fn retrieve_api_key(
     key_id: &str,
 ) -> RouterResponse<api::RetrieveApiKeyResponse> {
     let api_key = store
-        .find_api_key_optional(key_id)
+        .find_api_key_by_key_id_optional(key_id)
         .await
         .change_context(errors::ApiErrorResponse::InternalServerError) // If retrieve failed
         .attach_printable("Failed to retrieve new API key")?
@@ -224,12 +214,30 @@ pub async fn list_api_keys(
     Ok(ApplicationResponse::Json(api_keys))
 }
 
+impl From<&str> for PlaintextApiKey {
+    fn from(s: &str) -> Self {
+        Self(s.to_owned().into())
+    }
+}
+
+impl From<String> for PlaintextApiKey {
+    fn from(s: String) -> Self {
+        Self(s.into())
+    }
+}
+
 impl From<HashedApiKey> for storage::HashedApiKey {
     fn from(hashed_api_key: HashedApiKey) -> Self {
         hashed_api_key.0.into()
     }
 }
 
+impl From<storage::HashedApiKey> for HashedApiKey {
+    fn from(hashed_api_key: storage::HashedApiKey) -> Self {
+        Self(hashed_api_key.into_inner())
+    }
+}
+
 #[cfg(test)]
 mod tests {
     #![allow(clippy::expect_used, clippy::unwrap_used)]
@@ -251,8 +259,7 @@ mod tests {
             hashed_api_key.0.as_bytes()
         );
 
-        plaintext_api_key
-            .verify_hash(hash_key.peek(), &hashed_api_key)
-            .unwrap();
+        let new_hashed_api_key = plaintext_api_key.keyed_hash(hash_key.peek());
+        assert_eq!(hashed_api_key, new_hashed_api_key)
     }
 }
diff --git a/crates/router/src/core/errors.rs b/crates/router/src/core/errors.rs
index f3bd6c4a7d4..7c9bfa42306 100644
--- a/crates/router/src/core/errors.rs
+++ b/crates/router/src/core/errors.rs
@@ -414,11 +414,3 @@ pub enum WebhooksFlowError {
     #[error("Resource not found")]
     ResourceNotFound,
 }
-
-#[derive(Debug, thiserror::Error)]
-pub enum ApiKeyError {
-    #[error("Failed to read API key hash from hexadecimal string")]
-    FailedToReadHashFromHex,
-    #[error("Failed to verify provided API key hash against stored API key hash")]
-    HashVerificationFailed,
-}
diff --git a/crates/router/src/db/api_keys.rs b/crates/router/src/db/api_keys.rs
index 85aa26ee3ff..3fc17302854 100644
--- a/crates/router/src/db/api_keys.rs
+++ b/crates/router/src/db/api_keys.rs
@@ -22,11 +22,16 @@ pub trait ApiKeyInterface {
 
     async fn revoke_api_key(&self, key_id: &str) -> CustomResult<bool, errors::StorageError>;
 
-    async fn find_api_key_optional(
+    async fn find_api_key_by_key_id_optional(
         &self,
         key_id: &str,
     ) -> CustomResult<Option<storage::ApiKey>, errors::StorageError>;
 
+    async fn find_api_key_by_hash_optional(
+        &self,
+        hashed_api_key: storage::HashedApiKey,
+    ) -> CustomResult<Option<storage::ApiKey>, errors::StorageError>;
+
     async fn list_api_keys_by_merchant_id(
         &self,
         merchant_id: &str,
@@ -69,7 +74,7 @@ impl ApiKeyInterface for Store {
             .into_report()
     }
 
-    async fn find_api_key_optional(
+    async fn find_api_key_by_key_id_optional(
         &self,
         key_id: &str,
     ) -> CustomResult<Option<storage::ApiKey>, errors::StorageError> {
@@ -80,6 +85,17 @@ impl ApiKeyInterface for Store {
             .into_report()
     }
 
+    async fn find_api_key_by_hash_optional(
+        &self,
+        hashed_api_key: storage::HashedApiKey,
+    ) -> CustomResult<Option<storage::ApiKey>, errors::StorageError> {
+        let conn = pg_connection(&self.master_pool).await?;
+        storage::ApiKey::find_optional_by_hashed_api_key(&conn, hashed_api_key)
+            .await
+            .map_err(Into::into)
+            .into_report()
+    }
+
     async fn list_api_keys_by_merchant_id(
         &self,
         merchant_id: &str,
@@ -118,7 +134,7 @@ impl ApiKeyInterface for MockDb {
         Err(errors::StorageError::MockDbError)?
     }
 
-    async fn find_api_key_optional(
+    async fn find_api_key_by_key_id_optional(
         &self,
         _key_id: &str,
     ) -> CustomResult<Option<storage::ApiKey>, errors::StorageError> {
@@ -126,6 +142,14 @@ impl ApiKeyInterface for MockDb {
         Err(errors::StorageError::MockDbError)?
     }
 
+    async fn find_api_key_by_hash_optional(
+        &self,
+        _hashed_api_key: storage::HashedApiKey,
+    ) -> CustomResult<Option<storage::ApiKey>, errors::StorageError> {
+        // [#172]: Implement function for `MockDb`
+        Err(errors::StorageError::MockDbError)?
+    }
+
     async fn list_api_keys_by_merchant_id(
         &self,
         _merchant_id: &str,
diff --git a/crates/router/src/db/merchant_account.rs b/crates/router/src/db/merchant_account.rs
index 83460fc7e9e..7c611aea428 100644
--- a/crates/router/src/db/merchant_account.rs
+++ b/crates/router/src/db/merchant_account.rs
@@ -215,6 +215,7 @@ impl MerchantAccountInterface for MockDb {
             storage_scheme: enums::MerchantStorageScheme::PostgresOnly,
             locker_id: merchant_account.locker_id,
             metadata: merchant_account.metadata,
+            primary_business_details: merchant_account.primary_business_details,
         };
         accounts.push(account.clone());
         Ok(account)
diff --git a/crates/router/src/db/merchant_connector_account.rs b/crates/router/src/db/merchant_connector_account.rs
index 640a4dd503c..6f89ece579a 100644
--- a/crates/router/src/db/merchant_connector_account.rs
+++ b/crates/router/src/db/merchant_connector_account.rs
@@ -290,6 +290,9 @@ impl MerchantConnectorAccountInterface for MockDb {
             connector_type: t
                 .connector_type
                 .unwrap_or(crate::types::storage::enums::ConnectorType::FinOperations),
+            connector_label: t.connector_label.unwrap_or_default(),
+            business_country: t.business_country.unwrap_or_default(),
+            business_label: t.business_label.unwrap_or_default(),
         };
         accounts.push(account.clone());
         Ok(account)
diff --git a/crates/router/src/routes/metrics.rs b/crates/router/src/routes/metrics.rs
index d01e4c0090f..c2a60311ca4 100644
--- a/crates/router/src/routes/metrics.rs
+++ b/crates/router/src/routes/metrics.rs
@@ -5,11 +5,12 @@ use router_env::opentelemetry::{
     Context,
 };
 
+use crate::create_counter;
+
 pub static CONTEXT: Lazy<Context> = Lazy::new(Context::current);
 static GLOBAL_METER: Lazy<Meter> = Lazy::new(|| global::meter("ROUTER_API"));
 
-pub(crate) static HEALTH_METRIC: Lazy<Counter<u64>> =
-    Lazy::new(|| GLOBAL_METER.u64_counter("HEALTH_API").init());
-
-pub(crate) static KV_MISS: Lazy<Counter<u64>> =
-    Lazy::new(|| GLOBAL_METER.u64_counter("KV_MISS").init());
+create_counter!(HEALTH_METRIC, GLOBAL_METER); // No. of health API hits
+create_counter!(KV_MISS, GLOBAL_METER); // No. of KV misses
+#[cfg(feature = "kms")]
+create_counter!(AWS_KMS_FAILURES, GLOBAL_METER); // No. of AWS KMS API failures
diff --git a/crates/router/src/scheduler/metrics.rs b/crates/router/src/scheduler/metrics.rs
index aa4363c329b..3fe40a6d32e 100644
--- a/crates/router/src/scheduler/metrics.rs
+++ b/crates/router/src/scheduler/metrics.rs
@@ -11,6 +11,7 @@ static PT_METER: Lazy<Meter> = Lazy::new(|| global::meter("PROCESS_TRACKER"));
 pub(crate) static CONSUMER_STATS: Lazy<Histogram<f64>> =
     Lazy::new(|| PT_METER.f64_histogram("CONSUMER_OPS").init());
 
+#[macro_export]
 macro_rules! create_counter {
     ($name:ident, $meter:ident) => {
         pub(crate) static $name: Lazy<Counter<u64>> =
diff --git a/crates/router/src/services/authentication.rs b/crates/router/src/services/authentication.rs
index e56d3efbe1d..15e5fe2ff9f 100644
--- a/crates/router/src/services/authentication.rs
+++ b/crates/router/src/services/authentication.rs
@@ -1,11 +1,16 @@
 use actix_web::http::header::HeaderMap;
 use api_models::{payment_methods::PaymentMethodListRequest, payments::PaymentsRequest};
 use async_trait::async_trait;
+use common_utils::date_time;
 use error_stack::{report, IntoReport, ResultExt};
 use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation};
+use masking::PeekInterface;
 
 use crate::{
-    core::errors::{self, RouterResult},
+    core::{
+        api_keys,
+        errors::{self, RouterResult},
+    },
     db::StorageInterface,
     routes::{app::AppStateInfo, AppState},
     services::api,
@@ -38,11 +43,45 @@ where
         request_headers: &HeaderMap,
         state: &A,
     ) -> RouterResult<storage::MerchantAccount> {
-        let api_key =
-            get_api_key(request_headers).change_context(errors::ApiErrorResponse::Unauthorized)?;
+        let api_key = get_api_key(request_headers)
+            .change_context(errors::ApiErrorResponse::Unauthorized)?
+            .trim();
+        if api_key.is_empty() {
+            return Err(errors::ApiErrorResponse::Unauthorized)
+                .into_report()
+                .attach_printable("API key is empty");
+        }
+
+        let api_key = api_keys::PlaintextApiKey::from(api_key);
+        let hash_key = {
+            let config = state.conf();
+            api_keys::HASH_KEY
+                .get_or_try_init(|| api_keys::get_hash_key(&config.api_keys))
+                .await?
+        };
+        let hashed_api_key = api_key.keyed_hash(hash_key.peek());
+
+        let stored_api_key = state
+            .store()
+            .find_api_key_by_hash_optional(hashed_api_key.into())
+            .await
+            .change_context(errors::ApiErrorResponse::InternalServerError) // If retrieve failed
+            .attach_printable("Failed to retrieve API key")?
+            .ok_or(report!(errors::ApiErrorResponse::Unauthorized)) // If retrieve returned `None`
+            .attach_printable("Merchant not authenticated")?;
+
+        if stored_api_key
+            .expires_at
+            .map(|expires_at| expires_at < date_time::now())
+            .unwrap_or(false)
+        {
+            return Err(report!(errors::ApiErrorResponse::Unauthorized))
+                .attach_printable("API key has expired");
+        }
+
         state
             .store()
-            .find_merchant_account_by_api_key(api_key)
+            .find_merchant_account_by_merchant_id(&stored_api_key.merchant_id)
             .await
             .map_err(|e| {
                 if e.current_context().is_db_not_found() {
diff --git a/crates/router/src/types/api/admin.rs b/crates/router/src/types/api/admin.rs
index 0d353785bf0..e5758a9ae49 100644
--- a/crates/router/src/types/api/admin.rs
+++ b/crates/router/src/types/api/admin.rs
@@ -1,8 +1,8 @@
 pub use api_models::admin::{
     MerchantAccountCreate, MerchantAccountDeleteResponse, MerchantAccountResponse,
     MerchantAccountUpdate, MerchantConnector, MerchantConnectorDeleteResponse, MerchantConnectorId,
-    MerchantDetails, MerchantId, PaymentMethodsEnabled, RoutingAlgorithm, ToggleKVRequest,
-    ToggleKVResponse, WebhookDetails,
+    MerchantDetails, MerchantId, PaymentMethodsEnabled, PrimaryBusinessDetails, RoutingAlgorithm,
+    ToggleKVRequest, ToggleKVResponse, WebhookDetails,
 };
 
 use crate::types::{storage, transformers::ForeignFrom};
@@ -26,6 +26,7 @@ impl ForeignFrom<storage::MerchantAccount> for MerchantAccountResponse {
             publishable_key: item.publishable_key,
             metadata: item.metadata,
             locker_id: item.locker_id,
+            primary_business_details: item.primary_business_details,
         }
     }
 }
diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs
index 1ad30bd3a60..f80ae964845 100644
--- a/crates/router/src/types/transformers.rs
+++ b/crates/router/src/types/transformers.rs
@@ -336,6 +336,9 @@ impl ForeignTryFrom<storage::MerchantConnectorAccount> for api_models::admin::Me
             disabled: merchant_ca.disabled,
             metadata: merchant_ca.metadata,
             payment_methods_enabled,
+            connector_label: merchant_ca.connector_label,
+            business_country: merchant_ca.business_country,
+            business_label: merchant_ca.business_label,
         })
     }
 }
diff --git a/crates/storage_models/src/api_keys.rs b/crates/storage_models/src/api_keys.rs
index 01df902e8ee..650ea0c7fa1 100644
--- a/crates/storage_models/src/api_keys.rs
+++ b/crates/storage_models/src/api_keys.rs
@@ -81,6 +81,12 @@ impl From<ApiKeyUpdate> for ApiKeyUpdateInternal {
 #[diesel(sql_type = diesel::sql_types::Text)]
 pub struct HashedApiKey(String);
 
+impl HashedApiKey {
+    pub fn into_inner(self) -> String {
+        self.0
+    }
+}
+
 impl From<String> for HashedApiKey {
     fn from(hashed_api_key: String) -> Self {
         Self(hashed_api_key)
diff --git a/crates/storage_models/src/merchant_account.rs b/crates/storage_models/src/merchant_account.rs
index 6a207bb194e..dcb638180a5 100644
--- a/crates/storage_models/src/merchant_account.rs
+++ b/crates/storage_models/src/merchant_account.rs
@@ -34,6 +34,7 @@ pub struct MerchantAccount {
     pub locker_id: Option<String>,
     pub metadata: Option<pii::SecretSerdeValue>,
     pub routing_algorithm: Option<serde_json::Value>,
+    pub primary_business_details: Option<serde_json::Value>,
 }
 
 #[derive(Clone, Debug, Default, Insertable, router_derive::DebugAsDisplay)]
@@ -54,6 +55,7 @@ pub struct MerchantAccountNew {
     pub locker_id: Option<String>,
     pub metadata: Option<pii::SecretSerdeValue>,
     pub routing_algorithm: Option<serde_json::Value>,
+    pub primary_business_details: Option<serde_json::Value>,
 }
 
 #[derive(Debug)]
@@ -73,6 +75,7 @@ pub enum MerchantAccountUpdate {
         locker_id: Option<String>,
         metadata: Option<pii::SecretSerdeValue>,
         routing_algorithm: Option<serde_json::Value>,
+        primary_business_details: Option<serde_json::Value>,
     },
     StorageSchemeUpdate {
         storage_scheme: storage_enums::MerchantStorageScheme,
@@ -97,6 +100,7 @@ pub struct MerchantAccountUpdateInternal {
     locker_id: Option<String>,
     metadata: Option<pii::SecretSerdeValue>,
     routing_algorithm: Option<serde_json::Value>,
+    primary_business_details: Option<serde_json::Value>,
 }
 
 impl From<MerchantAccountUpdate> for MerchantAccountUpdateInternal {
@@ -117,6 +121,7 @@ impl From<MerchantAccountUpdate> for MerchantAccountUpdateInternal {
                 publishable_key,
                 locker_id,
                 metadata,
+                primary_business_details,
             } => Self {
                 merchant_name,
                 api_key,
@@ -132,6 +137,7 @@ impl From<MerchantAccountUpdate> for MerchantAccountUpdateInternal {
                 publishable_key,
                 locker_id,
                 metadata,
+                primary_business_details,
                 ..Default::default()
             },
             MerchantAccountUpdate::StorageSchemeUpdate { storage_scheme } => Self {
diff --git a/crates/storage_models/src/merchant_connector_account.rs b/crates/storage_models/src/merchant_connector_account.rs
index 08d3fa21fa3..0f3560d01fc 100644
--- a/crates/storage_models/src/merchant_connector_account.rs
+++ b/crates/storage_models/src/merchant_connector_account.rs
@@ -28,6 +28,9 @@ pub struct MerchantConnectorAccount {
     pub payment_methods_enabled: Option<Vec<serde_json::Value>>,
     pub connector_type: storage_enums::ConnectorType,
     pub metadata: Option<pii::SecretSerdeValue>,
+    pub connector_label: String,
+    pub business_country: String,
+    pub business_label: String,
 }
 
 #[derive(Clone, Debug, Default, Insertable, router_derive::DebugAsDisplay)]
@@ -42,6 +45,9 @@ pub struct MerchantConnectorAccountNew {
     pub merchant_connector_id: String,
     pub payment_methods_enabled: Option<Vec<serde_json::Value>>,
     pub metadata: Option<pii::SecretSerdeValue>,
+    pub connector_label: Option<String>,
+    pub business_country: Option<String>,
+    pub business_label: Option<String>,
 }
 
 #[derive(Debug)]
@@ -56,6 +62,9 @@ pub enum MerchantConnectorAccountUpdate {
         merchant_connector_id: Option<String>,
         payment_methods_enabled: Option<Vec<serde_json::Value>>,
         metadata: Option<pii::SecretSerdeValue>,
+        connector_label: Option<String>,
+        business_country: Option<String>,
+        business_label: Option<String>,
     },
 }
 #[derive(Clone, Debug, Default, AsChangeset, router_derive::DebugAsDisplay)]
@@ -70,6 +79,9 @@ pub struct MerchantConnectorAccountUpdateInternal {
     merchant_connector_id: Option<String>,
     payment_methods_enabled: Option<Vec<serde_json::Value>>,
     metadata: Option<pii::SecretSerdeValue>,
+    connector_label: Option<String>,
+    business_country: Option<String>,
+    business_label: Option<String>,
 }
 
 impl From<MerchantConnectorAccountUpdate> for MerchantConnectorAccountUpdateInternal {
@@ -85,6 +97,9 @@ impl From<MerchantConnectorAccountUpdate> for MerchantConnectorAccountUpdateInte
                 merchant_connector_id,
                 payment_methods_enabled,
                 metadata,
+                connector_label,
+                business_country,
+                business_label,
             } => Self {
                 merchant_id,
                 connector_type,
@@ -95,6 +110,9 @@ impl From<MerchantConnectorAccountUpdate> for MerchantConnectorAccountUpdateInte
                 merchant_connector_id,
                 payment_methods_enabled,
                 metadata,
+                connector_label,
+                business_country,
+                business_label,
             },
         }
     }
diff --git a/crates/storage_models/src/query/api_keys.rs b/crates/storage_models/src/query/api_keys.rs
index dde38dc6f82..4d1e317276c 100644
--- a/crates/storage_models/src/query/api_keys.rs
+++ b/crates/storage_models/src/query/api_keys.rs
@@ -3,7 +3,7 @@ use router_env::{instrument, tracing};
 
 use super::generics;
 use crate::{
-    api_keys::{ApiKey, ApiKeyNew, ApiKeyUpdate, ApiKeyUpdateInternal},
+    api_keys::{ApiKey, ApiKeyNew, ApiKeyUpdate, ApiKeyUpdateInternal, HashedApiKey},
     errors,
     schema::api_keys::dsl,
     PgPooledConn, StorageResult,
@@ -65,6 +65,18 @@ impl ApiKey {
         .await
     }
 
+    #[instrument(skip(conn))]
+    pub async fn find_optional_by_hashed_api_key(
+        conn: &PgPooledConn,
+        hashed_api_key: HashedApiKey,
+    ) -> StorageResult<Option<Self>> {
+        generics::generic_find_one_optional::<<Self as HasTable>::Table, _, _>(
+            conn,
+            dsl::hashed_api_key.eq(hashed_api_key),
+        )
+        .await
+    }
+
     #[instrument(skip(conn))]
     pub async fn find_by_merchant_id(
         conn: &PgPooledConn,
diff --git a/crates/storage_models/src/schema.rs b/crates/storage_models/src/schema.rs
index 37177412dee..d1da47b694e 100644
--- a/crates/storage_models/src/schema.rs
+++ b/crates/storage_models/src/schema.rs
@@ -177,6 +177,7 @@ diesel::table! {
         locker_id -> Nullable<Varchar>,
         metadata -> Nullable<Jsonb>,
         routing_algorithm -> Nullable<Json>,
+        primary_business_details -> Nullable<Json>,
     }
 }
 
@@ -195,6 +196,9 @@ diesel::table! {
         payment_methods_enabled -> Nullable<Array<Nullable<Json>>>,
         connector_type -> ConnectorType,
         metadata -> Nullable<Jsonb>,
+        connector_label -> Varchar,
+        business_country -> Varchar,
+        business_label -> Varchar,
     }
 }
 
diff --git a/loadtest/config/Development.toml b/loadtest/config/Development.toml
index dc13cba049f..b011c3866b6 100644
--- a/loadtest/config/Development.toml
+++ b/loadtest/config/Development.toml
@@ -52,59 +52,29 @@ outgoing_enabled = true
 [api_keys]
 hash_key = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
 
-[connectors.aci]
-base_url = "https://eu-test.oppwa.com/"
-
-[connectors.adyen]
-base_url = "https://checkout-test.adyen.com/"
-
-[connectors.authorizedotnet]
-base_url = "https://apitest.authorize.net/xml/v1/request.api"
-
-[connectors.checkout]
-base_url = "https://api.sandbox.checkout.com/"
-
-[connectors.stripe]
-base_url = "http://stripe-mock:12111/"
-
-[connectors.braintree]
-base_url = "https://api.sandbox.braintreegateway.com/"
-
-[connectors.cybersource]
-base_url = "https://apitest.cybersource.com/"
-
-[connectors.shift4]
-base_url = "https://api.shift4.com/"
-
-[connectors.worldpay]
-base_url = "https://try.access.worldpay.com/"
-
-[connectors.globalpay]
-base_url = "https://apis.sandbox.globalpay.com/ucp/"
-
-[connectors.applepay]
-base_url = "https://apple-pay-gateway.apple.com/"
-
-[connectors.klarna]
-base_url = "https://api-na.playground.klarna.com/"
-
-[connectors.bluesnap]
-base_url = "https://sandbox.bluesnap.com/"
-
-[connectors.nuvei]
-base_url = "https://ppp-test.nuvei.com/"
-
-[connectors.airwallex]
-base_url = "https://api-demo.airwallex.com/"
-
-[connectors.multisafepay]
-base_url = "https://testapi.multisafepay.com/"
-
-[connectors.dlocal]
-base_url = "https://sandbox.dlocal.com/"
-
-[connectors.bambora]
-base_url = "https://api.na.bambora.com"
+[connectors]
+aci.base_url = "https://eu-test.oppwa.com/"
+adyen.base_url = "https://checkout-test.adyen.com/"
+airwallex.base_url = "https://api-demo.airwallex.com/"
+applepay.base_url = "https://apple-pay-gateway.apple.com/"
+authorizedotnet.base_url = "https://apitest.authorize.net/xml/v1/request.api"
+bambora.base_url = "https://api.na.bambora.com"
+bluesnap.base_url = "https://sandbox.bluesnap.com/"
+braintree.base_url = "https://api.sandbox.braintreegateway.com/"
+checkout.base_url = "https://api.sandbox.checkout.com/"
+cybersource.base_url = "https://apitest.cybersource.com/"
+dlocal.base_url = "https://sandbox.dlocal.com/"
+fiserv.base_url = "https://cert.api.fiservapps.com/"
+globalpay.base_url = "https://apis.sandbox.globalpay.com/ucp/"
+klarna.base_url = "https://api-na.playground.klarna.com/"
+multisafepay.base_url = "https://testapi.multisafepay.com/"
+nuvei.base_url = "https://ppp-test.nuvei.com/"
+payu.base_url = "https://secure.snd.payu.com/"
+rapyd.base_url = "https://sandboxapi.rapyd.net"
+shift4.base_url = "https://api.shift4.com/"
+stripe.base_url = "https://api.stripe.com/"
+worldline.base_url = "https://eu.sandbox.api-ingenico.com/"
+worldpay.base_url = "https://try.access.worldpay.com/"
 
 [connectors.supported]
 wallets = ["klarna", "braintree", "applepay"]
diff --git a/migrations/2023-02-20-101809_update_merchant_connector_account/down.sql b/migrations/2023-02-20-101809_update_merchant_connector_account/down.sql
new file mode 100644
index 00000000000..8f751101092
--- /dev/null
+++ b/migrations/2023-02-20-101809_update_merchant_connector_account/down.sql
@@ -0,0 +1,7 @@
+ALTER TABLE merchant_connector_account
+DROP COLUMN IF EXISTS connector_label,
+DROP COLUMN IF EXISTS business_country,
+DROP COLUMN IF EXISTS business_label;
+
+DROP INDEX IF EXISTS merchant_connector_account_merchant_id_connector_label_index;
+CREATE UNIQUE INDEX merchant_connector_account_merchant_id_connector_name_index ON merchant_connector_account (merchant_id, connector_name);
\ No newline at end of file
diff --git a/migrations/2023-02-20-101809_update_merchant_connector_account/up.sql b/migrations/2023-02-20-101809_update_merchant_connector_account/up.sql
new file mode 100644
index 00000000000..567c869041a
--- /dev/null
+++ b/migrations/2023-02-20-101809_update_merchant_connector_account/up.sql
@@ -0,0 +1,8 @@
+ALTER TABLE merchant_connector_account
+ADD COLUMN connector_label VARCHAR(255) NOT NULL,
+ADD COLUMN business_country VARCHAR(64) NOT NULL,
+ADD COLUMN business_label VARCHAR(255) NOT NULL;
+
+DROP INDEX merchant_connector_account_merchant_id_connector_name_index;
+
+CREATE UNIQUE INDEX merchant_connector_account_merchant_id_connector_label_index ON merchant_connector_account (merchant_id, connector_label);
\ No newline at end of file
diff --git a/migrations/2023-02-21-065628_update_merchant_account/down.sql b/migrations/2023-02-21-065628_update_merchant_account/down.sql
new file mode 100644
index 00000000000..7ed0ee435ce
--- /dev/null
+++ b/migrations/2023-02-21-065628_update_merchant_account/down.sql
@@ -0,0 +1,2 @@
+ALTER TABLE merchant_account
+DROP COLUMN primary_business_details;
\ No newline at end of file
diff --git a/migrations/2023-02-21-065628_update_merchant_account/up.sql b/migrations/2023-02-21-065628_update_merchant_account/up.sql
new file mode 100644
index 00000000000..606d58b6603
--- /dev/null
+++ b/migrations/2023-02-21-065628_update_merchant_account/up.sql
@@ -0,0 +1,2 @@
+ALTER TABLE merchant_account
+ADD COLUMN primary_business_details JSON;
\ No newline at end of file
diff --git a/scripts/add_connector.sh b/scripts/add_connector.sh
old mode 100644
new mode 100755
index be5f201656e..061e3e5b71f
--- a/scripts/add_connector.sh
+++ b/scripts/add_connector.sh
@@ -1,3 +1,5 @@
+#! /usr/bin/env bash
+
 pg=$1;
 pgc="$(tr '[:lower:]' '[:upper:]' <<< ${pg:0:1})${pg:1}"
 src="crates/router/src"
@@ -9,41 +11,45 @@ if [[ -z "$pg" ]]; then
     exit
 fi
 cd $SCRIPT/..
+
 # remove template files if already created for this connector
 rm -rf $conn/$pg $conn/$pg.rs
 git checkout $conn.rs $src/types/api.rs $src/configs/settings.rs config/Development.toml config/docker_compose.toml config/config.example.toml loadtest/config/Development.toml crates/api_models/src/enums.rs
+
 # add enum for this connector in required places
 sed -i'' -e "s/pub use self::{/pub mod ${pg};\n\npub use self::{/" $conn.rs
 sed -i'' -e "s/};/${pg}::${pgc},\n};/" $conn.rs 
 sed -i'' -e "s/_ => Err/\"${pg}\" => Ok(Box::new(\&connector::${pgc})),\n\t\t\t_ => Err/" $src/types/api.rs
 sed -i'' -e "s/pub supported: SupportedConnectors,/pub supported: SupportedConnectors,\n\tpub ${pg}: ConnectorParams,/" $src/configs/settings.rs
-sed -i'' -e "s/\[scheduler\]/[connectors.${pg}]\nbase_url = \"\"\n\n[scheduler]/" config/Development.toml
-sed  -r -i'' -e "s/cards = \[/cards = [\n\t\"${pg}\",/" config/Development.toml
-sed -i'' -e "s/\[connectors.supported\]/[connectors.${pg}]\nbase_url = ""\n\n[connectors.supported]/" config/docker_compose.toml
-sed  -r -i'' -e "s/cards = \[/cards = [\n\t\"${pg}\",/" config/docker_compose.toml
-sed -i'' -e "s/\[connectors.supported\]/[connectors.${pg}]\nbase_url = ""\n\n[connectors.supported]/" config/config.example.toml
-sed  -r -i'' -e "s/cards = \[/cards = [\n\t\"${pg}\",/" config/config.example.toml
-sed -i'' -e "s/\[connectors.supported\]/[connectors.${pg}]\nbase_url = ""\n\n[connectors.supported]/" loadtest/config/Development.toml
-sed  -r -i'' -e "s/cards = \[/cards = [\n\t\"${pg}\",/" loadtest/config/Development.toml
+sed -i'' -e "s/\[connectors\]/[connectors]\n${pg}.base_url = \"\"/" config/Development.toml config/docker_compose.toml config/config.example.toml loadtest/config/Development.toml
+sed  -r -i'' -e "s/cards = \[/cards = [\n    \"${pg}\",/" config/Development.toml config/docker_compose.toml config/config.example.toml loadtest/config/Development.toml
 sed -i'' -e "s/Dummy,/Dummy,\n\t${pgc},/" crates/api_models/src/enums.rs
 sed -i'' -e "s/pub enum RoutableConnectors {/pub enum RoutableConnectors {\n\t${pgc},/" crates/api_models/src/enums.rs
+
 # remove temporary files created in above step
 rm $conn.rs-e $src/types/api.rs-e $src/configs/settings.rs-e config/Development.toml-e config/docker_compose.toml-e config/config.example.toml-e loadtest/config/Development.toml-e crates/api_models/src/enums.rs-e
 cd $conn/ 
+
 # generate template files for the connector
 cargo install cargo-generate
 cargo gen-pg $pg
+
 # move sub files and test files to appropriate folder
 mv $pg/mod.rs $pg.rs
 mv $pg/test.rs ${tests}/$pg.rs
+
 # remove changes from tests if already done for this connector
 git checkout ${tests}/main.rs ${tests}/connector_auth.rs 
+
 # add enum for this connector in test folder
 sed -i'' -e "s/mod utils;/mod ${pg};\nmod utils;/" ${tests}/main.rs
 sed -i'' -e "s/struct ConnectorAuthentication {/struct ConnectorAuthentication {\n\tpub ${pg}: Option<HeaderKey>,/" ${tests}/connector_auth.rs 
+
 # remove temporary files created in above step
 rm ${tests}/main.rs-e ${tests}/connector_auth.rs-e 
-cargo build
+cargo +nightly fmt --all
+cargo check
 echo "Successfully created connector. Running the tests of "$pg.rs
+
 # runs tests for the new connector
 cargo test --package router --test connectors -- $pg
\ No newline at end of file

# 0.5.0 (2023-03-21)

## Build System / Dependencies

* **deps:**  update deps (#734) (16bc886c)

## Chores

* **merchant_account:**  remove `api_key` field (#713) (230fcdd4)
* **config:**  move connector base URLs under the `[connectors]` table (#723) (df8c8b5a)
*  address Rust 1.68 clippy lints (#728) (1ffabb40)

## Continuous Integration

* **release:**  specify `fetch-depth` for code checkout and use official Docker GitHub actions (#722) (c451368f)

## Documentation Changes

*  Update naming conventions and added examples (#709) (98415193)
* **openapi:**  document path parameters for API keys endpoints (#702) (9062dc80)

## New Features

* **connector:**
  *  [Mollie]: add authorize, void, refund, psync, rsync support for mollie connector (#740) (168fa32)
  *  [worldline] add webhook support for connector (#721) (13a8ce8e)
  *  [Trustpay] add authorize (cards 3ds, no3ds and bank redirects), refund, psync, rsync (#717) (e102cae7)
  *  [Fiserv] add Refunds, Cancel and Wallets flow along with Unit Tests (#593) (cd1c5409)
  *  Add support for complete authorize payment after 3DS redirection (#741) (ec2b1b18)
*  removing unnecessary logs from console (#753) (1021d1ae)
*  Time based deletion of temp card (#729) (db3d3164)
*  populate fields from payment attempt in payment list (#736) (b5b3d57c)
*  add generic in-memory cache interface (#737) (7f5e5d86)
*  Add HSTS headers to response (#725) (7ed665ec)
*  cache reverse lookup fetches on redis (#719) (1a27faca)
* **compatibility:**  add webhook support for stripe compatibility (#710) (79160504)

## Bug Fixes

* **docker-compose:**  remove port for hyperswitch-server-init in docker-compose.yml (#763) (20b93276)
*  fixing docker compose setup & adding redisinsight (#748) (5c9bec9f)
* **kms:**  log KMS SDK errors using the `Debug` impl (#720) (468aa87f)
* **errors:**
  *  Replace PaymentMethod with PaymentModethodData in test.rs (#716) (763ee094)
  *  use `Debug` impl instead of `Display` for error types wrapping `error_stack::Report` (#714) (45484752)

## Other Changes

*  card_fingerprint not sent by basilisk_hs (#754) (5ae2f63f)

## Refactors

* **merchant_account:**  add back `api_key` field for backward compatibility (#761) (661dd48a)
* **connector:**  update add_connector script (#762) (78794ed6)
* **metrics:**  use macros for constructing counter and histogram metrics (#755) (58106d91)
* **kms:**  share a KMS client for all KMS operations (#744) (a3ff2e8d)
*  Basilisk hs integration (#704) (585618e5)
*  Add service_name to get and delete request (#738) (8b7ae9c3)
*  Add secret to metadata (#706) (d36afbed)
* **client:**
  *  simplify HTTP client construction (#731) (1756d1c4)
  *  remove dependence on `ROUTER_HTTP_PROXY` and `ROUTER_HTTPS_PROXY` env vars (#730) (c085e460)
* **authentication:**  authenticate merchant by API keys from API keys table (#712) (afd08d42)
* **api_keys:**  use a KMS encrypted API key hashing key and remove key ID prefix from plaintext API keys (#639) (3a3b33ac)

## Tests

* **masking:**  add suitable feature gates for basic tests (#745) (4859b6e4)