Bug: fix(analytics): refactor auth analytics to support profile,org and merchant level auth



### Feature Description

Exposed the auth analytics under profile, merchant and org levels

### Possible Implementation

Expose different endpoints for auth analytics sankey

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

None
diff --git a/crates/analytics/src/auth_events/core.rs b/crates/analytics/src/auth_events/core.rs
index 41b7b724954..011633dce3d 100644
--- a/crates/analytics/src/auth_events/core.rs
+++ b/crates/analytics/src/auth_events/core.rs
@@ -27,7 +27,7 @@ use crate::{
 #[instrument(skip_all)]
 pub async fn get_metrics(
     pool: &AnalyticsProvider,
-    merchant_id: &common_utils::id_type::MerchantId,
+    auth: &AuthInfo,
     req: GetAuthEventMetricRequest,
 ) -> AnalyticsResult<AuthEventMetricsResponse<MetricsBucketResponse>> {
     let mut metrics_accumulator: HashMap<
@@ -38,14 +38,14 @@ pub async fn get_metrics(
     let mut set = tokio::task::JoinSet::new();
     for metric_type in req.metrics.iter().cloned() {
         let req = req.clone();
-        let merchant_id_scoped = merchant_id.to_owned();
+        let auth_scoped = auth.to_owned();
         let pool = pool.clone();
         set.spawn(async move {
             let data = pool
                 .get_auth_event_metrics(
                     &metric_type,
                     &req.group_by_names.clone(),
-                    &merchant_id_scoped,
+                    &auth_scoped,
                     &req.filters,
                     req.time_series.map(|t| t.granularity),
                     &req.time_range,
@@ -130,7 +130,7 @@ pub async fn get_metrics(
 pub async fn get_filters(
     pool: &AnalyticsProvider,
     req: GetAuthEventFilterRequest,
-    merchant_id: &common_utils::id_type::MerchantId,
+    auth: &AuthInfo,
 ) -> AnalyticsResult<AuthEventFiltersResponse> {
     let mut res = AuthEventFiltersResponse::default();
     for dim in req.group_by_names {
@@ -139,14 +139,14 @@ pub async fn get_filters(
                             Err(report!(AnalyticsError::UnknownError))
             }
                         AnalyticsProvider::Clickhouse(pool) => {
-                get_auth_events_filter_for_dimension(dim, merchant_id, &req.time_range, pool)
+                get_auth_events_filter_for_dimension(dim, auth, &req.time_range, pool)
                     .await
                     .map_err(|e| e.change_context(AnalyticsError::UnknownError))
             }
                     AnalyticsProvider::CombinedCkh(sqlx_pool, ckh_pool) | AnalyticsProvider::CombinedSqlx(sqlx_pool, ckh_pool) => {
                 let ckh_result = get_auth_events_filter_for_dimension(
                     dim,
-                    merchant_id,
+                    auth,
                     &req.time_range,
                     ckh_pool,
                 )
@@ -154,7 +154,7 @@ pub async fn get_filters(
                 .map_err(|e| e.change_context(AnalyticsError::UnknownError));
                 let sqlx_result = get_auth_events_filter_for_dimension(
                     dim,
-                    merchant_id,
+                    auth,
                     &req.time_range,
                     sqlx_pool,
                 )
diff --git a/crates/analytics/src/auth_events/filters.rs b/crates/analytics/src/auth_events/filters.rs
index 92496131727..7ecf2426dfa 100644
--- a/crates/analytics/src/auth_events/filters.rs
+++ b/crates/analytics/src/auth_events/filters.rs
@@ -6,6 +6,7 @@ use error_stack::ResultExt;
 use time::PrimitiveDateTime;
 
 use crate::{
+    enums::AuthInfo,
     query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, ToSql, Window},
     types::{
         AnalyticsCollection, AnalyticsDataSource, DBEnumWrapper, FiltersError, FiltersResult,
@@ -17,7 +18,7 @@ pub trait AuthEventFilterAnalytics: LoadRow<AuthEventFilterRow> {}
 
 pub async fn get_auth_events_filter_for_dimension<T>(
     dimension: AuthEventDimensions,
-    merchant_id: &common_utils::id_type::MerchantId,
+    auth: &AuthInfo,
     time_range: &TimeRange,
     pool: &T,
 ) -> FiltersResult<Vec<AuthEventFilterRow>>
@@ -38,12 +39,10 @@ where
         .attach_printable("Error filtering time range")
         .switch()?;
 
-    query_builder
-        .add_filter_clause("merchant_id", merchant_id)
-        .switch()?;
-
     query_builder.set_distinct();
 
+    auth.set_filter_clause(&mut query_builder).switch()?;
+
     query_builder
         .execute_query::<AuthEventFilterRow, _>(pool)
         .await
diff --git a/crates/analytics/src/auth_events/metrics.rs b/crates/analytics/src/auth_events/metrics.rs
index 46c3805662a..ebb1d5d1f00 100644
--- a/crates/analytics/src/auth_events/metrics.rs
+++ b/crates/analytics/src/auth_events/metrics.rs
@@ -12,6 +12,7 @@ use time::PrimitiveDateTime;
 use crate::{
     query::{Aggregate, GroupByClause, ToSql, Window},
     types::{AnalyticsCollection, AnalyticsDataSource, DBEnumWrapper, LoadRow, MetricsResult},
+    AuthInfo,
 };
 
 mod authentication_attempt_count;
@@ -86,7 +87,7 @@ where
 {
     async fn load_metrics(
         &self,
-        merchant_id: &common_utils::id_type::MerchantId,
+        auth: &AuthInfo,
         dimensions: &[AuthEventDimensions],
         filters: &AuthEventFilters,
         granularity: Option<Granularity>,
@@ -107,7 +108,7 @@ where
 {
     async fn load_metrics(
         &self,
-        merchant_id: &common_utils::id_type::MerchantId,
+        auth: &AuthInfo,
         dimensions: &[AuthEventDimensions],
         filters: &AuthEventFilters,
         granularity: Option<Granularity>,
@@ -117,146 +118,62 @@ where
         match self {
             Self::AuthenticationCount => {
                 AuthenticationCount
-                    .load_metrics(
-                        merchant_id,
-                        dimensions,
-                        filters,
-                        granularity,
-                        time_range,
-                        pool,
-                    )
+                    .load_metrics(auth, dimensions, filters, granularity, time_range, pool)
                     .await
             }
             Self::AuthenticationAttemptCount => {
                 AuthenticationAttemptCount
-                    .load_metrics(
-                        merchant_id,
-                        dimensions,
-                        filters,
-                        granularity,
-                        time_range,
-                        pool,
-                    )
+                    .load_metrics(auth, dimensions, filters, granularity, time_range, pool)
                     .await
             }
             Self::AuthenticationSuccessCount => {
                 AuthenticationSuccessCount
-                    .load_metrics(
-                        merchant_id,
-                        dimensions,
-                        filters,
-                        granularity,
-                        time_range,
-                        pool,
-                    )
+                    .load_metrics(auth, dimensions, filters, granularity, time_range, pool)
                     .await
             }
             Self::ChallengeFlowCount => {
                 ChallengeFlowCount
-                    .load_metrics(
-                        merchant_id,
-                        dimensions,
-                        filters,
-                        granularity,
-                        time_range,
-                        pool,
-                    )
+                    .load_metrics(auth, dimensions, filters, granularity, time_range, pool)
                     .await
             }
             Self::ChallengeAttemptCount => {
                 ChallengeAttemptCount
-                    .load_metrics(
-                        merchant_id,
-                        dimensions,
-                        filters,
-                        granularity,
-                        time_range,
-                        pool,
-                    )
+                    .load_metrics(auth, dimensions, filters, granularity, time_range, pool)
                     .await
             }
             Self::ChallengeSuccessCount => {
                 ChallengeSuccessCount
-                    .load_metrics(
-                        merchant_id,
-                        dimensions,
-                        filters,
-                        granularity,
-                        time_range,
-                        pool,
-                    )
+                    .load_metrics(auth, dimensions, filters, granularity, time_range, pool)
                     .await
             }
             Self::FrictionlessFlowCount => {
                 FrictionlessFlowCount
-                    .load_metrics(
-                        merchant_id,
-                        dimensions,
-                        filters,
-                        granularity,
-                        time_range,
-                        pool,
-                    )
+                    .load_metrics(auth, dimensions, filters, granularity, time_range, pool)
                     .await
             }
             Self::FrictionlessSuccessCount => {
                 FrictionlessSuccessCount
-                    .load_metrics(
-                        merchant_id,
-                        dimensions,
-                        filters,
-                        granularity,
-                        time_range,
-                        pool,
-                    )
+                    .load_metrics(auth, dimensions, filters, granularity, time_range, pool)
                     .await
             }
             Self::AuthenticationErrorMessage => {
                 AuthenticationErrorMessage
-                    .load_metrics(
-                        merchant_id,
-                        dimensions,
-                        filters,
-                        granularity,
-                        time_range,
-                        pool,
-                    )
+                    .load_metrics(auth, dimensions, filters, granularity, time_range, pool)
                     .await
             }
             Self::AuthenticationFunnel => {
                 AuthenticationFunnel
-                    .load_metrics(
-                        merchant_id,
-                        dimensions,
-                        filters,
-                        granularity,
-                        time_range,
-                        pool,
-                    )
+                    .load_metrics(auth, dimensions, filters, granularity, time_range, pool)
                     .await
             }
             Self::AuthenticationExemptionApprovedCount => {
                 AuthenticationExemptionApprovedCount
-                    .load_metrics(
-                        merchant_id,
-                        dimensions,
-                        filters,
-                        granularity,
-                        time_range,
-                        pool,
-                    )
+                    .load_metrics(auth, dimensions, filters, granularity, time_range, pool)
                     .await
             }
             Self::AuthenticationExemptionRequestedCount => {
                 AuthenticationExemptionRequestedCount
-                    .load_metrics(
-                        merchant_id,
-                        dimensions,
-                        filters,
-                        granularity,
-                        time_range,
-                        pool,
-                    )
+                    .load_metrics(auth, dimensions, filters, granularity, time_range, pool)
                     .await
             }
         }
diff --git a/crates/analytics/src/auth_events/metrics/authentication_attempt_count.rs b/crates/analytics/src/auth_events/metrics/authentication_attempt_count.rs
index 967513af32c..ce7d11e22a3 100644
--- a/crates/analytics/src/auth_events/metrics/authentication_attempt_count.rs
+++ b/crates/analytics/src/auth_events/metrics/authentication_attempt_count.rs
@@ -13,6 +13,7 @@ use super::AuthEventMetricRow;
 use crate::{
     query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window},
     types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+    AuthInfo,
 };
 
 #[derive(Default)]
@@ -30,7 +31,7 @@ where
 {
     async fn load_metrics(
         &self,
-        merchant_id: &common_utils::id_type::MerchantId,
+        auth: &AuthInfo,
         dimensions: &[AuthEventDimensions],
         filters: &AuthEventFilters,
         granularity: Option<Granularity>,
@@ -65,10 +66,6 @@ where
             })
             .switch()?;
 
-        query_builder
-            .add_filter_clause("merchant_id", merchant_id)
-            .switch()?;
-
         query_builder
             .add_filter_in_range_clause(
                 "authentication_status",
@@ -80,6 +77,7 @@ where
             .set_filter_clause(&mut query_builder)
             .attach_printable("Error filtering time range")
             .switch()?;
+        auth.set_filter_clause(&mut query_builder).switch()?;
 
         for dim in dimensions.iter() {
             query_builder
diff --git a/crates/analytics/src/auth_events/metrics/authentication_count.rs b/crates/analytics/src/auth_events/metrics/authentication_count.rs
index 0334f732f23..8ee5026d28e 100644
--- a/crates/analytics/src/auth_events/metrics/authentication_count.rs
+++ b/crates/analytics/src/auth_events/metrics/authentication_count.rs
@@ -12,6 +12,7 @@ use super::AuthEventMetricRow;
 use crate::{
     query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window},
     types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+    AuthInfo,
 };
 
 #[derive(Default)]
@@ -29,7 +30,7 @@ where
 {
     async fn load_metrics(
         &self,
-        merchant_id: &common_utils::id_type::MerchantId,
+        auth: &AuthInfo,
         dimensions: &[AuthEventDimensions],
         filters: &AuthEventFilters,
         granularity: Option<Granularity>,
@@ -62,14 +63,12 @@ where
             })
             .switch()?;
 
-        query_builder
-            .add_filter_clause("merchant_id", merchant_id)
-            .switch()?;
         filters.set_filter_clause(&mut query_builder).switch()?;
         time_range
             .set_filter_clause(&mut query_builder)
             .attach_printable("Error filtering time range")
             .switch()?;
+        auth.set_filter_clause(&mut query_builder).switch()?;
 
         for dim in dimensions.iter() {
             query_builder
diff --git a/crates/analytics/src/auth_events/metrics/authentication_error_message.rs b/crates/analytics/src/auth_events/metrics/authentication_error_message.rs
index ac0adc7bbff..180306d9efa 100644
--- a/crates/analytics/src/auth_events/metrics/authentication_error_message.rs
+++ b/crates/analytics/src/auth_events/metrics/authentication_error_message.rs
@@ -16,6 +16,7 @@ use crate::{
         ToSql, Window,
     },
     types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+    AuthInfo,
 };
 
 #[derive(Default)]
@@ -33,7 +34,7 @@ where
 {
     async fn load_metrics(
         &self,
-        merchant_id: &common_utils::id_type::MerchantId,
+        auth: &AuthInfo,
         dimensions: &[AuthEventDimensions],
         filters: &AuthEventFilters,
         granularity: Option<Granularity>,
@@ -64,10 +65,6 @@ where
             })
             .switch()?;
 
-        query_builder
-            .add_filter_clause("merchant_id", merchant_id)
-            .switch()?;
-
         query_builder
             .add_filter_clause("authentication_status", AuthenticationStatus::Failed)
             .switch()?;
@@ -84,6 +81,7 @@ where
             .set_filter_clause(&mut query_builder)
             .attach_printable("Error filtering time range")
             .switch()?;
+        auth.set_filter_clause(&mut query_builder).switch()?;
 
         for dim in dimensions.iter() {
             query_builder
diff --git a/crates/analytics/src/auth_events/metrics/authentication_exemption_approved_count.rs b/crates/analytics/src/auth_events/metrics/authentication_exemption_approved_count.rs
index 89ec3affe6b..994f66f5f51 100644
--- a/crates/analytics/src/auth_events/metrics/authentication_exemption_approved_count.rs
+++ b/crates/analytics/src/auth_events/metrics/authentication_exemption_approved_count.rs
@@ -12,6 +12,7 @@ use super::AuthEventMetricRow;
 use crate::{
     query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window},
     types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+    AuthInfo,
 };
 
 #[derive(Default)]
@@ -29,7 +30,7 @@ where
 {
     async fn load_metrics(
         &self,
-        merchant_id: &common_utils::id_type::MerchantId,
+        auth: &AuthInfo,
         dimensions: &[AuthEventDimensions],
         filters: &AuthEventFilters,
         granularity: Option<Granularity>,
@@ -62,10 +63,6 @@ where
             })
             .switch()?;
 
-        query_builder
-            .add_filter_clause("merchant_id", merchant_id)
-            .switch()?;
-
         query_builder
             .add_filter_clause(AuthEventDimensions::ExemptionAccepted, true)
             .switch()?;
@@ -74,6 +71,7 @@ where
             .set_filter_clause(&mut query_builder)
             .attach_printable("Error filtering time range")
             .switch()?;
+        auth.set_filter_clause(&mut query_builder).switch()?;
 
         for dim in dimensions.iter() {
             query_builder
diff --git a/crates/analytics/src/auth_events/metrics/authentication_exemption_requested_count.rs b/crates/analytics/src/auth_events/metrics/authentication_exemption_requested_count.rs
index aa4af1a47ff..f763533082b 100644
--- a/crates/analytics/src/auth_events/metrics/authentication_exemption_requested_count.rs
+++ b/crates/analytics/src/auth_events/metrics/authentication_exemption_requested_count.rs
@@ -12,6 +12,7 @@ use super::AuthEventMetricRow;
 use crate::{
     query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window},
     types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+    AuthInfo,
 };
 
 #[derive(Default)]
@@ -29,7 +30,7 @@ where
 {
     async fn load_metrics(
         &self,
-        merchant_id: &common_utils::id_type::MerchantId,
+        auth: &AuthInfo,
         dimensions: &[AuthEventDimensions],
         filters: &AuthEventFilters,
         granularity: Option<Granularity>,
@@ -62,10 +63,6 @@ where
             })
             .switch()?;
 
-        query_builder
-            .add_filter_clause("merchant_id", merchant_id)
-            .switch()?;
-
         query_builder
             .add_filter_clause(AuthEventDimensions::ExemptionRequested, true)
             .switch()?;
@@ -75,6 +72,7 @@ where
             .set_filter_clause(&mut query_builder)
             .attach_printable("Error filtering time range")
             .switch()?;
+        auth.set_filter_clause(&mut query_builder).switch()?;
 
         for dim in dimensions.iter() {
             query_builder
diff --git a/crates/analytics/src/auth_events/metrics/authentication_funnel.rs b/crates/analytics/src/auth_events/metrics/authentication_funnel.rs
index 145a70a542a..e2eb4ce83b8 100644
--- a/crates/analytics/src/auth_events/metrics/authentication_funnel.rs
+++ b/crates/analytics/src/auth_events/metrics/authentication_funnel.rs
@@ -15,6 +15,7 @@ use crate::{
         Window,
     },
     types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+    AuthInfo,
 };
 
 #[derive(Default)]
@@ -32,7 +33,7 @@ where
 {
     async fn load_metrics(
         &self,
-        merchant_id: &common_utils::id_type::MerchantId,
+        auth: &AuthInfo,
         dimensions: &[AuthEventDimensions],
         filters: &AuthEventFilters,
         granularity: Option<Granularity>,
@@ -65,10 +66,6 @@ where
             })
             .switch()?;
 
-        query_builder
-            .add_filter_clause("merchant_id", merchant_id)
-            .switch()?;
-
         query_builder
             .add_custom_filter_clause(
                 AuthEventDimensions::TransactionStatus,
@@ -81,6 +78,7 @@ where
             .set_filter_clause(&mut query_builder)
             .attach_printable("Error filtering time range")
             .switch()?;
+        auth.set_filter_clause(&mut query_builder).switch()?;
 
         for dim in dimensions.iter() {
             query_builder
diff --git a/crates/analytics/src/auth_events/metrics/authentication_success_count.rs b/crates/analytics/src/auth_events/metrics/authentication_success_count.rs
index 9788b6477c1..fbbcdb32086 100644
--- a/crates/analytics/src/auth_events/metrics/authentication_success_count.rs
+++ b/crates/analytics/src/auth_events/metrics/authentication_success_count.rs
@@ -13,6 +13,7 @@ use super::AuthEventMetricRow;
 use crate::{
     query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window},
     types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+    AuthInfo,
 };
 
 #[derive(Default)]
@@ -30,7 +31,7 @@ where
 {
     async fn load_metrics(
         &self,
-        merchant_id: &common_utils::id_type::MerchantId,
+        auth: &AuthInfo,
         dimensions: &[AuthEventDimensions],
         filters: &AuthEventFilters,
         granularity: Option<Granularity>,
@@ -63,10 +64,6 @@ where
             })
             .switch()?;
 
-        query_builder
-            .add_filter_clause("merchant_id", merchant_id)
-            .switch()?;
-
         query_builder
             .add_filter_clause("authentication_status", AuthenticationStatus::Success)
             .switch()?;
@@ -75,6 +72,7 @@ where
             .set_filter_clause(&mut query_builder)
             .attach_printable("Error filtering time range")
             .switch()?;
+        auth.set_filter_clause(&mut query_builder).switch()?;
 
         for dim in dimensions.iter() {
             query_builder
diff --git a/crates/analytics/src/auth_events/metrics/challenge_attempt_count.rs b/crates/analytics/src/auth_events/metrics/challenge_attempt_count.rs
index d3d7dcc7471..29d1bb2230b 100644
--- a/crates/analytics/src/auth_events/metrics/challenge_attempt_count.rs
+++ b/crates/analytics/src/auth_events/metrics/challenge_attempt_count.rs
@@ -13,6 +13,7 @@ use super::AuthEventMetricRow;
 use crate::{
     query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window},
     types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+    AuthInfo,
 };
 
 #[derive(Default)]
@@ -30,7 +31,7 @@ where
 {
     async fn load_metrics(
         &self,
-        merchant_id: &common_utils::id_type::MerchantId,
+        auth: &AuthInfo,
         dimensions: &[AuthEventDimensions],
         filters: &AuthEventFilters,
         granularity: Option<Granularity>,
@@ -63,10 +64,6 @@ where
             })
             .switch()?;
 
-        query_builder
-            .add_filter_clause("merchant_id", merchant_id)
-            .switch()?;
-
         query_builder
             .add_filter_clause(
                 "authentication_type",
@@ -85,6 +82,7 @@ where
             .set_filter_clause(&mut query_builder)
             .attach_printable("Error filtering time range")
             .switch()?;
+        auth.set_filter_clause(&mut query_builder).switch()?;
 
         for dim in dimensions.iter() {
             query_builder
diff --git a/crates/analytics/src/auth_events/metrics/challenge_flow_count.rs b/crates/analytics/src/auth_events/metrics/challenge_flow_count.rs
index 5b951e1fa85..55a9041ac62 100644
--- a/crates/analytics/src/auth_events/metrics/challenge_flow_count.rs
+++ b/crates/analytics/src/auth_events/metrics/challenge_flow_count.rs
@@ -13,6 +13,7 @@ use super::AuthEventMetricRow;
 use crate::{
     query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window},
     types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+    AuthInfo,
 };
 
 #[derive(Default)]
@@ -30,7 +31,7 @@ where
 {
     async fn load_metrics(
         &self,
-        merchant_id: &common_utils::id_type::MerchantId,
+        auth: &AuthInfo,
         dimensions: &[AuthEventDimensions],
         filters: &AuthEventFilters,
         granularity: Option<Granularity>,
@@ -63,10 +64,6 @@ where
             })
             .switch()?;
 
-        query_builder
-            .add_filter_clause("merchant_id", merchant_id)
-            .switch()?;
-
         query_builder
             .add_filter_clause(
                 "authentication_type",
@@ -78,6 +75,7 @@ where
             .set_filter_clause(&mut query_builder)
             .attach_printable("Error filtering time range")
             .switch()?;
+        auth.set_filter_clause(&mut query_builder).switch()?;
 
         for dim in dimensions.iter() {
             query_builder
diff --git a/crates/analytics/src/auth_events/metrics/challenge_success_count.rs b/crates/analytics/src/auth_events/metrics/challenge_success_count.rs
index 2bbd4d81982..307b9ada16c 100644
--- a/crates/analytics/src/auth_events/metrics/challenge_success_count.rs
+++ b/crates/analytics/src/auth_events/metrics/challenge_success_count.rs
@@ -13,6 +13,7 @@ use super::AuthEventMetricRow;
 use crate::{
     query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window},
     types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+    AuthInfo,
 };
 
 #[derive(Default)]
@@ -30,7 +31,7 @@ where
 {
     async fn load_metrics(
         &self,
-        merchant_id: &common_utils::id_type::MerchantId,
+        auth: &AuthInfo,
         dimensions: &[AuthEventDimensions],
         filters: &AuthEventFilters,
         granularity: Option<Granularity>,
@@ -63,10 +64,6 @@ where
             })
             .switch()?;
 
-        query_builder
-            .add_filter_clause("merchant_id", merchant_id)
-            .switch()?;
-
         query_builder
             .add_filter_clause("authentication_status", AuthenticationStatus::Success)
             .switch()?;
@@ -82,6 +79,7 @@ where
             .set_filter_clause(&mut query_builder)
             .attach_printable("Error filtering time range")
             .switch()?;
+        auth.set_filter_clause(&mut query_builder).switch()?;
 
         for dim in dimensions.iter() {
             query_builder
diff --git a/crates/analytics/src/auth_events/metrics/frictionless_flow_count.rs b/crates/analytics/src/auth_events/metrics/frictionless_flow_count.rs
index da8a119d226..fb9ecfa8ef0 100644
--- a/crates/analytics/src/auth_events/metrics/frictionless_flow_count.rs
+++ b/crates/analytics/src/auth_events/metrics/frictionless_flow_count.rs
@@ -13,6 +13,7 @@ use super::AuthEventMetricRow;
 use crate::{
     query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window},
     types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+    AuthInfo,
 };
 
 #[derive(Default)]
@@ -30,7 +31,7 @@ where
 {
     async fn load_metrics(
         &self,
-        merchant_id: &common_utils::id_type::MerchantId,
+        auth: &AuthInfo,
         dimensions: &[AuthEventDimensions],
         filters: &AuthEventFilters,
         granularity: Option<Granularity>,
@@ -63,10 +64,6 @@ where
             })
             .switch()?;
 
-        query_builder
-            .add_filter_clause("merchant_id", merchant_id)
-            .switch()?;
-
         query_builder
             .add_filter_clause(
                 "authentication_type",
@@ -78,6 +75,7 @@ where
             .set_filter_clause(&mut query_builder)
             .attach_printable("Error filtering time range")
             .switch()?;
+        auth.set_filter_clause(&mut query_builder).switch()?;
 
         for dim in dimensions.iter() {
             query_builder
diff --git a/crates/analytics/src/auth_events/metrics/frictionless_success_count.rs b/crates/analytics/src/auth_events/metrics/frictionless_success_count.rs
index b4fb18e48f6..a134b9b0e36 100644
--- a/crates/analytics/src/auth_events/metrics/frictionless_success_count.rs
+++ b/crates/analytics/src/auth_events/metrics/frictionless_success_count.rs
@@ -13,6 +13,7 @@ use super::AuthEventMetricRow;
 use crate::{
     query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window},
     types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
+    AuthInfo,
 };
 
 #[derive(Default)]
@@ -30,7 +31,7 @@ where
 {
     async fn load_metrics(
         &self,
-        merchant_id: &common_utils::id_type::MerchantId,
+        auth: &AuthInfo,
         dimensions: &[AuthEventDimensions],
         filters: &AuthEventFilters,
         granularity: Option<Granularity>,
@@ -63,10 +64,6 @@ where
             })
             .switch()?;
 
-        query_builder
-            .add_filter_clause("merchant_id", merchant_id)
-            .switch()?;
-
         query_builder
             .add_filter_clause(
                 "authentication_type",
@@ -82,6 +79,7 @@ where
             .set_filter_clause(&mut query_builder)
             .attach_printable("Error filtering time range")
             .switch()?;
+        auth.set_filter_clause(&mut query_builder).switch()?;
 
         for dim in dimensions.iter() {
             query_builder
diff --git a/crates/analytics/src/lib.rs b/crates/analytics/src/lib.rs
index 1718c5044ae..e8a01c27caf 100644
--- a/crates/analytics/src/lib.rs
+++ b/crates/analytics/src/lib.rs
@@ -912,7 +912,7 @@ impl AnalyticsProvider {
         &self,
         metric: &AuthEventMetrics,
         dimensions: &[AuthEventDimensions],
-        merchant_id: &common_utils::id_type::MerchantId,
+        auth: &AuthInfo,
         filters: &AuthEventFilters,
         granularity: Option<Granularity>,
         time_range: &TimeRange,
@@ -921,20 +921,13 @@ impl AnalyticsProvider {
             Self::Sqlx(_pool) => Err(report!(MetricsError::NotImplemented)),
             Self::Clickhouse(pool) => {
                 metric
-                    .load_metrics(
-                        merchant_id,
-                        dimensions,
-                        filters,
-                        granularity,
-                        time_range,
-                        pool,
-                    )
+                    .load_metrics(auth, dimensions, filters, granularity, time_range, pool)
                     .await
             }
             Self::CombinedCkh(_sqlx_pool, ckh_pool) | Self::CombinedSqlx(_sqlx_pool, ckh_pool) => {
                 metric
                     .load_metrics(
-                        merchant_id,
+                        auth,
                         dimensions,
                         filters,
                         granularity,
diff --git a/crates/router/src/analytics.rs b/crates/router/src/analytics.rs
index e40bce12339..e41b7e59531 100644
--- a/crates/router/src/analytics.rs
+++ b/crates/router/src/analytics.rs
@@ -116,11 +116,7 @@ pub mod routes {
                         )
                         .service(
                             web::resource("metrics/auth_events")
-                                .route(web::post().to(get_auth_event_metrics)),
-                        )
-                        .service(
-                            web::resource("metrics/auth_events/sankey")
-                                .route(web::post().to(get_auth_event_sankey)),
+                                .route(web::post().to(get_merchant_auth_event_metrics)),
                         )
                         .service(
                             web::resource("filters/auth_events")
@@ -177,6 +173,10 @@ pub mod routes {
                             web::resource("metrics/sankey")
                                 .route(web::post().to(get_merchant_sankey)),
                         )
+                        .service(
+                            web::resource("metrics/auth_events/sankey")
+                                .route(web::post().to(get_merchant_auth_event_sankey)),
+                        )
                         .service(
                             web::scope("/merchant")
                                 .service(
@@ -191,6 +191,10 @@ pub mod routes {
                                     web::resource("metrics/refunds")
                                         .route(web::post().to(get_merchant_refund_metrics)),
                                 )
+                                .service(
+                                    web::resource("metrics/auth_events")
+                                        .route(web::post().to(get_merchant_auth_event_metrics)),
+                                )
                                 .service(
                                     web::resource("filters/payments")
                                         .route(web::post().to(get_merchant_payment_filters)),
@@ -203,6 +207,10 @@ pub mod routes {
                                     web::resource("filters/refunds")
                                         .route(web::post().to(get_merchant_refund_filters)),
                                 )
+                                .service(
+                                    web::resource("filters/auth_events")
+                                        .route(web::post().to(get_merchant_auth_events_filters)),
+                                )
                                 .service(
                                     web::resource("{domain}/info").route(web::get().to(get_info)),
                                 )
@@ -242,6 +250,10 @@ pub mod routes {
                                 .service(
                                     web::resource("metrics/sankey")
                                         .route(web::post().to(get_merchant_sankey)),
+                                )
+                                .service(
+                                    web::resource("metrics/auth_events/sankey")
+                                        .route(web::post().to(get_merchant_auth_event_sankey)),
                                 ),
                         )
                         .service(
@@ -277,10 +289,18 @@ pub mod routes {
                                     web::resource("metrics/disputes")
                                         .route(web::post().to(get_org_dispute_metrics)),
                                 )
+                                .service(
+                                    web::resource("metrics/auth_events")
+                                        .route(web::post().to(get_org_auth_event_metrics)),
+                                )
                                 .service(
                                     web::resource("filters/disputes")
                                         .route(web::post().to(get_org_dispute_filters)),
                                 )
+                                .service(
+                                    web::resource("filters/auth_events")
+                                        .route(web::post().to(get_org_auth_events_filters)),
+                                )
                                 .service(
                                     web::resource("report/dispute")
                                         .route(web::post().to(generate_org_dispute_report)),
@@ -300,6 +320,10 @@ pub mod routes {
                                 .service(
                                     web::resource("metrics/sankey")
                                         .route(web::post().to(get_org_sankey)),
+                                )
+                                .service(
+                                    web::resource("metrics/auth_events/sankey")
+                                        .route(web::post().to(get_org_auth_event_sankey)),
                                 ),
                         )
                         .service(
@@ -335,10 +359,18 @@ pub mod routes {
                                     web::resource("metrics/disputes")
                                         .route(web::post().to(get_profile_dispute_metrics)),
                                 )
+                                .service(
+                                    web::resource("metrics/auth_events")
+                                        .route(web::post().to(get_profile_auth_event_metrics)),
+                                )
                                 .service(
                                     web::resource("filters/disputes")
                                         .route(web::post().to(get_profile_dispute_filters)),
                                 )
+                                .service(
+                                    web::resource("filters/auth_events")
+                                        .route(web::post().to(get_profile_auth_events_filters)),
+                                )
                                 .service(
                                     web::resource("connector_event_logs")
                                         .route(web::get().to(get_profile_connector_events)),
@@ -379,6 +411,10 @@ pub mod routes {
                                 .service(
                                     web::resource("metrics/sankey")
                                         .route(web::post().to(get_profile_sankey)),
+                                )
+                                .service(
+                                    web::resource("metrics/auth_events/sankey")
+                                        .route(web::post().to(get_profile_auth_event_sankey)),
                                 ),
                         ),
                 )
@@ -1043,7 +1079,7 @@ pub mod routes {
     /// # Panics
     ///
     /// Panics if `json_payload` array does not contain one `GetAuthEventMetricRequest` element.
-    pub async fn get_auth_event_metrics(
+    pub async fn get_merchant_auth_event_metrics(
         state: web::Data<AppState>,
         req: actix_web::HttpRequest,
         json_payload: web::Json<[GetAuthEventMetricRequest; 1]>,
@@ -1062,13 +1098,16 @@ pub mod routes {
             &req,
             payload,
             |state, auth: AuthenticationData, req, _| async move {
-                analytics::auth_events::get_metrics(
-                    &state.pool,
-                    auth.merchant_account.get_id(),
-                    req,
-                )
-                .await
-                .map(ApplicationResponse::Json)
+                let org_id = auth.merchant_account.get_org_id();
+                let merchant_id = auth.merchant_account.get_id();
+                let auth: AuthInfo = AuthInfo::MerchantLevel {
+                    org_id: org_id.clone(),
+                    merchant_ids: vec![merchant_id.clone()],
+                };
+
+                analytics::auth_events::get_metrics(&state.pool, &auth, req)
+                    .await
+                    .map(ApplicationResponse::Json)
             },
             &auth::JWTAuth {
                 permission: Permission::MerchantAnalyticsRead,
@@ -1078,6 +1117,98 @@ pub mod routes {
         .await
     }
 
+    #[cfg(feature = "v1")]
+    /// # Panics
+    ///
+    /// Panics if `json_payload` array does not contain one `GetAuthEventMetricRequest` element.
+    pub async fn get_profile_auth_event_metrics(
+        state: web::Data<AppState>,
+        req: actix_web::HttpRequest,
+        json_payload: web::Json<[GetAuthEventMetricRequest; 1]>,
+    ) -> impl Responder {
+        // safety: This shouldn't panic owing to the data type
+        #[allow(clippy::expect_used)]
+        let payload = json_payload
+            .into_inner()
+            .to_vec()
+            .pop()
+            .expect("Couldn't get GetAuthEventMetricRequest");
+        let flow = AnalyticsFlow::GetAuthMetrics;
+        Box::pin(api::server_wrap(
+            flow,
+            state,
+            &req,
+            payload,
+            |state, auth: AuthenticationData, req, _| async move {
+                let org_id = auth.merchant_account.get_org_id();
+                let merchant_id = auth.merchant_account.get_id();
+                let profile_id = auth
+                    .profile_id
+                    .ok_or(report!(UserErrors::JwtProfileIdMissing))
+                    .change_context(AnalyticsError::AccessForbiddenError)?;
+                let auth: AuthInfo = AuthInfo::ProfileLevel {
+                    org_id: org_id.clone(),
+                    merchant_id: merchant_id.clone(),
+                    profile_ids: vec![profile_id.clone()],
+                };
+                analytics::auth_events::get_metrics(&state.pool, &auth, req)
+                    .await
+                    .map(ApplicationResponse::Json)
+            },
+            &auth::JWTAuth {
+                permission: Permission::ProfileAnalyticsRead,
+            },
+            api_locking::LockAction::NotApplicable,
+        ))
+        .await
+    }
+
+    #[cfg(feature = "v1")]
+    /// # Panics
+    ///
+    /// Panics if `json_payload` array does not contain one `GetAuthEventMetricRequest` element.
+    pub async fn get_org_auth_event_metrics(
+        state: web::Data<AppState>,
+        req: actix_web::HttpRequest,
+        json_payload: web::Json<[GetAuthEventMetricRequest; 1]>,
+    ) -> impl Responder {
+        // safety: This shouldn't panic owing to the data type
+        #[allow(clippy::expect_used)]
+        let payload = json_payload
+            .into_inner()
+            .to_vec()
+            .pop()
+            .expect("Couldn't get GetAuthEventMetricRequest");
+        let flow = AnalyticsFlow::GetAuthMetrics;
+        Box::pin(api::server_wrap(
+            flow,
+            state,
+            &req,
+            payload,
+            |state, auth: AuthenticationData, req, _| async move {
+                let org_id = auth.merchant_account.get_org_id();
+                let auth: AuthInfo = AuthInfo::OrgLevel {
+                    org_id: org_id.clone(),
+                };
+                analytics::auth_events::get_metrics(&state.pool, &auth, req)
+                    .await
+                    .map(ApplicationResponse::Json)
+            },
+            auth::auth_type(
+                &auth::PlatformOrgAdminAuth {
+                    is_admin_auth_allowed: false,
+                    organization_id: None,
+                },
+                &auth::JWTAuth {
+                    permission: Permission::OrganizationAnalyticsRead,
+                },
+                req.headers(),
+            ),
+            api_locking::LockAction::NotApplicable,
+        ))
+        .await
+    }
+
     pub async fn get_merchant_payment_filters(
         state: web::Data<AppState>,
         req: actix_web::HttpRequest,
@@ -1120,13 +1251,16 @@ pub mod routes {
             &req,
             json_payload.into_inner(),
             |state, auth: AuthenticationData, req, _| async move {
-                analytics::auth_events::get_filters(
-                    &state.pool,
-                    req,
-                    auth.merchant_account.get_id(),
-                )
-                .await
-                .map(ApplicationResponse::Json)
+                let org_id = auth.merchant_account.get_org_id();
+                let merchant_id = auth.merchant_account.get_id();
+
+                let auth: AuthInfo = AuthInfo::MerchantLevel {
+                    org_id: org_id.clone(),
+                    merchant_ids: vec![merchant_id.clone()],
+                };
+                analytics::auth_events::get_filters(&state.pool, req, &auth)
+                    .await
+                    .map(ApplicationResponse::Json)
             },
             &auth::JWTAuth {
                 permission: Permission::MerchantAnalyticsRead,
@@ -1136,6 +1270,80 @@ pub mod routes {
         .await
     }
 
+    #[cfg(feature = "v1")]
+    pub async fn get_org_auth_events_filters(
+        state: web::Data<AppState>,
+        req: actix_web::HttpRequest,
+        json_payload: web::Json<GetAuthEventFilterRequest>,
+    ) -> impl Responder {
+        let flow = AnalyticsFlow::GetAuthEventFilters;
+        Box::pin(api::server_wrap(
+            flow,
+            state,
+            &req,
+            json_payload.into_inner(),
+            |state, auth: AuthenticationData, req, _| async move {
+                let org_id = auth.merchant_account.get_org_id();
+                let auth: AuthInfo = AuthInfo::OrgLevel {
+                    org_id: org_id.clone(),
+                };
+
+                analytics::auth_events::get_filters(&state.pool, req, &auth)
+                    .await
+                    .map(ApplicationResponse::Json)
+            },
+            auth::auth_type(
+                &auth::PlatformOrgAdminAuth {
+                    is_admin_auth_allowed: false,
+                    organization_id: None,
+                },
+                &auth::JWTAuth {
+                    permission: Permission::OrganizationAnalyticsRead,
+                },
+                req.headers(),
+            ),
+            api_locking::LockAction::NotApplicable,
+        ))
+        .await
+    }
+
+    #[cfg(feature = "v1")]
+    pub async fn get_profile_auth_events_filters(
+        state: web::Data<AppState>,
+        req: actix_web::HttpRequest,
+        json_payload: web::Json<GetAuthEventFilterRequest>,
+    ) -> impl Responder {
+        let flow = AnalyticsFlow::GetAuthEventFilters;
+        Box::pin(api::server_wrap(
+            flow,
+            state,
+            &req,
+            json_payload.into_inner(),
+            |state, auth: AuthenticationData, req, _| async move {
+                let org_id = auth.merchant_account.get_org_id();
+                let merchant_id = auth.merchant_account.get_id();
+                let profile_id = auth
+                    .profile_id
+                    .ok_or(report!(UserErrors::JwtProfileIdMissing))
+                    .change_context(AnalyticsError::AccessForbiddenError)?;
+
+                let auth: AuthInfo = AuthInfo::ProfileLevel {
+                    org_id: org_id.clone(),
+                    merchant_id: merchant_id.clone(),
+                    profile_ids: vec![profile_id.clone()],
+                };
+                analytics::auth_events::get_filters(&state.pool, req, &auth)
+                    .await
+                    .map(ApplicationResponse::Json)
+            },
+            &auth::JWTAuth {
+                permission: Permission::ProfileAnalyticsRead,
+            },
+            api_locking::LockAction::NotApplicable,
+        ))
+        .await
+    }
+
     #[cfg(feature = "v1")]
     pub async fn get_org_payment_filters(
         state: web::Data<AppState>,
@@ -2809,7 +3017,7 @@ pub mod routes {
         .await
     }
 
-    pub async fn get_auth_event_sankey(
+    pub async fn get_merchant_auth_event_sankey(
         state: web::Data<AppState>,
         req: actix_web::HttpRequest,
         json_payload: web::Json<TimeRange>,
@@ -2840,6 +3048,80 @@ pub mod routes {
         .await
     }
 
+    #[cfg(feature = "v1")]
+    pub async fn get_org_auth_event_sankey(
+        state: web::Data<AppState>,
+        req: actix_web::HttpRequest,
+        json_payload: web::Json<TimeRange>,
+    ) -> impl Responder {
+        let flow = AnalyticsFlow::GetSankey;
+        let payload = json_payload.into_inner();
+        Box::pin(api::server_wrap(
+            flow,
+            state,
+            &req,
+            payload,
+            |state, auth: AuthenticationData, req, _| async move {
+                let org_id = auth.merchant_account.get_org_id();
+                let auth: AuthInfo = AuthInfo::OrgLevel {
+                    org_id: org_id.clone(),
+                };
+                analytics::auth_events::get_sankey(&state.pool, &auth, req)
+                    .await
+                    .map(ApplicationResponse::Json)
+            },
+            auth::auth_type(
+                &auth::PlatformOrgAdminAuth {
+                    is_admin_auth_allowed: false,
+                    organization_id: None,
+                },
+                &auth::JWTAuth {
+                    permission: Permission::OrganizationAnalyticsRead,
+                },
+                req.headers(),
+            ),
+            api_locking::LockAction::NotApplicable,
+        ))
+        .await
+    }
+
+    #[cfg(feature = "v1")]
+    pub async fn get_profile_auth_event_sankey(
+        state: web::Data<AppState>,
+        req: actix_web::HttpRequest,
+        json_payload: web::Json<TimeRange>,
+    ) -> impl Responder {
+        let flow = AnalyticsFlow::GetSankey;
+        let payload = json_payload.into_inner();
+        Box::pin(api::server_wrap(
+            flow,
+            state,
+            &req,
+            payload,
+            |state, auth: AuthenticationData, req, _| async move {
+                let org_id = auth.merchant_account.get_org_id();
+                let merchant_id = auth.merchant_account.get_id();
+                let profile_id = auth
+                    .profile_id
+                    .ok_or(report!(UserErrors::JwtProfileIdMissing))
+                    .change_context(AnalyticsError::AccessForbiddenError)?;
+                let auth: AuthInfo = AuthInfo::ProfileLevel {
+                    org_id: org_id.clone(),
+                    merchant_id: merchant_id.clone(),
+                    profile_ids: vec![profile_id.clone()],
+                };
+                analytics::auth_events::get_sankey(&state.pool, &auth, req)
+                    .await
+                    .map(ApplicationResponse::Json)
+            },
+            &auth::JWTAuth {
+                permission: Permission::ProfileAnalyticsRead,
+            },
+            api_locking::LockAction::NotApplicable,
+        ))
+        .await
+    }
+
     #[cfg(feature = "v1")]
     pub async fn get_org_sankey(
         state: web::Data<AppState>,

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

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

## Description
Exposed endpoints for auth analytics under profile, merchant and org access levels.


### Additional Changes

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



Here are the cURLs for the endpoint modified

```
curl 'http://localhost:8080/analytics/v1/merchant/metrics/auth_events' \
  -H 'Accept: */*' \
  -H 'Accept-Language: en-US,en;q=0.5' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/json' \
  -b 'login_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiY2IzYjdjNGQtYjQ0Mi00ZDk0LWJkMjQtNjk5NjI4ZjQ1MzBkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzQ4Mjg1ODc1Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTc1MDQxODczNiwib3JnX2lkIjoib3JnX1VBQnlpWmZ4TW44dFpuSnZUemlvIiwicHJvZmlsZV9pZCI6InByb19Pcjh5cmlGYzBPY1pJZHFBOVFVVyIsInRlbmFudF9pZCI6InB1YmxpYyJ9.ihLlIahjaxw1Tq8OYv0601E93UpT8TKgYoskRK6Os0M' \
  -H 'Origin: http://localhost:9000' \
  -H 'Pragma: no-cache' \
  -H 'Referer: http://localhost:9000/dashboard/analytics-authentication' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: same-origin' \
  -H 'Sec-GPC: 1' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36' \
  -H 'X-Merchant-Id: merchant_1748285875' \
  -H 'X-Profile-Id: pro_Or8yriFc0OcZIdqA9QUW' \
  -H 'api-key: hyperswitch' \
  -H 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiY2IzYjdjNGQtYjQ0Mi00ZDk0LWJkMjQtNjk5NjI4ZjQ1MzBkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzQ4Mjg1ODc1Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTc1MDQxODczNiwib3JnX2lkIjoib3JnX1VBQnlpWmZ4TW44dFpuSnZUemlvIiwicHJvZmlsZV9pZCI6InByb19Pcjh5cmlGYzBPY1pJZHFBOVFVVyIsInRlbmFudF9pZCI6InB1YmxpYyJ9.ihLlIahjaxw1Tq8OYv0601E93UpT8TKgYoskRK6Os0M' \
  -H 'sec-ch-ua: "Brave";v="137", "Chromium";v="137", "Not/A)Brand";v="24"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "macOS"' \
  --data-raw '[{"timeRange":{"startTime":"2025-01-10T18:30:00Z","endTime":"2025-06-18T11:25:39Z"},"mode":"ORDER","source":"BATCH","metrics":["authentication_count","authentication_attempt_count","authentication_success_count","challenge_flow_count","frictionless_flow_count","frictionless_success_count","challenge_attempt_count","challenge_success_count"],"delta":true}]'
```

```
curl 'http://localhost:8080/analytics/v1/org/metrics/auth_events' \
  -H 'Accept: */*' \
  -H 'Accept-Language: en-US,en;q=0.5' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/json' \
  -b 'login_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiY2IzYjdjNGQtYjQ0Mi00ZDk0LWJkMjQtNjk5NjI4ZjQ1MzBkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzQ4Mjg1ODc1Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTc1MDQxODczNiwib3JnX2lkIjoib3JnX1VBQnlpWmZ4TW44dFpuSnZUemlvIiwicHJvZmlsZV9pZCI6InByb19Pcjh5cmlGYzBPY1pJZHFBOVFVVyIsInRlbmFudF9pZCI6InB1YmxpYyJ9.ihLlIahjaxw1Tq8OYv0601E93UpT8TKgYoskRK6Os0M' \
  -H 'Origin: http://localhost:9000' \
  -H 'Pragma: no-cache' \
  -H 'Referer: http://localhost:9000/dashboard/analytics-authentication' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: same-origin' \
  -H 'Sec-GPC: 1' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36' \
  -H 'X-Merchant-Id: merchant_1748285875' \
  -H 'X-Profile-Id: pro_Or8yriFc0OcZIdqA9QUW' \
  -H 'api-key: hyperswitch' \
  -H 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiY2IzYjdjNGQtYjQ0Mi00ZDk0LWJkMjQtNjk5NjI4ZjQ1MzBkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzQ4Mjg1ODc1Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTc1MDQxODczNiwib3JnX2lkIjoib3JnX1VBQnlpWmZ4TW44dFpuSnZUemlvIiwicHJvZmlsZV9pZCI6InByb19Pcjh5cmlGYzBPY1pJZHFBOVFVVyIsInRlbmFudF9pZCI6InB1YmxpYyJ9.ihLlIahjaxw1Tq8OYv0601E93UpT8TKgYoskRK6Os0M' \
  -H 'sec-ch-ua: "Brave";v="137", "Chromium";v="137", "Not/A)Brand";v="24"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "macOS"' \
  --data-raw '[{"timeRange":{"startTime":"2025-01-10T18:30:00Z","endTime":"2025-06-18T11:25:39Z"},"mode":"ORDER","source":"BATCH","metrics":["authentication_count","authentication_attempt_count","authentication_success_count","challenge_flow_count","frictionless_flow_count","frictionless_success_count","challenge_attempt_count","challenge_success_count"],"delta":true}]'
```


```
curl 'http://localhost:8080/analytics/v1/profile/metrics/auth_events' \
  -H 'Accept: */*' \
  -H 'Accept-Language: en-US,en;q=0.5' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/json' \
  -b 'login_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiY2IzYjdjNGQtYjQ0Mi00ZDk0LWJkMjQtNjk5NjI4ZjQ1MzBkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzQ4Mjg1ODc1Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTc1MDQxODczNiwib3JnX2lkIjoib3JnX1VBQnlpWmZ4TW44dFpuSnZUemlvIiwicHJvZmlsZV9pZCI6InByb19Pcjh5cmlGYzBPY1pJZHFBOVFVVyIsInRlbmFudF9pZCI6InB1YmxpYyJ9.ihLlIahjaxw1Tq8OYv0601E93UpT8TKgYoskRK6Os0M' \
  -H 'Origin: http://localhost:9000' \
  -H 'Pragma: no-cache' \
  -H 'Referer: http://localhost:9000/dashboard/analytics-authentication' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: same-origin' \
  -H 'Sec-GPC: 1' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36' \
  -H 'X-Merchant-Id: merchant_1748285875' \
  -H 'X-Profile-Id: pro_Or8yriFc0OcZIdqA9QUW' \
  -H 'api-key: hyperswitch' \
  -H 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiY2IzYjdjNGQtYjQ0Mi00ZDk0LWJkMjQtNjk5NjI4ZjQ1MzBkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzQ4Mjg1ODc1Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTc1MDQxODczNiwib3JnX2lkIjoib3JnX1VBQnlpWmZ4TW44dFpuSnZUemlvIiwicHJvZmlsZV9pZCI6InByb19Pcjh5cmlGYzBPY1pJZHFBOVFVVyIsInRlbmFudF9pZCI6InB1YmxpYyJ9.ihLlIahjaxw1Tq8OYv0601E93UpT8TKgYoskRK6Os0M' \
  -H 'sec-ch-ua: "Brave";v="137", "Chromium";v="137", "Not/A)Brand";v="24"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "macOS"' \
  --data-raw '[{"timeRange":{"startTime":"2025-01-10T18:30:00Z","endTime":"2025-06-18T11:25:39Z"},"mode":"ORDER","source":"BATCH","metrics":["authentication_count","authentication_attempt_count","authentication_success_count","challenge_flow_count","frictionless_flow_count","frictionless_success_count","challenge_attempt_count","challenge_success_count"],"delta":true}]'
```



```
curl 'http://localhost:8080/analytics/v1/org/metrics/auth_events/sankey' \
  -H 'Accept: */*' \
  -H 'Accept-Language: en-US,en;q=0.6' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/json' \
  -b 'login_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiY2IzYjdjNGQtYjQ0Mi00ZDk0LWJkMjQtNjk5NjI4ZjQ1MzBkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzQ4Mjg1ODc1Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTc0OTg5OTA3MCwib3JnX2lkIjoib3JnX1VBQnlpWmZ4TW44dFpuSnZUemlvIiwicHJvZmlsZV9pZCI6InByb19Pcjh5cmlGYzBPY1pJZHFBOVFVVyIsInRlbmFudF9pZCI6InB1YmxpYyJ9.mSG74WirYlo_Bogh2P8mN-EujL3nw9xlRGlOZ5t7Aiw' \
  -H 'Origin: http://localhost:9000' \
  -H 'Pragma: no-cache' \
  -H 'Referer: http://localhost:9000/dashboard/analytics-authentication' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: same-origin' \
  -H 'Sec-GPC: 1' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36' \
  -H 'X-Merchant-Id: merchant_1748285875' \
  -H 'X-Profile-Id: pro_Or8yriFc0OcZIdqA9QUW' \
  -H 'api-key: hyperswitch' \
  -H 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiY2IzYjdjNGQtYjQ0Mi00ZDk0LWJkMjQtNjk5NjI4ZjQ1MzBkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzQ4Mjg1ODc1Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTc0OTg5OTA3MCwib3JnX2lkIjoib3JnX1VBQnlpWmZ4TW44dFpuSnZUemlvIiwicHJvZmlsZV9pZCI6InByb19Pcjh5cmlGYzBPY1pJZHFBOVFVVyIsInRlbmFudF9pZCI6InB1YmxpYyJ9.mSG74WirYlo_Bogh2P8mN-EujL3nw9xlRGlOZ5t7Aiw' \
  -H 'sec-ch-ua: "Brave";v="137", "Chromium";v="137", "Not/A)Brand";v="24"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "macOS"' \
  --data-raw '{"startTime": "2025-01-22T18:30:00Z","endTime": "2025-05-29T12:59:33Z"}'
```

```
curl 'http://localhost:8080/analytics/v1/merchant/metrics/auth_events/sankey' \
  -H 'Accept: */*' \
  -H 'Accept-Language: en-US,en;q=0.6' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/json' \
  -b 'login_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiY2IzYjdjNGQtYjQ0Mi00ZDk0LWJkMjQtNjk5NjI4ZjQ1MzBkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzQ4Mjg1ODc1Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTc0OTg5OTA3MCwib3JnX2lkIjoib3JnX1VBQnlpWmZ4TW44dFpuSnZUemlvIiwicHJvZmlsZV9pZCI6InByb19Pcjh5cmlGYzBPY1pJZHFBOVFVVyIsInRlbmFudF9pZCI6InB1YmxpYyJ9.mSG74WirYlo_Bogh2P8mN-EujL3nw9xlRGlOZ5t7Aiw' \
  -H 'Origin: http://localhost:9000' \
  -H 'Pragma: no-cache' \
  -H 'Referer: http://localhost:9000/dashboard/analytics-authentication' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: same-origin' \
  -H 'Sec-GPC: 1' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36' \
  -H 'X-Merchant-Id: merchant_1748285875' \
  -H 'X-Profile-Id: pro_Or8yriFc0OcZIdqA9QUW' \
  -H 'api-key: hyperswitch' \
  -H 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiY2IzYjdjNGQtYjQ0Mi00ZDk0LWJkMjQtNjk5NjI4ZjQ1MzBkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzQ4Mjg1ODc1Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTc0OTg5OTA3MCwib3JnX2lkIjoib3JnX1VBQnlpWmZ4TW44dFpuSnZUemlvIiwicHJvZmlsZV9pZCI6InByb19Pcjh5cmlGYzBPY1pJZHFBOVFVVyIsInRlbmFudF9pZCI6InB1YmxpYyJ9.mSG74WirYlo_Bogh2P8mN-EujL3nw9xlRGlOZ5t7Aiw' \
  -H 'sec-ch-ua: "Brave";v="137", "Chromium";v="137", "Not/A)Brand";v="24"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "macOS"' \
  --data-raw '{"startTime": "2025-01-22T18:30:00Z","endTime": "2025-05-29T12:59:33Z"}'
```

```
curl 'http://localhost:8080/analytics/v1/profile/metrics/auth_events/sankey' \
  -H 'Accept: */*' \
  -H 'Accept-Language: en-US,en;q=0.6' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/json' \
  -b 'login_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiY2IzYjdjNGQtYjQ0Mi00ZDk0LWJkMjQtNjk5NjI4ZjQ1MzBkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzQ4Mjg1ODc1Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTc0OTg5OTA3MCwib3JnX2lkIjoib3JnX1VBQnlpWmZ4TW44dFpuSnZUemlvIiwicHJvZmlsZV9pZCI6InByb19Pcjh5cmlGYzBPY1pJZHFBOVFVVyIsInRlbmFudF9pZCI6InB1YmxpYyJ9.mSG74WirYlo_Bogh2P8mN-EujL3nw9xlRGlOZ5t7Aiw' \
  -H 'Origin: http://localhost:9000' \
  -H 'Pragma: no-cache' \
  -H 'Referer: http://localhost:9000/dashboard/analytics-authentication' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: same-origin' \
  -H 'Sec-GPC: 1' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36' \
  -H 'X-Merchant-Id: merchant_1748285875' \
  -H 'X-Profile-Id: pro_Or8yriFc0OcZIdqA9QUW' \
  -H 'api-key: hyperswitch' \
  -H 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiY2IzYjdjNGQtYjQ0Mi00ZDk0LWJkMjQtNjk5NjI4ZjQ1MzBkIiwibWVyY2hhbnRfaWQiOiJtZXJjaGFudF8xNzQ4Mjg1ODc1Iiwicm9sZV9pZCI6Im9yZ19hZG1pbiIsImV4cCI6MTc0OTg5OTA3MCwib3JnX2lkIjoib3JnX1VBQnlpWmZ4TW44dFpuSnZUemlvIiwicHJvZmlsZV9pZCI6InByb19Pcjh5cmlGYzBPY1pJZHFBOVFVVyIsInRlbmFudF9pZCI6InB1YmxpYyJ9.mSG74WirYlo_Bogh2P8mN-EujL3nw9xlRGlOZ5t7Aiw' \
  -H 'sec-ch-ua: "Brave";v="137", "Chromium";v="137", "Not/A)Brand";v="24"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "macOS"' \
  --data-raw '{"startTime": "2025-01-22T18:30:00Z","endTime": "2025-05-29T12:59:33Z"}'
```


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

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


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


## Checklist
<!-- Put an `x` in the boxes that apply -->

- [ ] 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
