Bug: Create a payments API client to connect subscription service with payments




diff --git a/config/config.example.toml b/config/config.example.toml
index 1b767adb4eb..d588c22a638 100644
--- a/config/config.example.toml
+++ b/config/config.example.toml
@@ -1279,4 +1279,7 @@ connector_list = "worldpayvantiv"
 # Authentication to communicate between internal services using common_api_key, merchant id and profile id
 [internal_merchant_id_profile_id_auth]
 enabled = false # Enable or disable internal api key, merchant id and profile id based authentication
-internal_api_key = "test_internal_api_key" # API key for internal merchant id and profile id based authentication
\ No newline at end of file
+internal_api_key = "test_internal_api_key" # API key for internal merchant id and profile id based authentication
+
+[internal_services] # Internal services base urls and configs
+payments_base_url = "http://localhost:8080"
diff --git a/config/deployments/env_specific.toml b/config/deployments/env_specific.toml
index d48ab2d148d..b8523401448 100644
--- a/config/deployments/env_specific.toml
+++ b/config/deployments/env_specific.toml
@@ -428,3 +428,6 @@ encryption_key = ""                            # Key to encrypt and decrypt chat
 
 [proxy_status_mapping]
 proxy_connector_http_status_code = false    # If enabled, the http status code of the connector will be proxied in the response
+
+[internal_services] # Internal services base urls and configs
+payments_base_url = "http://localhost:8080"
\ No newline at end of file
diff --git a/config/deployments/integration_test.toml b/config/deployments/integration_test.toml
index 2128079b3d3..bde1e29ba78 100644
--- a/config/deployments/integration_test.toml
+++ b/config/deployments/integration_test.toml
@@ -920,8 +920,3 @@ connector_list = "worldpayvantiv"
 [grpc_client.unified_connector_service]
 ucs_only_connectors = "paytm, phonepe"    # Comma-separated list of connectors that use UCS only
 ucs_psync_disabled_connectors = "cashtocode"    # Comma-separated list of connectors to disable UCS PSync call
-
-# Authentication to communicate between internal services using common_api_key, merchant id and profile id
-[internal_merchant_id_profile_id_auth]
-enabled = false # Enable or disable internal api key, merchant id and profile id based authentication
-internal_api_key = "test_internal_api_key" # API key for internal merchant id and profile id based authentication
\ No newline at end of file
diff --git a/config/deployments/production.toml b/config/deployments/production.toml
index c7c85bc1f85..e078e4c50cf 100644
--- a/config/deployments/production.toml
+++ b/config/deployments/production.toml
@@ -926,8 +926,3 @@ click_to_pay = {connector_list = "adyen, cybersource, trustpay"}
 [grpc_client.unified_connector_service]
 ucs_only_connectors = "paytm, phonepe"    # Comma-separated list of connectors that use UCS only
 ucs_psync_disabled_connectors = "cashtocode"    # Comma-separated list of connectors to disable UCS PSync call
-
-# Authentication to communicate between internal services using common_api_key, merchant id and profile id
-[internal_merchant_id_profile_id_auth]
-enabled = false # Enable or disable internal api key, merchant id and profile id based authentication
-internal_api_key = "test_internal_api_key" # API key for internal merchant id and profile id based authentication
diff --git a/config/deployments/sandbox.toml b/config/deployments/sandbox.toml
index 916636bcc45..4c777e8a62f 100644
--- a/config/deployments/sandbox.toml
+++ b/config/deployments/sandbox.toml
@@ -935,8 +935,3 @@ connector_list = "worldpayvantiv"
 [grpc_client.unified_connector_service]
 ucs_only_connectors = "paytm, phonepe"    # Comma-separated list of connectors that use UCS only
 ucs_psync_disabled_connectors = "cashtocode"    # Comma-separated list of connectors to disable UCS PSync call
-
-# Authentication to communicate between internal services using common_api_key, merchant id and profile id
-[internal_merchant_id_profile_id_auth]
-enabled = false # Enable or disable internal api key, merchant id and profile id based authentication
-internal_api_key = "test_internal_api_key" # API key for internal merchant id and profile id based authentication
\ No newline at end of file
diff --git a/config/development.toml b/config/development.toml
index a82fe46afd9..6d468c4656d 100644
--- a/config/development.toml
+++ b/config/development.toml
@@ -1399,4 +1399,7 @@ connector_list = "worldpayvantiv"
 
 [internal_merchant_id_profile_id_auth]
 enabled = false
-internal_api_key = "test_internal_api_key"
\ No newline at end of file
+internal_api_key = "test_internal_api_key"
+
+[internal_services]
+payments_base_url = "http://localhost:8080"
diff --git a/config/docker_compose.toml b/config/docker_compose.toml
index e4f7197c04d..86e82aaf487 100644
--- a/config/docker_compose.toml
+++ b/config/docker_compose.toml
@@ -1291,4 +1291,7 @@ connector_list = "worldpayvantiv"
 # Authentication to communicate between internal services using common_api_key, merchant id and profile id
 [internal_merchant_id_profile_id_auth]
 enabled = false # Enable or disable internal api key, merchant id and profile id based authentication
-internal_api_key = "test_internal_api_key" # API key for internal merchant id and profile id based authentication
\ No newline at end of file
+internal_api_key = "test_internal_api_key" # API key for internal merchant id and profile id based authentication
+
+[internal_services] # Internal services base urls and configs
+payments_base_url = "http://localhost:8080"
diff --git a/crates/api_models/src/subscription.rs b/crates/api_models/src/subscription.rs
index 4ed14a9c64e..c0403848b9d 100644
--- a/crates/api_models/src/subscription.rs
+++ b/crates/api_models/src/subscription.rs
@@ -8,17 +8,18 @@ use crate::{
     payments::{Address, PaymentMethodDataRequest},
 };
 
-// use crate::{
-//     customers::{CustomerRequest, CustomerResponse},
-//     payments::CustomerDetailsResponse,
-// };
-
 /// Request payload for creating a subscription.
 ///
 /// This struct captures details required to create a subscription,
 /// including plan, profile, merchant connector, and optional customer info.
 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
 pub struct CreateSubscriptionRequest {
+    /// Amount to be charged for the invoice.
+    pub amount: MinorUnit,
+
+    /// Currency for the amount.
+    pub currency: api_enums::Currency,
+
     /// Merchant specific Unique identifier.
     pub merchant_reference_id: Option<String>,
 
@@ -30,13 +31,22 @@ pub struct CreateSubscriptionRequest {
 
     /// customer ID associated with this subscription.
     pub customer_id: common_utils::id_type::CustomerId,
+
+    /// payment details for the subscription.
+    pub payment_details: CreateSubscriptionPaymentDetails,
+
+    /// billing address for the subscription.
+    pub billing: Option<Address>,
+
+    /// shipping address for the subscription.
+    pub shipping: Option<Address>,
 }
 
 /// Response payload returned after successfully creating a subscription.
 ///
 /// Includes details such as subscription ID, status, plan, merchant, and customer info.
 #[derive(Debug, Clone, serde::Serialize, ToSchema)]
-pub struct CreateSubscriptionResponse {
+pub struct SubscriptionResponse {
     /// Unique identifier for the subscription.
     pub id: common_utils::id_type::SubscriptionId,
 
@@ -78,6 +88,7 @@ pub struct CreateSubscriptionResponse {
 /// - `Cancelled`: Subscription has been cancelled.
 /// - `Failed`: Subscription has failed.
 #[derive(Debug, Clone, serde::Serialize, strum::EnumString, strum::Display, ToSchema)]
+#[serde(rename_all = "snake_case")]
 pub enum SubscriptionStatus {
     /// Subscription is active.
     Active,
@@ -101,7 +112,7 @@ pub enum SubscriptionStatus {
     Failed,
 }
 
-impl CreateSubscriptionResponse {
+impl SubscriptionResponse {
     /// Creates a new [`CreateSubscriptionResponse`] with the given identifiers.
     ///
     /// By default, `client_secret`, `coupon_code`, and `customer` fields are `None`.
@@ -130,15 +141,77 @@ impl CreateSubscriptionResponse {
     }
 }
 
-impl ApiEventMetric for CreateSubscriptionResponse {}
+impl ApiEventMetric for SubscriptionResponse {}
 impl ApiEventMetric for CreateSubscriptionRequest {}
 
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
+pub struct ConfirmSubscriptionPaymentDetails {
+    pub payment_method: api_enums::PaymentMethod,
+    pub payment_method_type: Option<api_enums::PaymentMethodType>,
+    pub payment_method_data: PaymentMethodDataRequest,
+    pub customer_acceptance: Option<CustomerAcceptance>,
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
+pub struct CreateSubscriptionPaymentDetails {
+    pub return_url: common_utils::types::Url,
+    pub setup_future_usage: Option<api_enums::FutureUsage>,
+    pub capture_method: Option<api_enums::CaptureMethod>,
+    pub authentication_type: Option<api_enums::AuthenticationType>,
+}
+
 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
 pub struct PaymentDetails {
+    pub payment_method: Option<api_enums::PaymentMethod>,
+    pub payment_method_type: Option<api_enums::PaymentMethodType>,
+    pub payment_method_data: Option<PaymentMethodDataRequest>,
+    pub setup_future_usage: Option<api_enums::FutureUsage>,
+    pub customer_acceptance: Option<CustomerAcceptance>,
+    pub return_url: Option<common_utils::types::Url>,
+    pub capture_method: Option<api_enums::CaptureMethod>,
+    pub authentication_type: Option<api_enums::AuthenticationType>,
+}
+
+// Creating new type for PaymentRequest API call as usage of api_models::PaymentsRequest will result in invalid payment request during serialization
+// Eg: Amount will be serialized as { amount: {Value: 100 }}
+#[derive(Debug, Clone, serde::Serialize, ToSchema)]
+pub struct CreatePaymentsRequestData {
+    pub amount: MinorUnit,
+    pub currency: api_enums::Currency,
+    pub customer_id: Option<common_utils::id_type::CustomerId>,
+    pub billing: Option<Address>,
+    pub shipping: Option<Address>,
+    pub setup_future_usage: Option<api_enums::FutureUsage>,
+    pub return_url: Option<common_utils::types::Url>,
+    pub capture_method: Option<api_enums::CaptureMethod>,
+    pub authentication_type: Option<api_enums::AuthenticationType>,
+}
+
+#[derive(Debug, Clone, serde::Serialize, ToSchema)]
+pub struct ConfirmPaymentsRequestData {
+    pub billing: Option<Address>,
+    pub shipping: Option<Address>,
     pub payment_method: api_enums::PaymentMethod,
     pub payment_method_type: Option<api_enums::PaymentMethodType>,
     pub payment_method_data: PaymentMethodDataRequest,
+    pub customer_acceptance: Option<CustomerAcceptance>,
+}
+
+#[derive(Debug, Clone, serde::Serialize, ToSchema)]
+pub struct CreateAndConfirmPaymentsRequestData {
+    pub amount: MinorUnit,
+    pub currency: api_enums::Currency,
+    pub customer_id: Option<common_utils::id_type::CustomerId>,
+    pub confirm: bool,
+    pub billing: Option<Address>,
+    pub shipping: Option<Address>,
     pub setup_future_usage: Option<api_enums::FutureUsage>,
+    pub return_url: Option<common_utils::types::Url>,
+    pub capture_method: Option<api_enums::CaptureMethod>,
+    pub authentication_type: Option<api_enums::AuthenticationType>,
+    pub payment_method: Option<api_enums::PaymentMethod>,
+    pub payment_method_type: Option<api_enums::PaymentMethodType>,
+    pub payment_method_data: Option<PaymentMethodDataRequest>,
     pub customer_acceptance: Option<CustomerAcceptance>,
 }
 
@@ -149,18 +222,16 @@ pub struct PaymentResponseData {
     pub amount: MinorUnit,
     pub currency: api_enums::Currency,
     pub connector: Option<String>,
+    pub payment_method_id: Option<Secret<String>>,
+    pub payment_experience: Option<api_enums::PaymentExperience>,
+    pub error_code: Option<String>,
+    pub error_message: Option<String>,
 }
 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
 pub struct ConfirmSubscriptionRequest {
     /// Client secret for SDK based interaction.
     pub client_secret: Option<String>,
 
-    /// Amount to be charged for the invoice.
-    pub amount: MinorUnit,
-
-    /// Currency for the amount.
-    pub currency: api_enums::Currency,
-
     /// Identifier for the associated plan_id.
     pub plan_id: Option<String>,
 
@@ -174,10 +245,13 @@ pub struct ConfirmSubscriptionRequest {
     pub customer_id: common_utils::id_type::CustomerId,
 
     /// Billing address for the subscription.
-    pub billing_address: Option<Address>,
+    pub billing: Option<Address>,
+
+    /// Shipping address for the subscription.
+    pub shipping: Option<Address>,
 
     /// Payment details for the invoice.
-    pub payment_details: PaymentDetails,
+    pub payment_details: ConfirmSubscriptionPaymentDetails,
 }
 
 impl ConfirmSubscriptionRequest {
@@ -190,9 +264,9 @@ impl ConfirmSubscriptionRequest {
     }
 
     pub fn get_billing_address(&self) -> Result<Address, error_stack::Report<ValidationError>> {
-        self.billing_address.clone().ok_or(error_stack::report!(
+        self.billing.clone().ok_or(error_stack::report!(
             ValidationError::MissingRequiredField {
-                field_name: "billing_address".to_string()
+                field_name: "billing".to_string()
             }
         ))
     }
@@ -200,6 +274,41 @@ impl ConfirmSubscriptionRequest {
 
 impl ApiEventMetric for ConfirmSubscriptionRequest {}
 
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
+pub struct CreateAndConfirmSubscriptionRequest {
+    /// Amount to be charged for the invoice.
+    pub amount: Option<MinorUnit>,
+
+    /// Currency for the amount.
+    pub currency: Option<api_enums::Currency>,
+
+    /// Identifier for the associated plan_id.
+    pub plan_id: Option<String>,
+
+    /// Identifier for the associated item_price_id for the subscription.
+    pub item_price_id: Option<String>,
+
+    /// Idenctifier for the coupon code for the subscription.
+    pub coupon_code: Option<String>,
+
+    /// Identifier for customer.
+    pub customer_id: common_utils::id_type::CustomerId,
+
+    /// Billing address for the subscription.
+    pub billing: Option<Address>,
+
+    /// Shipping address for the subscription.
+    pub shipping: Option<Address>,
+
+    /// Payment details for the invoice.
+    pub payment_details: PaymentDetails,
+
+    /// Merchant specific Unique identifier.
+    pub merchant_reference_id: Option<String>,
+}
+
+impl ApiEventMetric for CreateAndConfirmSubscriptionRequest {}
+
 #[derive(Debug, Clone, serde::Serialize, ToSchema)]
 pub struct ConfirmSubscriptionResponse {
     /// Unique identifier for the subscription.
@@ -231,6 +340,9 @@ pub struct ConfirmSubscriptionResponse {
 
     /// Invoice Details for the subscription.
     pub invoice: Option<Invoice>,
+
+    /// Billing Processor subscription ID.
+    pub billing_processor_subscription_id: Option<String>,
 }
 
 #[derive(Debug, Clone, serde::Serialize, ToSchema)]
diff --git a/crates/common_enums/src/connector_enums.rs b/crates/common_enums/src/connector_enums.rs
index 51dc6469424..532123c3501 100644
--- a/crates/common_enums/src/connector_enums.rs
+++ b/crates/common_enums/src/connector_enums.rs
@@ -894,7 +894,8 @@ impl TryFrom<Connector> for RoutableConnectors {
 }
 
 // Enum representing different status an invoice can have.
-#[derive(Debug, Clone, PartialEq, Eq, strum::Display, strum::EnumString)]
+#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, strum::Display, strum::EnumString)]
+#[strum(serialize_all = "snake_case")]
 pub enum InvoiceStatus {
     InvoiceCreated,
     PaymentPending,
@@ -904,4 +905,5 @@ pub enum InvoiceStatus {
     PaymentCanceled,
     InvoicePaid,
     ManualReview,
+    Voided,
 }
diff --git a/crates/common_utils/src/id_type/subscription.rs b/crates/common_utils/src/id_type/subscription.rs
index 20f0c483fa1..abccf711787 100644
--- a/crates/common_utils/src/id_type/subscription.rs
+++ b/crates/common_utils/src/id_type/subscription.rs
@@ -9,7 +9,7 @@ crate::impl_id_type_methods!(SubscriptionId, "subscription_id");
 crate::impl_debug_id_type!(SubscriptionId);
 crate::impl_try_from_cow_str_id_type!(SubscriptionId, "subscription_id");
 
-crate::impl_generate_id_id_type!(SubscriptionId, "subscription");
+crate::impl_generate_id_id_type!(SubscriptionId, "sub");
 crate::impl_serializable_secret_id_type!(SubscriptionId);
 crate::impl_queryable_id_type!(SubscriptionId);
 crate::impl_to_sql_from_sql_id_type!(SubscriptionId);
diff --git a/crates/diesel_models/src/query/invoice.rs b/crates/diesel_models/src/query/invoice.rs
index 10df8620461..0166469d340 100644
--- a/crates/diesel_models/src/query/invoice.rs
+++ b/crates/diesel_models/src/query/invoice.rs
@@ -38,4 +38,32 @@ impl Invoice {
         >(conn, dsl::id.eq(id.to_owned()), invoice_update)
         .await
     }
+
+    pub async fn list_invoices_by_subscription_id(
+        conn: &PgPooledConn,
+        subscription_id: String,
+        limit: Option<i64>,
+        offset: Option<i64>,
+        order_by_ascending_order: bool,
+    ) -> StorageResult<Vec<Self>> {
+        if order_by_ascending_order {
+            generics::generic_filter::<<Self as HasTable>::Table, _, _, _>(
+                conn,
+                dsl::subscription_id.eq(subscription_id.to_owned()),
+                limit,
+                offset,
+                Some(dsl::created_at.asc()),
+            )
+            .await
+        } else {
+            generics::generic_filter::<<Self as HasTable>::Table, _, _, _>(
+                conn,
+                dsl::subscription_id.eq(subscription_id.to_owned()),
+                limit,
+                offset,
+                Some(dsl::created_at.desc()),
+            )
+            .await
+        }
+    }
 }
diff --git a/crates/diesel_models/src/query/utils.rs b/crates/diesel_models/src/query/utils.rs
index 96a41f10ca0..98589804a35 100644
--- a/crates/diesel_models/src/query/utils.rs
+++ b/crates/diesel_models/src/query/utils.rs
@@ -103,6 +103,7 @@ impl_get_primary_key!(
     schema::events::table,
     schema::merchant_account::table,
     schema::process_tracker::table,
+    schema::invoice::table,
     // v2 tables
     schema_v2::dashboard_metadata::table,
     schema_v2::merchant_connector_account::table,
diff --git a/crates/diesel_models/src/subscription.rs b/crates/diesel_models/src/subscription.rs
index f49fef4a7be..7124c2eebd6 100644
--- a/crates/diesel_models/src/subscription.rs
+++ b/crates/diesel_models/src/subscription.rs
@@ -1,6 +1,6 @@
 use common_utils::{generate_id_with_default_len, pii::SecretSerdeValue};
 use diesel::{AsChangeset, Identifiable, Insertable, Queryable, Selectable};
-use masking::Secret;
+use masking::{PeekInterface, Secret};
 use serde::{Deserialize, Serialize};
 
 use crate::schema::subscription;
@@ -48,6 +48,7 @@ pub struct Subscription {
 #[derive(Clone, Debug, Eq, PartialEq, AsChangeset, router_derive::DebugAsDisplay, Deserialize)]
 #[diesel(table_name = subscription)]
 pub struct SubscriptionUpdate {
+    pub connector_subscription_id: Option<String>,
     pub payment_method_id: Option<String>,
     pub status: Option<String>,
     pub modified_at: time::PrimitiveDateTime,
@@ -97,10 +98,15 @@ impl SubscriptionNew {
 }
 
 impl SubscriptionUpdate {
-    pub fn new(payment_method_id: Option<String>, status: Option<String>) -> Self {
+    pub fn new(
+        payment_method_id: Option<Secret<String>>,
+        status: Option<String>,
+        connector_subscription_id: Option<String>,
+    ) -> Self {
         Self {
-            payment_method_id,
+            payment_method_id: payment_method_id.map(|pmid| pmid.peek().clone()),
             status,
+            connector_subscription_id,
             modified_at: common_utils::date_time::now(),
         }
     }
diff --git a/crates/hyperswitch_connectors/src/connectors/chargebee/transformers.rs b/crates/hyperswitch_connectors/src/connectors/chargebee/transformers.rs
index 3bf78b0e68b..64d9431c195 100644
--- a/crates/hyperswitch_connectors/src/connectors/chargebee/transformers.rs
+++ b/crates/hyperswitch_connectors/src/connectors/chargebee/transformers.rs
@@ -1,7 +1,7 @@
 #[cfg(all(feature = "revenue_recovery", feature = "v2"))]
 use std::str::FromStr;
 
-use common_enums::enums;
+use common_enums::{connector_enums, enums};
 use common_utils::{
     errors::CustomResult,
     ext_traits::ByteSliceExt,
@@ -29,8 +29,8 @@ use hyperswitch_domain_models::{
         revenue_recovery::InvoiceRecordBackResponse,
         subscriptions::{
             self, GetSubscriptionEstimateResponse, GetSubscriptionPlanPricesResponse,
-            GetSubscriptionPlansResponse, SubscriptionCreateResponse, SubscriptionLineItem,
-            SubscriptionStatus,
+            GetSubscriptionPlansResponse, SubscriptionCreateResponse, SubscriptionInvoiceData,
+            SubscriptionLineItem, SubscriptionStatus,
         },
         ConnectorCustomerResponseData, PaymentsResponseData, RefundsResponseData,
     },
@@ -120,6 +120,7 @@ impl TryFrom<&ChargebeeRouterData<&hyperswitch_domain_models::types::Subscriptio
 #[derive(Debug, Deserialize, Serialize, Clone)]
 pub struct ChargebeeSubscriptionCreateResponse {
     pub subscription: ChargebeeSubscriptionDetails,
+    pub invoice: Option<ChargebeeInvoiceData>,
 }
 
 #[derive(Debug, Deserialize, Serialize, Clone)]
@@ -192,6 +193,7 @@ impl
                 total_amount: subscription.total_dues.unwrap_or(MinorUnit::new(0)),
                 next_billing_at: subscription.next_billing_at,
                 created_at: subscription.created_at,
+                invoice_details: item.response.invoice.map(SubscriptionInvoiceData::from),
             }),
             ..item.data
         })
@@ -461,17 +463,18 @@ pub enum ChargebeeEventType {
     InvoiceDeleted,
 }
 
-#[derive(Serialize, Deserialize, Debug)]
+#[derive(Serialize, Deserialize, Clone, Debug)]
 pub struct ChargebeeInvoiceData {
     // invoice id
     pub id: String,
     pub total: MinorUnit,
     pub currency_code: enums::Currency,
+    pub status: Option<ChargebeeInvoiceStatus>,
     pub billing_address: Option<ChargebeeInvoiceBillingAddress>,
     pub linked_payments: Option<Vec<ChargebeeInvoicePayments>>,
 }
 
-#[derive(Serialize, Deserialize, Debug)]
+#[derive(Serialize, Deserialize, Clone, Debug)]
 pub struct ChargebeeInvoicePayments {
     pub txn_status: Option<String>,
 }
@@ -539,7 +542,7 @@ pub struct ChargebeeCustomer {
     pub payment_method: ChargebeePaymentMethod,
 }
 
-#[derive(Serialize, Deserialize, Debug)]
+#[derive(Serialize, Deserialize, Clone, Debug)]
 pub struct ChargebeeInvoiceBillingAddress {
     pub line1: Option<Secret<String>>,
     pub line2: Option<Secret<String>>,
@@ -788,7 +791,6 @@ impl TryFrom<ChargebeeInvoiceBody> for revenue_recovery::RevenueRecoveryInvoiceD
     }
 }
 
-#[cfg(all(feature = "revenue_recovery", feature = "v2"))]
 impl From<ChargebeeInvoiceData> for api_models::payments::Address {
     fn from(item: ChargebeeInvoiceData) -> Self {
         Self {
@@ -801,7 +803,6 @@ impl From<ChargebeeInvoiceData> for api_models::payments::Address {
     }
 }
 
-#[cfg(all(feature = "revenue_recovery", feature = "v2"))]
 impl From<ChargebeeInvoiceBillingAddress> for api_models::payments::AddressDetails {
     fn from(item: ChargebeeInvoiceBillingAddress) -> Self {
         Self {
@@ -1337,3 +1338,40 @@ pub struct LineItem {
     pub discount_amount: MinorUnit,
     pub item_level_discount_amount: MinorUnit,
 }
+
+#[derive(Serialize, Deserialize, Clone, Debug)]
+#[serde(rename_all = "snake_case")]
+pub enum ChargebeeInvoiceStatus {
+    Paid,
+    Posted,
+    PaymentDue,
+    NotPaid,
+    Voided,
+    #[serde(other)]
+    Pending,
+}
+
+impl From<ChargebeeInvoiceData> for SubscriptionInvoiceData {
+    fn from(item: ChargebeeInvoiceData) -> Self {
+        Self {
+            billing_address: Some(api_models::payments::Address::from(item.clone())),
+            id: item.id,
+            total: item.total,
+            currency_code: item.currency_code,
+            status: item.status.map(connector_enums::InvoiceStatus::from),
+        }
+    }
+}
+
+impl From<ChargebeeInvoiceStatus> for connector_enums::InvoiceStatus {
+    fn from(status: ChargebeeInvoiceStatus) -> Self {
+        match status {
+            ChargebeeInvoiceStatus::Paid => Self::InvoicePaid,
+            ChargebeeInvoiceStatus::Posted => Self::PaymentPendingTimeout,
+            ChargebeeInvoiceStatus::PaymentDue => Self::PaymentPending,
+            ChargebeeInvoiceStatus::NotPaid => Self::PaymentFailed,
+            ChargebeeInvoiceStatus::Voided => Self::Voided,
+            ChargebeeInvoiceStatus::Pending => Self::InvoiceCreated,
+        }
+    }
+}
diff --git a/crates/hyperswitch_domain_models/src/router_response_types/subscriptions.rs b/crates/hyperswitch_domain_models/src/router_response_types/subscriptions.rs
index 73b80b82075..e60b7783cb5 100644
--- a/crates/hyperswitch_domain_models/src/router_response_types/subscriptions.rs
+++ b/crates/hyperswitch_domain_models/src/router_response_types/subscriptions.rs
@@ -11,6 +11,16 @@ pub struct SubscriptionCreateResponse {
     pub total_amount: MinorUnit,
     pub next_billing_at: Option<PrimitiveDateTime>,
     pub created_at: Option<PrimitiveDateTime>,
+    pub invoice_details: Option<SubscriptionInvoiceData>,
+}
+
+#[derive(Debug, Clone, serde::Serialize)]
+pub struct SubscriptionInvoiceData {
+    pub id: String,
+    pub total: MinorUnit,
+    pub currency_code: Currency,
+    pub status: Option<common_enums::connector_enums::InvoiceStatus>,
+    pub billing_address: Option<api_models::payments::Address>,
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Copy)]
diff --git a/crates/router/src/configs/secrets_transformers.rs b/crates/router/src/configs/secrets_transformers.rs
index 67b6854922a..7aef8d74464 100644
--- a/crates/router/src/configs/secrets_transformers.rs
+++ b/crates/router/src/configs/secrets_transformers.rs
@@ -580,5 +580,6 @@ pub(crate) async fn fetch_raw_secrets(
         infra_values: conf.infra_values,
         enhancement: conf.enhancement,
         proxy_status_mapping: conf.proxy_status_mapping,
+        internal_services: conf.internal_services,
     }
 }
diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs
index 6a7bf225473..2dd028cf72e 100644
--- a/crates/router/src/configs/settings.rs
+++ b/crates/router/src/configs/settings.rs
@@ -169,6 +169,7 @@ pub struct Settings<S: SecretState> {
     #[serde(default)]
     pub enhancement: Option<HashMap<String, String>>,
     pub proxy_status_mapping: ProxyStatusMapping,
+    pub internal_services: InternalServicesConfig,
 }
 
 #[derive(Debug, Deserialize, Clone, Default)]
@@ -972,6 +973,12 @@ pub struct NetworkTokenizationSupportedConnectors {
     pub connector_list: HashSet<enums::Connector>,
 }
 
+#[derive(Debug, Deserialize, Clone, Default)]
+#[serde(default)]
+pub struct InternalServicesConfig {
+    pub payments_base_url: String,
+}
+
 impl Settings<SecuredSecret> {
     pub fn new() -> ApplicationResult<Self> {
         Self::with_config_path(None)
diff --git a/crates/router/src/core/subscription.rs b/crates/router/src/core/subscription.rs
index 6b98eabf8bb..71e32c43bf6 100644
--- a/crates/router/src/core/subscription.rs
+++ b/crates/router/src/core/subscription.rs
@@ -1,148 +1,167 @@
-use std::str::FromStr;
-
-use api_models::{
-    enums as api_enums,
-    subscription::{self as subscription_types, CreateSubscriptionResponse, SubscriptionStatus},
+use api_models::subscription::{
+    self as subscription_types, SubscriptionResponse, SubscriptionStatus,
 };
-use common_utils::{ext_traits::ValueExt, id_type::GenerateId, pii};
-use diesel_models::subscription::SubscriptionNew;
+use common_enums::connector_enums;
+use common_utils::id_type::GenerateId;
 use error_stack::ResultExt;
-use hyperswitch_domain_models::{
-    api::ApplicationResponse,
-    merchant_context::MerchantContext,
-    router_data_v2::flow_common_types::{SubscriptionCreateData, SubscriptionCustomerData},
-    router_request_types::{subscriptions as subscription_request_types, ConnectorCustomerData},
-    router_response_types::{
-        subscriptions as subscription_response_types, ConnectorCustomerResponseData,
-        PaymentsResponseData,
-    },
-};
-use masking::Secret;
+use hyperswitch_domain_models::{api::ApplicationResponse, merchant_context::MerchantContext};
 
 use super::errors::{self, RouterResponse};
 use crate::{
-    core::payments as payments_core, routes::SessionState, services, types::api as api_types,
+    core::subscription::{
+        billing_processor_handler::BillingHandler, invoice_handler::InvoiceHandler,
+        subscription_handler::SubscriptionHandler,
+    },
+    routes::SessionState,
 };
 
+pub mod billing_processor_handler;
+pub mod invoice_handler;
+pub mod payments_api_client;
+pub mod subscription_handler;
+
 pub const SUBSCRIPTION_CONNECTOR_ID: &str = "DefaultSubscriptionConnectorId";
 pub const SUBSCRIPTION_PAYMENT_ID: &str = "DefaultSubscriptionPaymentId";
 
 pub async fn create_subscription(
     state: SessionState,
     merchant_context: MerchantContext,
-    profile_id: String,
+    profile_id: common_utils::id_type::ProfileId,
     request: subscription_types::CreateSubscriptionRequest,
-) -> RouterResponse<CreateSubscriptionResponse> {
-    let store = state.store.clone();
-    let db = store.as_ref();
-    let id = common_utils::id_type::SubscriptionId::generate();
-    let profile_id = common_utils::id_type::ProfileId::from_str(&profile_id).change_context(
-        errors::ApiErrorResponse::InvalidDataValue {
-            field_name: "X-Profile-Id",
-        },
-    )?;
-
-    let mut subscription = SubscriptionNew::new(
-        id,
-        SubscriptionStatus::Created.to_string(),
-        None,
-        None,
-        None,
-        None,
-        None,
-        merchant_context.get_merchant_account().get_id().clone(),
-        request.customer_id.clone(),
-        None,
-        profile_id,
-        request.merchant_reference_id,
-    );
+) -> RouterResponse<SubscriptionResponse> {
+    let subscription_id = common_utils::id_type::SubscriptionId::generate();
 
-    subscription.generate_and_set_client_secret();
-    let subscription_response = db
-        .insert_subscription_entry(subscription)
+    let profile =
+        SubscriptionHandler::find_business_profile(&state, &merchant_context, &profile_id)
+            .await
+            .attach_printable("subscriptions: failed to find business profile")?;
+    let customer =
+        SubscriptionHandler::find_customer(&state, &merchant_context, &request.customer_id)
+            .await
+            .attach_printable("subscriptions: failed to find customer")?;
+    let billing_handler =
+        BillingHandler::create(&state, &merchant_context, customer, profile.clone()).await?;
+
+    let subscription_handler = SubscriptionHandler::new(&state, &merchant_context, profile);
+    let mut subscription = subscription_handler
+        .create_subscription_entry(
+            subscription_id,
+            &request.customer_id,
+            billing_handler.connector_data.connector_name,
+            billing_handler.merchant_connector_id.clone(),
+            request.merchant_reference_id.clone(),
+        )
+        .await
+        .attach_printable("subscriptions: failed to create subscription entry")?;
+    let invoice_handler = subscription.get_invoice_handler();
+    let payment = invoice_handler
+        .create_payment_with_confirm_false(subscription.handler.state, &request)
+        .await
+        .attach_printable("subscriptions: failed to create payment")?;
+    invoice_handler
+        .create_invoice_entry(
+            &state,
+            billing_handler.merchant_connector_id,
+            Some(payment.payment_id.clone()),
+            request.amount,
+            request.currency,
+            connector_enums::InvoiceStatus::InvoiceCreated,
+            billing_handler.connector_data.connector_name,
+            None,
+        )
         .await
-        .change_context(errors::ApiErrorResponse::InternalServerError)
-        .attach_printable("subscriptions: unable to insert subscription entry to database")?;
+        .attach_printable("subscriptions: failed to create invoice")?;
 
-    let response = CreateSubscriptionResponse::new(
-        subscription_response.id.clone(),
-        subscription_response.merchant_reference_id,
-        SubscriptionStatus::from_str(&subscription_response.status)
-            .unwrap_or(SubscriptionStatus::Created),
-        None,
-        subscription_response.profile_id,
-        subscription_response.merchant_id,
-        subscription_response.client_secret.map(Secret::new),
-        request.customer_id,
-    );
+    subscription
+        .update_subscription(diesel_models::subscription::SubscriptionUpdate::new(
+            payment.payment_method_id.clone(),
+            None,
+            None,
+        ))
+        .await
+        .attach_printable("subscriptions: failed to update subscription")?;
 
-    Ok(ApplicationResponse::Json(response))
+    Ok(ApplicationResponse::Json(
+        subscription.to_subscription_response(),
+    ))
 }
 
-pub async fn confirm_subscription(
+/// Creates and confirms a subscription in one operation.
+/// This method combines the creation and confirmation flow to reduce API calls
+pub async fn create_and_confirm_subscription(
     state: SessionState,
     merchant_context: MerchantContext,
-    profile_id: String,
-    request: subscription_types::ConfirmSubscriptionRequest,
-    subscription_id: common_utils::id_type::SubscriptionId,
+    profile_id: common_utils::id_type::ProfileId,
+    request: subscription_types::CreateAndConfirmSubscriptionRequest,
 ) -> RouterResponse<subscription_types::ConfirmSubscriptionResponse> {
-    let profile_id = common_utils::id_type::ProfileId::from_str(&profile_id).change_context(
-        errors::ApiErrorResponse::InvalidDataValue {
-            field_name: "X-Profile-Id",
-        },
-    )?;
-
-    let key_manager_state = &(&state).into();
-    let merchant_key_store = merchant_context.get_merchant_key_store();
+    let subscription_id = common_utils::id_type::SubscriptionId::generate();
 
-    let profile = state
-        .store
-        .find_business_profile_by_profile_id(key_manager_state, merchant_key_store, &profile_id)
-        .await
-        .change_context(errors::ApiErrorResponse::ProfileNotFound {
-            id: profile_id.get_string_repr().to_string(),
-        })?;
-
-    let customer = state
-        .store
-        .find_customer_by_customer_id_merchant_id(
-            key_manager_state,
+    let profile =
+        SubscriptionHandler::find_business_profile(&state, &merchant_context, &profile_id)
+            .await
+            .attach_printable("subscriptions: failed to find business profile")?;
+    let customer =
+        SubscriptionHandler::find_customer(&state, &merchant_context, &request.customer_id)
+            .await
+            .attach_printable("subscriptions: failed to find customer")?;
+
+    let billing_handler =
+        BillingHandler::create(&state, &merchant_context, customer, profile.clone()).await?;
+    let subscription_handler = SubscriptionHandler::new(&state, &merchant_context, profile.clone());
+    let mut subs_handler = subscription_handler
+        .create_subscription_entry(
+            subscription_id.clone(),
             &request.customer_id,
-            merchant_context.get_merchant_account().get_id(),
-            merchant_key_store,
-            merchant_context.get_merchant_account().storage_scheme,
+            billing_handler.connector_data.connector_name,
+            billing_handler.merchant_connector_id.clone(),
+            request.merchant_reference_id.clone(),
         )
         .await
-        .change_context(errors::ApiErrorResponse::CustomerNotFound)
-        .attach_printable("subscriptions: unable to fetch customer from database")?;
-
-    let handler = SubscriptionHandler::new(state, merchant_context, request, profile);
-
-    let mut subscription_entry = handler
-        .find_subscription(subscription_id.get_string_repr().to_string())
-        .await?;
-
-    let billing_handler = subscription_entry.get_billing_handler(customer).await?;
-    let invoice_handler = subscription_entry.get_invoice_handler().await?;
+        .attach_printable("subscriptions: failed to create subscription entry")?;
+    let invoice_handler = subs_handler.get_invoice_handler();
 
     let _customer_create_response = billing_handler
-        .create_customer_on_connector(&handler.state)
+        .create_customer_on_connector(
+            &state,
+            request.customer_id.clone(),
+            request.billing.clone(),
+            request
+                .payment_details
+                .payment_method_data
+                .clone()
+                .and_then(|data| data.payment_method_data),
+        )
         .await?;
 
     let subscription_create_response = billing_handler
-        .create_subscription_on_connector(&handler.state)
+        .create_subscription_on_connector(
+            &state,
+            subs_handler.subscription.clone(),
+            request.item_price_id.clone(),
+            request.billing.clone(),
+        )
         .await?;
 
-    // let payment_response = invoice_handler.create_cit_payment().await?;
+    let invoice_details = subscription_create_response.invoice_details;
+    let (amount, currency) = InvoiceHandler::get_amount_and_currency(
+        (request.amount, request.currency),
+        invoice_details.clone(),
+    );
+
+    let payment_response = invoice_handler
+        .create_and_confirm_payment(&state, &request, amount, currency)
+        .await?;
 
     let invoice_entry = invoice_handler
         .create_invoice_entry(
-            &handler.state,
-            subscription_entry.profile.get_billing_processor_id()?,
-            None,
-            billing_handler.request.amount,
-            billing_handler.request.currency.to_string(),
-            common_enums::connector_enums::InvoiceStatus::InvoiceCreated,
+            &state,
+            profile.get_billing_processor_id()?,
+            Some(payment_response.payment_id.clone()),
+            amount,
+            currency,
+            invoice_details
+                .and_then(|invoice| invoice.status)
+                .unwrap_or(connector_enums::InvoiceStatus::InvoiceCreated),
             billing_handler.connector_data.connector_name,
             None,
         )
@@ -152,470 +171,144 @@ pub async fn confirm_subscription(
     //     .create_invoice_record_back_job(&payment_response)
     //     .await?;
 
-    subscription_entry
-        .update_subscription_status(
-            SubscriptionStatus::from(subscription_create_response.status).to_string(),
-        )
+    subs_handler
+        .update_subscription(diesel_models::subscription::SubscriptionUpdate::new(
+            payment_response.payment_method_id.clone(),
+            Some(SubscriptionStatus::from(subscription_create_response.status).to_string()),
+            Some(
+                subscription_create_response
+                    .subscription_id
+                    .get_string_repr()
+                    .to_string(),
+            ),
+        ))
         .await?;
 
-    let response = subscription_entry
-        .generate_response(&invoice_entry, subscription_create_response.status)?;
+    let response = subs_handler.generate_response(
+        &invoice_entry,
+        &payment_response,
+        subscription_create_response.status,
+    )?;
 
     Ok(ApplicationResponse::Json(response))
 }
 
-pub struct SubscriptionHandler {
+pub async fn confirm_subscription(
     state: SessionState,
     merchant_context: MerchantContext,
+    profile_id: common_utils::id_type::ProfileId,
     request: subscription_types::ConfirmSubscriptionRequest,
-    profile: hyperswitch_domain_models::business_profile::Profile,
-}
-
-impl SubscriptionHandler {
-    pub fn new(
-        state: SessionState,
-        merchant_context: MerchantContext,
-        request: subscription_types::ConfirmSubscriptionRequest,
-        profile: hyperswitch_domain_models::business_profile::Profile,
-    ) -> Self {
-        Self {
-            state,
-            merchant_context,
-            request,
-            profile,
-        }
-    }
-    pub async fn find_subscription(
-        &self,
-        subscription_id: String,
-    ) -> errors::RouterResult<SubscriptionWithHandler<'_>> {
-        let subscription = self
-            .state
-            .store
-            .find_by_merchant_id_subscription_id(
-                self.merchant_context.get_merchant_account().get_id(),
-                subscription_id.clone(),
-            )
-            .await
-            .change_context(errors::ApiErrorResponse::GenericNotFoundError {
-                message: format!("subscription not found for id: {subscription_id}"),
-            })?;
-
-        Ok(SubscriptionWithHandler {
-            handler: self,
-            subscription,
-            profile: self.profile.clone(),
-        })
-    }
-}
-pub struct SubscriptionWithHandler<'a> {
-    handler: &'a SubscriptionHandler,
-    subscription: diesel_models::subscription::Subscription,
-    profile: hyperswitch_domain_models::business_profile::Profile,
-}
-
-impl SubscriptionWithHandler<'_> {
-    fn generate_response(
-        &self,
-        invoice: &diesel_models::invoice::Invoice,
-        // _payment_response: &subscription_types::PaymentResponseData,
-        status: subscription_response_types::SubscriptionStatus,
-    ) -> errors::RouterResult<subscription_types::ConfirmSubscriptionResponse> {
-        Ok(subscription_types::ConfirmSubscriptionResponse {
-            id: self.subscription.id.clone(),
-            merchant_reference_id: self.subscription.merchant_reference_id.clone(),
-            status: SubscriptionStatus::from(status),
-            plan_id: None,
-            profile_id: self.subscription.profile_id.to_owned(),
-            payment: None,
-            customer_id: Some(self.subscription.customer_id.clone()),
-            price_id: None,
-            coupon: None,
-            invoice: Some(subscription_types::Invoice {
-                id: invoice.id.clone(),
-                subscription_id: invoice.subscription_id.clone(),
-                merchant_id: invoice.merchant_id.clone(),
-                profile_id: invoice.profile_id.clone(),
-                merchant_connector_id: invoice.merchant_connector_id.clone(),
-                payment_intent_id: invoice.payment_intent_id.clone(),
-                payment_method_id: invoice.payment_method_id.clone(),
-                customer_id: invoice.customer_id.clone(),
-                amount: invoice.amount,
-                currency: api_enums::Currency::from_str(invoice.currency.as_str())
-                    .change_context(errors::ApiErrorResponse::InvalidDataValue {
-                        field_name: "currency",
-                    })
-                    .attach_printable(format!(
-                        "unable to parse currency name {currency:?}",
-                        currency = invoice.currency
-                    ))?,
-                status: invoice.status.clone(),
-            }),
-        })
-    }
-
-    async fn update_subscription_status(&mut self, status: String) -> errors::RouterResult<()> {
-        let db = self.handler.state.store.as_ref();
-        let updated_subscription = db
-            .update_subscription_entry(
-                self.handler
-                    .merchant_context
-                    .get_merchant_account()
-                    .get_id(),
-                self.subscription.id.get_string_repr().to_string(),
-                diesel_models::subscription::SubscriptionUpdate::new(None, Some(status)),
-            )
+    subscription_id: common_utils::id_type::SubscriptionId,
+) -> RouterResponse<subscription_types::ConfirmSubscriptionResponse> {
+    // Find the subscription from database
+    let profile =
+        SubscriptionHandler::find_business_profile(&state, &merchant_context, &profile_id)
             .await
-            .change_context(errors::ApiErrorResponse::SubscriptionError {
-                operation: "Subscription Update".to_string(),
-            })
-            .attach_printable("subscriptions: unable to update subscription entry in database")?;
-
-        self.subscription = updated_subscription;
-
-        Ok(())
-    }
-
-    pub async fn get_billing_handler(
-        &self,
-        customer: hyperswitch_domain_models::customer::Customer,
-    ) -> errors::RouterResult<BillingHandler> {
-        let mca_id = self.profile.get_billing_processor_id()?;
-
-        let billing_processor_mca = self
-            .handler
-            .state
-            .store
-            .find_by_merchant_connector_account_merchant_id_merchant_connector_id(
-                &(&self.handler.state).into(),
-                self.handler
-                    .merchant_context
-                    .get_merchant_account()
-                    .get_id(),
-                &mca_id,
-                self.handler.merchant_context.get_merchant_key_store(),
-            )
+            .attach_printable("subscriptions: failed to find business profile")?;
+    let customer =
+        SubscriptionHandler::find_customer(&state, &merchant_context, &request.customer_id)
             .await
-            .change_context(errors::ApiErrorResponse::MerchantConnectorAccountNotFound {
-                id: mca_id.get_string_repr().to_string(),
-            })?;
-
-        let connector_name = billing_processor_mca.connector_name.clone();
-
-        let auth_type: hyperswitch_domain_models::router_data::ConnectorAuthType =
-            payments_core::helpers::MerchantConnectorAccountType::DbVal(Box::new(
-                billing_processor_mca.clone(),
-            ))
-            .get_connector_account_details()
-            .parse_value("ConnectorAuthType")
-            .change_context(errors::ApiErrorResponse::InvalidDataFormat {
-                field_name: "connector_account_details".to_string(),
-                expected_format: "auth_type and api_key".to_string(),
-            })?;
+            .attach_printable("subscriptions: failed to find customer")?;
 
-        let connector_data = api_types::ConnectorData::get_connector_by_name(
-            &self.handler.state.conf.connectors,
-            &connector_name,
-            api_types::GetToken::Connector,
-            Some(billing_processor_mca.get_id()),
+    let handler = SubscriptionHandler::new(&state, &merchant_context, profile.clone());
+    let mut subscription_entry = handler.find_subscription(subscription_id).await?;
+    let invoice_handler = subscription_entry.get_invoice_handler();
+    let invoice = invoice_handler
+        .get_latest_invoice(&state)
+        .await
+        .attach_printable("subscriptions: failed to get latest invoice")?;
+    let payment_response = invoice_handler
+        .confirm_payment(
+            &state,
+            invoice
+                .payment_intent_id
+                .ok_or(errors::ApiErrorResponse::MissingRequiredField {
+                    field_name: "payment_intent_id",
+                })?,
+            &request,
         )
-        .change_context(errors::ApiErrorResponse::IncorrectConnectorNameGiven)
-        .attach_printable(
-            "invalid connector name received in billing merchant connector account",
-        )?;
-
-        let connector_enum =
-            common_enums::connector_enums::Connector::from_str(connector_name.as_str())
-                .change_context(errors::ApiErrorResponse::InternalServerError)
-                .attach_printable(format!("unable to parse connector name {connector_name:?}"))?;
-
-        let connector_params =
-            hyperswitch_domain_models::connector_endpoints::Connectors::get_connector_params(
-                &self.handler.state.conf.connectors,
-                connector_enum,
-            )
-            .change_context(errors::ApiErrorResponse::ConfigNotFound)
-            .attach_printable(format!(
-                "cannot find connector params for this connector {connector_name} in this flow",
-            ))?;
-
-        Ok(BillingHandler {
-            subscription: self.subscription.clone(),
-            auth_type,
-            connector_data,
-            connector_params,
-            request: self.handler.request.clone(),
-            connector_metadata: billing_processor_mca.metadata.clone(),
-            customer,
-        })
-    }
-
-    pub async fn get_invoice_handler(&self) -> errors::RouterResult<InvoiceHandler> {
-        Ok(InvoiceHandler {
-            subscription: self.subscription.clone(),
-        })
-    }
-}
-
-pub struct BillingHandler {
-    subscription: diesel_models::subscription::Subscription,
-    auth_type: hyperswitch_domain_models::router_data::ConnectorAuthType,
-    connector_data: api_types::ConnectorData,
-    connector_params: hyperswitch_domain_models::connector_endpoints::ConnectorParams,
-    connector_metadata: Option<pii::SecretSerdeValue>,
-    customer: hyperswitch_domain_models::customer::Customer,
-    request: subscription_types::ConfirmSubscriptionRequest,
-}
-
-pub struct InvoiceHandler {
-    subscription: diesel_models::subscription::Subscription,
-}
-
-#[allow(clippy::todo)]
-impl InvoiceHandler {
-    #[allow(clippy::too_many_arguments)]
-    pub async fn create_invoice_entry(
-        self,
-        state: &SessionState,
-        merchant_connector_id: common_utils::id_type::MerchantConnectorAccountId,
-        payment_intent_id: Option<common_utils::id_type::PaymentId>,
-        amount: common_utils::types::MinorUnit,
-        currency: String,
-        status: common_enums::connector_enums::InvoiceStatus,
-        provider_name: common_enums::connector_enums::Connector,
-        metadata: Option<pii::SecretSerdeValue>,
-    ) -> errors::RouterResult<diesel_models::invoice::Invoice> {
-        let invoice_new = diesel_models::invoice::InvoiceNew::new(
-            self.subscription.id.to_owned(),
-            self.subscription.merchant_id.to_owned(),
-            self.subscription.profile_id.to_owned(),
-            merchant_connector_id,
-            payment_intent_id,
-            self.subscription.payment_method_id.clone(),
-            self.subscription.customer_id.to_owned(),
-            amount,
-            currency,
-            status,
-            provider_name,
-            metadata,
-        );
-
-        let invoice = state
-            .store
-            .insert_invoice_entry(invoice_new)
-            .await
-            .change_context(errors::ApiErrorResponse::SubscriptionError {
-                operation: "Subscription Confirm".to_string(),
-            })
-            .attach_printable("invoices: unable to insert invoice entry to database")?;
-
-        Ok(invoice)
-    }
-
-    pub async fn create_cit_payment(
-        &self,
-    ) -> errors::RouterResult<subscription_types::PaymentResponseData> {
-        // Create a CIT payment for the invoice
-        todo!("Create a CIT payment for the invoice")
-    }
+        .await?;
 
-    pub async fn create_invoice_record_back_job(
-        &self,
-        // _invoice: &subscription_types::Invoice,
-        _payment_response: &subscription_types::PaymentResponseData,
-    ) -> errors::RouterResult<()> {
-        // Create an invoice job entry based on payment status
-        todo!("Create an invoice job entry based on payment status")
-    }
-}
+    let billing_handler =
+        BillingHandler::create(&state, &merchant_context, customer, profile).await?;
+    let invoice_handler = subscription_entry.get_invoice_handler();
+    let subscription = subscription_entry.subscription.clone();
 
-#[allow(clippy::todo)]
-impl BillingHandler {
-    pub async fn create_customer_on_connector(
-        &self,
-        state: &SessionState,
-    ) -> errors::RouterResult<ConnectorCustomerResponseData> {
-        let customer_req = ConnectorCustomerData {
-            email: self.customer.email.clone().map(pii::Email::from),
-            payment_method_data: self
-                .request
+    let _customer_create_response = billing_handler
+        .create_customer_on_connector(
+            &state,
+            subscription.customer_id.clone(),
+            request.billing.clone(),
+            request
                 .payment_details
                 .payment_method_data
-                .payment_method_data
-                .clone()
-                .map(|pmd| pmd.into()),
-            description: None,
-            phone: None,
-            name: None,
-            preprocessing_id: None,
-            split_payments: None,
-            setup_future_usage: None,
-            customer_acceptance: None,
-            customer_id: Some(self.subscription.customer_id.to_owned()),
-            billing_address: self
-                .request
-                .billing_address
-                .as_ref()
-                .and_then(|add| add.address.clone())
-                .and_then(|addr| addr.into()),
-        };
-        let router_data = self.build_router_data(
-            state,
-            customer_req,
-            SubscriptionCustomerData {
-                connector_meta_data: self.connector_metadata.clone(),
-            },
-        )?;
-        let connector_integration = self.connector_data.connector.get_connector_integration();
-
-        let response = Box::pin(self.call_connector(
-            state,
-            router_data,
-            "create customer on connector",
-            connector_integration,
-        ))
+                .payment_method_data,
+        )
         .await?;
 
-        match response {
-            Ok(response_data) => match response_data {
-                PaymentsResponseData::ConnectorCustomerResponse(customer_response) => {
-                    Ok(customer_response)
-                }
-                _ => Err(errors::ApiErrorResponse::SubscriptionError {
-                    operation: "Subscription Customer Create".to_string(),
-                }
-                .into()),
-            },
-            Err(err) => Err(errors::ApiErrorResponse::ExternalConnectorError {
-                code: err.code,
-                message: err.message,
-                connector: self.connector_data.connector_name.to_string(),
-                status_code: err.status_code,
-                reason: err.reason,
-            }
-            .into()),
-        }
-    }
-    pub async fn create_subscription_on_connector(
-        &self,
-        state: &SessionState,
-    ) -> errors::RouterResult<subscription_response_types::SubscriptionCreateResponse> {
-        let subscription_item = subscription_request_types::SubscriptionItem {
-            item_price_id: self.request.get_item_price_id().change_context(
-                errors::ApiErrorResponse::MissingRequiredField {
-                    field_name: "item_price_id",
-                },
-            )?,
-            quantity: Some(1),
-        };
-        let subscription_req = subscription_request_types::SubscriptionCreateRequest {
-            subscription_id: self.subscription.id.to_owned(),
-            customer_id: self.subscription.customer_id.to_owned(),
-            subscription_items: vec![subscription_item],
-            billing_address: self.request.get_billing_address().change_context(
-                errors::ApiErrorResponse::MissingRequiredField {
-                    field_name: "billing_address",
-                },
-            )?,
-            auto_collection: subscription_request_types::SubscriptionAutoCollection::Off,
-            connector_params: self.connector_params.clone(),
-        };
+    let subscription_create_response = billing_handler
+        .create_subscription_on_connector(
+            &state,
+            subscription,
+            request.item_price_id,
+            request.billing,
+        )
+        .await?;
 
-        let router_data = self.build_router_data(
-            state,
-            subscription_req,
-            SubscriptionCreateData {
-                connector_meta_data: self.connector_metadata.clone(),
-            },
-        )?;
-        let connector_integration = self.connector_data.connector.get_connector_integration();
+    let invoice_details = subscription_create_response.invoice_details;
+    let invoice_entry = invoice_handler
+        .update_invoice(
+            &state,
+            invoice.id,
+            payment_response.payment_method_id.clone(),
+            invoice_details
+                .clone()
+                .and_then(|invoice| invoice.status)
+                .unwrap_or(connector_enums::InvoiceStatus::InvoiceCreated),
+        )
+        .await?;
 
-        let response = self
-            .call_connector(
-                state,
-                router_data,
-                "create subscription on connector",
-                connector_integration,
-            )
-            .await?;
+    subscription_entry
+        .update_subscription(diesel_models::subscription::SubscriptionUpdate::new(
+            payment_response.payment_method_id.clone(),
+            Some(SubscriptionStatus::from(subscription_create_response.status).to_string()),
+            Some(
+                subscription_create_response
+                    .subscription_id
+                    .get_string_repr()
+                    .to_string(),
+            ),
+        ))
+        .await?;
 
-        match response {
-            Ok(response_data) => Ok(response_data),
-            Err(err) => Err(errors::ApiErrorResponse::ExternalConnectorError {
-                code: err.code,
-                message: err.message,
-                connector: self.connector_data.connector_name.to_string(),
-                status_code: err.status_code,
-                reason: err.reason,
-            }
-            .into()),
-        }
-    }
+    let response = subscription_entry.generate_response(
+        &invoice_entry,
+        &payment_response,
+        subscription_create_response.status,
+    )?;
 
-    async fn call_connector<F, ResourceCommonData, Req, Resp>(
-        &self,
-        state: &SessionState,
-        router_data: hyperswitch_domain_models::router_data_v2::RouterDataV2<
-            F,
-            ResourceCommonData,
-            Req,
-            Resp,
-        >,
-        operation_name: &str,
-        connector_integration: hyperswitch_interfaces::connector_integration_interface::BoxedConnectorIntegrationInterface<F, ResourceCommonData, Req, Resp>,
-    ) -> errors::RouterResult<Result<Resp, hyperswitch_domain_models::router_data::ErrorResponse>>
-    where
-        F: Clone + std::fmt::Debug + 'static,
-        Req: Clone + std::fmt::Debug + 'static,
-        Resp: Clone + std::fmt::Debug + 'static,
-        ResourceCommonData:
-            hyperswitch_interfaces::connector_integration_interface::RouterDataConversion<
-                    F,
-                    Req,
-                    Resp,
-                > + Clone
-                + 'static,
-    {
-        let old_router_data = ResourceCommonData::to_old_router_data(router_data).change_context(
-            errors::ApiErrorResponse::SubscriptionError {
-                operation: { operation_name.to_string() },
-            },
-        )?;
+    Ok(ApplicationResponse::Json(response))
+}
 
-        let router_resp = services::execute_connector_processing_step(
-            state,
-            connector_integration,
-            &old_router_data,
-            payments_core::CallConnectorAction::Trigger,
-            None,
-            None,
-        )
+pub async fn get_subscription(
+    state: SessionState,
+    merchant_context: MerchantContext,
+    profile_id: common_utils::id_type::ProfileId,
+    subscription_id: common_utils::id_type::SubscriptionId,
+) -> RouterResponse<SubscriptionResponse> {
+    let profile =
+        SubscriptionHandler::find_business_profile(&state, &merchant_context, &profile_id)
+            .await
+            .attach_printable(
+                "subscriptions: failed to find business profile in get_subscription",
+            )?;
+    let handler = SubscriptionHandler::new(&state, &merchant_context, profile);
+    let subscription = handler
+        .find_subscription(subscription_id)
         .await
-        .change_context(errors::ApiErrorResponse::SubscriptionError {
-            operation: operation_name.to_string(),
-        })
-        .attach_printable(format!(
-            "Failed while in subscription operation: {operation_name}"
-        ))?;
-
-        Ok(router_resp.response)
-    }
+        .attach_printable("subscriptions: failed to get subscription entry in get_subscription")?;
 
-    fn build_router_data<F, ResourceCommonData, Req, Resp>(
-        &self,
-        state: &SessionState,
-        req: Req,
-        resource_common_data: ResourceCommonData,
-    ) -> errors::RouterResult<
-        hyperswitch_domain_models::router_data_v2::RouterDataV2<F, ResourceCommonData, Req, Resp>,
-    > {
-        Ok(hyperswitch_domain_models::router_data_v2::RouterDataV2 {
-            flow: std::marker::PhantomData,
-            connector_auth_type: self.auth_type.clone(),
-            resource_common_data,
-            tenant_id: state.tenant.tenant_id.clone(),
-            request: req,
-            response: Err(hyperswitch_domain_models::router_data::ErrorResponse::default()),
-        })
-    }
+    Ok(ApplicationResponse::Json(
+        subscription.to_subscription_response(),
+    ))
 }
diff --git a/crates/router/src/core/subscription/billing_processor_handler.rs b/crates/router/src/core/subscription/billing_processor_handler.rs
new file mode 100644
index 00000000000..7e0e303f042
--- /dev/null
+++ b/crates/router/src/core/subscription/billing_processor_handler.rs
@@ -0,0 +1,283 @@
+use std::str::FromStr;
+
+use common_enums::connector_enums;
+use common_utils::{ext_traits::ValueExt, pii};
+use error_stack::ResultExt;
+use hyperswitch_domain_models::{
+    merchant_context::MerchantContext,
+    router_data_v2::flow_common_types::{SubscriptionCreateData, SubscriptionCustomerData},
+    router_request_types::{subscriptions as subscription_request_types, ConnectorCustomerData},
+    router_response_types::{
+        subscriptions as subscription_response_types, ConnectorCustomerResponseData,
+        PaymentsResponseData,
+    },
+};
+
+use super::errors;
+use crate::{
+    core::payments as payments_core, routes::SessionState, services, types::api as api_types,
+};
+
+pub struct BillingHandler {
+    pub auth_type: hyperswitch_domain_models::router_data::ConnectorAuthType,
+    pub connector_data: api_types::ConnectorData,
+    pub connector_params: hyperswitch_domain_models::connector_endpoints::ConnectorParams,
+    pub connector_metadata: Option<pii::SecretSerdeValue>,
+    pub customer: hyperswitch_domain_models::customer::Customer,
+    pub merchant_connector_id: common_utils::id_type::MerchantConnectorAccountId,
+}
+
+#[allow(clippy::todo)]
+impl BillingHandler {
+    pub async fn create(
+        state: &SessionState,
+        merchant_context: &MerchantContext,
+        customer: hyperswitch_domain_models::customer::Customer,
+        profile: hyperswitch_domain_models::business_profile::Profile,
+    ) -> errors::RouterResult<Self> {
+        let merchant_connector_id = profile.get_billing_processor_id()?;
+
+        let billing_processor_mca = state
+            .store
+            .find_by_merchant_connector_account_merchant_id_merchant_connector_id(
+                &(state).into(),
+                merchant_context.get_merchant_account().get_id(),
+                &merchant_connector_id,
+                merchant_context.get_merchant_key_store(),
+            )
+            .await
+            .change_context(errors::ApiErrorResponse::MerchantConnectorAccountNotFound {
+                id: merchant_connector_id.get_string_repr().to_string(),
+            })?;
+
+        let connector_name = billing_processor_mca.connector_name.clone();
+
+        let auth_type: hyperswitch_domain_models::router_data::ConnectorAuthType =
+            payments_core::helpers::MerchantConnectorAccountType::DbVal(Box::new(
+                billing_processor_mca.clone(),
+            ))
+            .get_connector_account_details()
+            .parse_value("ConnectorAuthType")
+            .change_context(errors::ApiErrorResponse::InvalidDataFormat {
+                field_name: "connector_account_details".to_string(),
+                expected_format: "auth_type and api_key".to_string(),
+            })?;
+
+        let connector_data = api_types::ConnectorData::get_connector_by_name(
+            &state.conf.connectors,
+            &connector_name,
+            api_types::GetToken::Connector,
+            Some(billing_processor_mca.get_id()),
+        )
+        .change_context(errors::ApiErrorResponse::IncorrectConnectorNameGiven)
+        .attach_printable(
+            "invalid connector name received in billing merchant connector account",
+        )?;
+
+        let connector_enum = connector_enums::Connector::from_str(connector_name.as_str())
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable(format!("unable to parse connector name {connector_name:?}"))?;
+
+        let connector_params =
+            hyperswitch_domain_models::connector_endpoints::Connectors::get_connector_params(
+                &state.conf.connectors,
+                connector_enum,
+            )
+            .change_context(errors::ApiErrorResponse::ConfigNotFound)
+            .attach_printable(format!(
+                "cannot find connector params for this connector {connector_name} in this flow",
+            ))?;
+
+        Ok(Self {
+            auth_type,
+            connector_data,
+            connector_params,
+            connector_metadata: billing_processor_mca.metadata.clone(),
+            customer,
+            merchant_connector_id,
+        })
+    }
+    pub async fn create_customer_on_connector(
+        &self,
+        state: &SessionState,
+        customer_id: common_utils::id_type::CustomerId,
+        billing_address: Option<api_models::payments::Address>,
+        payment_method_data: Option<api_models::payments::PaymentMethodData>,
+    ) -> errors::RouterResult<ConnectorCustomerResponseData> {
+        let customer_req = ConnectorCustomerData {
+            email: self.customer.email.clone().map(pii::Email::from),
+            payment_method_data: payment_method_data.clone().map(|pmd| pmd.into()),
+            description: None,
+            phone: None,
+            name: None,
+            preprocessing_id: None,
+            split_payments: None,
+            setup_future_usage: None,
+            customer_acceptance: None,
+            customer_id: Some(customer_id.clone()),
+            billing_address: billing_address
+                .as_ref()
+                .and_then(|add| add.address.clone())
+                .and_then(|addr| addr.into()),
+        };
+        let router_data = self.build_router_data(
+            state,
+            customer_req,
+            SubscriptionCustomerData {
+                connector_meta_data: self.connector_metadata.clone(),
+            },
+        )?;
+        let connector_integration = self.connector_data.connector.get_connector_integration();
+
+        let response = Box::pin(self.call_connector(
+            state,
+            router_data,
+            "create customer on connector",
+            connector_integration,
+        ))
+        .await?;
+
+        match response {
+            Ok(response_data) => match response_data {
+                PaymentsResponseData::ConnectorCustomerResponse(customer_response) => {
+                    Ok(customer_response)
+                }
+                _ => Err(errors::ApiErrorResponse::SubscriptionError {
+                    operation: "Subscription Customer Create".to_string(),
+                }
+                .into()),
+            },
+            Err(err) => Err(errors::ApiErrorResponse::ExternalConnectorError {
+                code: err.code,
+                message: err.message,
+                connector: self.connector_data.connector_name.to_string(),
+                status_code: err.status_code,
+                reason: err.reason,
+            }
+            .into()),
+        }
+    }
+    pub async fn create_subscription_on_connector(
+        &self,
+        state: &SessionState,
+        subscription: diesel_models::subscription::Subscription,
+        item_price_id: Option<String>,
+        billing_address: Option<api_models::payments::Address>,
+    ) -> errors::RouterResult<subscription_response_types::SubscriptionCreateResponse> {
+        let subscription_item = subscription_request_types::SubscriptionItem {
+            item_price_id: item_price_id.ok_or(errors::ApiErrorResponse::MissingRequiredField {
+                field_name: "item_price_id",
+            })?,
+            quantity: Some(1),
+        };
+        let subscription_req = subscription_request_types::SubscriptionCreateRequest {
+            subscription_id: subscription.id.to_owned(),
+            customer_id: subscription.customer_id.to_owned(),
+            subscription_items: vec![subscription_item],
+            billing_address: billing_address.ok_or(
+                errors::ApiErrorResponse::MissingRequiredField {
+                    field_name: "billing",
+                },
+            )?,
+            auto_collection: subscription_request_types::SubscriptionAutoCollection::Off,
+            connector_params: self.connector_params.clone(),
+        };
+
+        let router_data = self.build_router_data(
+            state,
+            subscription_req,
+            SubscriptionCreateData {
+                connector_meta_data: self.connector_metadata.clone(),
+            },
+        )?;
+        let connector_integration = self.connector_data.connector.get_connector_integration();
+
+        let response = self
+            .call_connector(
+                state,
+                router_data,
+                "create subscription on connector",
+                connector_integration,
+            )
+            .await?;
+
+        match response {
+            Ok(response_data) => Ok(response_data),
+            Err(err) => Err(errors::ApiErrorResponse::ExternalConnectorError {
+                code: err.code,
+                message: err.message,
+                connector: self.connector_data.connector_name.to_string(),
+                status_code: err.status_code,
+                reason: err.reason,
+            }
+            .into()),
+        }
+    }
+
+    async fn call_connector<F, ResourceCommonData, Req, Resp>(
+        &self,
+        state: &SessionState,
+        router_data: hyperswitch_domain_models::router_data_v2::RouterDataV2<
+            F,
+            ResourceCommonData,
+            Req,
+            Resp,
+        >,
+        operation_name: &str,
+        connector_integration: hyperswitch_interfaces::connector_integration_interface::BoxedConnectorIntegrationInterface<F, ResourceCommonData, Req, Resp>,
+    ) -> errors::RouterResult<Result<Resp, hyperswitch_domain_models::router_data::ErrorResponse>>
+    where
+        F: Clone + std::fmt::Debug + 'static,
+        Req: Clone + std::fmt::Debug + 'static,
+        Resp: Clone + std::fmt::Debug + 'static,
+        ResourceCommonData:
+            hyperswitch_interfaces::connector_integration_interface::RouterDataConversion<
+                    F,
+                    Req,
+                    Resp,
+                > + Clone
+                + 'static,
+    {
+        let old_router_data = ResourceCommonData::to_old_router_data(router_data).change_context(
+            errors::ApiErrorResponse::SubscriptionError {
+                operation: { operation_name.to_string() },
+            },
+        )?;
+
+        let router_resp = services::execute_connector_processing_step(
+            state,
+            connector_integration,
+            &old_router_data,
+            payments_core::CallConnectorAction::Trigger,
+            None,
+            None,
+        )
+        .await
+        .change_context(errors::ApiErrorResponse::SubscriptionError {
+            operation: operation_name.to_string(),
+        })
+        .attach_printable(format!(
+            "Failed while in subscription operation: {operation_name}"
+        ))?;
+
+        Ok(router_resp.response)
+    }
+
+    fn build_router_data<F, ResourceCommonData, Req, Resp>(
+        &self,
+        state: &SessionState,
+        req: Req,
+        resource_common_data: ResourceCommonData,
+    ) -> errors::RouterResult<
+        hyperswitch_domain_models::router_data_v2::RouterDataV2<F, ResourceCommonData, Req, Resp>,
+    > {
+        Ok(hyperswitch_domain_models::router_data_v2::RouterDataV2 {
+            flow: std::marker::PhantomData,
+            connector_auth_type: self.auth_type.clone(),
+            resource_common_data,
+            tenant_id: state.tenant.tenant_id.clone(),
+            request: req,
+            response: Err(hyperswitch_domain_models::router_data::ErrorResponse::default()),
+        })
+    }
+}
diff --git a/crates/router/src/core/subscription/invoice_handler.rs b/crates/router/src/core/subscription/invoice_handler.rs
new file mode 100644
index 00000000000..eae1b9d05c7
--- /dev/null
+++ b/crates/router/src/core/subscription/invoice_handler.rs
@@ -0,0 +1,215 @@
+use api_models::{
+    enums as api_enums,
+    subscription::{self as subscription_types},
+};
+use common_enums::connector_enums;
+use common_utils::{pii, types::MinorUnit};
+use error_stack::ResultExt;
+use hyperswitch_domain_models::router_response_types::subscriptions as subscription_response_types;
+use masking::{PeekInterface, Secret};
+
+use super::errors;
+use crate::{core::subscription::payments_api_client, routes::SessionState};
+
+pub struct InvoiceHandler {
+    pub subscription: diesel_models::subscription::Subscription,
+    pub merchant_account: hyperswitch_domain_models::merchant_account::MerchantAccount,
+    pub profile: hyperswitch_domain_models::business_profile::Profile,
+}
+
+#[allow(clippy::todo)]
+impl InvoiceHandler {
+    #[allow(clippy::too_many_arguments)]
+    pub async fn create_invoice_entry(
+        self,
+        state: &SessionState,
+        merchant_connector_id: common_utils::id_type::MerchantConnectorAccountId,
+        payment_intent_id: Option<common_utils::id_type::PaymentId>,
+        amount: MinorUnit,
+        currency: common_enums::Currency,
+        status: connector_enums::InvoiceStatus,
+        provider_name: connector_enums::Connector,
+        metadata: Option<pii::SecretSerdeValue>,
+    ) -> errors::RouterResult<diesel_models::invoice::Invoice> {
+        let invoice_new = diesel_models::invoice::InvoiceNew::new(
+            self.subscription.id.to_owned(),
+            self.subscription.merchant_id.to_owned(),
+            self.subscription.profile_id.to_owned(),
+            merchant_connector_id,
+            payment_intent_id,
+            self.subscription.payment_method_id.clone(),
+            self.subscription.customer_id.to_owned(),
+            amount,
+            currency.to_string(),
+            status,
+            provider_name,
+            metadata,
+        );
+
+        let invoice = state
+            .store
+            .insert_invoice_entry(invoice_new)
+            .await
+            .change_context(errors::ApiErrorResponse::SubscriptionError {
+                operation: "Create Invoice".to_string(),
+            })
+            .attach_printable("invoices: unable to insert invoice entry to database")?;
+
+        Ok(invoice)
+    }
+
+    pub async fn update_invoice(
+        &self,
+        state: &SessionState,
+        invoice_id: common_utils::id_type::InvoiceId,
+        payment_method_id: Option<Secret<String>>,
+        status: connector_enums::InvoiceStatus,
+    ) -> errors::RouterResult<diesel_models::invoice::Invoice> {
+        let update_invoice = diesel_models::invoice::InvoiceUpdate::new(
+            payment_method_id.as_ref().map(|id| id.peek()).cloned(),
+            Some(status),
+        );
+        state
+            .store
+            .update_invoice_entry(invoice_id.get_string_repr().to_string(), update_invoice)
+            .await
+            .change_context(errors::ApiErrorResponse::SubscriptionError {
+                operation: "Invoice Update".to_string(),
+            })
+            .attach_printable("invoices: unable to update invoice entry in database")
+    }
+
+    pub fn get_amount_and_currency(
+        request: (Option<MinorUnit>, Option<api_enums::Currency>),
+        invoice_details: Option<subscription_response_types::SubscriptionInvoiceData>,
+    ) -> (MinorUnit, api_enums::Currency) {
+        // Use request amount and currency if provided, else fallback to invoice details from connector response
+        request.0.zip(request.1).unwrap_or(
+            invoice_details
+                .clone()
+                .map(|invoice| (invoice.total, invoice.currency_code))
+                .unwrap_or((MinorUnit::new(0), api_enums::Currency::default())),
+        ) // Default to 0 and a default currency if not provided
+    }
+
+    pub async fn create_payment_with_confirm_false(
+        &self,
+        state: &SessionState,
+        request: &subscription_types::CreateSubscriptionRequest,
+    ) -> errors::RouterResult<subscription_types::PaymentResponseData> {
+        let payment_details = &request.payment_details;
+        let payment_request = subscription_types::CreatePaymentsRequestData {
+            amount: request.amount,
+            currency: request.currency,
+            customer_id: Some(self.subscription.customer_id.clone()),
+            billing: request.billing.clone(),
+            shipping: request.shipping.clone(),
+            setup_future_usage: payment_details.setup_future_usage,
+            return_url: Some(payment_details.return_url.clone()),
+            capture_method: payment_details.capture_method,
+            authentication_type: payment_details.authentication_type,
+        };
+        payments_api_client::PaymentsApiClient::create_cit_payment(
+            state,
+            payment_request,
+            self.merchant_account.get_id().get_string_repr(),
+            self.profile.get_id().get_string_repr(),
+        )
+        .await
+    }
+
+    pub async fn get_payment_details(
+        &self,
+        state: &SessionState,
+        payment_id: common_utils::id_type::PaymentId,
+    ) -> errors::RouterResult<subscription_types::PaymentResponseData> {
+        payments_api_client::PaymentsApiClient::sync_payment(
+            state,
+            payment_id.get_string_repr().to_string(),
+            self.merchant_account.get_id().get_string_repr(),
+            self.profile.get_id().get_string_repr(),
+        )
+        .await
+    }
+
+    pub async fn create_and_confirm_payment(
+        &self,
+        state: &SessionState,
+        request: &subscription_types::CreateAndConfirmSubscriptionRequest,
+        amount: MinorUnit,
+        currency: common_enums::Currency,
+    ) -> errors::RouterResult<subscription_types::PaymentResponseData> {
+        let payment_details = &request.payment_details;
+        let payment_request = subscription_types::CreateAndConfirmPaymentsRequestData {
+            amount,
+            currency,
+            confirm: true,
+            customer_id: Some(self.subscription.customer_id.clone()),
+            billing: request.billing.clone(),
+            shipping: request.shipping.clone(),
+            setup_future_usage: payment_details.setup_future_usage,
+            return_url: payment_details.return_url.clone(),
+            capture_method: payment_details.capture_method,
+            authentication_type: payment_details.authentication_type,
+            payment_method: payment_details.payment_method,
+            payment_method_type: payment_details.payment_method_type,
+            payment_method_data: payment_details.payment_method_data.clone(),
+            customer_acceptance: payment_details.customer_acceptance.clone(),
+        };
+        payments_api_client::PaymentsApiClient::create_and_confirm_payment(
+            state,
+            payment_request,
+            self.merchant_account.get_id().get_string_repr(),
+            self.profile.get_id().get_string_repr(),
+        )
+        .await
+    }
+
+    pub async fn confirm_payment(
+        &self,
+        state: &SessionState,
+        payment_id: common_utils::id_type::PaymentId,
+        request: &subscription_types::ConfirmSubscriptionRequest,
+    ) -> errors::RouterResult<subscription_types::PaymentResponseData> {
+        let payment_details = &request.payment_details;
+        let cit_payment_request = subscription_types::ConfirmPaymentsRequestData {
+            billing: request.billing.clone(),
+            shipping: request.shipping.clone(),
+            payment_method: payment_details.payment_method,
+            payment_method_type: payment_details.payment_method_type,
+            payment_method_data: payment_details.payment_method_data.clone(),
+            customer_acceptance: payment_details.customer_acceptance.clone(),
+        };
+        payments_api_client::PaymentsApiClient::confirm_payment(
+            state,
+            cit_payment_request,
+            payment_id.get_string_repr().to_string(),
+            self.merchant_account.get_id().get_string_repr(),
+            self.profile.get_id().get_string_repr(),
+        )
+        .await
+    }
+
+    pub async fn get_latest_invoice(
+        &self,
+        state: &SessionState,
+    ) -> errors::RouterResult<diesel_models::invoice::Invoice> {
+        state
+            .store
+            .get_latest_invoice_for_subscription(self.subscription.id.get_string_repr().to_string())
+            .await
+            .change_context(errors::ApiErrorResponse::SubscriptionError {
+                operation: "Get Latest Invoice".to_string(),
+            })
+            .attach_printable("invoices: unable to get latest invoice from database")
+    }
+
+    pub async fn create_invoice_record_back_job(
+        &self,
+        // _invoice: &subscription_types::Invoice,
+        _payment_response: &subscription_types::PaymentResponseData,
+    ) -> errors::RouterResult<()> {
+        // Create an invoice job entry based on payment status
+        todo!("Create an invoice job entry based on payment status")
+    }
+}
diff --git a/crates/router/src/core/subscription/payments_api_client.rs b/crates/router/src/core/subscription/payments_api_client.rs
new file mode 100644
index 00000000000..e483469be96
--- /dev/null
+++ b/crates/router/src/core/subscription/payments_api_client.rs
@@ -0,0 +1,195 @@
+use api_models::subscription as subscription_types;
+use common_utils::{ext_traits::BytesExt, request as services};
+use error_stack::ResultExt;
+
+use crate::{core::errors, headers, routes::SessionState, services::api};
+
+pub struct PaymentsApiClient;
+
+#[derive(Debug, serde::Deserialize)]
+pub struct ErrorResponse {
+    error: ErrorResponseDetails,
+}
+
+#[derive(Debug, serde::Deserialize)]
+pub struct ErrorResponseDetails {
+    #[serde(rename = "type")]
+    error_type: Option<String>,
+    code: String,
+    message: String,
+}
+
+impl PaymentsApiClient {
+    fn get_internal_auth_headers(
+        state: &SessionState,
+        merchant_id: &str,
+        profile_id: &str,
+    ) -> Vec<(String, masking::Maskable<String>)> {
+        vec![
+            (
+                headers::X_INTERNAL_API_KEY.to_string(),
+                masking::Maskable::Masked(
+                    state
+                        .conf
+                        .internal_merchant_id_profile_id_auth
+                        .internal_api_key
+                        .clone(),
+                ),
+            ),
+            (
+                headers::X_MERCHANT_ID.to_string(),
+                masking::Maskable::Normal(merchant_id.to_string()),
+            ),
+            (
+                headers::X_PROFILE_ID.to_string(),
+                masking::Maskable::Normal(profile_id.to_string()),
+            ),
+        ]
+    }
+
+    /// Generic method to handle payment API calls with different HTTP methods and URL patterns
+    async fn make_payment_api_call(
+        state: &SessionState,
+        method: services::Method,
+        url: String,
+        request_body: Option<common_utils::request::RequestContent>,
+        operation_name: &str,
+        merchant_id: &str,
+        profile_id: &str,
+    ) -> errors::RouterResult<subscription_types::PaymentResponseData> {
+        let subscription_error = errors::ApiErrorResponse::SubscriptionError {
+            operation: operation_name.to_string(),
+        };
+        let headers = Self::get_internal_auth_headers(state, merchant_id, profile_id);
+
+        let mut request_builder = services::RequestBuilder::new()
+            .method(method)
+            .url(&url)
+            .headers(headers);
+
+        // Add request body only if provided (for POST requests)
+        if let Some(body) = request_body {
+            request_builder = request_builder.set_body(body);
+        }
+
+        let request = request_builder.build();
+        let response = api::call_connector_api(state, request, "Subscription Payments")
+            .await
+            .change_context(subscription_error.clone())?;
+
+        match response {
+            Ok(res) => {
+                let api_response: subscription_types::PaymentResponseData = res
+                    .response
+                    .parse_struct(std::any::type_name::<subscription_types::PaymentResponseData>())
+                    .change_context(subscription_error)?;
+                Ok(api_response)
+            }
+            Err(err) => {
+                let error_response: ErrorResponse = err
+                    .response
+                    .parse_struct(std::any::type_name::<ErrorResponse>())
+                    .change_context(subscription_error)?;
+                Err(errors::ApiErrorResponse::ExternalConnectorError {
+                    code: error_response.error.code,
+                    message: error_response.error.message,
+                    connector: "payments_microservice".to_string(),
+                    status_code: err.status_code,
+                    reason: error_response.error.error_type,
+                }
+                .into())
+            }
+        }
+    }
+
+    pub async fn create_cit_payment(
+        state: &SessionState,
+        request: subscription_types::CreatePaymentsRequestData,
+        merchant_id: &str,
+        profile_id: &str,
+    ) -> errors::RouterResult<subscription_types::PaymentResponseData> {
+        let base_url = &state.conf.internal_services.payments_base_url;
+        let url = format!("{}/payments", base_url);
+
+        Self::make_payment_api_call(
+            state,
+            services::Method::Post,
+            url,
+            Some(common_utils::request::RequestContent::Json(Box::new(
+                request,
+            ))),
+            "Create Payment",
+            merchant_id,
+            profile_id,
+        )
+        .await
+    }
+
+    pub async fn create_and_confirm_payment(
+        state: &SessionState,
+        request: subscription_types::CreateAndConfirmPaymentsRequestData,
+        merchant_id: &str,
+        profile_id: &str,
+    ) -> errors::RouterResult<subscription_types::PaymentResponseData> {
+        let base_url = &state.conf.internal_services.payments_base_url;
+        let url = format!("{}/payments", base_url);
+
+        Self::make_payment_api_call(
+            state,
+            services::Method::Post,
+            url,
+            Some(common_utils::request::RequestContent::Json(Box::new(
+                request,
+            ))),
+            "Create And Confirm Payment",
+            merchant_id,
+            profile_id,
+        )
+        .await
+    }
+
+    pub async fn confirm_payment(
+        state: &SessionState,
+        request: subscription_types::ConfirmPaymentsRequestData,
+        payment_id: String,
+        merchant_id: &str,
+        profile_id: &str,
+    ) -> errors::RouterResult<subscription_types::PaymentResponseData> {
+        let base_url = &state.conf.internal_services.payments_base_url;
+        let url = format!("{}/payments/{}/confirm", base_url, payment_id);
+
+        Self::make_payment_api_call(
+            state,
+            services::Method::Post,
+            url,
+            Some(common_utils::request::RequestContent::Json(Box::new(
+                request,
+            ))),
+            "Confirm Payment",
+            merchant_id,
+            profile_id,
+        )
+        .await
+    }
+
+    pub async fn sync_payment(
+        state: &SessionState,
+        payment_id: String,
+        merchant_id: &str,
+        profile_id: &str,
+    ) -> errors::RouterResult<subscription_types::PaymentResponseData> {
+        let base_url = &state.conf.internal_services.payments_base_url;
+        let url = format!("{}/payments/{}", base_url, payment_id);
+
+        Self::make_payment_api_call(
+            state,
+            services::Method::Get,
+            url,
+            None,
+            "Sync Payment",
+            merchant_id,
+            profile_id,
+        )
+        .await
+    }
+}
diff --git a/crates/router/src/core/subscription/subscription_handler.rs b/crates/router/src/core/subscription/subscription_handler.rs
new file mode 100644
index 00000000000..25259a47696
--- /dev/null
+++ b/crates/router/src/core/subscription/subscription_handler.rs
@@ -0,0 +1,247 @@
+use std::str::FromStr;
+
+use api_models::{
+    enums as api_enums,
+    subscription::{self as subscription_types, SubscriptionResponse, SubscriptionStatus},
+};
+use common_enums::connector_enums;
+use diesel_models::subscription::SubscriptionNew;
+use error_stack::ResultExt;
+use hyperswitch_domain_models::{
+    merchant_context::MerchantContext,
+    router_response_types::subscriptions as subscription_response_types,
+};
+use masking::Secret;
+
+use super::errors;
+use crate::{core::subscription::invoice_handler::InvoiceHandler, routes::SessionState};
+
+pub struct SubscriptionHandler<'a> {
+    pub state: &'a SessionState,
+    pub merchant_context: &'a MerchantContext,
+    pub profile: hyperswitch_domain_models::business_profile::Profile,
+}
+
+impl<'a> SubscriptionHandler<'a> {
+    pub fn new(
+        state: &'a SessionState,
+        merchant_context: &'a MerchantContext,
+        profile: hyperswitch_domain_models::business_profile::Profile,
+    ) -> Self {
+        Self {
+            state,
+            merchant_context,
+            profile,
+        }
+    }
+
+    /// Helper function to create a subscription entry in the database.
+    pub async fn create_subscription_entry(
+        &self,
+        subscription_id: common_utils::id_type::SubscriptionId,
+        customer_id: &common_utils::id_type::CustomerId,
+        billing_processor: connector_enums::Connector,
+        merchant_connector_id: common_utils::id_type::MerchantConnectorAccountId,
+        merchant_reference_id: Option<String>,
+    ) -> errors::RouterResult<SubscriptionWithHandler<'_>> {
+        let store = self.state.store.clone();
+        let db = store.as_ref();
+
+        let mut subscription = SubscriptionNew::new(
+            subscription_id,
+            SubscriptionStatus::Created.to_string(),
+            Some(billing_processor.to_string()),
+            None,
+            Some(merchant_connector_id),
+            None,
+            None,
+            self.merchant_context
+                .get_merchant_account()
+                .get_id()
+                .clone(),
+            customer_id.clone(),
+            None,
+            self.profile.get_id().clone(),
+            merchant_reference_id,
+        );
+
+        subscription.generate_and_set_client_secret();
+
+        let new_subscription = db
+            .insert_subscription_entry(subscription)
+            .await
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("subscriptions: unable to insert subscription entry to database")?;
+
+        Ok(SubscriptionWithHandler {
+            handler: self,
+            subscription: new_subscription,
+            profile: self.profile.clone(),
+            merchant_account: self.merchant_context.get_merchant_account().clone(),
+        })
+    }
+
+    /// Helper function to find and validate customer.
+    pub async fn find_customer(
+        state: &SessionState,
+        merchant_context: &MerchantContext,
+        customer_id: &common_utils::id_type::CustomerId,
+    ) -> errors::RouterResult<hyperswitch_domain_models::customer::Customer> {
+        let key_manager_state = &(state).into();
+        let merchant_key_store = merchant_context.get_merchant_key_store();
+        let merchant_id = merchant_context.get_merchant_account().get_id();
+
+        state
+            .store
+            .find_customer_by_customer_id_merchant_id(
+                key_manager_state,
+                customer_id,
+                merchant_id,
+                merchant_key_store,
+                merchant_context.get_merchant_account().storage_scheme,
+            )
+            .await
+            .change_context(errors::ApiErrorResponse::CustomerNotFound)
+            .attach_printable("subscriptions: unable to fetch customer from database")
+    }
+
+    /// Helper function to find business profile.
+    pub async fn find_business_profile(
+        state: &SessionState,
+        merchant_context: &MerchantContext,
+        profile_id: &common_utils::id_type::ProfileId,
+    ) -> errors::RouterResult<hyperswitch_domain_models::business_profile::Profile> {
+        let key_manager_state = &(state).into();
+        let merchant_key_store = merchant_context.get_merchant_key_store();
+
+        state
+            .store
+            .find_business_profile_by_profile_id(key_manager_state, merchant_key_store, profile_id)
+            .await
+            .change_context(errors::ApiErrorResponse::ProfileNotFound {
+                id: profile_id.get_string_repr().to_string(),
+            })
+    }
+
+    pub async fn find_subscription(
+        &self,
+        subscription_id: common_utils::id_type::SubscriptionId,
+    ) -> errors::RouterResult<SubscriptionWithHandler<'_>> {
+        let subscription = self
+            .state
+            .store
+            .find_by_merchant_id_subscription_id(
+                self.merchant_context.get_merchant_account().get_id(),
+                subscription_id.get_string_repr().to_string().clone(),
+            )
+            .await
+            .change_context(errors::ApiErrorResponse::GenericNotFoundError {
+                message: format!(
+                    "subscription not found for id: {}",
+                    subscription_id.get_string_repr()
+                ),
+            })?;
+
+        Ok(SubscriptionWithHandler {
+            handler: self,
+            subscription,
+            profile: self.profile.clone(),
+            merchant_account: self.merchant_context.get_merchant_account().clone(),
+        })
+    }
+}
+pub struct SubscriptionWithHandler<'a> {
+    pub handler: &'a SubscriptionHandler<'a>,
+    pub subscription: diesel_models::subscription::Subscription,
+    pub profile: hyperswitch_domain_models::business_profile::Profile,
+    pub merchant_account: hyperswitch_domain_models::merchant_account::MerchantAccount,
+}
+
+impl SubscriptionWithHandler<'_> {
+    pub fn generate_response(
+        &self,
+        invoice: &diesel_models::invoice::Invoice,
+        payment_response: &subscription_types::PaymentResponseData,
+        status: subscription_response_types::SubscriptionStatus,
+    ) -> errors::RouterResult<subscription_types::ConfirmSubscriptionResponse> {
+        Ok(subscription_types::ConfirmSubscriptionResponse {
+            id: self.subscription.id.clone(),
+            merchant_reference_id: self.subscription.merchant_reference_id.clone(),
+            status: SubscriptionStatus::from(status),
+            plan_id: None,
+            profile_id: self.subscription.profile_id.to_owned(),
+            payment: Some(payment_response.clone()),
+            customer_id: Some(self.subscription.customer_id.clone()),
+            price_id: None,
+            coupon: None,
+            billing_processor_subscription_id: self.subscription.connector_subscription_id.clone(),
+            invoice: Some(subscription_types::Invoice {
+                id: invoice.id.clone(),
+                subscription_id: invoice.subscription_id.clone(),
+                merchant_id: invoice.merchant_id.clone(),
+                profile_id: invoice.profile_id.clone(),
+                merchant_connector_id: invoice.merchant_connector_id.clone(),
+                payment_intent_id: invoice.payment_intent_id.clone(),
+                payment_method_id: invoice.payment_method_id.clone(),
+                customer_id: invoice.customer_id.clone(),
+                amount: invoice.amount,
+                currency: api_enums::Currency::from_str(invoice.currency.as_str())
+                    .change_context(errors::ApiErrorResponse::InvalidDataValue {
+                        field_name: "currency",
+                    })
+                    .attach_printable(format!(
+                        "unable to parse currency name {currency:?}",
+                        currency = invoice.currency
+                    ))?,
+                status: invoice.status.clone(),
+            }),
+        })
+    }
+
+    pub fn to_subscription_response(&self) -> SubscriptionResponse {
+        SubscriptionResponse::new(
+            self.subscription.id.clone(),
+            self.subscription.merchant_reference_id.clone(),
+            SubscriptionStatus::from_str(&self.subscription.status)
+                .unwrap_or(SubscriptionStatus::Created),
+            None,
+            self.subscription.profile_id.to_owned(),
+            self.subscription.merchant_id.to_owned(),
+            self.subscription.client_secret.clone().map(Secret::new),
+            self.subscription.customer_id.clone(),
+        )
+    }
+
+    pub async fn update_subscription(
+        &mut self,
+        subscription_update: diesel_models::subscription::SubscriptionUpdate,
+    ) -> errors::RouterResult<()> {
+        let db = self.handler.state.store.as_ref();
+        let updated_subscription = db
+            .update_subscription_entry(
+                self.handler
+                    .merchant_context
+                    .get_merchant_account()
+                    .get_id(),
+                self.subscription.id.get_string_repr().to_string(),
+                subscription_update,
+            )
+            .await
+            .change_context(errors::ApiErrorResponse::SubscriptionError {
+                operation: "Subscription Update".to_string(),
+            })
+            .attach_printable("subscriptions: unable to update subscription entry in database")?;
+
+        self.subscription = updated_subscription;
+
+        Ok(())
+    }
+
+    pub fn get_invoice_handler(&self) -> InvoiceHandler {
+        InvoiceHandler {
+            subscription: self.subscription.clone(),
+            merchant_account: self.merchant_account.clone(),
+            profile: self.profile.clone(),
+        }
+    }
+}
diff --git a/crates/router/src/db/invoice.rs b/crates/router/src/db/invoice.rs
index 850f1c52730..b12a806840f 100644
--- a/crates/router/src/db/invoice.rs
+++ b/crates/router/src/db/invoice.rs
@@ -27,6 +27,11 @@ pub trait InvoiceInterface {
         invoice_id: String,
         data: storage::invoice::InvoiceUpdate,
     ) -> CustomResult<storage::Invoice, errors::StorageError>;
+
+    async fn get_latest_invoice_for_subscription(
+        &self,
+        subscription_id: String,
+    ) -> CustomResult<storage::Invoice, errors::StorageError>;
 }
 
 #[async_trait::async_trait]
@@ -65,6 +70,28 @@ impl InvoiceInterface for Store {
             .await
             .map_err(|error| report!(errors::StorageError::from(error)))
     }
+
+    #[instrument(skip_all)]
+    async fn get_latest_invoice_for_subscription(
+        &self,
+        subscription_id: String,
+    ) -> CustomResult<storage::Invoice, errors::StorageError> {
+        let conn = connection::pg_connection_write(self).await?;
+        storage::Invoice::list_invoices_by_subscription_id(
+            &conn,
+            subscription_id.clone(),
+            Some(1),
+            None,
+            false,
+        )
+        .await
+        .map_err(|error| report!(errors::StorageError::from(error)))
+        .map(|e| e.last().cloned())?
+        .ok_or(report!(errors::StorageError::ValueNotFound(format!(
+            "Invoice not found for subscription_id: {}",
+            subscription_id
+        ))))
+    }
 }
 
 #[async_trait::async_trait]
@@ -91,6 +118,13 @@ impl InvoiceInterface for MockDb {
     ) -> CustomResult<storage::Invoice, errors::StorageError> {
         Err(errors::StorageError::MockDbError)?
     }
+
+    async fn get_latest_invoice_for_subscription(
+        &self,
+        _subscription_id: String,
+    ) -> CustomResult<storage::Invoice, errors::StorageError> {
+        Err(errors::StorageError::MockDbError)?
+    }
 }
 
 #[async_trait::async_trait]
@@ -123,4 +157,13 @@ impl InvoiceInterface for KafkaStore {
             .update_invoice_entry(invoice_id, data)
             .await
     }
+
+    async fn get_latest_invoice_for_subscription(
+        &self,
+        subscription_id: String,
+    ) -> CustomResult<storage::Invoice, errors::StorageError> {
+        self.diesel_store
+            .get_latest_invoice_for_subscription(subscription_id)
+            .await
+    }
 }
diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs
index 044aaa1b4bb..60724830e0c 100644
--- a/crates/router/src/routes/app.rs
+++ b/crates/router/src/routes/app.rs
@@ -1177,6 +1177,11 @@ impl Subscription {
         let route = web::scope("/subscriptions").app_data(web::Data::new(state.clone()));
 
         route
+            .service(
+                web::resource("").route(web::post().to(|state, req, payload| {
+                    subscription::create_and_confirm_subscription(state, req, payload)
+                })),
+            )
             .service(web::resource("/create").route(
                 web::post().to(|state, req, payload| {
                     subscription::create_subscription(state, req, payload)
@@ -1189,6 +1194,10 @@ impl Subscription {
                     },
                 )),
             )
+            .service(
+                web::resource("/{subscription_id}")
+                    .route(web::get().to(subscription::get_subscription)),
+            )
     }
 }
 
diff --git a/crates/router/src/routes/lock_utils.rs b/crates/router/src/routes/lock_utils.rs
index 67ea61919d5..f6ba2af979a 100644
--- a/crates/router/src/routes/lock_utils.rs
+++ b/crates/router/src/routes/lock_utils.rs
@@ -88,7 +88,10 @@ impl From<Flow> for ApiIdentifier {
             | Flow::DecisionEngineDecideGatewayCall
             | Flow::DecisionEngineGatewayFeedbackCall => Self::Routing,
 
-            Flow::CreateSubscription | Flow::ConfirmSubscription => Self::Subscription,
+            Flow::CreateSubscription
+            | Flow::ConfirmSubscription
+            | Flow::CreateAndConfirmSubscription
+            | Flow::GetSubscription => Self::Subscription,
 
             Flow::RetrieveForexFlow => Self::Forex,
             Flow::AddToBlocklist => Self::Blocklist,
diff --git a/crates/router/src/routes/payments.rs b/crates/router/src/routes/payments.rs
index 3bf2f472837..770d0b2f9bd 100644
--- a/crates/router/src/routes/payments.rs
+++ b/crates/router/src/routes/payments.rs
@@ -925,11 +925,15 @@ pub async fn payments_confirm(
         is_platform_allowed: true,
     };
 
-    let (auth_type, auth_flow) =
-        match auth::check_client_secret_and_get_auth(req.headers(), &payload, api_auth) {
-            Ok(auth) => auth,
-            Err(e) => return api::log_and_return_error_response(e),
-        };
+    let (auth_type, auth_flow) = match auth::check_internal_api_key_auth(
+        req.headers(),
+        &payload,
+        api_auth,
+        state.conf.internal_merchant_id_profile_id_auth.clone(),
+    ) {
+        Ok(auth) => auth,
+        Err(e) => return api::log_and_return_error_response(e),
+    };
 
     let locking_action = payload.get_locking_input(flow.clone());
 
diff --git a/crates/router/src/routes/subscription.rs b/crates/router/src/routes/subscription.rs
index aacf03392be..a762da71972 100644
--- a/crates/router/src/routes/subscription.rs
+++ b/crates/router/src/routes/subscription.rs
@@ -3,6 +3,8 @@
 //! Functions that are used to perform the api level configuration and retrieval
 //! of various types under Subscriptions.
 
+use std::str::FromStr;
+
 use actix_web::{web, HttpRequest, HttpResponse, Responder};
 use api_models::subscription as subscription_types;
 use hyperswitch_domain_models::errors;
@@ -19,7 +21,34 @@ use crate::{
     types::domain,
 };
 
-#[cfg(all(feature = "oltp", feature = "v1"))]
+fn extract_profile_id(req: &HttpRequest) -> Result<common_utils::id_type::ProfileId, HttpResponse> {
+    let header_value = req.headers().get(X_PROFILE_ID).ok_or_else(|| {
+        HttpResponse::BadRequest().json(
+            errors::api_error_response::ApiErrorResponse::MissingRequiredField {
+                field_name: X_PROFILE_ID,
+            },
+        )
+    })?;
+
+    let profile_str = header_value.to_str().unwrap_or_default();
+
+    if profile_str.is_empty() {
+        return Err(HttpResponse::BadRequest().json(
+            errors::api_error_response::ApiErrorResponse::MissingRequiredField {
+                field_name: X_PROFILE_ID,
+            },
+        ));
+    }
+
+    common_utils::id_type::ProfileId::from_str(profile_str).map_err(|_| {
+        HttpResponse::BadRequest().json(
+            errors::api_error_response::ApiErrorResponse::InvalidDataValue {
+                field_name: X_PROFILE_ID,
+            },
+        )
+    })
+}
+
 #[instrument(skip_all)]
 pub async fn create_subscription(
     state: web::Data<AppState>,
@@ -27,15 +56,9 @@ pub async fn create_subscription(
     json_payload: web::Json<subscription_types::CreateSubscriptionRequest>,
 ) -> impl Responder {
     let flow = Flow::CreateSubscription;
-    let profile_id = match req.headers().get(X_PROFILE_ID) {
-        Some(val) => val.to_str().unwrap_or_default().to_string(),
-        None => {
-            return HttpResponse::BadRequest().json(
-                errors::api_error_response::ApiErrorResponse::MissingRequiredField {
-                    field_name: "x-profile-id",
-                },
-            );
-        }
+    let profile_id = match extract_profile_id(&req) {
+        Ok(id) => id,
+        Err(response) => return response,
     };
     Box::pin(oss_api::server_wrap(
         flow,
@@ -68,7 +91,6 @@ pub async fn create_subscription(
     .await
 }
 
-#[cfg(all(feature = "olap", feature = "v1"))]
 #[instrument(skip_all)]
 pub async fn confirm_subscription(
     state: web::Data<AppState>,
@@ -78,15 +100,9 @@ pub async fn confirm_subscription(
 ) -> impl Responder {
     let flow = Flow::ConfirmSubscription;
     let subscription_id = subscription_id.into_inner();
-    let profile_id = match req.headers().get(X_PROFILE_ID) {
-        Some(val) => val.to_str().unwrap_or_default().to_string(),
-        None => {
-            return HttpResponse::BadRequest().json(
-                errors::api_error_response::ApiErrorResponse::MissingRequiredField {
-                    field_name: "x-profile-id",
-                },
-            );
-        }
+    let profile_id = match extract_profile_id(&req) {
+        Ok(id) => id,
+        Err(response) => return response,
     };
     Box::pin(oss_api::server_wrap(
         flow,
@@ -119,3 +135,83 @@ pub async fn confirm_subscription(
     ))
     .await
 }
+
+/// Add support for get subscription by id
+#[instrument(skip_all)]
+pub async fn get_subscription(
+    state: web::Data<AppState>,
+    req: HttpRequest,
+    subscription_id: web::Path<common_utils::id_type::SubscriptionId>,
+) -> impl Responder {
+    let flow = Flow::GetSubscription;
+    let subscription_id = subscription_id.into_inner();
+    let profile_id = match extract_profile_id(&req) {
+        Ok(id) => id,
+        Err(response) => return response,
+    };
+    Box::pin(oss_api::server_wrap(
+        flow,
+        state,
+        &req,
+        (),
+        |state, auth: auth::AuthenticationData, _, _| {
+            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
+                domain::Context(auth.merchant_account, auth.key_store),
+            ));
+            subscription::get_subscription(
+                state,
+                merchant_context,
+                profile_id.clone(),
+                subscription_id.clone(),
+            )
+        },
+        auth::auth_type(
+            &auth::HeaderAuth(auth::ApiKeyAuth {
+                is_connected_allowed: false,
+                is_platform_allowed: false,
+            }),
+            &auth::JWTAuth {
+                permission: Permission::ProfileSubscriptionRead,
+            },
+            req.headers(),
+        ),
+        api_locking::LockAction::NotApplicable,
+    ))
+    .await
+}
+
+#[instrument(skip_all)]
+pub async fn create_and_confirm_subscription(
+    state: web::Data<AppState>,
+    req: HttpRequest,
+    json_payload: web::Json<subscription_types::CreateAndConfirmSubscriptionRequest>,
+) -> impl Responder {
+    let flow = Flow::CreateAndConfirmSubscription;
+    let profile_id = match extract_profile_id(&req) {
+        Ok(id) => id,
+        Err(response) => return response,
+    };
+    Box::pin(oss_api::server_wrap(
+        flow,
+        state,
+        &req,
+        json_payload.into_inner(),
+        |state, auth: auth::AuthenticationData, payload, _| {
+            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
+                domain::Context(auth.merchant_account, auth.key_store),
+            ));
+            subscription::create_and_confirm_subscription(
+                state,
+                merchant_context,
+                profile_id.clone(),
+                payload.clone(),
+            )
+        },
+        &auth::HeaderAuth(auth::ApiKeyAuth {
+            is_connected_allowed: false,
+            is_platform_allowed: false,
+        }),
+        api_locking::LockAction::NotApplicable,
+    ))
+    .await
+}
diff --git a/crates/router_env/src/logger/types.rs b/crates/router_env/src/logger/types.rs
index cc9632bf8f2..46eef6fab6b 100644
--- a/crates/router_env/src/logger/types.rs
+++ b/crates/router_env/src/logger/types.rs
@@ -267,6 +267,10 @@ pub enum Flow {
     CreateSubscription,
     /// Subscription confirm flow,
     ConfirmSubscription,
+    /// Subscription create and confirm flow,
+    CreateAndConfirmSubscription,
+    /// Get Subscription flow
+    GetSubscription,
     /// Create dynamic routing
     CreateDynamicRoutingConfig,
     /// Toggle dynamic routing
diff --git a/loadtest/config/development.toml b/loadtest/config/development.toml
index 536d23b8578..1f83b94199f 100644
--- a/loadtest/config/development.toml
+++ b/loadtest/config/development.toml
@@ -864,4 +864,7 @@ max_retry_count_for_thirty_day = 20
 # Authentication to communicate between internal services using common_api_key, merchant id and profile id
 [internal_merchant_id_profile_id_auth]
 enabled = false # Enable or disable internal api key, merchant id and profile id based authentication
-internal_api_key = "test_internal_api_key" # API key for internal merchant id and profile id based authentication
\ No newline at end of file
+internal_api_key = "test_internal_api_key" # API key for internal merchant id and profile id based authentication
+
+[internal_services] # Internal services base urls and configs
+payments_base_url = "http://localhost:8080"

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

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

## Description
<!-- Describe your changes in detail -->
Adding support to call payments microservice for subscription related usecases

### Additional Changes

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

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

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


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

If you don't have an issue, we'd recommend starting with one first so the PR
can focus on the implementation (unless it is an obvious bug or documentation fix
that will have little conversation).
-->
As part of the subscriptions, we need to make several payments API call, adding a API client to facilitate such calls by reusing the call_connector API we already have.

## 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)?
-->
```
Enable internal API key Auth by changing config/development.toml
[internal_merchant_id_profile_id_auth]
enabled = true
internal_api_key = "test_internal_api_key"
```
1. Create Merchant, API key, Payment connector, Billing Connector
2. Update profile to set the billing processor
Request
```
curl --location 'http://localhost:8080/account/merchant_1759125756/business_profile/pro_71jcERFiZERp44d8fuSJ' \
--header 'Content-Type: application/json' \
--header 'api-key: dev_0RJW0cwZDeGfSkod0eJWOkfZHK0PCoZtDYJJ1FxeHqhHky1VNPU6nkgFQiTFSDvA' \
--data '{
  "billing_processor_id": "mca_NLnCEvS2DfuHWHFVa09o"
}'
```
Response
```
{"merchant_id":"merchant_1759125756","profile_id":"pro_71jcERFiZERp44d8fuSJ","profile_name":"US_default","return_url":"https://google.com/success","enable_payment_response_hash":true,"payment_response_hash_key":"ZFjTKSE1EYiXaPcRhacrwlNh4wieUorlmP7r2uSHI8fyHigGmNCKY2hqVtzAq51m","redirect_to_merchant_with_http_post":false,"webhook_details":{"webhook_version":"1.0.1","webhook_username":"ekart_retail","webhook_password":"password_ekart@123","webhook_url":null,"payment_created_enabled":true,"payment_succeeded_enabled":true,"payment_failed_enabled":true,"payment_statuses_enabled":null,"refund_statuses_enabled":null,"payout_statuses_enabled":null},"metadata":null,"routing_algorithm":null,"intent_fulfillment_time":900,"frm_routing_algorithm":null,"payout_routing_algorithm":null,"applepay_verified_domains":null,"session_expiry":900,"payment_link_config":null,"authentication_connector_details":null,"use_billing_as_payment_method_billing":true,"extended_card_info_config":null,"collect_shipping_details_from_wallet_connector":false,"collect_billing_details_from_wallet_connector":false,"always_collect_shipping_details_from_wallet_connector":false,"always_collect_billing_details_from_wallet_connector":false,"is_connector_agnostic_mit_enabled":false,"payout_link_config":null,"outgoing_webhook_custom_http_headers":null,"tax_connector_id":null,"is_tax_connector_enabled":false,"is_network_tokenization_enabled":false,"is_auto_retries_enabled":false,"max_auto_retries_enabled":null,"always_request_extended_authorization":null,"is_click_to_pay_enabled":false,"authentication_product_ids":null,"card_testing_guard_config":{"card_ip_blocking_status":"disabled","card_ip_blocking_threshold":3,"guest_user_card_blocking_status":"disabled","guest_user_card_blocking_threshold":10,"customer_id_blocking_status":"disabled","customer_id_blocking_threshold":5,"card_testing_guard_expiry":3600},"is_clear_pan_retries_enabled":false,"force_3ds_challenge":false,"is_debit_routing_enabled":false,"merchant_business_country":null,"is_pre_network_tokenization_enabled":false,"acquirer_configs":null,"is_iframe_redirection_enabled":null,"merchant_category_code":null,"merchant_country_code":null,"dispute_polling_interval":null,"is_manual_retry_enabled":null,"always_enable_overcapture":null,"is_external_vault_enabled":"skip","external_vault_connector_details":null,"billing_processor_id":"mca_NLnCEvS2DfuHWHFVa09o"}
```
3. Create Customer
Request
```
curl --location 'http://localhost:8080/customers' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_0RJW0cwZDeGfSkod0eJWOkfZHK0PCoZtDYJJ1FxeHqhHky1VNPU6nkgFQiTFSDvA' \
--data-raw '{
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+65",
    "description": "First customer",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    }
}'
```
Response
```
{
    "customer_id": "cus_OYy3hzTTt04Enegu3Go3",
    "name": "John Doe",
    "email": "guest@example.com",
    "phone": "999999999",
    "phone_country_code": "+65",
    "description": "First customer",
    "address": null,
    "created_at": "2025-09-29T14:45:14.430Z",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    },
    "default_payment_method_id": null,
    "tax_registration_id": null
}
```
4. Create Subscription
Request
```
curl --location 'http://localhost:8080/subscriptions/create' \
--header 'Content-Type: application/json' \
--header 'X-Profile-Id: pro_MiKOgwbj84jJ095MoWdj' \
--header 'api-key: dev_I62cGvBVijteiN61aMcAOeYvXpO8s36gT8BFvPznYYDXF4GFtVtjzgiel9oIpvUK' \
--data '{
    "customer_id": "cus_uBtUJLSVSICr8ctmoL8i",
    "amount": 14100,
    "currency": "USD",
    "payment_details": {
        "authentication_type": "no_three_ds",
        "setup_future_usage": "off_session",
        "capture_method": "automatic",
        "return_url": "https://google.com"
    }
}'
```
Response
```
{
    "id": "sub_dNLiu9sB55eCnByGNPdd",
    "merchant_reference_id": null,
    "status": "created",
    "plan_id": null,
    "profile_id": "pro_MiKOgwbj84jJ095MoWdj",
    "client_secret": "sub_dNLiu9sB55eCnByGNPdd_secret_4QTnPXm7c3B4zMF07WXt",
    "merchant_id": "merchant_1759157014",
    "coupon_code": null,
    "customer_id": "cus_aNko2i9A9Mg7EwXMJKzz"
}
```
5. Confirm Subscription
Request
```
curl --location 'http://localhost:8080/subscriptions/sub_CkPzNaFAyxzX2WwdKFCr/confirm' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'X-Profile-Id: pro_MiKOgwbj84jJ095MoWdj' \
--header 'api-key: dev_I62cGvBVijteiN61aMcAOeYvXpO8s36gT8BFvPznYYDXF4GFtVtjzgiel9oIpvUK' \
--data '{
    "item_price_id": "cbdemo_enterprise-suite-monthly",
    "customer_id": "cus_uBtUJLSVSICr8ctmoL8i",
    "description": "Hello this is description",
    "shipping": {
        "address": {
            "state": "zsaasdas",
            "city": "Banglore",
            "country": "US",
            "line1": "sdsdfsdf",
            "line2": "hsgdbhd",
            "line3": "alsksoe",
            "zip": "571201",
            "first_name": "joseph",
            "last_name": "doe"
        },
        "phone": {
            "number": "123456789",
            "country_code": "+1"
        }
    },
    "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": "123456789",
            "country_code": "+1"
        }
    },
    "payment_details": {
        "payment_method": "card",
        "payment_method_type": "credit",
        "payment_method_data": {
            "card": {
                "card_number": "4111111111111111",
                "card_exp_month": "03",
                "card_exp_year": "2030",
                "card_holder_name": "CLBRW dffdg",
                "card_cvc": "737"
            }
        },
        "customer_acceptance": {
            "acceptance_type": "online",
            "accepted_at": "1963-05-03T04:07:52.723Z",
            "online": {
                "ip_address": "127.0.0.1",
                "user_agent": "amet irure esse"
            }
        }
    }
}'
```
Response
```
{
    "id": "sub_dNLiu9sB55eCnByGNPdd",
    "merchant_reference_id": null,
    "status": "active",
    "plan_id": null,
    "price_id": null,
    "coupon": null,
    "profile_id": "pro_MiKOgwbj84jJ095MoWdj",
    "payment": {
        "payment_id": "sub_pay_WiJK7OF07DGdlJGjp1BC",
        "status": "succeeded",
        "amount": 14100,
        "currency": "USD",
        "connector": "stripe",
        "payment_method_id": "pm_aMEJiPUp3y0kMPUzzUcU",
        "payment_experience": null,
        "error_code": null,
        "error_message": null
    },
    "customer_id": "cus_aNko2i9A9Mg7EwXMJKzz",
    "invoice": {
        "id": "invoice_9VSdsGCGJGxyXQiTaeaX",
        "subscription_id": "sub_dNLiu9sB55eCnByGNPdd",
        "merchant_id": "merchant_1759157014",
        "profile_id": "pro_MiKOgwbj84jJ095MoWdj",
        "merchant_connector_id": "mca_oMyzcBFcpfISftwDDVuG",
        "payment_intent_id": "sub_pay_WiJK7OF07DGdlJGjp1BC",
        "payment_method_id": "pm_aMEJiPUp3y0kMPUzzUcU",
        "customer_id": "cus_aNko2i9A9Mg7EwXMJKzz",
        "amount": 14100,
        "currency": "USD",
        "status": "payment_pending"
    },
    "billing_processor_subscription_id": "sub_dNLiu9sB55eCnByGNPdd"
}
```
6. Create Customer and Create subscription again, do subscription confirm with Invalid postal code
Request
```
curl --location 'http://localhost:8080/subscriptions/sub_PRAyYMVAalH7kPjfMpZP/confirm' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'X-Profile-Id: pro_MiKOgwbj84jJ095MoWdj' \
--header 'api-key: dev_I62cGvBVijteiN61aMcAOeYvXpO8s36gT8BFvPznYYDXF4GFtVtjzgiel9oIpvUK' \
--data '{
    "item_price_id": "cbdemo_enterprise-suite-monthly",
    "customer_id": "cus_efEv4nqfrYEo8wSKZ10C",
    "description": "Hello this is description",
    "shipping": {
        "address": {
            "state": "zsaasdas",
            "city": "Banglore",
            "country": "US",
            "line1": "sdsdfsdf",
            "line2": "hsgdbhd",
            "line3": "alsksoe",
            "zip": "571201",
            "first_name": "joseph",
            "last_name": "doe"
        },
        "phone": {
            "number": "123456789",
            "country_code": "+1"
        }
    },
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "IN",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "123456789",
            "country_code": "+1"
        }
    },
    "payment_details": {
        "payment_method": "card",
        "payment_method_type": "credit",
        "payment_method_data": {
            "card": {
                "card_number": "4111111111111111",
                "card_exp_month": "03",
                "card_exp_year": "2030",
                "card_holder_name": "CLBRW dffdg",
                "card_cvc": "737"
            }
        },
        "customer_acceptance": {
            "acceptance_type": "online",
            "accepted_at": "1963-05-03T04:07:52.723Z",
            "online": {
                "ip_address": "127.0.0.1",
                "user_agent": "amet irure esse"
            }
        }
    }
}'
```
Response
```
{
    "error": {
        "type": "connector",
        "message": "param_wrong_value: param_wrong_value",
        "code": "CE_00",
        "connector": "chargebee",
        "reason": "billing_address[zip] : invalid zip/postal code"
    }
}
```

7. Subscription create and confirm 
Request
```
curl --location 'http://localhost:8080/subscriptions' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'X-Profile-Id: pro_MiKOgwbj84jJ095MoWdj' \
--header 'api-key: dev_I62cGvBVijteiN61aMcAOeYvXpO8s36gT8BFvPznYYDXF4GFtVtjzgiel9oIpvUK' \
--data '{
    "item_price_id": "cbdemo_enterprise-suite-monthly",
    "customer_id": "cus_efEv4nqfrYEo8wSKZ10C",
    "description": "Hello this is description",
    "merchant_reference_id": "mer_ref_1759334677",
    "shipping": {
        "address": {
            "state": "zsaasdas",
            "city": "Banglore",
            "country": "US",
            "line1": "sdsdfsdf",
            "line2": "hsgdbhd",
            "line3": "alsksoe",
            "zip": "571201",
            "first_name": "joseph",
            "last_name": "doe"
        },
        "phone": {
            "number": "123456789",
            "country_code": "+1"
        }
    },
    "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": "123456789",
            "country_code": "+1"
        }
    },
    "payment_details": {
        "payment_method": "card",
        "payment_method_type": "credit",
        "payment_method_data": {
            "card": {
                "card_number": "4111111111111111",
                "card_exp_month": "03",
                "card_exp_year": "2030",
                "card_holder_name": "CLBRW dffdg",
                "card_cvc": "737"
            }
        },
        "authentication_type": "no_three_ds",
        "setup_future_usage": "off_session",
        "capture_method": "automatic",
        "return_url": "https://google.com",
        "customer_acceptance": {
            "acceptance_type": "online",
            "accepted_at": "1963-05-03T04:07:52.723Z",
            "online": {
                "ip_address": "127.0.0.1",
                "user_agent": "amet irure esse"
            }
        }
    }
}'
```
Response
```
{
    "id": "sub_CkPzNaFAyxzX2WwdKFCr",
    "merchant_reference_id": "mer_ref_1759334529",
    "status": "active",
    "plan_id": null,
    "price_id": null,
    "coupon": null,
    "profile_id": "pro_MiKOgwbj84jJ095MoWdj",
    "payment": {
        "payment_id": "sub_pay_KXEtoTxvu0EsadB5wxNn",
        "status": "succeeded",
        "amount": 14100,
        "currency": "INR",
        "connector": "stripe",
        "payment_method_id": "pm_bDPHgNaP7UZGjtZ7QPrS",
        "payment_experience": null,
        "error_code": null,
        "error_message": null
    },
    "customer_id": "cus_uBtUJLSVSICr8ctmoL8i",
    "invoice": {
        "id": "invoice_Ht72m0Enqy4YOGRKAtbZ",
        "subscription_id": "sub_CkPzNaFAyxzX2WwdKFCr",
        "merchant_id": "merchant_1759157014",
        "profile_id": "pro_MiKOgwbj84jJ095MoWdj",
        "merchant_connector_id": "mca_oMyzcBFcpfISftwDDVuG",
        "payment_intent_id": "sub_pay_KXEtoTxvu0EsadB5wxNn",
        "payment_method_id": null,
        "customer_id": "cus_uBtUJLSVSICr8ctmoL8i",
        "amount": 14100,
        "currency": "INR",
        "status": "payment_pending"
    },
    "billing_processor_subscription_id": "sub_CkPzNaFAyxzX2WwdKFCr"
}
```
8. Get subscription
```
curl --location 'http://localhost:8080/subscriptions/sub_PRAyYMVAalH7kPjfMpZP' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'X-Profile-Id: pro_MiKOgwbj84jJ095MoWdj' \
--header 'api-key: dev_I62cGvBVijteiN61aMcAOeYvXpO8s36gT8BFvPznYYDXF4GFtVtjzgiel9oIpvUK'
```
Response
```
{
    "id": "sub_CkPzNaFAyxzX2WwdKFCr",
    "merchant_reference_id": "mer_ref_1759334529",
    "status": "active",
    "plan_id": null,
    "profile_id": "pro_MiKOgwbj84jJ095MoWdj",
    "client_secret": "sub_CkPzNaFAyxzX2WwdKFCr_secret_F8z6T70udfgFVYpd4FsX",
    "merchant_id": "merchant_1759157014",
    "coupon_code": null,
    "customer_id": "cus_uBtUJLSVSICr8ctmoL8i"
}
```
## Checklist
<!-- Put an `x` in the boxes that apply -->

- [ ] I formatted the code `cargo +nightly fmt --all`
- [ ] I addressed lints thrown by `cargo clippy`
- [ ] I reviewed the submitted code
- [ ] I added unit tests for my changes where possible
