Bug: [FEATURE] Decision Engine Config API integration



### Feature Description

Need to integrate config APIs of Decision Engine with Hyperswitch

### Possible Implementation

We'll update the dynamic routing config API flows to incorporate the decision engine calls as well.

### 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/crates/api_models/src/open_router.rs b/crates/api_models/src/open_router.rs
index f80623efc64..f15d9cbcfeb 100644
--- a/crates/api_models/src/open_router.rs
+++ b/crates/api_models/src/open_router.rs
@@ -9,6 +9,7 @@ pub use euclid::{
     },
 };
 use serde::{Deserialize, Serialize};
+use utoipa::ToSchema;
 
 use crate::{
     enums::{Currency, PaymentMethod},
@@ -172,3 +173,148 @@ pub enum TxnStatus {
     Failure,
     Declined,
 }
+
+#[derive(Debug, Serialize, Deserialize, Clone)]
+pub struct DecisionEngineConfigSetupRequest {
+    pub merchant_id: String,
+    pub config: DecisionEngineConfigVariant,
+}
+
+#[derive(Debug, Serialize, Deserialize, Clone)]
+#[serde(tag = "type", content = "data")]
+#[serde(rename_all = "camelCase")]
+pub enum DecisionEngineConfigVariant {
+    SuccessRate(DecisionEngineSuccessRateData),
+    Elimination(DecisionEngineEliminationData),
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
+#[serde(rename_all = "camelCase")]
+pub struct DecisionEngineSuccessRateData {
+    pub default_latency_threshold: Option<f64>,
+    pub default_bucket_size: Option<i32>,
+    pub default_hedging_percent: Option<f64>,
+    pub default_lower_reset_factor: Option<f64>,
+    pub default_upper_reset_factor: Option<f64>,
+    pub default_gateway_extra_score: Option<Vec<DecisionEngineGatewayWiseExtraScore>>,
+    pub sub_level_input_config: Option<Vec<DecisionEngineSRSubLevelInputConfig>>,
+}
+
+impl DecisionEngineSuccessRateData {
+    pub fn update(&mut self, new_config: Self) {
+        if let Some(threshold) = new_config.default_latency_threshold {
+            self.default_latency_threshold = Some(threshold);
+        }
+        if let Some(bucket_size) = new_config.default_bucket_size {
+            self.default_bucket_size = Some(bucket_size);
+        }
+        if let Some(hedging_percent) = new_config.default_hedging_percent {
+            self.default_hedging_percent = Some(hedging_percent);
+        }
+        if let Some(lower_reset_factor) = new_config.default_lower_reset_factor {
+            self.default_lower_reset_factor = Some(lower_reset_factor);
+        }
+        if let Some(upper_reset_factor) = new_config.default_upper_reset_factor {
+            self.default_upper_reset_factor = Some(upper_reset_factor);
+        }
+        if let Some(gateway_extra_score) = new_config.default_gateway_extra_score {
+            self.default_gateway_extra_score
+                .as_mut()
+                .map(|score| score.extend(gateway_extra_score));
+        }
+        if let Some(sub_level_input_config) = new_config.sub_level_input_config {
+            self.sub_level_input_config.as_mut().map(|config| {
+                config.extend(sub_level_input_config);
+            });
+        }
+    }
+}
+#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
+#[serde(rename_all = "camelCase")]
+pub struct DecisionEngineSRSubLevelInputConfig {
+    pub payment_method_type: Option<String>,
+    pub payment_method: Option<String>,
+    pub latency_threshold: Option<f64>,
+    pub bucket_size: Option<i32>,
+    pub hedging_percent: Option<f64>,
+    pub lower_reset_factor: Option<f64>,
+    pub upper_reset_factor: Option<f64>,
+    pub gateway_extra_score: Option<Vec<DecisionEngineGatewayWiseExtraScore>>,
+}
+
+impl DecisionEngineSRSubLevelInputConfig {
+    pub fn update(&mut self, new_config: Self) {
+        if let Some(payment_method_type) = new_config.payment_method_type {
+            self.payment_method_type = Some(payment_method_type);
+        }
+        if let Some(payment_method) = new_config.payment_method {
+            self.payment_method = Some(payment_method);
+        }
+        if let Some(latency_threshold) = new_config.latency_threshold {
+            self.latency_threshold = Some(latency_threshold);
+        }
+        if let Some(bucket_size) = new_config.bucket_size {
+            self.bucket_size = Some(bucket_size);
+        }
+        if let Some(hedging_percent) = new_config.hedging_percent {
+            self.hedging_percent = Some(hedging_percent);
+        }
+        if let Some(lower_reset_factor) = new_config.lower_reset_factor {
+            self.lower_reset_factor = Some(lower_reset_factor);
+        }
+        if let Some(upper_reset_factor) = new_config.upper_reset_factor {
+            self.upper_reset_factor = Some(upper_reset_factor);
+        }
+        if let Some(gateway_extra_score) = new_config.gateway_extra_score {
+            self.gateway_extra_score
+                .as_mut()
+                .map(|score| score.extend(gateway_extra_score));
+        }
+    }
+}
+
+#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
+#[serde(rename_all = "camelCase")]
+pub struct DecisionEngineGatewayWiseExtraScore {
+    pub gateway_name: String,
+    pub gateway_sigma_factor: f64,
+}
+
+impl DecisionEngineGatewayWiseExtraScore {
+    pub fn update(&mut self, new_config: Self) {
+        self.gateway_name = new_config.gateway_name;
+        self.gateway_sigma_factor = new_config.gateway_sigma_factor;
+    }
+}
+
+#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
+#[serde(rename_all = "camelCase")]
+pub struct DecisionEngineEliminationData {
+    pub threshold: f64,
+}
+
+impl DecisionEngineEliminationData {
+    pub fn update(&mut self, new_config: Self) {
+        self.threshold = new_config.threshold;
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
+pub struct MerchantAccount {
+    pub merchant_id: String,
+    pub gateway_success_rate_based_decider_input: Option<String>,
+}
+
+#[derive(Debug, Serialize, Deserialize, Clone)]
+pub struct FetchRoutingConfig {
+    pub merchant_id: String,
+    pub algorithm: AlgorithmType,
+}
+
+#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
+#[serde(rename_all = "camelCase")]
+pub enum AlgorithmType {
+    SuccessRate,
+    Elimination,
+    DebitRouting,
+}
diff --git a/crates/api_models/src/routing.rs b/crates/api_models/src/routing.rs
index e1802ab56f5..12075935cd4 100644
--- a/crates/api_models/src/routing.rs
+++ b/crates/api_models/src/routing.rs
@@ -1,6 +1,10 @@
 use std::fmt::Debug;
 
-use common_utils::{errors::ParsingError, ext_traits::ValueExt, pii};
+use common_utils::{
+    errors::{ParsingError, ValidationError},
+    ext_traits::ValueExt,
+    pii,
+};
 pub use euclid::{
     dssa::types::EuclidAnalysable,
     frontend::{
@@ -11,7 +15,17 @@ pub use euclid::{
 use serde::{Deserialize, Serialize};
 use utoipa::ToSchema;
 
-use crate::enums::{RoutableConnectors, TransactionType};
+use crate::{
+    enums::{RoutableConnectors, TransactionType},
+    open_router,
+};
+
+// Define constants for default values
+const DEFAULT_LATENCY_THRESHOLD: f64 = 90.0;
+const DEFAULT_BUCKET_SIZE: i32 = 200;
+const DEFAULT_HEDGING_PERCENT: f64 = 5.0;
+const DEFAULT_ELIMINATION_THRESHOLD: f64 = 0.35;
+const DEFAULT_PAYMENT_METHOD: &str = "CARD";
 
 #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
 #[serde(tag = "type", content = "data", rename_all = "snake_case")]
@@ -834,6 +848,8 @@ pub struct ToggleDynamicRoutingPath {
 pub struct EliminationRoutingConfig {
     pub params: Option<Vec<DynamicRoutingConfigParams>>,
     pub elimination_analyser_config: Option<EliminationAnalyserConfig>,
+    #[schema(value_type = DecisionEngineEliminationData)]
+    pub decision_engine_configs: Option<open_router::DecisionEngineEliminationData>,
 }
 
 #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Copy, ToSchema)]
@@ -861,6 +877,7 @@ impl Default for EliminationRoutingConfig {
                 bucket_size: Some(5),
                 bucket_leak_interval_in_secs: Some(60),
             }),
+            decision_engine_configs: None,
         }
     }
 }
@@ -875,6 +892,34 @@ impl EliminationRoutingConfig {
                 .as_mut()
                 .map(|config| config.update(new_config));
         }
+        if let Some(new_config) = new.decision_engine_configs {
+            self.decision_engine_configs
+                .as_mut()
+                .map(|config| config.update(new_config));
+        }
+    }
+
+    pub fn open_router_config_default() -> Self {
+        Self {
+            elimination_analyser_config: None,
+            params: None,
+            decision_engine_configs: Some(open_router::DecisionEngineEliminationData {
+                threshold: DEFAULT_ELIMINATION_THRESHOLD,
+            }),
+        }
+    }
+
+    pub fn get_decision_engine_configs(
+        &self,
+    ) -> Result<open_router::DecisionEngineEliminationData, error_stack::Report<ValidationError>>
+    {
+        self.decision_engine_configs
+            .clone()
+            .ok_or(error_stack::Report::new(
+                ValidationError::MissingRequiredField {
+                    field_name: "decision_engine_configs".to_string(),
+                },
+            ))
     }
 }
 
@@ -882,6 +927,8 @@ impl EliminationRoutingConfig {
 pub struct SuccessBasedRoutingConfig {
     pub params: Option<Vec<DynamicRoutingConfigParams>>,
     pub config: Option<SuccessBasedRoutingConfigBody>,
+    #[schema(value_type = DecisionEngineSuccessRateData)]
+    pub decision_engine_configs: Option<open_router::DecisionEngineSuccessRateData>,
 }
 
 impl Default for SuccessBasedRoutingConfig {
@@ -898,6 +945,7 @@ impl Default for SuccessBasedRoutingConfig {
                 }),
                 specificity_level: SuccessRateSpecificityLevel::default(),
             }),
+            decision_engine_configs: None,
         }
     }
 }
@@ -982,6 +1030,51 @@ impl SuccessBasedRoutingConfig {
         if let Some(new_config) = new.config {
             self.config.as_mut().map(|config| config.update(new_config));
         }
+        if let Some(new_config) = new.decision_engine_configs {
+            self.decision_engine_configs
+                .as_mut()
+                .map(|config| config.update(new_config));
+        }
+    }
+
+    pub fn open_router_config_default() -> Self {
+        Self {
+            params: None,
+            config: None,
+            decision_engine_configs: Some(open_router::DecisionEngineSuccessRateData {
+                default_latency_threshold: Some(DEFAULT_LATENCY_THRESHOLD),
+                default_bucket_size: Some(DEFAULT_BUCKET_SIZE),
+                default_hedging_percent: Some(DEFAULT_HEDGING_PERCENT),
+                default_lower_reset_factor: None,
+                default_upper_reset_factor: None,
+                default_gateway_extra_score: None,
+                sub_level_input_config: Some(vec![
+                    open_router::DecisionEngineSRSubLevelInputConfig {
+                        payment_method_type: Some(DEFAULT_PAYMENT_METHOD.to_string()),
+                        payment_method: None,
+                        latency_threshold: None,
+                        bucket_size: Some(DEFAULT_BUCKET_SIZE),
+                        hedging_percent: Some(DEFAULT_HEDGING_PERCENT),
+                        lower_reset_factor: None,
+                        upper_reset_factor: None,
+                        gateway_extra_score: None,
+                    },
+                ]),
+            }),
+        }
+    }
+
+    pub fn get_decision_engine_configs(
+        &self,
+    ) -> Result<open_router::DecisionEngineSuccessRateData, error_stack::Report<ValidationError>>
+    {
+        self.decision_engine_configs
+            .clone()
+            .ok_or(error_stack::Report::new(
+                ValidationError::MissingRequiredField {
+                    field_name: "decision_engine_configs".to_string(),
+                },
+            ))
     }
 }
 
diff --git a/crates/openapi/src/openapi.rs b/crates/openapi/src/openapi.rs
index 79c4467f039..b042d2bdbd6 100644
--- a/crates/openapi/src/openapi.rs
+++ b/crates/openapi/src/openapi.rs
@@ -743,6 +743,10 @@ Never share your secret api keys. Keep them guarded and secure.
         api_models::feature_matrix::PaymentMethodSpecificFeatures,
         api_models::feature_matrix::CardSpecificFeatures,
         api_models::feature_matrix::SupportedPaymentMethod,
+        api_models::open_router::DecisionEngineSuccessRateData,
+        api_models::open_router::DecisionEngineGatewayWiseExtraScore,
+        api_models::open_router::DecisionEngineSRSubLevelInputConfig,
+        api_models::open_router::DecisionEngineEliminationData,
     )),
     modifiers(&SecurityAddon)
 )]
diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs
index 5db9e708a47..860d82ab487 100644
--- a/crates/router/src/core/admin.rs
+++ b/crates/router/src/core/admin.rs
@@ -258,6 +258,26 @@ pub async fn create_merchant_account(
         .await
         .to_duplicate_response(errors::ApiErrorResponse::DuplicateMerchantAccount)?;
 
+    // Call to DE here
+    // Check if creation should be based on default profile
+    #[cfg(all(feature = "dynamic_routing", feature = "v1"))]
+    {
+        if state.conf.open_router.enabled {
+            merchant_account
+                .default_profile
+                .as_ref()
+                .async_map(|profile_id| {
+                    routing::helpers::create_decision_engine_merchant(&state, profile_id)
+                })
+                .await
+                .transpose()
+                .map_err(|err| {
+                    crate::logger::error!("Failed to create merchant in Decision Engine {err:?}");
+                })
+                .ok();
+        }
+    }
+
     let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(domain::Context(
         merchant_account.clone(),
         key_store.clone(),
@@ -1171,6 +1191,25 @@ pub async fn merchant_account_delete(
         is_deleted = is_merchant_account_deleted && is_merchant_key_store_deleted;
     }
 
+    // Call to DE here
+    #[cfg(all(feature = "dynamic_routing", feature = "v1"))]
+    {
+        if state.conf.open_router.enabled && is_deleted {
+            merchant_account
+                .default_profile
+                .as_ref()
+                .async_map(|profile_id| {
+                    routing::helpers::delete_decision_engine_merchant(&state, profile_id)
+                })
+                .await
+                .transpose()
+                .map_err(|err| {
+                    crate::logger::error!("Failed to delete merchant in Decision Engine {err:?}");
+                })
+                .ok();
+        }
+    }
+
     let state = state.clone();
     authentication::decision::spawn_tracked_job(
         async move {
diff --git a/crates/router/src/core/payments/routing.rs b/crates/router/src/core/payments/routing.rs
index 83d3abef44e..2b851c192b0 100644
--- a/crates/router/src/core/payments/routing.rs
+++ b/crates/router/src/core/payments/routing.rs
@@ -59,7 +59,9 @@ use crate::core::routing::transformers::OpenRouterDecideGatewayRequestExt;
 #[cfg(all(feature = "v1", feature = "dynamic_routing"))]
 use crate::headers;
 use crate::{
-    core::{errors, errors as oss_errors, payments::routing::utils::EuclidApiHandler, routing},
+    core::{
+        errors, errors as oss_errors, payments::routing::utils::DecisionEngineApiHandler, routing,
+    },
     logger, services,
     types::{
         api::{self, routing as routing_types},
@@ -1605,14 +1607,15 @@ pub async fn perform_open_routing_for_debit_routing(
         Some(or_types::RankingAlgorithm::NtwBasedRouting),
     );
 
-    let response: RoutingResult<DecidedGateway> = utils::EuclidApiClient::send_euclid_request(
-        state,
-        services::Method::Post,
-        "decide-gateway",
-        Some(open_router_req_body),
-        None,
-    )
-    .await;
+    let response: RoutingResult<DecidedGateway> =
+        utils::EuclidApiClient::send_decision_engine_request(
+            state,
+            services::Method::Post,
+            "decide-gateway",
+            Some(open_router_req_body),
+            None,
+        )
+        .await;
 
     let output = match response {
         Ok(decided_gateway) => {
diff --git a/crates/router/src/core/payments/routing/utils.rs b/crates/router/src/core/payments/routing/utils.rs
index 551694a0aaf..e82ab1d8bee 100644
--- a/crates/router/src/core/payments/routing/utils.rs
+++ b/crates/router/src/core/payments/routing/utils.rs
@@ -18,8 +18,8 @@ use crate::{
 
 // New Trait for handling Euclid API calls
 #[async_trait]
-pub trait EuclidApiHandler {
-    async fn send_euclid_request<Req, Res>(
+pub trait DecisionEngineApiHandler {
+    async fn send_decision_engine_request<Req, Res>(
         state: &SessionState,
         http_method: services::Method,
         path: &str,
@@ -30,7 +30,7 @@ pub trait EuclidApiHandler {
         Req: Serialize + Send + Sync + 'static,
         Res: serde::de::DeserializeOwned + Send + 'static + std::fmt::Debug;
 
-    async fn send_euclid_request_without_response_parsing<Req>(
+    async fn send_decision_engine_request_without_response_parsing<Req>(
         state: &SessionState,
         http_method: services::Method,
         path: &str,
@@ -41,65 +41,132 @@ pub trait EuclidApiHandler {
         Req: Serialize + Send + Sync + 'static;
 }
 
-// Struct to implement the EuclidApiHandler trait
+// Struct to implement the DecisionEngineApiHandler trait
 pub struct EuclidApiClient;
 
-impl EuclidApiClient {
-    async fn build_and_send_euclid_http_request<Req>(
+pub struct ConfigApiClient;
+
+pub async fn build_and_send_decision_engine_http_request<Req>(
+    state: &SessionState,
+    http_method: services::Method,
+    path: &str,
+    request_body: Option<Req>,
+    timeout: Option<u64>,
+    context_message: &str,
+) -> RoutingResult<reqwest::Response>
+where
+    Req: Serialize + Send + Sync + 'static,
+{
+    let decision_engine_base_url = &state.conf.open_router.url;
+    let url = format!("{}/{}", decision_engine_base_url, path);
+    logger::debug!(decision_engine_api_call_url = %url, decision_engine_request_path = %path, http_method = ?http_method, "decision_engine: Initiating decision_engine API call ({})", context_message);
+
+    let mut request_builder = services::RequestBuilder::new()
+        .method(http_method)
+        .url(&url);
+
+    if let Some(body_content) = request_body {
+        let body = common_utils::request::RequestContent::Json(Box::new(body_content));
+        request_builder = request_builder.set_body(body);
+    }
+
+    let http_request = request_builder.build();
+    logger::info!(?http_request, decision_engine_request_path = %path, "decision_engine: Constructed Decision Engine API request details ({})", context_message);
+
+    state
+        .api_client
+        .send_request(state, http_request, timeout, false)
+        .await
+        .change_context(errors::RoutingError::DslExecutionError)
+        .attach_printable_lazy(|| {
+            format!(
+                "Decision Engine API call to path '{}' unresponsive ({})",
+                path, context_message
+            )
+        })
+}
+
+#[async_trait]
+impl DecisionEngineApiHandler for EuclidApiClient {
+    async fn send_decision_engine_request<Req, Res>(
         state: &SessionState,
         http_method: services::Method,
         path: &str,
-        request_body: Option<Req>,
+        request_body: Option<Req>, // Option to handle GET/DELETE requests without body
         timeout: Option<u64>,
-        context_message: &str,
-    ) -> RoutingResult<reqwest::Response>
+    ) -> RoutingResult<Res>
     where
         Req: Serialize + Send + Sync + 'static,
+        Res: serde::de::DeserializeOwned + Send + 'static + std::fmt::Debug,
     {
-        let euclid_base_url = &state.conf.open_router.url;
-        let url = format!("{}/{}", euclid_base_url, path);
-        logger::debug!(euclid_api_call_url = %url, euclid_request_path = %path, http_method = ?http_method, "decision_engine_euclid: Initiating Euclid API call ({})", context_message);
-
-        let mut request_builder = services::RequestBuilder::new()
-            .method(http_method)
-            .url(&url);
-
-        if let Some(body_content) = request_body {
-            let body = common_utils::request::RequestContent::Json(Box::new(body_content));
-            request_builder = request_builder.set_body(body);
-        }
-
-        let http_request = request_builder.build();
-        logger::info!(?http_request, euclid_request_path = %path, "decision_engine_euclid: Constructed Euclid API request details ({})", context_message);
+        let response = build_and_send_decision_engine_http_request(
+            state,
+            http_method,
+            path,
+            request_body,
+            timeout,
+            "parsing response",
+        )
+        .await?;
+        logger::debug!(euclid_response = ?response, euclid_request_path = %path, "decision_engine_euclid: Received raw response from Euclid API");
 
-        state
-            .api_client
-            .send_request(state, http_request, timeout, false)
+        let parsed_response = response
+            .json::<Res>()
             .await
-            .change_context(errors::RoutingError::DslExecutionError)
+            .change_context(errors::RoutingError::GenericConversionError {
+                from: "ApiResponse".to_string(),
+                to: std::any::type_name::<Res>().to_string(),
+            })
             .attach_printable_lazy(|| {
                 format!(
-                    "Euclid API call to path '{}' unresponsive ({})",
-                    path, context_message
+                    "Unable to parse response of type '{}' received from Euclid API path: {}",
+                    std::any::type_name::<Res>(),
+                    path
                 )
-            })
+            })?;
+        logger::debug!(parsed_response = ?parsed_response, response_type = %std::any::type_name::<Res>(), euclid_request_path = %path, "decision_engine_euclid: Successfully parsed response from Euclid API");
+        Ok(parsed_response)
+    }
+
+    async fn send_decision_engine_request_without_response_parsing<Req>(
+        state: &SessionState,
+        http_method: services::Method,
+        path: &str,
+        request_body: Option<Req>,
+        timeout: Option<u64>,
+    ) -> RoutingResult<()>
+    where
+        Req: Serialize + Send + Sync + 'static,
+    {
+        let response = build_and_send_decision_engine_http_request(
+            state,
+            http_method,
+            path,
+            request_body,
+            timeout,
+            "not parsing response",
+        )
+        .await?;
+
+        logger::debug!(euclid_response = ?response, euclid_request_path = %path, "decision_engine_routing: Received raw response from Euclid API");
+        Ok(())
     }
 }
 
 #[async_trait]
-impl EuclidApiHandler for EuclidApiClient {
-    async fn send_euclid_request<Req, Res>(
+impl DecisionEngineApiHandler for ConfigApiClient {
+    async fn send_decision_engine_request<Req, Res>(
         state: &SessionState,
         http_method: services::Method,
         path: &str,
-        request_body: Option<Req>, // Option to handle GET/DELETE requests without body
+        request_body: Option<Req>,
         timeout: Option<u64>,
     ) -> RoutingResult<Res>
     where
         Req: Serialize + Send + Sync + 'static,
         Res: serde::de::DeserializeOwned + Send + 'static + std::fmt::Debug,
     {
-        let response = Self::build_and_send_euclid_http_request(
+        let response = build_and_send_decision_engine_http_request(
             state,
             http_method,
             path,
@@ -108,7 +175,7 @@ impl EuclidApiHandler for EuclidApiClient {
             "parsing response",
         )
         .await?;
-        logger::debug!(euclid_response = ?response, euclid_request_path = %path, "decision_engine_euclid: Received raw response from Euclid API");
+        logger::debug!(decision_engine_config_response = ?response, decision_engine_request_path = %path, "decision_engine_config: Received raw response from Decision Engine config API");
 
         let parsed_response = response
             .json::<Res>()
@@ -119,16 +186,16 @@ impl EuclidApiHandler for EuclidApiClient {
             })
             .attach_printable_lazy(|| {
                 format!(
-                    "Unable to parse response of type '{}' received from Euclid API path: {}",
+                    "Unable to parse response of type '{}' received from Decision Engine config API path: {}",
                     std::any::type_name::<Res>(),
                     path
                 )
             })?;
-        logger::debug!(parsed_response = ?parsed_response, response_type = %std::any::type_name::<Res>(), euclid_request_path = %path, "decision_engine_euclid: Successfully parsed response from Euclid API");
+        logger::debug!(parsed_response = ?parsed_response, response_type = %std::any::type_name::<Res>(), decision_engine_request_path = %path, "decision_engine_config: Successfully parsed response from Decision Engine config API");
         Ok(parsed_response)
     }
 
-    async fn send_euclid_request_without_response_parsing<Req>(
+    async fn send_decision_engine_request_without_response_parsing<Req>(
         state: &SessionState,
         http_method: services::Method,
         path: &str,
@@ -138,7 +205,7 @@ impl EuclidApiHandler for EuclidApiClient {
     where
         Req: Serialize + Send + Sync + 'static,
     {
-        let response = Self::build_and_send_euclid_http_request(
+        let response = build_and_send_decision_engine_http_request(
             state,
             http_method,
             path,
@@ -148,7 +215,7 @@ impl EuclidApiHandler for EuclidApiClient {
         )
         .await?;
 
-        logger::debug!(euclid_response = ?response, euclid_request_path = %path, "decision_engine_routing: Received raw response from Euclid API");
+        logger::debug!(decision_engine_response = ?response, decision_engine_request_path = %path, "decision_engine_config: Received raw response from Decision Engine config API");
         Ok(())
     }
 }
@@ -164,7 +231,7 @@ pub async fn perform_decision_euclid_routing(
 
     let routing_request = convert_backend_input_to_routing_eval(created_by, input)?;
 
-    let euclid_response: RoutingEvaluateResponse = EuclidApiClient::send_euclid_request(
+    let euclid_response: RoutingEvaluateResponse = EuclidApiClient::send_decision_engine_request(
         state,
         services::Method::Post,
         "routing/evaluate",
@@ -186,7 +253,7 @@ pub async fn create_de_euclid_routing_algo(
     logger::debug!("decision_engine_euclid: create api call for euclid routing rule creation");
 
     logger::debug!(decision_engine_euclid_request=?routing_request,"decision_engine_euclid");
-    let euclid_response: RoutingDictionaryRecord = EuclidApiClient::send_euclid_request(
+    let euclid_response: RoutingDictionaryRecord = EuclidApiClient::send_decision_engine_request(
         state,
         services::Method::Post,
         "routing/create",
@@ -205,7 +272,7 @@ pub async fn link_de_euclid_routing_algorithm(
 ) -> RoutingResult<()> {
     logger::debug!("decision_engine_euclid: link api call for euclid routing algorithm");
 
-    EuclidApiClient::send_euclid_request_without_response_parsing(
+    EuclidApiClient::send_decision_engine_request_without_response_parsing(
         state,
         services::Method::Post,
         "routing/activate",
@@ -224,7 +291,7 @@ pub async fn list_de_euclid_routing_algorithms(
 ) -> RoutingResult<Vec<api_routing::RoutingDictionaryRecord>> {
     logger::debug!("decision_engine_euclid: list api call for euclid routing algorithms");
     let created_by = routing_list_request.created_by;
-    let response: Vec<RoutingAlgorithmRecord> = EuclidApiClient::send_euclid_request(
+    let response: Vec<RoutingAlgorithmRecord> = EuclidApiClient::send_decision_engine_request(
         state,
         services::Method::Post,
         format!("routing/list/{created_by}").as_str(),
diff --git a/crates/router/src/core/routing.rs b/crates/router/src/core/routing.rs
index 6b86bb83f54..893c66af24c 100644
--- a/crates/router/src/core/routing.rs
+++ b/crates/router/src/core/routing.rs
@@ -19,6 +19,8 @@ use external_services::grpc_client::dynamic_routing::{
     elimination_based_client::EliminationBasedRouting,
     success_rate_client::SuccessBasedDynamicRouting,
 };
+#[cfg(all(feature = "v1", feature = "dynamic_routing"))]
+use helpers::update_decision_engine_dynamic_routing_setup;
 use hyperswitch_domain_models::{mandates, payment_address};
 #[cfg(all(feature = "v1", feature = "dynamic_routing"))]
 use router_env::logger;
@@ -564,6 +566,24 @@ pub async fn link_routing_config(
                     .enabled_feature,
                 routing_types::DynamicRoutingType::SuccessRateBasedRouting,
             );
+
+                // Call to DE here to update SR configs
+                #[cfg(all(feature = "dynamic_routing", feature = "v1"))]
+                {
+                    if state.conf.open_router.enabled {
+                        update_decision_engine_dynamic_routing_setup(
+                            &state,
+                            business_profile.get_id(),
+                            routing_algorithm.algorithm_data.clone(),
+                            routing_types::DynamicRoutingType::SuccessRateBasedRouting,
+                        )
+                        .await
+                        .change_context(errors::ApiErrorResponse::InternalServerError)
+                        .attach_printable(
+                            "Failed to update the success rate routing config in Decision Engine",
+                        )?;
+                    }
+                }
             } else if routing_algorithm.name == helpers::ELIMINATION_BASED_DYNAMIC_ROUTING_ALGORITHM
             {
                 dynamic_routing_ref.update_algorithm_id(
@@ -578,6 +598,22 @@ pub async fn link_routing_config(
                     .enabled_feature,
                 routing_types::DynamicRoutingType::EliminationRouting,
             );
+                #[cfg(all(feature = "dynamic_routing", feature = "v1"))]
+                {
+                    if state.conf.open_router.enabled {
+                        update_decision_engine_dynamic_routing_setup(
+                            &state,
+                            business_profile.get_id(),
+                            routing_algorithm.algorithm_data.clone(),
+                            routing_types::DynamicRoutingType::EliminationRouting,
+                        )
+                        .await
+                        .change_context(errors::ApiErrorResponse::InternalServerError)
+                        .attach_printable(
+                            "Failed to update the elimination routing config in Decision Engine",
+                        )?;
+                    }
+                }
             } else if routing_algorithm.name == helpers::CONTRACT_BASED_DYNAMIC_ROUTING_ALGORITHM {
                 dynamic_routing_ref.update_algorithm_id(
                 algorithm_id,
@@ -1516,7 +1552,7 @@ pub async fn success_based_routing_update_configs(
         name: dynamic_routing_algo_to_update.name,
         description: dynamic_routing_algo_to_update.description,
         kind: dynamic_routing_algo_to_update.kind,
-        algorithm_data: serde_json::json!(config_to_update),
+        algorithm_data: serde_json::json!(config_to_update.clone()),
         created_at: timestamp,
         modified_at: timestamp,
         algorithm_for: dynamic_routing_algo_to_update.algorithm_for,
@@ -1551,23 +1587,25 @@ pub async fn success_based_routing_update_configs(
         router_env::metric_attributes!(("profile_id", profile_id.clone())),
     );
 
-    state
-        .grpc_client
-        .dynamic_routing
-        .success_rate_client
-        .as_ref()
-        .async_map(|sr_client| async {
-            sr_client
-                .invalidate_success_rate_routing_keys(
-                    profile_id.get_string_repr().into(),
-                    state.get_grpc_headers(),
-                )
-                .await
-                .change_context(errors::ApiErrorResponse::InternalServerError)
-                .attach_printable("Failed to invalidate the routing keys")
-        })
-        .await
-        .transpose()?;
+    if !state.conf.open_router.enabled {
+        state
+            .grpc_client
+            .dynamic_routing
+            .success_rate_client
+            .as_ref()
+            .async_map(|sr_client| async {
+                sr_client
+                    .invalidate_success_rate_routing_keys(
+                        profile_id.get_string_repr().into(),
+                        state.get_grpc_headers(),
+                    )
+                    .await
+                    .change_context(errors::ApiErrorResponse::InternalServerError)
+                    .attach_printable("Failed to invalidate the routing keys")
+            })
+            .await
+            .transpose()?;
+    }
 
     Ok(service_api::ApplicationResponse::Json(new_record))
 }
@@ -1653,23 +1691,25 @@ pub async fn elimination_routing_update_configs(
         router_env::metric_attributes!(("profile_id", profile_id.clone())),
     );
 
-    state
-        .grpc_client
-        .dynamic_routing
-        .elimination_based_client
-        .as_ref()
-        .async_map(|er_client| async {
-            er_client
-                .invalidate_elimination_bucket(
-                    profile_id.get_string_repr().into(),
-                    state.get_grpc_headers(),
-                )
-                .await
-                .change_context(errors::ApiErrorResponse::InternalServerError)
-                .attach_printable("Failed to invalidate the elimination routing keys")
-        })
-        .await
-        .transpose()?;
+    if !state.conf.open_router.enabled {
+        state
+            .grpc_client
+            .dynamic_routing
+            .elimination_based_client
+            .as_ref()
+            .async_map(|er_client| async {
+                er_client
+                    .invalidate_elimination_bucket(
+                        profile_id.get_string_repr().into(),
+                        state.get_grpc_headers(),
+                    )
+                    .await
+                    .change_context(errors::ApiErrorResponse::InternalServerError)
+                    .attach_printable("Failed to invalidate the elimination routing keys")
+            })
+            .await
+            .transpose()?;
+    }
 
     Ok(service_api::ApplicationResponse::Json(new_record))
 }
diff --git a/crates/router/src/core/routing/helpers.rs b/crates/router/src/core/routing/helpers.rs
index e5cbd1b653f..1a092c8cf68 100644
--- a/crates/router/src/core/routing/helpers.rs
+++ b/crates/router/src/core/routing/helpers.rs
@@ -52,7 +52,12 @@ use crate::{
 };
 #[cfg(all(feature = "dynamic_routing", feature = "v1"))]
 use crate::{
-    core::{metrics as core_metrics, routing},
+    core::{
+        metrics as core_metrics,
+        payments::routing::utils::{self as routing_utils, DecisionEngineApiHandler},
+        routing,
+    },
+    services,
     types::transformers::ForeignInto,
 };
 pub const SUCCESS_BASED_DYNAMIC_ROUTING_ALGORITHM: &str =
@@ -62,6 +67,12 @@ pub const ELIMINATION_BASED_DYNAMIC_ROUTING_ALGORITHM: &str =
 pub const CONTRACT_BASED_DYNAMIC_ROUTING_ALGORITHM: &str =
     "Contract based dynamic routing algorithm";
 
+pub const DECISION_ENGINE_RULE_CREATE_ENDPOINT: &str = "rule/create";
+pub const DECISION_ENGINE_RULE_UPDATE_ENDPOINT: &str = "rule/update";
+pub const DECISION_ENGINE_RULE_DELETE_ENDPOINT: &str = "rule/delete";
+pub const DECISION_ENGINE_MERCHANT_BASE_ENDPOINT: &str = "merchant-account";
+pub const DECISION_ENGINE_MERCHANT_CREATE_ENDPOINT: &str = "merchant-account/create";
+
 /// Provides us with all the configured configs of the Merchant in the ascending time configured
 /// manner and chooses the first of them
 pub async fn get_merchant_default_config(
@@ -1625,6 +1636,18 @@ pub async fn disable_dynamic_routing_algorithm(
             }
         };
 
+    // Call to DE here
+    if state.conf.open_router.enabled {
+        disable_decision_engine_dynamic_routing_setup(
+            state,
+            business_profile.get_id(),
+            dynamic_routing_type,
+        )
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("unable to disable dynamic routing setup in decision engine")?;
+    }
+
     // redact cache for dynamic routing config
     let _ = cache::redact_from_redis_and_publish(
         state.store.get_cache_store().as_ref(),
@@ -1801,8 +1824,12 @@ pub async fn default_specific_dynamic_routing_setup(
     let timestamp = common_utils::date_time::now();
     let algo = match dynamic_routing_type {
         routing_types::DynamicRoutingType::SuccessRateBasedRouting => {
-            let default_success_based_routing_config =
-                routing_types::SuccessBasedRoutingConfig::default();
+            let default_success_based_routing_config = if state.conf.open_router.enabled {
+                routing_types::SuccessBasedRoutingConfig::open_router_config_default()
+            } else {
+                routing_types::SuccessBasedRoutingConfig::default()
+            };
+
             routing_algorithm::RoutingAlgorithm {
                 algorithm_id: algorithm_id.clone(),
                 profile_id: profile_id.clone(),
@@ -1818,8 +1845,11 @@ pub async fn default_specific_dynamic_routing_setup(
             }
         }
         routing_types::DynamicRoutingType::EliminationRouting => {
-            let default_elimination_routing_config =
-                routing_types::EliminationRoutingConfig::default();
+            let default_elimination_routing_config = if state.conf.open_router.enabled {
+                routing_types::EliminationRoutingConfig::open_router_config_default()
+            } else {
+                routing_types::EliminationRoutingConfig::default()
+            };
             routing_algorithm::RoutingAlgorithm {
                 algorithm_id: algorithm_id.clone(),
                 profile_id: profile_id.clone(),
@@ -1843,6 +1873,19 @@ pub async fn default_specific_dynamic_routing_setup(
         }
     };
 
+    // Call to DE here
+    // Need to map out the cases if this call should always be made or not
+    if state.conf.open_router.enabled {
+        enable_decision_engine_dynamic_routing_setup(
+            state,
+            business_profile.get_id(),
+            dynamic_routing_type,
+        )
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Unable to setup decision engine dynamic routing")?;
+    }
+
     let record = db
         .insert_routing_algorithm(algo)
         .await
@@ -1945,3 +1988,234 @@ impl DynamicRoutingConfigParamsInterpolator {
         parts.join(":")
     }
 }
+
+#[cfg(all(feature = "dynamic_routing", feature = "v1"))]
+#[instrument(skip_all)]
+pub async fn enable_decision_engine_dynamic_routing_setup(
+    state: &SessionState,
+    profile_id: &id_type::ProfileId,
+    dynamic_routing_type: routing_types::DynamicRoutingType,
+) -> RouterResult<()> {
+    logger::debug!(
+        "performing call with open_router for profile {}",
+        profile_id.get_string_repr()
+    );
+
+    let default_engine_config_request = match dynamic_routing_type {
+        routing_types::DynamicRoutingType::SuccessRateBasedRouting => {
+            let default_success_based_routing_config =
+                routing_types::SuccessBasedRoutingConfig::open_router_config_default();
+            open_router::DecisionEngineConfigSetupRequest {
+                merchant_id: profile_id.get_string_repr().to_string(),
+                config: open_router::DecisionEngineConfigVariant::SuccessRate(
+                    default_success_based_routing_config
+                        .get_decision_engine_configs()
+                        .change_context(errors::ApiErrorResponse::GenericNotFoundError {
+                            message: "Decision engine config not found".to_string(),
+                        })
+                        .attach_printable("Decision engine config not found")?,
+                ),
+            }
+        }
+        routing_types::DynamicRoutingType::EliminationRouting => {
+            let default_elimination_based_routing_config =
+                routing_types::EliminationRoutingConfig::open_router_config_default();
+            open_router::DecisionEngineConfigSetupRequest {
+                merchant_id: profile_id.get_string_repr().to_string(),
+                config: open_router::DecisionEngineConfigVariant::Elimination(
+                    default_elimination_based_routing_config
+                        .get_decision_engine_configs()
+                        .change_context(errors::ApiErrorResponse::GenericNotFoundError {
+                            message: "Decision engine config not found".to_string(),
+                        })
+                        .attach_printable("Decision engine config not found")?,
+                ),
+            }
+        }
+        routing_types::DynamicRoutingType::ContractBasedRouting => {
+            return Err((errors::ApiErrorResponse::InvalidRequestData {
+                message: "Contract routing cannot be set as default".to_string(),
+            })
+            .into())
+        }
+    };
+
+    routing_utils::ConfigApiClient::send_decision_engine_request::<_, String>(
+        state,
+        services::Method::Post,
+        DECISION_ENGINE_RULE_CREATE_ENDPOINT,
+        Some(default_engine_config_request),
+        None,
+    )
+    .await
+    .change_context(errors::ApiErrorResponse::InternalServerError)
+    .attach_printable("Unable to setup decision engine dynamic routing")?;
+
+    Ok(())
+}
+
+#[cfg(all(feature = "dynamic_routing", feature = "v1"))]
+#[instrument(skip_all)]
+pub async fn update_decision_engine_dynamic_routing_setup(
+    state: &SessionState,
+    profile_id: &id_type::ProfileId,
+    request: serde_json::Value,
+    dynamic_routing_type: routing_types::DynamicRoutingType,
+) -> RouterResult<()> {
+    logger::debug!(
+        "performing call with open_router for profile {}",
+        profile_id.get_string_repr()
+    );
+
+    let decision_engine_request = match dynamic_routing_type {
+        routing_types::DynamicRoutingType::SuccessRateBasedRouting => {
+            let success_rate_config: routing_types::SuccessBasedRoutingConfig = request
+                .parse_value("SuccessBasedRoutingConfig")
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("unable to deserialize SuccessBasedRoutingConfig")?;
+
+            open_router::DecisionEngineConfigSetupRequest {
+                merchant_id: profile_id.get_string_repr().to_string(),
+                config: open_router::DecisionEngineConfigVariant::SuccessRate(
+                    success_rate_config
+                        .get_decision_engine_configs()
+                        .change_context(errors::ApiErrorResponse::GenericNotFoundError {
+                            message: "Decision engine config not found".to_string(),
+                        })
+                        .attach_printable("Decision engine config not found")?,
+                ),
+            }
+        }
+        routing_types::DynamicRoutingType::EliminationRouting => {
+            let elimination_config: routing_types::EliminationRoutingConfig = request
+                .parse_value("EliminationRoutingConfig")
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("unable to deserialize EliminationRoutingConfig")?;
+
+            open_router::DecisionEngineConfigSetupRequest {
+                merchant_id: profile_id.get_string_repr().to_string(),
+                config: open_router::DecisionEngineConfigVariant::Elimination(
+                    elimination_config
+                        .get_decision_engine_configs()
+                        .change_context(errors::ApiErrorResponse::GenericNotFoundError {
+                            message: "Decision engine config not found".to_string(),
+                        })
+                        .attach_printable("Decision engine config not found")?,
+                ),
+            }
+        }
+        routing_types::DynamicRoutingType::ContractBasedRouting => {
+            return Err((errors::ApiErrorResponse::InvalidRequestData {
+                message: "Contract routing cannot be set as default".to_string(),
+            })
+            .into())
+        }
+    };
+
+    routing_utils::ConfigApiClient::send_decision_engine_request::<_, String>(
+        state,
+        services::Method::Post,
+        DECISION_ENGINE_RULE_UPDATE_ENDPOINT,
+        Some(decision_engine_request),
+        None,
+    )
+    .await
+    .change_context(errors::ApiErrorResponse::InternalServerError)
+    .attach_printable("Unable to update decision engine dynamic routing")?;
+
+    Ok(())
+}
+
+#[cfg(all(feature = "dynamic_routing", feature = "v1"))]
+#[instrument(skip_all)]
+pub async fn disable_decision_engine_dynamic_routing_setup(
+    state: &SessionState,
+    profile_id: &id_type::ProfileId,
+    dynamic_routing_type: routing_types::DynamicRoutingType,
+) -> RouterResult<()> {
+    logger::debug!(
+        "performing call with open_router for profile {}",
+        profile_id.get_string_repr()
+    );
+
+    let decision_engine_request = open_router::FetchRoutingConfig {
+        merchant_id: profile_id.get_string_repr().to_string(),
+        algorithm: match dynamic_routing_type {
+            routing_types::DynamicRoutingType::SuccessRateBasedRouting => {
+                open_router::AlgorithmType::SuccessRate
+            }
+            routing_types::DynamicRoutingType::EliminationRouting => {
+                open_router::AlgorithmType::Elimination
+            }
+            routing_types::DynamicRoutingType::ContractBasedRouting => {
+                return Err((errors::ApiErrorResponse::InvalidRequestData {
+                    message: "Contract routing is not enabled for decision engine".to_string(),
+                })
+                .into())
+            }
+        },
+    };
+
+    routing_utils::ConfigApiClient::send_decision_engine_request::<_, String>(
+        state,
+        services::Method::Post,
+        DECISION_ENGINE_RULE_DELETE_ENDPOINT,
+        Some(decision_engine_request),
+        None,
+    )
+    .await
+    .change_context(errors::ApiErrorResponse::InternalServerError)
+    .attach_printable("Unable to disable decision engine dynamic routing")?;
+
+    Ok(())
+}
+
+#[cfg(all(feature = "dynamic_routing", feature = "v1"))]
+#[instrument(skip_all)]
+pub async fn create_decision_engine_merchant(
+    state: &SessionState,
+    profile_id: &id_type::ProfileId,
+) -> RouterResult<()> {
+    let merchant_account_req = open_router::MerchantAccount {
+        merchant_id: profile_id.get_string_repr().to_string(),
+        gateway_success_rate_based_decider_input: None,
+    };
+
+    routing_utils::ConfigApiClient::send_decision_engine_request::<_, String>(
+        state,
+        services::Method::Post,
+        DECISION_ENGINE_MERCHANT_CREATE_ENDPOINT,
+        Some(merchant_account_req),
+        None,
+    )
+    .await
+    .change_context(errors::ApiErrorResponse::InternalServerError)
+    .attach_printable("Failed to create merchant account on decision engine")?;
+
+    Ok(())
+}
+
+#[cfg(all(feature = "dynamic_routing", feature = "v1"))]
+#[instrument(skip_all)]
+pub async fn delete_decision_engine_merchant(
+    state: &SessionState,
+    profile_id: &id_type::ProfileId,
+) -> RouterResult<()> {
+    let path = format!(
+        "{}/{}",
+        DECISION_ENGINE_MERCHANT_BASE_ENDPOINT,
+        profile_id.get_string_repr()
+    );
+    routing_utils::ConfigApiClient::send_decision_engine_request_without_response_parsing::<()>(
+        state,
+        services::Method::Delete,
+        &path,
+        None,
+        None,
+    )
+    .await
+    .change_context(errors::ApiErrorResponse::InternalServerError)
+    .attach_printable("Failed to delete merchant account on decision engine")?;
+
+    Ok(())
+}

## 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 -->
This PR integrates the decision engine config APIs
The integration sits in the dynamic routing config flows. Based on ENV, if decision engine is enabled, we would call DE instead of Dynamo.

### Additional Changes

- [x] 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)?
-->
1. Create a merchant account (Call to Decision Engine should be made for merchant creation)
<img width="791" alt="image" src="https://github.com/user-attachments/assets/d01b64a5-9767-4fb2-ae88-8ebbe187dafe" />

2. Toggle SR config (Call to Decision Engine should be made for SR config creation)
```
curl --location --request POST 'http://localhost:8080/account/merchant_1747841259/business_profile/pro_GUovaynfuaBwH3DUaBbJ/dynamic_routing/success_based/toggle?enable=dynamic_connector_selection' \
--header 'api-key: dev_9gwSrzjH1Xbs7HMswLgx0Av8upsibfu8wORNxyzpIls3NvT08auKe4RBQlkBgqRl'
```
```
{"id":"routing_wd4JSbjaMmLDB96OxP7d","profile_id":"pro_GUovaynfuaBwH3DUaBbJ","name":"Success rate based dynamic routing algorithm","kind":"dynamic","description":"","created_at":1747841362,"modified_at":1747841362,"algorithm_for":"payment","decision_engine_routing_id":null}
```
<img width="816" alt="image" src="https://github.com/user-attachments/assets/92a3dba9-b77a-4f54-a004-51e52b452334" />

3. Update SR config
```
curl --location --request PATCH 'http://localhost:8080/account/merchant_1747841259/business_profile/pro_GUovaynfuaBwH3DUaBbJ/dynamic_routing/success_based/config/routing_wd4JSbjaMmLDB96OxP7d' \
--header 'api-key: dev_9gwSrzjH1Xbs7HMswLgx0Av8upsibfu8wORNxyzpIls3NvT08auKe4RBQlkBgqRl' \
--header 'Content-Type: application/json' \
--data '{
    "decision_engine_configs": {
        "defaultLatencyThreshold": 90,
        "defaultSuccessRate": 0.5,
        "defaultBucketSize": 200,
        "defaultHedgingPercent": 5,
        "subLevelInputConfig": [
            {
                "paymentMethodType": "upi",
                "paymentMethod": "upi_collect",
                "bucketSize": 250,
                "hedgingPercent": 1
            }
        ]
    }
}'
```
```
{"id":"routing_tgng0ubQwdK3hSaSjRye","profile_id":"pro_GUovaynfuaBwH3DUaBbJ","name":"Success rate based dynamic routing algorithm","kind":"dynamic","description":"","created_at":1747841498,"modified_at":1747841498,"algorithm_for":"payment","decision_engine_routing_id":null}
```
4. Activate updated SR config (Call to Decision Engine should be made for SR config updation)
```
curl --location --request POST 'http://localhost:8080/routing/routing_tgng0ubQwdK3hSaSjRye/activate' \
--header 'api-key: dev_9gwSrzjH1Xbs7HMswLgx0Av8upsibfu8wORNxyzpIls3NvT08auKe4RBQlkBgqRl'
```
<img width="805" alt="image" src="https://github.com/user-attachments/assets/09345e37-8cf7-478f-b53a-44043883df4b" />


4. Enable volume split
```
curl --location --request POST 'http://localhost:8080/account/merchant_1747841259/business_profile/pro_GUovaynfuaBwH3DUaBbJ/dynamic_routing/set_volume_split?split=100' \
--header 'api-key: dev_9gwSrzjH1Xbs7HMswLgx0Av8upsibfu8wORNxyzpIls3NvT08auKe4RBQlkBgqRl'
```

5. Toggle ER config (Call to Decision Engine should be made for ER config creation)
```
curl --location --request POST 'http://localhost:8080/account/merchant_1747380349/business_profile/pro_28WNE1lOkSX9w3VdEPAN/dynamic_routing/elimination/toggle?enable=dynamic_connector_selection' \
--header 'api-key: dev_d87bY8HlyzBj4YYtGOIK2cj6yZLnPTxEkJN2o3lNJSxck0t3RghiH9zwrOR6Rexs'
```
```
{"id":"routing_S5d4ArS1VLlyrnpZ3tTx","profile_id":"pro_28WNE1lOkSX9w3VdEPAN","name":"Elimination based dynamic routing algorithm","kind":"dynamic","description":"","created_at":1747380532,"modified_at":1747380532,"algorithm_for":"payment"}
```
<img width="1559" alt="image" src="https://github.com/user-attachments/assets/f849243c-1f51-4a7f-94e6-9f7c60917dfd" />

6. Update ER config
```
curl --location --request PATCH 'http://localhost:8080/account/merchant_1747380349/business_profile/pro_28WNE1lOkSX9w3VdEPAN/dynamic_routing/elimination/config/routing_S5d4ArS1VLlyrnpZ3tTx' \
--header 'api-key: dev_d87bY8HlyzBj4YYtGOIK2cj6yZLnPTxEkJN2o3lNJSxck0t3RghiH9zwrOR6Rexs' \
--header 'Content-Type: application/json' \
--data '{
    "decision_engine_configs": {
        "threshold": 0.45
    }
}'
```
```
{"id":"routing_vOZoBnvZarFhmmLVXElW","profile_id":"pro_28WNE1lOkSX9w3VdEPAN","name":"Elimination based dynamic routing algorithm","kind":"dynamic","description":"","created_at":1747380711,"modified_at":1747380711,"algorithm_for":"payment"}
```
7. Activate updated ER config (Call to Decision Engine should be made for ER config updation)
```
curl --location --request POST 'http://localhost:8080/routing/routing_vOZoBnvZarFhmmLVXElW/activate' \
--header 'api-key: dev_d87bY8HlyzBj4YYtGOIK2cj6yZLnPTxEkJN2o3lNJSxck0t3RghiH9zwrOR6Rexs'
```
<img width="1536" alt="image" src="https://github.com/user-attachments/assets/21c83167-e5c4-4f5b-9b1e-ca9b1e2f91ef" />
8. Disable ER config

```
curl --location --request POST 'http://localhost:8080/account/merchant_1747380349/business_profile/pro_28WNE1lOkSX9w3VdEPAN/dynamic_routing/elimination/toggle?enable=none' \
--header 'api-key: dev_d87bY8HlyzBj4YYtGOIK2cj6yZLnPTxEkJN2o3lNJSxck0t3RghiH9zwrOR6Rexs'
```

<img width="1545" alt="image" src="https://github.com/user-attachments/assets/6e5ca5b1-06ef-4083-8271-603b6e108000" />

9. make a payment
```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_d87bY8HlyzBj4YYtGOIK2cj6yZLnPTxEkJN2o3lNJSxck0t3RghiH9zwrOR6Rexs' \
--data-raw '{
  "amount": 6540,
  "currency": "USD",
  "confirm": true,
  "capture_method": "automatic",
  "capture_on": "2022-09-10T10:11:12Z",
  "amount_to_capture": 6540,
  "customer_id": "StripeCustomer",
  "email": "guest@example.com",
  "name": "John Doe",
  "phone": "999999999",
  "phone_country_code": "+1",
  "description": "Its my first payment request",
  "authentication_type": "no_three_ds",
  "return_url": "https://google.com",
  "payment_method": "card",
  "payment_method_type": "credit",
  "payment_method_data": {
    "card": {
      "card_number": "4242424242424242",
      "card_exp_month": "10",
      "card_exp_year": "25",
      "card_holder_name": "joseph Doe",
      "card_cvc": "123"
    }
  },
  "billing": {
    "address": {
      "line1": "1467",
      "line2": "Harrison Street",
      "line3": "Harrison Street",
      "city": "San Fransico",
      "state": "California",
      "zip": "94122",
      "country": "US",
      "first_name": "joseph",
      "last_name": "Doe"
    },
    "phone": {
      "number": "8056594427",
      "country_code": "+91"
    }
  },
  "shipping": {
    "address": {
      "line1": "1467",
      "line2": "Harrison Street",
      "line3": "Harrison Street",
      "city": "San Fransico",
      "state": "California",
      "zip": "94122",
      "country": "US",
      "first_name": "joseph",
      "last_name": "Doe"
    },
    "phone": {
      "number": "8056594427",
      "country_code": "+91"
    }
  },
  "statement_descriptor_name": "joseph",
  "statement_descriptor_suffix": "JS",
  "metadata": {
    "udf1": "value1",
    "new_customer": "true",
    "login_date": "2019-09-10T10:11:12Z"
  }
}'
```
```
{"payment_id":"pay_WMa1HPuv2m4y1eUa8bJf","merchant_id":"merchant_1747380349","status":"succeeded","amount":6540,"net_amount":6540,"shipping_cost":null,"amount_capturable":0,"amount_received":6540,"connector":"stripe","client_secret":"pay_WMa1HPuv2m4y1eUa8bJf_secret_dLcjgQ2dafDp8Nl1vWZ7","created":"2025-05-16T07:52:09.020Z","currency":"USD","customer_id":"StripeCustomer","customer":{"id":"StripeCustomer","name":"John Doe","email":"guest@example.com","phone":"999999999","phone_country_code":"+1"},"description":"Its my first payment request","refunds":null,"disputes":null,"mandate_id":null,"mandate_data":null,"setup_future_usage":null,"off_session":null,"capture_on":null,"capture_method":"automatic","payment_method":"card","payment_method_data":{"card":{"last4":"4242","card_type":null,"card_network":null,"card_issuer":null,"card_issuing_country":null,"card_isin":"424242","card_extended_bin":null,"card_exp_month":"10","card_exp_year":"25","card_holder_name":"joseph Doe","payment_checks":{"cvc_check":"pass","address_line1_check":"pass","address_postal_code_check":"pass"},"authentication_data":null},"billing":null},"payment_token":null,"shipping":{"address":{"city":"San Fransico","country":"US","line1":"1467","line2":"Harrison Street","line3":"Harrison Street","zip":"94122","state":"California","first_name":"joseph","last_name":"Doe"},"phone":{"number":"8056594427","country_code":"+91"},"email":null},"billing":{"address":{"city":"San Fransico","country":"US","line1":"1467","line2":"Harrison Street","line3":"Harrison Street","zip":"94122","state":"California","first_name":"joseph","last_name":"Doe"},"phone":{"number":"8056594427","country_code":"+91"},"email":null},"order_details":null,"email":"guest@example.com","name":"John Doe","phone":"999999999","return_url":"https://google.com/","authentication_type":"no_three_ds","statement_descriptor_name":"joseph","statement_descriptor_suffix":"JS","next_action":null,"cancellation_reason":null,"error_code":null,"error_message":null,"unified_code":null,"unified_message":null,"payment_experience":null,"payment_method_type":"credit","connector_label":null,"business_country":null,"business_label":"default","business_sub_label":null,"allowed_payment_method_types":null,"ephemeral_key":{"customer_id":"StripeCustomer","created_at":1747381929,"expires":1747385529,"secret":"epk_30f63c59ee2f4ce8b0d4e34a1bdd9119"},"manual_retry_allowed":false,"connector_transaction_id":"pi_3RPJ3tD5R7gDAGff0Jgz3U6C","frm_message":null,"metadata":{"udf1":"value1","login_date":"2019-09-10T10:11:12Z","new_customer":"true"},"connector_metadata":null,"feature_metadata":null,"reference_id":"pi_3RPJ3tD5R7gDAGff0Jgz3U6C","payment_link":null,"profile_id":"pro_28WNE1lOkSX9w3VdEPAN","surcharge_details":null,"attempt_count":1,"merchant_decision":null,"merchant_connector_id":"mca_Zm1nyERaPTww6jSUgtak","incremental_authorization_allowed":null,"authorization_count":null,"incremental_authorizations":null,"external_authentication_details":null,"external_3ds_authentication_attempted":false,"expires_on":"2025-05-16T08:07:09.020Z","fingerprint":null,"browser_info":null,"payment_method_id":null,"payment_method_status":null,"updated":"2025-05-16T07:52:10.486Z","split_payments":null,"frm_metadata":null,"extended_authorization_applied":null,"capture_before":null,"merchant_order_reference_id":null,"order_tax_amount":null,"connector_mandate_id":null,"card_discovery":"manual","force_3ds_challenge":false,"force_3ds_challenge_trigger":false,"issuer_error_code":null,"issuer_error_message":null}
```
<img width="1253" alt="image" src="https://github.com/user-attachments/assets/ec3600d7-08f5-47d1-ac08-992890ea1bcd" />

<img width="1241" alt="image" src="https://github.com/user-attachments/assets/2d51e889-3e75-428f-b995-bf936c0cb905" />



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