Bug: [FEATURE] Ephemeral Auth for v2



### Feature Description

We need to support ephemeral auth in v2. 
This would replace the current client secret auth being used in Payment methods

### Possible Implementation

Need to add implementation for ephemeral auth

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

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

### Have you read the Contributing Guidelines?

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

### Are you willing to submit a PR?

Yes, I am willing to submit a PR!
diff --git a/api-reference-v2/openapi_spec.json b/api-reference-v2/openapi_spec.json
index 58a81caeed3..7a9448a4fd4 100644
--- a/api-reference-v2/openapi_spec.json
+++ b/api-reference-v2/openapi_spec.json
@@ -13696,16 +13696,11 @@
       "PaymentMethodIntentConfirm": {
         "type": "object",
         "required": [
-          "client_secret",
           "payment_method_data",
           "payment_method_type",
           "payment_method_subtype"
         ],
         "properties": {
-          "client_secret": {
-            "type": "string",
-            "description": "For SDK based calls, client_secret would be required"
-          },
           "customer_id": {
             "type": "string",
             "description": "The unique identifier of the customer.",
@@ -13991,7 +13986,7 @@
             "example": "2024-02-24T11:04:09.922Z",
             "nullable": true
           },
-          "client_secret": {
+          "ephemeral_key": {
             "type": "string",
             "description": "For Client based calls",
             "nullable": true
@@ -14140,14 +14135,6 @@
         "properties": {
           "payment_method_data": {
             "$ref": "#/components/schemas/PaymentMethodUpdateData"
-          },
-          "client_secret": {
-            "type": "string",
-            "description": "This is a 15 minute expiry token which shall be used from the client to authenticate and perform sessions from the SDK",
-            "example": "secret_k2uj3he2893eiu2d",
-            "nullable": true,
-            "maxLength": 30,
-            "minLength": 30
           }
         },
         "additionalProperties": false
diff --git a/crates/api_models/src/ephemeral_key.rs b/crates/api_models/src/ephemeral_key.rs
index d06490d6bac..fa61642e353 100644
--- a/crates/api_models/src/ephemeral_key.rs
+++ b/crates/api_models/src/ephemeral_key.rs
@@ -1,7 +1,10 @@
 use common_utils::id_type;
+#[cfg(feature = "v2")]
+use masking::Secret;
 use serde;
 use utoipa::ToSchema;
 
+#[cfg(feature = "v1")]
 /// Information required to create an ephemeral key.
 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
 pub struct EphemeralKeyCreateRequest {
@@ -15,12 +18,52 @@ pub struct EphemeralKeyCreateRequest {
     pub customer_id: id_type::CustomerId,
 }
 
+#[cfg(feature = "v2")]
+/// Information required to create an ephemeral key.
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
+pub struct EphemeralKeyCreateRequest {
+    /// Customer ID for which an ephemeral key must be created
+    #[schema(
+        min_length = 32,
+        max_length = 64,
+        value_type = String,
+        example = "12345_cus_01926c58bc6e77c09e809964e72af8c8"
+    )]
+    pub customer_id: id_type::GlobalCustomerId,
+}
+
+#[cfg(feature = "v2")]
+/// ephemeral_key for the customer_id mentioned
+#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, Eq, PartialEq, ToSchema)]
+pub struct EphemeralKeyResponse {
+    /// Ephemeral key id
+    #[schema(value_type = String, max_length = 32, min_length = 1)]
+    pub id: id_type::EphemeralKeyId,
+    /// customer_id to which this ephemeral key belongs to
+    #[schema(value_type = String, max_length = 64, min_length = 32, example = "12345_cus_01926c58bc6e77c09e809964e72af8c8")]
+    pub customer_id: id_type::GlobalCustomerId,
+    /// time at which this ephemeral key was created
+    pub created_at: time::PrimitiveDateTime,
+    /// time at which this ephemeral key would expire
+    pub expires: time::PrimitiveDateTime,
+    #[schema(value_type=String)]
+    /// ephemeral key
+    pub secret: Secret<String>,
+}
+
 impl common_utils::events::ApiEventMetric for EphemeralKeyCreateRequest {
     fn get_api_event_type(&self) -> Option<common_utils::events::ApiEventsType> {
         Some(common_utils::events::ApiEventsType::Miscellaneous)
     }
 }
 
+#[cfg(feature = "v2")]
+impl common_utils::events::ApiEventMetric for EphemeralKeyResponse {
+    fn get_api_event_type(&self) -> Option<common_utils::events::ApiEventsType> {
+        Some(common_utils::events::ApiEventsType::Miscellaneous)
+    }
+}
+
 /// ephemeral_key for the customer_id mentioned
 #[derive(Debug, serde::Serialize, serde::Deserialize, Clone, Eq, PartialEq, ToSchema)]
 pub struct EphemeralKeyCreateResponse {
diff --git a/crates/api_models/src/payment_methods.rs b/crates/api_models/src/payment_methods.rs
index c821feaff57..fe5cb2933f9 100644
--- a/crates/api_models/src/payment_methods.rs
+++ b/crates/api_models/src/payment_methods.rs
@@ -163,9 +163,6 @@ pub struct PaymentMethodIntentCreate {
 #[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
 #[serde(deny_unknown_fields)]
 pub struct PaymentMethodIntentConfirm {
-    /// For SDK based calls, client_secret would be required
-    pub client_secret: String,
-
     /// The unique identifier of the customer.
     #[schema(value_type = Option<String>, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
     pub customer_id: Option<id_type::CustomerId>,
@@ -211,9 +208,6 @@ pub struct PaymentMethodIntentConfirmInternal {
     #[schema(value_type = PaymentMethodType,example = "credit")]
     pub payment_method_subtype: api_enums::PaymentMethodType,
 
-    /// For SDK based calls, client_secret would be required
-    pub client_secret: String,
-
     /// The unique identifier of the customer.
     #[schema(value_type = Option<String>, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
     pub customer_id: Option<id_type::CustomerId>,
@@ -226,7 +220,6 @@ pub struct PaymentMethodIntentConfirmInternal {
 impl From<PaymentMethodIntentConfirmInternal> for PaymentMethodIntentConfirm {
     fn from(item: PaymentMethodIntentConfirmInternal) -> Self {
         Self {
-            client_secret: item.client_secret,
             payment_method_type: item.payment_method_type,
             payment_method_subtype: item.payment_method_subtype,
             customer_id: item.customer_id,
@@ -408,10 +401,6 @@ pub struct PaymentMethodUpdate {
 pub struct PaymentMethodUpdate {
     /// payment method data to be passed
     pub payment_method_data: PaymentMethodUpdateData,
-
-    /// This is a 15 minute expiry token which shall be used from the client to authenticate and perform sessions from the SDK
-    #[schema(max_length = 30, min_length = 30, example = "secret_k2uj3he2893eiu2d")]
-    pub client_secret: Option<String>,
 }
 
 #[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
@@ -826,7 +815,8 @@ pub struct PaymentMethodResponse {
     pub last_used_at: Option<time::PrimitiveDateTime>,
 
     /// For Client based calls
-    pub client_secret: Option<String>,
+    #[schema(value_type=Option<String>)]
+    pub ephemeral_key: Option<masking::Secret<String>>,
 
     pub payment_method_data: Option<PaymentMethodResponseData>,
 }
diff --git a/crates/common_utils/src/events.rs b/crates/common_utils/src/events.rs
index b9af92786f5..9494b8209e7 100644
--- a/crates/common_utils/src/events.rs
+++ b/crates/common_utils/src/events.rs
@@ -102,6 +102,9 @@ pub enum ApiEventsType {
         poll_id: String,
     },
     Analytics,
+    EphemeralKey {
+        key_id: id_type::EphemeralKeyId,
+    },
 }
 
 impl ApiEventMetric for serde_json::Value {}
diff --git a/crates/common_utils/src/id_type.rs b/crates/common_utils/src/id_type.rs
index 594078bb405..da013b3489e 100644
--- a/crates/common_utils/src/id_type.rs
+++ b/crates/common_utils/src/id_type.rs
@@ -3,6 +3,7 @@
 
 mod api_key;
 mod customer;
+mod ephemeral_key;
 #[cfg(feature = "v2")]
 mod global_id;
 mod merchant;
@@ -37,6 +38,7 @@ pub use self::global_id::{
 pub use self::{
     api_key::ApiKeyId,
     customer::CustomerId,
+    ephemeral_key::EphemeralKeyId,
     merchant::MerchantId,
     merchant_connector_account::MerchantConnectorAccountId,
     organization::OrganizationId,
diff --git a/crates/common_utils/src/id_type/ephemeral_key.rs b/crates/common_utils/src/id_type/ephemeral_key.rs
new file mode 100644
index 00000000000..071980fc6a4
--- /dev/null
+++ b/crates/common_utils/src/id_type/ephemeral_key.rs
@@ -0,0 +1,31 @@
+crate::id_type!(
+    EphemeralKeyId,
+    "A type for key_id that can be used for Ephemeral key IDs"
+);
+crate::impl_id_type_methods!(EphemeralKeyId, "key_id");
+
+// This is to display the `EphemeralKeyId` as EphemeralKeyId(abcd)
+crate::impl_debug_id_type!(EphemeralKeyId);
+crate::impl_try_from_cow_str_id_type!(EphemeralKeyId, "key_id");
+
+crate::impl_generate_id_id_type!(EphemeralKeyId, "eki");
+crate::impl_serializable_secret_id_type!(EphemeralKeyId);
+crate::impl_queryable_id_type!(EphemeralKeyId);
+crate::impl_to_sql_from_sql_id_type!(EphemeralKeyId);
+
+impl crate::events::ApiEventMetric for EphemeralKeyId {
+    fn get_api_event_type(&self) -> Option<crate::events::ApiEventsType> {
+        Some(crate::events::ApiEventsType::EphemeralKey {
+            key_id: self.clone(),
+        })
+    }
+}
+
+crate::impl_default_id_type!(EphemeralKeyId, "key");
+
+impl EphemeralKeyId {
+    /// Generate a key for redis
+    pub fn generate_redis_key(&self) -> String {
+        format!("epkey_{}", self.get_string_repr())
+    }
+}
diff --git a/crates/diesel_models/src/ephemeral_key.rs b/crates/diesel_models/src/ephemeral_key.rs
index d398ecdf784..c7fc103ed09 100644
--- a/crates/diesel_models/src/ephemeral_key.rs
+++ b/crates/diesel_models/src/ephemeral_key.rs
@@ -1,3 +1,33 @@
+#[cfg(feature = "v2")]
+use masking::{PeekInterface, Secret};
+#[cfg(feature = "v2")]
+pub struct EphemeralKeyTypeNew {
+    pub id: common_utils::id_type::EphemeralKeyId,
+    pub merchant_id: common_utils::id_type::MerchantId,
+    pub customer_id: common_utils::id_type::GlobalCustomerId,
+    pub secret: Secret<String>,
+    pub resource_type: ResourceType,
+}
+
+#[cfg(feature = "v2")]
+#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
+pub struct EphemeralKeyType {
+    pub id: common_utils::id_type::EphemeralKeyId,
+    pub merchant_id: common_utils::id_type::MerchantId,
+    pub customer_id: common_utils::id_type::GlobalCustomerId,
+    pub resource_type: ResourceType,
+    pub created_at: time::PrimitiveDateTime,
+    pub expires: time::PrimitiveDateTime,
+    pub secret: Secret<String>,
+}
+
+#[cfg(feature = "v2")]
+impl EphemeralKeyType {
+    pub fn generate_secret_key(&self) -> String {
+        format!("epkey_{}", self.secret.peek())
+    }
+}
+
 pub struct EphemeralKeyNew {
     pub id: String,
     pub merchant_id: common_utils::id_type::MerchantId,
@@ -20,3 +50,21 @@ impl common_utils::events::ApiEventMetric for EphemeralKey {
         Some(common_utils::events::ApiEventsType::Miscellaneous)
     }
 }
+
+#[derive(
+    Clone,
+    Copy,
+    Debug,
+    serde::Serialize,
+    serde::Deserialize,
+    strum::Display,
+    strum::EnumString,
+    PartialEq,
+    Eq,
+)]
+#[serde(rename_all = "snake_case")]
+#[strum(serialize_all = "snake_case")]
+pub enum ResourceType {
+    Payment,
+    PaymentMethod,
+}
diff --git a/crates/diesel_models/src/payment_method.rs b/crates/diesel_models/src/payment_method.rs
index 46af78d6d91..912ea96c486 100644
--- a/crates/diesel_models/src/payment_method.rs
+++ b/crates/diesel_models/src/payment_method.rs
@@ -288,6 +288,7 @@ pub enum PaymentMethodUpdate {
         network_token_requestor_reference_id: Option<String>,
         network_token_locker_id: Option<String>,
         network_token_payment_method_data: Option<Encryption>,
+        locker_fingerprint_id: Option<String>,
     },
     ConnectorMandateDetailsUpdate {
         connector_mandate_details: Option<PaymentsMandateReference>,
@@ -322,6 +323,7 @@ pub struct PaymentMethodUpdateInternal {
     network_token_requestor_reference_id: Option<String>,
     network_token_locker_id: Option<String>,
     network_token_payment_method_data: Option<Encryption>,
+    locker_fingerprint_id: Option<String>,
 }
 
 #[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
@@ -341,6 +343,7 @@ impl PaymentMethodUpdateInternal {
             network_token_requestor_reference_id,
             network_token_locker_id,
             network_token_payment_method_data,
+            locker_fingerprint_id,
         } = self;
 
         PaymentMethod {
@@ -359,7 +362,7 @@ impl PaymentMethodUpdateInternal {
             client_secret: source.client_secret,
             payment_method_billing_address: source.payment_method_billing_address,
             updated_by: updated_by.or(source.updated_by),
-            locker_fingerprint_id: source.locker_fingerprint_id,
+            locker_fingerprint_id: locker_fingerprint_id.or(source.locker_fingerprint_id),
             payment_method_type_v2: payment_method_type_v2.or(source.payment_method_type_v2),
             payment_method_subtype: payment_method_subtype.or(source.payment_method_subtype),
             id: source.id,
@@ -695,6 +698,7 @@ impl From<PaymentMethodUpdate> for PaymentMethodUpdateInternal {
                 network_token_locker_id: None,
                 network_token_requestor_reference_id: None,
                 network_token_payment_method_data: None,
+                locker_fingerprint_id: None,
             },
             PaymentMethodUpdate::LastUsedUpdate { last_used_at } => Self {
                 payment_method_data: None,
@@ -710,6 +714,7 @@ impl From<PaymentMethodUpdate> for PaymentMethodUpdateInternal {
                 network_token_locker_id: None,
                 network_token_requestor_reference_id: None,
                 network_token_payment_method_data: None,
+                locker_fingerprint_id: None,
             },
             PaymentMethodUpdate::UpdatePaymentMethodDataAndLastUsed {
                 payment_method_data,
@@ -728,6 +733,7 @@ impl From<PaymentMethodUpdate> for PaymentMethodUpdateInternal {
                 network_token_locker_id: None,
                 network_token_requestor_reference_id: None,
                 network_token_payment_method_data: None,
+                locker_fingerprint_id: None,
             },
             PaymentMethodUpdate::NetworkTransactionIdAndStatusUpdate {
                 network_transaction_id,
@@ -746,6 +752,7 @@ impl From<PaymentMethodUpdate> for PaymentMethodUpdateInternal {
                 network_token_locker_id: None,
                 network_token_requestor_reference_id: None,
                 network_token_payment_method_data: None,
+                locker_fingerprint_id: None,
             },
             PaymentMethodUpdate::StatusUpdate { status } => Self {
                 payment_method_data: None,
@@ -761,6 +768,7 @@ impl From<PaymentMethodUpdate> for PaymentMethodUpdateInternal {
                 network_token_locker_id: None,
                 network_token_requestor_reference_id: None,
                 network_token_payment_method_data: None,
+                locker_fingerprint_id: None,
             },
             PaymentMethodUpdate::AdditionalDataUpdate {
                 payment_method_data,
@@ -771,6 +779,7 @@ impl From<PaymentMethodUpdate> for PaymentMethodUpdateInternal {
                 network_token_requestor_reference_id,
                 network_token_locker_id,
                 network_token_payment_method_data,
+                locker_fingerprint_id,
             } => Self {
                 payment_method_data,
                 last_used_at: None,
@@ -785,6 +794,7 @@ impl From<PaymentMethodUpdate> for PaymentMethodUpdateInternal {
                 network_token_requestor_reference_id,
                 network_token_locker_id,
                 network_token_payment_method_data,
+                locker_fingerprint_id,
             },
             PaymentMethodUpdate::ConnectorMandateDetailsUpdate {
                 connector_mandate_details,
@@ -802,6 +812,7 @@ impl From<PaymentMethodUpdate> for PaymentMethodUpdateInternal {
                 network_token_locker_id: None,
                 network_token_requestor_reference_id: None,
                 network_token_payment_method_data: None,
+                locker_fingerprint_id: None,
             },
         }
     }
diff --git a/crates/hyperswitch_domain_models/src/payments.rs b/crates/hyperswitch_domain_models/src/payments.rs
index 0243c254920..6772d0de408 100644
--- a/crates/hyperswitch_domain_models/src/payments.rs
+++ b/crates/hyperswitch_domain_models/src/payments.rs
@@ -29,7 +29,10 @@ pub mod payment_intent;
 
 use common_enums as storage_enums;
 #[cfg(feature = "v2")]
-use diesel_models::types::{FeatureMetadata, OrderDetailsWithAmount};
+use diesel_models::{
+    ephemeral_key,
+    types::{FeatureMetadata, OrderDetailsWithAmount},
+};
 
 use self::payment_attempt::PaymentAttempt;
 #[cfg(feature = "v1")]
diff --git a/crates/router/src/consts.rs b/crates/router/src/consts.rs
index 823f0a4bf04..e2784b968ad 100644
--- a/crates/router/src/consts.rs
+++ b/crates/router/src/consts.rs
@@ -171,19 +171,19 @@ pub const DEFAULT_SDK_LAYOUT: &str = "tabs";
 
 /// Vault Add request url
 #[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
-pub const ADD_VAULT_REQUEST_URL: &str = "/vault/add";
+pub const ADD_VAULT_REQUEST_URL: &str = "/api/v2/vault/add";
 
 /// Vault Get Fingerprint request url
 #[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
-pub const VAULT_FINGERPRINT_REQUEST_URL: &str = "/fingerprint";
+pub const VAULT_FINGERPRINT_REQUEST_URL: &str = "/api/v2/vault/fingerprint";
 
 /// Vault Retrieve request url
 #[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
-pub const VAULT_RETRIEVE_REQUEST_URL: &str = "/vault/retrieve";
+pub const VAULT_RETRIEVE_REQUEST_URL: &str = "/api/v2/vault/retrieve";
 
 /// Vault Delete request url
 #[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
-pub const VAULT_DELETE_REQUEST_URL: &str = "/vault/delete";
+pub const VAULT_DELETE_REQUEST_URL: &str = "/api/v2/vault/delete";
 
 /// Vault Header content type
 #[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
diff --git a/crates/router/src/core/payment_methods.rs b/crates/router/src/core/payment_methods.rs
index 61dc70ac479..6cdadf07320 100644
--- a/crates/router/src/core/payment_methods.rs
+++ b/crates/router/src/core/payment_methods.rs
@@ -62,7 +62,7 @@ use crate::{
     types::{
         api::{self, payment_methods::PaymentMethodCreateExt},
         payment_methods as pm_types,
-        storage::PaymentMethodListContext,
+        storage::{ephemeral_key, PaymentMethodListContext},
     },
     utils::ext_traits::OptionExt,
 };
@@ -851,21 +851,23 @@ pub async fn create_payment_method(
     let db = &*state.store;
     let merchant_id = merchant_account.get_id();
     let customer_id = req.customer_id.to_owned();
+    let key_manager_state = &(state).into();
 
     db.find_customer_by_global_id(
-        &(state.into()),
+        key_manager_state,
         &customer_id,
         merchant_account.get_id(),
         key_store,
         merchant_account.storage_scheme,
     )
     .await
-    .to_not_found_response(errors::ApiErrorResponse::CustomerNotFound)?;
-    let key_manager_state = state.into();
+    .to_not_found_response(errors::ApiErrorResponse::CustomerNotFound)
+    .attach_printable("Customer not found for the payment method")?;
+
     let payment_method_billing_address: Option<Encryptable<Secret<serde_json::Value>>> = req
         .billing
         .clone()
-        .async_map(|billing| cards::create_encrypted_data(&key_manager_state, key_store, billing))
+        .async_map(|billing| cards::create_encrypted_data(key_manager_state, key_store, billing))
         .await
         .transpose()
         .change_context(errors::ApiErrorResponse::InternalServerError)
@@ -877,7 +879,7 @@ pub async fn create_payment_method(
             .change_context(errors::ApiErrorResponse::InternalServerError)
             .attach_printable("Unable to generate GlobalPaymentMethodId")?;
 
-    let payment_method = create_payment_method_for_intent(
+    let (payment_method, ephemeral_key) = create_payment_method_for_intent(
         state,
         req.metadata.clone(),
         &customer_id,
@@ -902,14 +904,15 @@ pub async fn create_payment_method(
     .await;
 
     let response = match vaulting_result {
-        Ok(resp) => {
+        Ok((vaulting_resp, fingerprint_id)) => {
             let pm_update = create_pm_additional_data_update(
                 &payment_method_data,
                 state,
                 key_store,
-                Some(resp.vault_id.get_string_repr().clone()),
+                Some(vaulting_resp.vault_id.get_string_repr().clone()),
                 Some(req.payment_method_type),
                 Some(req.payment_method_subtype),
+                Some(fingerprint_id),
             )
             .await
             .attach_printable("Unable to create Payment method data")?;
@@ -926,7 +929,10 @@ pub async fn create_payment_method(
                 .change_context(errors::ApiErrorResponse::InternalServerError)
                 .attach_printable("Failed to update payment method in db")?;
 
-            let resp = pm_transforms::generate_payment_method_response(&payment_method)?;
+            let resp = pm_transforms::generate_payment_method_response(
+                &payment_method,
+                Some(ephemeral_key),
+            )?;
 
             Ok(resp)
         }
@@ -964,21 +970,23 @@ pub async fn payment_method_intent_create(
     let db = &*state.store;
     let merchant_id = merchant_account.get_id();
     let customer_id = req.customer_id.to_owned();
+    let key_manager_state = &(state).into();
 
     db.find_customer_by_global_id(
-        &(state.into()),
+        key_manager_state,
         &customer_id,
         merchant_account.get_id(),
         key_store,
         merchant_account.storage_scheme,
     )
     .await
-    .to_not_found_response(errors::ApiErrorResponse::CustomerNotFound)?;
-    let key_manager_state = state.into();
+    .to_not_found_response(errors::ApiErrorResponse::CustomerNotFound)
+    .attach_printable("Customer not found for the payment method")?;
+
     let payment_method_billing_address: Option<Encryptable<Secret<serde_json::Value>>> = req
         .billing
         .clone()
-        .async_map(|billing| cards::create_encrypted_data(&key_manager_state, key_store, billing))
+        .async_map(|billing| cards::create_encrypted_data(key_manager_state, key_store, billing))
         .await
         .transpose()
         .change_context(errors::ApiErrorResponse::InternalServerError)
@@ -991,7 +999,7 @@ pub async fn payment_method_intent_create(
             .change_context(errors::ApiErrorResponse::InternalServerError)
             .attach_printable("Unable to generate GlobalPaymentMethodId")?;
 
-    let payment_method = create_payment_method_for_intent(
+    let (payment_method, ephemeral_key) = create_payment_method_for_intent(
         state,
         req.metadata.clone(),
         &customer_id,
@@ -1004,7 +1012,8 @@ pub async fn payment_method_intent_create(
     .await
     .attach_printable("Failed to add Payment method to DB")?;
 
-    let resp = pm_transforms::generate_payment_method_response(&payment_method)?;
+    let resp =
+        pm_transforms::generate_payment_method_response(&payment_method, Some(ephemeral_key))?;
 
     Ok(services::ApplicationResponse::Json(resp))
 }
@@ -1018,10 +1027,10 @@ pub async fn payment_method_intent_confirm(
     key_store: &domain::MerchantKeyStore,
     pm_id: String,
 ) -> RouterResponse<api::PaymentMethodResponse> {
+    let key_manager_state = &(state).into();
     req.validate()?;
 
     let db = &*state.store;
-    let client_secret = req.client_secret.clone();
     let pm_id = id_type::GlobalPaymentMethodId::generate_from_string(pm_id)
         .change_context(errors::ApiErrorResponse::InternalServerError)
         .attach_printable("Unable to generate GlobalPaymentMethodId")?;
@@ -1037,11 +1046,6 @@ pub async fn payment_method_intent_confirm(
         .change_context(errors::ApiErrorResponse::PaymentMethodNotFound)
         .attach_printable("Unable to find payment method")?;
 
-    when(
-        cards::authenticate_pm_client_secret_and_check_expiry(&client_secret, &payment_method)?,
-        || Err(errors::ApiErrorResponse::ClientSecretExpired),
-    )?;
-
     when(
         payment_method.status != enums::PaymentMethodStatus::AwaitingData,
         || {
@@ -1054,7 +1058,7 @@ pub async fn payment_method_intent_confirm(
 
     let customer_id = payment_method.customer_id.to_owned();
     db.find_customer_by_global_id(
-        &(state.into()),
+        key_manager_state,
         &customer_id,
         merchant_account.get_id(),
         key_store,
@@ -1075,14 +1079,15 @@ pub async fn payment_method_intent_confirm(
     .await;
 
     let response = match vaulting_result {
-        Ok(resp) => {
+        Ok((vaulting_resp, fingerprint_id)) => {
             let pm_update = create_pm_additional_data_update(
                 &payment_method_data,
                 state,
                 key_store,
-                Some(resp.vault_id.get_string_repr().clone()),
+                Some(vaulting_resp.vault_id.get_string_repr().clone()),
                 Some(req.payment_method_type),
                 Some(req.payment_method_subtype),
+                Some(fingerprint_id),
             )
             .await
             .attach_printable("Unable to create Payment method data")?;
@@ -1099,7 +1104,7 @@ pub async fn payment_method_intent_confirm(
                 .change_context(errors::ApiErrorResponse::InternalServerError)
                 .attach_printable("Failed to update payment method in db")?;
 
-            let resp = pm_transforms::generate_payment_method_response(&payment_method)?;
+            let resp = pm_transforms::generate_payment_method_response(&payment_method, None)?;
 
             Ok(resp)
         }
@@ -1153,7 +1158,6 @@ pub async fn create_payment_method_in_db(
     card_scheme: Option<String>,
 ) -> errors::CustomResult<domain::PaymentMethod, errors::ApiErrorResponse> {
     let db = &*state.store;
-    let client_secret = pm_types::PaymentMethodClientSecret::generate(&payment_method_id);
     let current_time = common_utils::date_time::now();
 
     let response = db
@@ -1170,7 +1174,7 @@ pub async fn create_payment_method_in_db(
                 payment_method_data,
                 connector_mandate_details,
                 customer_acceptance,
-                client_secret: Some(client_secret),
+                client_secret: None,
                 status: status.unwrap_or(enums::PaymentMethodStatus::Active),
                 network_transaction_id: network_transaction_id.to_owned(),
                 created_at: current_time,
@@ -1205,9 +1209,18 @@ pub async fn create_payment_method_for_intent(
     key_store: &domain::MerchantKeyStore,
     storage_scheme: enums::MerchantStorageScheme,
     payment_method_billing_address: crypto::OptionalEncryptableValue,
-) -> errors::CustomResult<domain::PaymentMethod, errors::ApiErrorResponse> {
+) -> errors::CustomResult<(domain::PaymentMethod, Secret<String>), errors::ApiErrorResponse> {
     let db = &*state.store;
-    let client_secret = pm_types::PaymentMethodClientSecret::generate(&payment_method_id);
+    let ephemeral_key = payment_helpers::create_ephemeral_key(
+        state,
+        customer_id,
+        merchant_id,
+        ephemeral_key::ResourceType::PaymentMethod,
+    )
+    .await
+    .change_context(errors::ApiErrorResponse::InternalServerError)
+    .attach_printable("Failed to create ephemeral_key")?;
+
     let current_time = common_utils::date_time::now();
 
     let response = db
@@ -1224,7 +1237,7 @@ pub async fn create_payment_method_for_intent(
                 payment_method_data: None,
                 connector_mandate_details: None,
                 customer_acceptance: None,
-                client_secret: Some(client_secret),
+                client_secret: None,
                 status: enums::PaymentMethodStatus::AwaitingData,
                 network_transaction_id: None,
                 created_at: current_time,
@@ -1244,7 +1257,7 @@ pub async fn create_payment_method_for_intent(
         .change_context(errors::ApiErrorResponse::InternalServerError)
         .attach_printable("Failed to add payment method in db")?;
 
-    Ok(response)
+    Ok((response, ephemeral_key.secret))
 }
 
 #[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
@@ -1255,15 +1268,16 @@ pub async fn create_pm_additional_data_update(
     vault_id: Option<String>,
     payment_method_type: Option<api_enums::PaymentMethod>,
     payment_method_subtype: Option<api_enums::PaymentMethodType>,
+    vault_fingerprint_id: Option<String>,
 ) -> RouterResult<storage::PaymentMethodUpdate> {
     let card = match pmd {
         pm_types::PaymentMethodVaultingData::Card(card) => {
             api::PaymentMethodsData::Card(card.clone().into())
         }
     };
-    let key_manager_state = state.into();
+    let key_manager_state = &(state).into();
     let pmd: Encryptable<Secret<serde_json::Value>> =
-        cards::create_encrypted_data(&key_manager_state, key_store, card)
+        cards::create_encrypted_data(key_manager_state, key_store, card)
             .await
             .change_context(errors::ApiErrorResponse::InternalServerError)
             .attach_printable("Unable to encrypt Payment method data")?;
@@ -1277,6 +1291,7 @@ pub async fn create_pm_additional_data_update(
         network_token_requestor_reference_id: None,
         network_token_locker_id: None,
         network_token_payment_method_data: None,
+        locker_fingerprint_id: vault_fingerprint_id,
     };
 
     Ok(pm_update)
@@ -1290,7 +1305,7 @@ pub async fn vault_payment_method(
     merchant_account: &domain::MerchantAccount,
     key_store: &domain::MerchantKeyStore,
     existing_vault_id: Option<domain::VaultId>,
-) -> RouterResult<pm_types::AddVaultResponse> {
+) -> RouterResult<(pm_types::AddVaultResponse, String)> {
     let db = &*state.store;
 
     // get fingerprint_id from vault
@@ -1301,17 +1316,16 @@ pub async fn vault_payment_method(
 
     // throw back error if payment method is duplicated
     when(
-        Some(
-            db.find_payment_method_by_fingerprint_id(
-                &(state.into()),
-                key_store,
-                &fingerprint_id_from_vault,
-            )
-            .await
-            .change_context(errors::ApiErrorResponse::InternalServerError)
-            .attach_printable("Failed to find payment method by fingerprint_id")?,
+        db.find_payment_method_by_fingerprint_id(
+            &(state.into()),
+            key_store,
+            &fingerprint_id_from_vault,
         )
-        .is_some(),
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Failed to find payment method by fingerprint_id")
+        .inspect_err(|e| logger::error!("Vault Fingerprint_id error: {:?}", e))
+        .is_ok(),
         || {
             Err(report!(errors::ApiErrorResponse::DuplicatePaymentMethod)
                 .attach_printable("Cannot vault duplicate payment method"))
@@ -1324,7 +1338,7 @@ pub async fn vault_payment_method(
             .change_context(errors::ApiErrorResponse::InternalServerError)
             .attach_printable("Failed to add payment method in vault")?;
 
-    Ok(resp_from_vault)
+    Ok((resp_from_vault, fingerprint_id_from_vault))
 }
 
 #[cfg(all(
@@ -1754,6 +1768,11 @@ pub async fn retrieve_payment_method(
         .await
         .to_not_found_response(errors::ApiErrorResponse::PaymentMethodNotFound)?;
 
+    when(
+        payment_method.status == enums::PaymentMethodStatus::Inactive,
+        || Err(errors::ApiErrorResponse::PaymentMethodNotFound),
+    )?;
+
     let pmd = payment_method
         .payment_method_data
         .clone()
@@ -1774,7 +1793,7 @@ pub async fn retrieve_payment_method(
         created: Some(payment_method.created_at),
         recurring_enabled: false,
         last_used_at: Some(payment_method.last_used_at),
-        client_secret: payment_method.client_secret.clone(),
+        ephemeral_key: None,
         payment_method_data: pmd,
     };
 
@@ -1822,16 +1841,12 @@ pub async fn update_payment_method(
             .await
             .change_context(errors::ApiErrorResponse::InternalServerError)
             .attach_printable("Failed to retrieve payment method from vault")?
-            .data
-            .expose()
-            .parse_struct("PaymentMethodVaultingData")
-            .change_context(errors::ApiErrorResponse::InternalServerError)
-            .attach_printable("Failed to parse PaymentMethodVaultingData")?;
+            .data;
 
     let vault_request_data =
         pm_transforms::generate_pm_vaulting_req_from_update_request(pmd, req.payment_method_data);
 
-    let vaulting_response = vault_payment_method(
+    let (vaulting_response, fingerprint_id) = vault_payment_method(
         &state,
         &vault_request_data,
         &merchant_account,
@@ -1848,6 +1863,7 @@ pub async fn update_payment_method(
         Some(vaulting_response.vault_id.get_string_repr().clone()),
         payment_method.get_payment_method_type(),
         payment_method.get_payment_method_subtype(),
+        Some(fingerprint_id),
     )
     .await
     .attach_printable("Unable to create Payment method data")?;
@@ -1864,7 +1880,7 @@ pub async fn update_payment_method(
         .change_context(errors::ApiErrorResponse::InternalServerError)
         .attach_printable("Failed to update payment method in db")?;
 
-    let response = pm_transforms::generate_payment_method_response(&payment_method)?;
+    let response = pm_transforms::generate_payment_method_response(&payment_method, None)?;
 
     // Add a PT task to handle payment_method delete from vault
 
@@ -1896,6 +1912,11 @@ pub async fn delete_payment_method(
         .await
         .to_not_found_response(errors::ApiErrorResponse::PaymentMethodNotFound)?;
 
+    when(
+        payment_method.status == enums::PaymentMethodStatus::Inactive,
+        || Err(errors::ApiErrorResponse::PaymentMethodNotFound),
+    )?;
+
     let vault_id = payment_method
         .locker_id
         .clone()
diff --git a/crates/router/src/core/payment_methods/transformers.rs b/crates/router/src/core/payment_methods/transformers.rs
index c3fbfd8afbf..ce95096a0fb 100644
--- a/crates/router/src/core/payment_methods/transformers.rs
+++ b/crates/router/src/core/payment_methods/transformers.rs
@@ -551,6 +551,7 @@ pub fn generate_pm_vaulting_req_from_update_request(
 #[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
 pub fn generate_payment_method_response(
     pm: &domain::PaymentMethod,
+    ephemeral_key: Option<Secret<String>>,
 ) -> errors::RouterResult<api::PaymentMethodResponse> {
     let pmd = pm
         .payment_method_data
@@ -572,7 +573,7 @@ pub fn generate_payment_method_response(
         created: Some(pm.created_at),
         recurring_enabled: false,
         last_used_at: Some(pm.last_used_at),
-        client_secret: pm.client_secret.clone(),
+        ephemeral_key,
         payment_method_data: pmd,
     };
 
diff --git a/crates/router/src/core/payment_methods/vault.rs b/crates/router/src/core/payment_methods/vault.rs
index fcff711f6c9..65ef16cb449 100644
--- a/crates/router/src/core/payment_methods/vault.rs
+++ b/crates/router/src/core/payment_methods/vault.rs
@@ -1186,6 +1186,7 @@ async fn create_vault_request<R: pm_types::VaultingInterface>(
     jwekey: &settings::Jwekey,
     locker: &settings::Locker,
     payload: Vec<u8>,
+    tenant_id: id_type::TenantId,
 ) -> CustomResult<request::Request, errors::VaultError> {
     let private_key = jwekey.vault_private_key.peek().as_bytes();
 
@@ -1206,6 +1207,10 @@ async fn create_vault_request<R: pm_types::VaultingInterface>(
         headers::CONTENT_TYPE,
         consts::VAULT_HEADER_CONTENT_TYPE.into(),
     );
+    request.add_header(
+        headers::X_TENANT_ID,
+        tenant_id.get_string_repr().to_owned().into(),
+    );
     request.set_body(request::RequestContent::Json(Box::new(jwe_payload)));
     Ok(request)
 }
@@ -1219,7 +1224,9 @@ pub async fn call_to_vault<V: pm_types::VaultingInterface>(
     let locker = &state.conf.locker;
     let jwekey = state.conf.jwekey.get_inner();
 
-    let request = create_vault_request::<V>(jwekey, locker, payload).await?;
+    let request =
+        create_vault_request::<V>(jwekey, locker, payload, state.tenant.tenant_id.to_owned())
+            .await?;
     let response = services::call_connector_api(state, request, V::get_vaulting_flow_name())
         .await
         .change_context(errors::VaultError::VaultAPIError);
diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs
index 78cfdda33b4..c243686a76c 100644
--- a/crates/router/src/core/payments/helpers.rs
+++ b/crates/router/src/core/payments/helpers.rs
@@ -1,11 +1,15 @@
 use std::{borrow::Cow, str::FromStr};
 
+#[cfg(feature = "v2")]
+use api_models::ephemeral_key::EphemeralKeyResponse;
 use api_models::{
     mandates::RecurringDetails,
     payments::{additional_info as payment_additional_types, RequestSurchargeDetails},
 };
 use base64::Engine;
 use common_enums::ConnectorType;
+#[cfg(feature = "v2")]
+use common_utils::id_type::GenerateId;
 use common_utils::{
     crypto::Encryptable,
     ext_traits::{AsyncExt, ByteSliceExt, Encode, ValueExt},
@@ -40,6 +44,8 @@ use openssl::{
     pkey::PKey,
     symm::{decrypt_aead, Cipher},
 };
+#[cfg(feature = "v2")]
+use redis_interface::errors::RedisError;
 use router_env::{instrument, logger, tracing};
 use uuid::Uuid;
 use x509_parser::parse_x509_certificate;
@@ -48,8 +54,6 @@ use super::{
     operations::{BoxedOperation, Operation, PaymentResponse},
     CustomerDetails, PaymentData,
 };
-#[cfg(feature = "v2")]
-use crate::core::admin as core_admin;
 use crate::{
     configs::settings::{ConnectorRequestReferenceIdConfig, TempLockerEnableConfig},
     connector,
@@ -84,6 +88,8 @@ use crate::{
         OptionExt, StringExt,
     },
 };
+#[cfg(feature = "v2")]
+use crate::{core::admin as core_admin, headers};
 #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))]
 use crate::{
     core::payment_methods::cards::create_encrypted_data, types::storage::CustomerUpdate::Update,
@@ -3021,6 +3027,7 @@ pub fn make_merchant_url_with_response(
     Ok(merchant_url_with_response.to_string())
 }
 
+#[cfg(feature = "v1")]
 pub async fn make_ephemeral_key(
     state: SessionState,
     customer_id: id_type::CustomerId,
@@ -3043,6 +3050,80 @@ pub async fn make_ephemeral_key(
     Ok(services::ApplicationResponse::Json(ek))
 }
 
+#[cfg(feature = "v2")]
+pub async fn make_ephemeral_key(
+    state: SessionState,
+    customer_id: id_type::GlobalCustomerId,
+    merchant_account: domain::MerchantAccount,
+    key_store: domain::MerchantKeyStore,
+    headers: &actix_web::http::header::HeaderMap,
+) -> errors::RouterResponse<EphemeralKeyResponse> {
+    let db = &state.store;
+    let key_manager_state = &((&state).into());
+    db.find_customer_by_global_id(
+        key_manager_state,
+        &customer_id,
+        merchant_account.get_id(),
+        &key_store,
+        merchant_account.storage_scheme,
+    )
+    .await
+    .to_not_found_response(errors::ApiErrorResponse::CustomerNotFound)?;
+
+    let resource_type = services::authentication::get_header_value_by_key(
+        headers::X_RESOURCE_TYPE.to_string(),
+        headers,
+    )?
+    .map(ephemeral_key::ResourceType::from_str)
+    .transpose()
+    .change_context(errors::ApiErrorResponse::InvalidRequestData {
+        message: format!("`{}` header is invalid", headers::X_RESOURCE_TYPE),
+    })?
+    .get_required_value("ResourceType")
+    .attach_printable("Failed to convert ResourceType from string")?;
+
+    let ephemeral_key = create_ephemeral_key(
+        &state,
+        &customer_id,
+        merchant_account.get_id(),
+        resource_type,
+    )
+    .await
+    .change_context(errors::ApiErrorResponse::InternalServerError)
+    .attach_printable("Unable to create ephemeral key")?;
+
+    let response = EphemeralKeyResponse::foreign_from(ephemeral_key);
+    Ok(services::ApplicationResponse::Json(response))
+}
+
+#[cfg(feature = "v2")]
+pub async fn create_ephemeral_key(
+    state: &SessionState,
+    customer_id: &id_type::GlobalCustomerId,
+    merchant_id: &id_type::MerchantId,
+    resource_type: ephemeral_key::ResourceType,
+) -> RouterResult<ephemeral_key::EphemeralKeyType> {
+    use common_utils::generate_time_ordered_id;
+
+    let store = &state.store;
+    let id = id_type::EphemeralKeyId::generate();
+    let secret = masking::Secret::new(generate_time_ordered_id("epk"));
+    let ephemeral_key = ephemeral_key::EphemeralKeyTypeNew {
+        id,
+        customer_id: customer_id.to_owned(),
+        merchant_id: merchant_id.to_owned(),
+        secret,
+        resource_type,
+    };
+    let ephemeral_key = store
+        .create_ephemeral_key(ephemeral_key, state.conf.eph_key.validity)
+        .await
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Unable to create ephemeral key")?;
+    Ok(ephemeral_key)
+}
+
+#[cfg(feature = "v1")]
 pub async fn delete_ephemeral_key(
     state: SessionState,
     ek_id: String,
@@ -3056,6 +3137,29 @@ pub async fn delete_ephemeral_key(
     Ok(services::ApplicationResponse::Json(ek))
 }
 
+#[cfg(feature = "v2")]
+pub async fn delete_ephemeral_key(
+    state: SessionState,
+    ephemeral_key_id: String,
+) -> errors::RouterResponse<EphemeralKeyResponse> {
+    let db = state.store.as_ref();
+    let ephemeral_key = db
+        .delete_ephemeral_key(&ephemeral_key_id)
+        .await
+        .map_err(|err| match err.current_context() {
+            errors::StorageError::ValueNotFound(_) => {
+                err.change_context(errors::ApiErrorResponse::GenericNotFoundError {
+                    message: "Ephemeral Key not found".to_string(),
+                })
+            }
+            _ => err.change_context(errors::ApiErrorResponse::InternalServerError),
+        })
+        .attach_printable("Unable to delete ephemeral key")?;
+
+    let response = EphemeralKeyResponse::foreign_from(ephemeral_key);
+    Ok(services::ApplicationResponse::Json(response))
+}
+
 pub fn make_pg_redirect_response(
     payment_id: id_type::PaymentId,
     response: &api::PaymentsResponse,
diff --git a/crates/router/src/db/ephemeral_key.rs b/crates/router/src/db/ephemeral_key.rs
index a1d43e83b87..a77995e4e58 100644
--- a/crates/router/src/db/ephemeral_key.rs
+++ b/crates/router/src/db/ephemeral_key.rs
@@ -1,5 +1,9 @@
+#[cfg(feature = "v2")]
+use common_utils::id_type;
 use time::ext::NumericalDuration;
 
+#[cfg(feature = "v2")]
+use crate::types::storage::ephemeral_key::{EphemeralKeyType, EphemeralKeyTypeNew, ResourceType};
 use crate::{
     core::errors::{self, CustomResult},
     db::MockDb,
@@ -8,30 +12,64 @@ use crate::{
 
 #[async_trait::async_trait]
 pub trait EphemeralKeyInterface {
+    #[cfg(feature = "v1")]
     async fn create_ephemeral_key(
         &self,
         _ek: EphemeralKeyNew,
         _validity: i64,
     ) -> CustomResult<EphemeralKey, errors::StorageError>;
+
+    #[cfg(feature = "v2")]
+    async fn create_ephemeral_key(
+        &self,
+        _ek: EphemeralKeyTypeNew,
+        _validity: i64,
+    ) -> CustomResult<EphemeralKeyType, errors::StorageError>;
+
+    #[cfg(feature = "v1")]
     async fn get_ephemeral_key(
         &self,
         _key: &str,
     ) -> CustomResult<EphemeralKey, errors::StorageError>;
+
+    #[cfg(feature = "v2")]
+    async fn get_ephemeral_key(
+        &self,
+        _key: &str,
+    ) -> CustomResult<EphemeralKeyType, errors::StorageError>;
+
+    #[cfg(feature = "v1")]
     async fn delete_ephemeral_key(
         &self,
         _id: &str,
     ) -> CustomResult<EphemeralKey, errors::StorageError>;
+
+    #[cfg(feature = "v2")]
+    async fn delete_ephemeral_key(
+        &self,
+        _id: &str,
+    ) -> CustomResult<EphemeralKeyType, errors::StorageError>;
 }
 
 mod storage {
     use common_utils::date_time;
+    #[cfg(feature = "v2")]
+    use common_utils::id_type;
     use error_stack::ResultExt;
+    #[cfg(feature = "v2")]
+    use masking::PeekInterface;
+    #[cfg(feature = "v2")]
+    use redis_interface::errors::RedisError;
     use redis_interface::HsetnxReply;
     use router_env::{instrument, tracing};
     use storage_impl::redis::kv_store::RedisConnInterface;
     use time::ext::NumericalDuration;
 
     use super::EphemeralKeyInterface;
+    #[cfg(feature = "v2")]
+    use crate::types::storage::ephemeral_key::{
+        EphemeralKeyType, EphemeralKeyTypeNew, ResourceType,
+    };
     use crate::{
         core::errors::{self, CustomResult},
         services::Store,
@@ -40,6 +78,7 @@ mod storage {
 
     #[async_trait::async_trait]
     impl EphemeralKeyInterface for Store {
+        #[cfg(feature = "v1")]
         #[instrument(skip_all)]
         async fn create_ephemeral_key(
             &self,
@@ -94,6 +133,68 @@ mod storage {
                 Err(er) => Err(er).change_context(errors::StorageError::KVError),
             }
         }
+
+        #[cfg(feature = "v2")]
+        #[instrument(skip_all)]
+        async fn create_ephemeral_key(
+            &self,
+            new: EphemeralKeyTypeNew,
+            validity: i64,
+        ) -> CustomResult<EphemeralKeyType, errors::StorageError> {
+            let created_at = date_time::now();
+            let expires = created_at.saturating_add(validity.hours());
+            let id_key = new.id.generate_redis_key();
+
+            let created_ephemeral_key = EphemeralKeyType {
+                id: new.id,
+                created_at,
+                expires,
+                customer_id: new.customer_id,
+                merchant_id: new.merchant_id,
+                secret: new.secret,
+                resource_type: new.resource_type,
+            };
+            let secret_key = created_ephemeral_key.generate_secret_key();
+
+            match self
+                .get_redis_conn()
+                .map_err(Into::<errors::StorageError>::into)?
+                .serialize_and_set_multiple_hash_field_if_not_exist(
+                    &[
+                        (&secret_key, &created_ephemeral_key),
+                        (&id_key, &created_ephemeral_key),
+                    ],
+                    "ephkey",
+                    None,
+                )
+                .await
+            {
+                Ok(v) if v.contains(&HsetnxReply::KeyNotSet) => {
+                    Err(errors::StorageError::DuplicateValue {
+                        entity: "ephemeral key",
+                        key: None,
+                    }
+                    .into())
+                }
+                Ok(_) => {
+                    let expire_at = expires.assume_utc().unix_timestamp();
+                    self.get_redis_conn()
+                        .map_err(Into::<errors::StorageError>::into)?
+                        .set_expire_at(&secret_key, expire_at)
+                        .await
+                        .change_context(errors::StorageError::KVError)?;
+                    self.get_redis_conn()
+                        .map_err(Into::<errors::StorageError>::into)?
+                        .set_expire_at(&id_key, expire_at)
+                        .await
+                        .change_context(errors::StorageError::KVError)?;
+                    Ok(created_ephemeral_key)
+                }
+                Err(er) => Err(er).change_context(errors::StorageError::KVError),
+            }
+        }
+
+        #[cfg(feature = "v1")]
         #[instrument(skip_all)]
         async fn get_ephemeral_key(
             &self,
@@ -106,6 +207,22 @@ mod storage {
                 .await
                 .change_context(errors::StorageError::KVError)
         }
+
+        #[cfg(feature = "v2")]
+        #[instrument(skip_all)]
+        async fn get_ephemeral_key(
+            &self,
+            key: &str,
+        ) -> CustomResult<EphemeralKeyType, errors::StorageError> {
+            let key = format!("epkey_{key}");
+            self.get_redis_conn()
+                .map_err(Into::<errors::StorageError>::into)?
+                .get_hash_field_and_deserialize(&key, "ephkey", "EphemeralKeyType")
+                .await
+                .change_context(errors::StorageError::KVError)
+        }
+
+        #[cfg(feature = "v1")]
         async fn delete_ephemeral_key(
             &self,
             id: &str,
@@ -125,11 +242,45 @@ mod storage {
                 .change_context(errors::StorageError::KVError)?;
             Ok(ek)
         }
+
+        #[cfg(feature = "v2")]
+        async fn delete_ephemeral_key(
+            &self,
+            id: &str,
+        ) -> CustomResult<EphemeralKeyType, errors::StorageError> {
+            let ephemeral_key = self.get_ephemeral_key(id).await?;
+            let redis_id_key = ephemeral_key.id.generate_redis_key();
+            let secret_key = ephemeral_key.generate_secret_key();
+
+            self.get_redis_conn()
+                .map_err(Into::<errors::StorageError>::into)?
+                .delete_key(&redis_id_key)
+                .await
+                .map_err(|err| match err.current_context() {
+                    RedisError::NotFound => {
+                        err.change_context(errors::StorageError::ValueNotFound(redis_id_key))
+                    }
+                    _ => err.change_context(errors::StorageError::KVError),
+                })?;
+
+            self.get_redis_conn()
+                .map_err(Into::<errors::StorageError>::into)?
+                .delete_key(&secret_key)
+                .await
+                .map_err(|err| match err.current_context() {
+                    RedisError::NotFound => {
+                        err.change_context(errors::StorageError::ValueNotFound(secret_key))
+                    }
+                    _ => err.change_context(errors::StorageError::KVError),
+                })?;
+            Ok(ephemeral_key)
+        }
     }
 }
 
 #[async_trait::async_trait]
 impl EphemeralKeyInterface for MockDb {
+    #[cfg(feature = "v1")]
     async fn create_ephemeral_key(
         &self,
         ek: EphemeralKeyNew,
@@ -150,6 +301,17 @@ impl EphemeralKeyInterface for MockDb {
         ephemeral_keys.push(ephemeral_key.clone());
         Ok(ephemeral_key)
     }
+
+    #[cfg(feature = "v2")]
+    async fn create_ephemeral_key(
+        &self,
+        ek: EphemeralKeyTypeNew,
+        validity: i64,
+    ) -> CustomResult<EphemeralKeyType, errors::StorageError> {
+        todo!()
+    }
+
+    #[cfg(feature = "v1")]
     async fn get_ephemeral_key(
         &self,
         key: &str,
@@ -167,6 +329,16 @@ impl EphemeralKeyInterface for MockDb {
             ),
         }
     }
+
+    #[cfg(feature = "v2")]
+    async fn get_ephemeral_key(
+        &self,
+        key: &str,
+    ) -> CustomResult<EphemeralKeyType, errors::StorageError> {
+        todo!()
+    }
+
+    #[cfg(feature = "v1")]
     async fn delete_ephemeral_key(
         &self,
         id: &str,
@@ -181,4 +353,12 @@ impl EphemeralKeyInterface for MockDb {
             );
         }
     }
+
+    #[cfg(feature = "v2")]
+    async fn delete_ephemeral_key(
+        &self,
+        id: &str,
+    ) -> CustomResult<EphemeralKeyType, errors::StorageError> {
+        todo!()
+    }
 }
diff --git a/crates/router/src/db/kafka_store.rs b/crates/router/src/db/kafka_store.rs
index f49173b3549..4155bbf3ff9 100644
--- a/crates/router/src/db/kafka_store.rs
+++ b/crates/router/src/db/kafka_store.rs
@@ -6,6 +6,8 @@ use common_utils::{
     id_type,
     types::{keymanager::KeyManagerState, theme::ThemeLineage},
 };
+#[cfg(feature = "v2")]
+use diesel_models::ephemeral_key::{EphemeralKeyType, EphemeralKeyTypeNew};
 use diesel_models::{
     enums,
     enums::ProcessTrackerStatus,
@@ -646,6 +648,7 @@ impl DisputeInterface for KafkaStore {
 
 #[async_trait::async_trait]
 impl EphemeralKeyInterface for KafkaStore {
+    #[cfg(feature = "v1")]
     async fn create_ephemeral_key(
         &self,
         ek: EphemeralKeyNew,
@@ -653,18 +656,47 @@ impl EphemeralKeyInterface for KafkaStore {
     ) -> CustomResult<EphemeralKey, errors::StorageError> {
         self.diesel_store.create_ephemeral_key(ek, validity).await
     }
+
+    #[cfg(feature = "v2")]
+    async fn create_ephemeral_key(
+        &self,
+        ek: EphemeralKeyTypeNew,
+        validity: i64,
+    ) -> CustomResult<EphemeralKeyType, errors::StorageError> {
+        self.diesel_store.create_ephemeral_key(ek, validity).await
+    }
+
+    #[cfg(feature = "v1")]
     async fn get_ephemeral_key(
         &self,
         key: &str,
     ) -> CustomResult<EphemeralKey, errors::StorageError> {
         self.diesel_store.get_ephemeral_key(key).await
     }
+
+    #[cfg(feature = "v2")]
+    async fn get_ephemeral_key(
+        &self,
+        key: &str,
+    ) -> CustomResult<EphemeralKeyType, errors::StorageError> {
+        self.diesel_store.get_ephemeral_key(key).await
+    }
+
+    #[cfg(feature = "v1")]
     async fn delete_ephemeral_key(
         &self,
         id: &str,
     ) -> CustomResult<EphemeralKey, errors::StorageError> {
         self.diesel_store.delete_ephemeral_key(id).await
     }
+
+    #[cfg(feature = "v2")]
+    async fn delete_ephemeral_key(
+        &self,
+        id: &str,
+    ) -> CustomResult<EphemeralKeyType, errors::StorageError> {
+        self.diesel_store.delete_ephemeral_key(id).await
+    }
 }
 
 #[async_trait::async_trait]
diff --git a/crates/router/src/lib.rs b/crates/router/src/lib.rs
index d43fa054313..05c15b91674 100644
--- a/crates/router/src/lib.rs
+++ b/crates/router/src/lib.rs
@@ -90,6 +90,7 @@ pub mod headers {
     pub const X_REDIRECT_URI: &str = "x-redirect-uri";
     pub const X_TENANT_ID: &str = "x-tenant-id";
     pub const X_CLIENT_SECRET: &str = "X-Client-Secret";
+    pub const X_RESOURCE_TYPE: &str = "X-Resource-Type";
 }
 
 pub mod pii {
@@ -155,15 +156,17 @@ pub fn mk_app(
         }
     }
 
+    #[cfg(all(feature = "oltp", any(feature = "v1", feature = "v2"),))]
+    {
+        server_app = server_app.service(routes::EphemeralKey::server(state.clone()))
+    }
     #[cfg(all(
         feature = "oltp",
         any(feature = "v1", feature = "v2"),
         not(feature = "customer_v2")
     ))]
     {
-        server_app = server_app
-            .service(routes::EphemeralKey::server(state.clone()))
-            .service(routes::Poll::server(state.clone()))
+        server_app = server_app.service(routes::Poll::server(state.clone()))
     }
 
     #[cfg(feature = "olap")]
diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs
index 766679491c5..4192df58d2c 100644
--- a/crates/router/src/routes/app.rs
+++ b/crates/router/src/routes/app.rs
@@ -27,11 +27,7 @@ use self::settings::Tenant;
 use super::currency;
 #[cfg(feature = "dummy_connector")]
 use super::dummy_connector::*;
-#[cfg(all(
-    any(feature = "v1", feature = "v2"),
-    not(feature = "customer_v2"),
-    feature = "oltp"
-))]
+#[cfg(all(any(feature = "v1", feature = "v2"), feature = "oltp"))]
 use super::ephemeral_key::*;
 #[cfg(any(feature = "olap", feature = "oltp"))]
 use super::payment_methods::*;
@@ -1141,8 +1137,11 @@ impl PaymentMethods {
                 web::resource("/{id}/update-saved-payment-method")
                     .route(web::patch().to(payment_method_update_api)),
             )
-            .service(web::resource("/{id}").route(web::get().to(payment_method_retrieve_api)))
-            .service(web::resource("/{id}").route(web::delete().to(payment_method_delete_api)));
+            .service(
+                web::resource("/{id}")
+                    .route(web::get().to(payment_method_retrieve_api))
+                    .route(web::delete().to(payment_method_delete_api)),
+            );
 
         route
     }
@@ -1416,6 +1415,16 @@ impl EphemeralKey {
     }
 }
 
+#[cfg(feature = "v2")]
+impl EphemeralKey {
+    pub fn server(config: AppState) -> Scope {
+        web::scope("/v2/ephemeral-keys")
+            .app_data(web::Data::new(config))
+            .service(web::resource("").route(web::post().to(ephemeral_key_create)))
+            .service(web::resource("/{id}").route(web::delete().to(ephemeral_key_delete)))
+    }
+}
+
 pub struct Mandates;
 
 #[cfg(all(any(feature = "olap", feature = "oltp"), feature = "v1"))]
diff --git a/crates/router/src/routes/ephemeral_key.rs b/crates/router/src/routes/ephemeral_key.rs
index e6a33c59192..0330482e81a 100644
--- a/crates/router/src/routes/ephemeral_key.rs
+++ b/crates/router/src/routes/ephemeral_key.rs
@@ -1,11 +1,7 @@
-#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))]
 use actix_web::{web, HttpRequest, HttpResponse};
-#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))]
 use router_env::{instrument, tracing, Flow};
 
-#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))]
 use super::AppState;
-#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))]
 use crate::{
     core::{api_locking, payments::helpers},
     services::{api, authentication as auth},
@@ -38,7 +34,35 @@ pub async fn ephemeral_key_create(
     .await
 }
 
-#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))]
+#[cfg(feature = "v2")]
+#[instrument(skip_all, fields(flow = ?Flow::EphemeralKeyCreate))]
+pub async fn ephemeral_key_create(
+    state: web::Data<AppState>,
+    req: HttpRequest,
+    json_payload: web::Json<api_models::ephemeral_key::EphemeralKeyCreateRequest>,
+) -> HttpResponse {
+    let flow = Flow::EphemeralKeyCreate;
+    let payload = json_payload.into_inner();
+    api::server_wrap(
+        flow,
+        state,
+        &req,
+        payload,
+        |state, auth: auth::AuthenticationData, payload, _| {
+            helpers::make_ephemeral_key(
+                state,
+                payload.customer_id.to_owned(),
+                auth.merchant_account,
+                auth.key_store,
+                req.headers(),
+            )
+        },
+        &auth::HeaderAuth(auth::ApiKeyAuth),
+        api_locking::LockAction::NotApplicable,
+    )
+    .await
+}
+
 #[instrument(skip_all, fields(flow = ?Flow::EphemeralKeyDelete))]
 pub async fn ephemeral_key_delete(
     state: web::Data<AppState>,
diff --git a/crates/router/src/routes/payment_methods.rs b/crates/router/src/routes/payment_methods.rs
index c27a25677af..729a35aa8b7 100644
--- a/crates/router/src/routes/payment_methods.rs
+++ b/crates/router/src/routes/payment_methods.rs
@@ -141,8 +141,8 @@ pub async fn confirm_payment_method_intent_api(
     let pm_id = path.into_inner();
     let payload = json_payload.into_inner();
 
-    let (auth, _) = match auth::check_client_secret_and_get_auth(req.headers(), &payload) {
-        Ok((auth, _auth_flow)) => (auth, _auth_flow),
+    let auth = match auth::is_ephemeral_or_publishible_auth(req.headers()) {
+        Ok(auth) => auth,
         Err(e) => return api::log_and_return_error_response(e),
     };
 
@@ -150,7 +150,6 @@ pub async fn confirm_payment_method_intent_api(
         id: pm_id.clone(),
         payment_method_type: payload.payment_method_type,
         payment_method_subtype: payload.payment_method_subtype,
-        client_secret: payload.client_secret.clone(),
         customer_id: payload.customer_id.to_owned(),
         payment_method_data: payload.payment_method_data.clone(),
     };
@@ -191,6 +190,11 @@ pub async fn payment_method_update_api(
     let payment_method_id = path.into_inner();
     let payload = json_payload.into_inner();
 
+    let auth = match auth::is_ephemeral_or_publishible_auth(req.headers()) {
+        Ok(auth) => auth,
+        Err(e) => return api::log_and_return_error_response(e),
+    };
+
     Box::pin(api::server_wrap(
         flow,
         state,
@@ -205,7 +209,7 @@ pub async fn payment_method_update_api(
                 auth.key_store,
             )
         },
-        &auth::HeaderAuth(auth::ApiKeyAuth),
+        &*auth,
         api_locking::LockAction::NotApplicable,
     ))
     .await
diff --git a/crates/router/src/services/authentication.rs b/crates/router/src/services/authentication.rs
index e8435243ff4..3df0313668c 100644
--- a/crates/router/src/services/authentication.rs
+++ b/crates/router/src/services/authentication.rs
@@ -1,3 +1,5 @@
+use std::str::FromStr;
+
 use actix_web::http::header::HeaderMap;
 #[cfg(all(
     any(feature = "v2", feature = "v1"),
@@ -11,7 +13,11 @@ use api_models::payouts;
 use api_models::{payment_methods::PaymentMethodListRequest, payments};
 use async_trait::async_trait;
 use common_enums::TokenPurpose;
+#[cfg(feature = "v2")]
+use common_utils::fp_utils;
 use common_utils::{date_time, id_type};
+#[cfg(feature = "v2")]
+use diesel_models::ephemeral_key;
 use error_stack::{report, ResultExt};
 use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation};
 use masking::PeekInterface;
@@ -1329,6 +1335,32 @@ where
 #[derive(Debug)]
 pub struct EphemeralKeyAuth;
 
+#[cfg(feature = "v1")]
+#[async_trait]
+impl<A> AuthenticateAndFetch<AuthenticationData, A> for EphemeralKeyAuth
+where
+    A: SessionStateInfo + Sync,
+{
+    async fn authenticate_and_fetch(
+        &self,
+        request_headers: &HeaderMap,
+        state: &A,
+    ) -> RouterResult<(AuthenticationData, AuthenticationType)> {
+        let api_key =
+            get_api_key(request_headers).change_context(errors::ApiErrorResponse::Unauthorized)?;
+        let ephemeral_key = state
+            .store()
+            .get_ephemeral_key(api_key)
+            .await
+            .change_context(errors::ApiErrorResponse::Unauthorized)?;
+
+        MerchantIdAuth(ephemeral_key.merchant_id)
+            .authenticate_and_fetch(request_headers, state)
+            .await
+    }
+}
+
+#[cfg(feature = "v2")]
 #[async_trait]
 impl<A> AuthenticateAndFetch<AuthenticationData, A> for EphemeralKeyAuth
 where
@@ -1347,6 +1379,20 @@ where
             .await
             .change_context(errors::ApiErrorResponse::Unauthorized)?;
 
+        let resource_type = HeaderMapStruct::new(request_headers)
+            .get_mandatory_header_value_by_key(headers::X_RESOURCE_TYPE)
+            .and_then(|val| {
+                ephemeral_key::ResourceType::from_str(val).change_context(
+                    errors::ApiErrorResponse::InvalidRequestData {
+                        message: format!("`{}` header is invalid", headers::X_RESOURCE_TYPE),
+                    },
+                )
+            })?;
+
+        fp_utils::when(resource_type != ephemeral_key.resource_type, || {
+            Err(errors::ApiErrorResponse::Unauthorized)
+        })?;
+
         MerchantIdAuth(ephemeral_key.merchant_id)
             .authenticate_and_fetch(request_headers, state)
             .await
@@ -2938,13 +2984,6 @@ impl ClientSecretFetch for PaymentMethodCreate {
     }
 }
 
-#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
-impl ClientSecretFetch for PaymentMethodIntentConfirm {
-    fn get_client_secret(&self) -> Option<&String> {
-        Some(&self.client_secret)
-    }
-}
-
 impl ClientSecretFetch for api_models::cards_info::CardsInfoRequest {
     fn get_client_secret(&self) -> Option<&String> {
         self.client_secret.as_ref()
@@ -2969,6 +3008,7 @@ impl ClientSecretFetch for api_models::pm_auth::ExchangeTokenCreateRequest {
     }
 }
 
+#[cfg(feature = "v1")]
 impl ClientSecretFetch for api_models::payment_methods::PaymentMethodUpdate {
     fn get_client_secret(&self) -> Option<&String> {
         self.client_secret.as_ref()
@@ -3059,6 +3099,20 @@ where
     }
 }
 
+pub fn is_ephemeral_or_publishible_auth<A: SessionStateInfo + Sync + Send>(
+    headers: &HeaderMap,
+) -> RouterResult<Box<dyn AuthenticateAndFetch<AuthenticationData, A>>> {
+    let api_key = get_api_key(headers)?;
+
+    if api_key.starts_with("epk") {
+        Ok(Box::new(EphemeralKeyAuth))
+    } else if api_key.starts_with("pk_") {
+        Ok(Box::new(HeaderAuth(PublishableKeyAuth)))
+    } else {
+        Ok(Box::new(HeaderAuth(ApiKeyAuth)))
+    }
+}
+
 pub fn is_ephemeral_auth<A: SessionStateInfo + Sync + Send>(
     headers: &HeaderMap,
 ) -> RouterResult<Box<dyn AuthenticateAndFetch<AuthenticationData, A>>> {
@@ -3109,7 +3163,7 @@ pub fn get_header_value_by_key(key: String, headers: &HeaderMap) -> RouterResult
         })
         .transpose()
 }
-pub fn get_id_type_by_key_from_headers<T: std::str::FromStr>(
+pub fn get_id_type_by_key_from_headers<T: FromStr>(
     key: String,
     headers: &HeaderMap,
 ) -> RouterResult<Option<T>> {
diff --git a/crates/router/src/types/payment_methods.rs b/crates/router/src/types/payment_methods.rs
index 1a6b9053dcb..c40d6fedfe7 100644
--- a/crates/router/src/types/payment_methods.rs
+++ b/crates/router/src/types/payment_methods.rs
@@ -126,16 +126,6 @@ impl VaultingDataInterface for PaymentMethodVaultingData {
     }
 }
 
-#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
-pub struct PaymentMethodClientSecret;
-
-#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
-impl PaymentMethodClientSecret {
-    pub fn generate(payment_method_id: &common_utils::id_type::GlobalPaymentMethodId) -> String {
-        todo!()
-    }
-}
-
 #[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
 pub struct SavedPMLPaymentsInfo {
     pub payment_intent: storage::PaymentIntent,
@@ -155,7 +145,7 @@ pub struct VaultRetrieveRequest {
 #[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
 #[derive(Debug, serde::Deserialize, serde::Serialize)]
 pub struct VaultRetrieveResponse {
-    pub data: Secret<String>,
+    pub data: PaymentMethodVaultingData,
 }
 
 #[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
diff --git a/crates/router/src/types/storage/ephemeral_key.rs b/crates/router/src/types/storage/ephemeral_key.rs
index 9927e16b3fa..c4b8e2ba701 100644
--- a/crates/router/src/types/storage/ephemeral_key.rs
+++ b/crates/router/src/types/storage/ephemeral_key.rs
@@ -1 +1,18 @@
 pub use diesel_models::ephemeral_key::{EphemeralKey, EphemeralKeyNew};
+#[cfg(feature = "v2")]
+pub use diesel_models::ephemeral_key::{EphemeralKeyType, EphemeralKeyTypeNew, ResourceType};
+
+#[cfg(feature = "v2")]
+use crate::types::transformers::ForeignFrom;
+#[cfg(feature = "v2")]
+impl ForeignFrom<EphemeralKeyType> for api_models::ephemeral_key::EphemeralKeyResponse {
+    fn foreign_from(from: EphemeralKeyType) -> Self {
+        Self {
+            customer_id: from.customer_id,
+            created_at: from.created_at,
+            expires: from.expires,
+            secret: from.secret,
+            id: from.id,
+        }
+    }
+}

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

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

## Description
<!-- Describe your changes in detail -->
This PR contains - 
- Ephemeral auth support for v2 (including resource type product identifier)
- Minor Fixes for Payment methods v2 CRUD APIs
- Removed Client secret auth from PaymentMethod CRUD APIs

### Additional Changes

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

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

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


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

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


## How did you test it?
<!--
Did you write an integration/unit/API test to verify the code changes?
Or did you test this change manually (provide relevant screenshots)?
-->
1. Create Payment Method Intent 
```
curl --location --request POST 'http://localhost:8080/v2/payment-methods/create-intent' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'X-Profile-Id: pro_DMmRBLpkNczeVDPd2EKd' \
--header 'api-key: dev_HVwdf7yWqJ9GGfw1CLDbAgjOFYHrPXoisK8pJcVPfdbc73238GROVpDhN3M9cPe2' \
--data-raw '{
  "customer_id": "cus_0193ab7e6cc074939f389817610cd5b1"
}'
```
Response
```
{
    "merchant_id": "cloth_seller_pcGA5SfzTmVUTBKvh2T3",
    "customer_id": "cus_0193ab7e6cc074939f389817610cd5b1",
    "payment_method_id": "12345_pm_0193b69ba645716086c0fe21c462cf2d",
    "payment_method_type": null,
    "payment_method_subtype": null,
    "recurring_enabled": false,
    "created": "2024-12-11T16:44:34.261Z",
    "last_used_at": "2024-12-11T16:44:34.261Z",
    "ephemeral_key": "epk_0c6ebab77f51446ab30467640a6f8f02",
    "payment_method_data": null
}
```
2. Use Ephemeral key to confirm intent
```
curl --location --request POST 'http://localhost:8080/v2/payment-methods/12345_pm_0193b69ba645716086c0fe21c462cf2d/confirm-intent' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'X-Profile-Id: pro_DMmRBLpkNczeVDPd2EKd' \
--header 'X-Resource-Type: payment_method' \
--header 'api-key: epk_0c6ebab77f51446ab30467640a6f8f02' \
--data-raw '{
    "payment_method_type": "card",
    "payment_method_subtype": "credit",
    "payment_method_data": {
        "card": {
            "card_number": "4242424242424242",
            "card_exp_month": "12",
            "card_exp_year": "2025",
            "card_holder_name": "joseph Doe"
        }
    },
    "customer_id": "cus_0193ab7e6cc074939f389817610cd5b1"
}'
```
Response - 
```
{
    "merchant_id": "cloth_seller_pcGA5SfzTmVUTBKvh2T3",
    "customer_id": "cus_0193ab7e6cc074939f389817610cd5b1",
    "payment_method_id": "12345_pm_0193b69ba645716086c0fe21c462cf2d",
    "payment_method_type": "card",
    "payment_method_subtype": "credit",
    "recurring_enabled": false,
    "created": "2024-12-11T16:44:34.261Z",
    "last_used_at": "2024-12-11T16:44:34.261Z",
    "ephemeral_key": null,
    "payment_method_data": {
        "card": {
            "issuer_country": null,
            "last4_digits": "4242",
            "expiry_month": "12",
            "expiry_year": "2025",
            "card_holder_name": "joseph Doe",
            "card_fingerprint": null,
            "nick_name": null,
            "card_network": null,
            "card_isin": null,
            "card_issuer": null,
            "card_type": null,
            "saved_to_locker": true
        }
    }
}
```
3. Retrieve a PM - 
```
curl --location --request GET 'http://localhost:8080/v2/payment-methods/12345_pm_0193cec5b7637f33a36b1f9ce34137bd' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'X-Profile-Id: pro_OqoV7IKp695hRjM1zRfE' \
--header 'X-Resource-Type: payment_method' \
--header 'api-key: dev_qxDW3eUAAg8u1Yagzfzur089lWvt4ZwendCYibU4XBTV9Mo6tJ3wi0inMiO9gnTO'
```
Response - 
```
{
    "merchant_id": "cloth_seller_R8JPuhk0GnkqHNDBzs7g",
    "customer_id": "cus_0193ce809d9e7411bd207c8f85eac45b",
    "payment_method_id": "12345_pm_0193cec5b7637f33a36b1f9ce34137bd",
    "payment_method_type": "card",
    "payment_method_subtype": "credit",
    "recurring_enabled": false,
    "created": "2024-12-16T09:21:24.377Z",
    "last_used_at": "2024-12-16T09:21:24.377Z",
    "ephemeral_key": null,
    "payment_method_data": {
        "card": {
            "issuer_country": null,
            "last4_digits": "4242",
            "expiry_month": "12",
            "expiry_year": "2025",
            "card_holder_name": "joseph Doe",
            "card_fingerprint": null,
            "nick_name": null,
            "card_network": null,
            "card_isin": null,
            "card_issuer": null,
            "card_type": null,
            "saved_to_locker": true
        }
    }
}
```
4. Update a PM - 
```
curl --location --request PATCH 'http://localhost:8080/v2/payment-methods/12345_pm_0193b69ba645716086c0fe21c462cf2d/update-saved-payment-method' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'X-Profile-Id: pro_DMmRBLpkNczeVDPd2EKd' \
--header 'X-Resource-Type: payment_method' \
--header 'api-key: epk_0c6ebab77f51446ab30467640a6f8f02' \
--data-raw '{
    "payment_method_data": {
        "card": {
            "card_holder_name": "joseph",
            "nick_name": "some_name11"
        }
    }
}'
```
Response - 
```
{
    "merchant_id": "cloth_seller_pcGA5SfzTmVUTBKvh2T3",
    "customer_id": "cus_0193ab7e6cc074939f389817610cd5b1",
    "payment_method_id": "12345_pm_0193b69ba645716086c0fe21c462cf2d",
    "payment_method_type": "card",
    "payment_method_subtype": "credit",
    "recurring_enabled": false,
    "created": "2024-12-11T16:44:34.261Z",
    "last_used_at": "2024-12-11T16:44:34.261Z",
    "ephemeral_key": null,
    "payment_method_data": {
        "card": {
            "issuer_country": null,
            "last4_digits": "4242",
            "expiry_month": "12",
            "expiry_year": "2025",
            "card_holder_name": "joseph",
            "card_fingerprint": null,
            "nick_name": "some_name11",
            "card_network": null,
            "card_isin": null,
            "card_issuer": null,
            "card_type": null,
            "saved_to_locker": true
        }
    }
}
```
5. Delete a PM - 
```
curl --location --request DELETE 'http://localhost:8080/v2/payment-methods/12345_pm_0193cec5b7637f33a36b1f9ce34137bd' \
--header 'Accept: application/json' \
--header 'X-Profile-Id: pro_OqoV7IKp695hRjM1zRfE' \
--header 'X-Resource-Type: payment_method' \
--header 'api-key: dev_qxDW3eUAAg8u1Yagzfzur089lWvt4ZwendCYibU4XBTV9Mo6tJ3wi0inMiO9gnTO'
```
Response - 
```
{
    "payment_method_id": "12345_pm_0193b69ba645716086c0fe21c462cf2d"
}
```
6. Standalone Ephemeral key create - 
```
curl --location --request POST 'http://localhost:8080/v2/ephemeral-keys' \
--header 'Content-Type: application/json' \
--header 'X-Profile-Id: pro_CwrzjgurYtopm4AU4ckw' \
--header 'X-Resource-Type: payment_method' \
--header 'api-key: dev_XhFPyn6hxjHV0kwfx5TuqP01AACTenU00ioSS352L5uUFufVKqfWNAtI1reaYO3S' \
--data-raw '{
    "customer_id": "12345_cus_0193d93f0f267882b5b843a648890ede"
}'
```
Response - 
```
{
    "id": "eki_TEEmZPBA0XL1jyQYaXVY",
    "customer_id": "12345_cus_0193d93f0f267882b5b843a648890ede",
    "created_at": "2024-12-19 12:17:01.909893",
    "expires": "2024-12-19 13:17:01.909893",
    "secret": "epk_0193ded995d57fd290ed0ce218e01cf9"
}
```
Can use the ephemeral key obtained here to hit the above APIs
## Checklist
<!-- Put an `x` in the boxes that apply -->

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