diff --git a/gov-portal-db/src/mongo_client.rs b/gov-portal-db/src/mongo_client.rs
index 5e96634..cea5881 100644
--- a/gov-portal-db/src/mongo_client.rs
+++ b/gov-portal-db/src/mongo_client.rs
@@ -1,7 +1,10 @@
 use async_trait::async_trait;
 use mongodb::{
     bson::Document,
-    options::{ClientOptions, FindOptions, InsertOneOptions, UpdateModifications, UpdateOptions},
+    options::{
+        ClientOptions, CountOptions, FindOptions, InsertOneOptions, UpdateModifications,
+        UpdateOptions,
+    },
     results::{InsertOneResult, UpdateResult},
     Client, Collection, Cursor, Database,
 };
@@ -46,6 +49,17 @@ impl MongoCollection {
             .with_options(find_options)
             .await
     }
+    /// Query count request from collection by filter
+    pub async fn count(
+        &self,
+        filter: impl Into<Document>,
+        count_options: impl Into<Option<CountOptions>>,
+    ) -> Result<u64, mongodb::error::Error> {
+        self.inner
+            .count_documents(filter.into())
+            .with_options(count_options)
+            .await
+    }
 
     /// Insert single document to collection
     #[allow(unused)]
diff --git a/gov-portal-db/src/rewards_manager/mod.rs b/gov-portal-db/src/rewards_manager/mod.rs
index 811ba2e..2e95d24 100644
--- a/gov-portal-db/src/rewards_manager/mod.rs
+++ b/gov-portal-db/src/rewards_manager/mod.rs
@@ -1,10 +1,10 @@
 pub mod client;
 pub mod error;
 
-use bson::doc;
+use bson::{doc, Document};
 use ethereum_types::Address;
 use futures_util::TryStreamExt;
-use mongodb::options::{FindOptions, UpdateOptions};
+use mongodb::options::{CountOptions, FindOptions, UpdateOptions};
 use serde::Deserialize;
 
 use shared::common::{
@@ -104,7 +104,43 @@ impl RewardsManager {
         }
     }
 
-    /// Searches for multiple user profiles within MongoDB by provided EVM-like address [`Address`] list and returns [`Vec<UserProfile>`]
+    /// Counts all rewards allocated by requestor within MongoDB by provided wallet EVM-like address [`Address`]
+    pub async fn count_rewards(
+        &self,
+        requestor: &Address,
+        from: Option<u64>,
+        to: Option<u64>,
+        community: Option<&str>,
+    ) -> Result<u64, error::Error> {
+        if !self
+            .config
+            .moderators
+            .iter()
+            .any(|wallet| wallet == requestor)
+        {
+            return Err(error::Error::Unauthorized);
+        }
+
+        let expr = self.build_rewards_filter_expr(from, to, community)?;
+        let filter = doc! {
+            "$expr": bson::to_bson(&expr)?,
+        };
+
+        let res = tokio::time::timeout(
+            self.db_client.req_timeout,
+            self.db_client
+                .collection()
+                .count(filter, CountOptions::default()),
+        )
+        .await?
+        .map_err(error::Error::from);
+
+        tracing::debug!("Count total rewards result: {res:?}");
+
+        res
+    }
+
+    /// Searches all rewards allocated by requestor within MongoDB by provided wallet EVM-like address [`Address`] and returns [`Vec<Rewards>`]
     pub async fn get_rewards(
         &self,
         requestor: &Address,
@@ -112,7 +148,7 @@ impl RewardsManager {
         limit: Option<u64>,
         from: Option<u64>,
         to: Option<u64>,
-        community: Option<String>,
+        community: Option<&str>,
     ) -> Result<Vec<Rewards>, error::Error> {
         let start = start.unwrap_or_default();
         let limit = limit
@@ -128,75 +164,9 @@ impl RewardsManager {
             return Err(error::Error::Unauthorized);
         }
 
-        let mut in_and_cond_doc = doc! {
-            "$and": []
-        };
-
-        let mut cond = doc! {};
-
-        if let Some(community) = community {
-            cond.insert("$eq", bson::to_bson(&["$$wallet.v.community", &community])?);
-
-            in_and_cond_doc.get_array_mut("$and")?.push(
-                doc! {
-                    "$gt": [{ "$size": "$$entries" }, 0]
-                }
-                .into(),
-            );
-        }
-
-        if from.is_some() || to.is_some() {
-            if let Some(from) = from {
-                in_and_cond_doc.get_array_mut("$and")?.push(
-                    doc! {
-                        "$gte": ["$$timestamp", bson::to_bson(&from)?]
-                    }
-                    .into(),
-                );
-            }
-
-            if let Some(to) = to {
-                in_and_cond_doc.get_array_mut("$and")?.push(
-                    doc! {
-                        "$lte": ["$$timestamp", bson::to_bson(&to)?]
-                    }
-                    .into(),
-                );
-            }
-        }
-
+        let expr = self.build_rewards_filter_expr(from, to, community)?;
         let filter = doc! {
-            "$expr":{
-                "$let":{
-                    "vars":{
-                        "entries":{
-                            "$filter":{
-                                "input":{
-                                    "$objectToArray":"$wallets"
-                                },
-                                "as":"wallet",
-                                "cond": cond
-                            }
-                        }
-                    },
-                    "in":{
-                        "$let": {
-                            "vars": {
-                                "timestamp":{
-                                    "$arrayElemAt":[{
-                                        "$map":{
-                                            "input":"$$entries",
-                                            "as":"entry",
-                                            "in":"$$entry.v.timestamp"
-                                        }
-                                    },0]
-                                }
-                            },
-                            "in": in_and_cond_doc
-                        }
-                    }
-                }
-            }
+            "$expr": expr
         };
 
         let find_options = FindOptions::builder()
@@ -250,7 +220,48 @@ impl RewardsManager {
         })
     }
 
-    /// Searches for multiple user profiles within MongoDB by provided EVM-like address [`Address`] list and returns [`Vec<UserProfile>`]
+    /// Counts rewards allocated for user within MongoDB by provided wallet EVM-like address [`Address`]
+    pub async fn count_rewards_by_wallet(
+        &self,
+        requestor: &Address,
+        wallet: &Address,
+        from: Option<u64>,
+        to: Option<u64>,
+        community: Option<&str>,
+    ) -> Result<u64, error::Error> {
+        let requires_moderator_access_rights = wallet != requestor;
+
+        if requires_moderator_access_rights
+            && !self
+                .config
+                .moderators
+                .iter()
+                .any(|wallet| wallet == requestor)
+        {
+            return Err(error::Error::Unauthorized);
+        }
+
+        let expr = self.build_rewards_filter_expr(from, to, community)?;
+        let filter = doc! {
+            format!("wallets.0x{}", hex::encode(wallet)): { "$exists": true },
+            "$expr": bson::to_bson(&expr)?,
+        };
+
+        let res = tokio::time::timeout(
+            self.db_client.req_timeout,
+            self.db_client
+                .collection()
+                .count(filter, CountOptions::default()),
+        )
+        .await?
+        .map_err(error::Error::from);
+
+        tracing::debug!("Count total rewards by wallet ({wallet:?}) result: {res:?}");
+
+        res
+    }
+
+    /// Searches rewards allocated for user within MongoDB by provided wallet EVM-like address [`Address`] and returns [`Vec<Rewards>`]
     #[allow(clippy::too_many_arguments)]
     pub async fn get_rewards_by_wallet(
         &self,
@@ -260,7 +271,7 @@ impl RewardsManager {
         limit: Option<u64>,
         from: Option<u64>,
         to: Option<u64>,
-        community: Option<String>,
+        community: Option<&str>,
     ) -> Result<Vec<Rewards>, error::Error> {
         let start = start.unwrap_or_default();
         let limit = limit
@@ -279,76 +290,10 @@ impl RewardsManager {
             return Err(error::Error::Unauthorized);
         }
 
-        let mut in_and_cond_doc = doc! {
-            "$and": []
-        };
-
-        let mut cond = doc! {};
-
-        if let Some(community) = community {
-            cond.insert("$eq", bson::to_bson(&["$$wallet.v.community", &community])?);
-
-            in_and_cond_doc.get_array_mut("$and")?.push(
-                doc! {
-                    "$gt": [{ "$size": "$$entries" }, 0]
-                }
-                .into(),
-            );
-        }
-
-        if from.is_some() || to.is_some() {
-            if let Some(from) = from {
-                in_and_cond_doc.get_array_mut("$and")?.push(
-                    doc! {
-                        "$gte": ["$$timestamp", bson::to_bson(&from)?]
-                    }
-                    .into(),
-                );
-            }
-
-            if let Some(to) = to {
-                in_and_cond_doc.get_array_mut("$and")?.push(
-                    doc! {
-                        "$lt": ["$$timestamp", bson::to_bson(&to)?]
-                    }
-                    .into(),
-                );
-            }
-        }
-
+        let expr = self.build_rewards_filter_expr(from, to, community)?;
         let filter = doc! {
             format!("wallets.0x{}", hex::encode(wallet)): { "$exists": true },
-            "$expr":{
-                "$let":{
-                    "vars":{
-                        "entries":{
-                            "$filter":{
-                                "input":{
-                                    "$objectToArray":"$wallets"
-                                },
-                                "as":"wallet",
-                                "cond": cond
-                            }
-                        }
-                    },
-                    "in":{
-                        "$let": {
-                            "vars": {
-                                "timestamp":{
-                                    "$arrayElemAt":[{
-                                        "$map":{
-                                            "input":"$$entries",
-                                            "as":"entry",
-                                            "in":"$$entry.v.timestamp"
-                                        }
-                                    },0]
-                                }
-                            },
-                            "in": in_and_cond_doc
-                        }
-                    }
-                }
-            }
+            "$expr": bson::to_bson(&expr)?,
         };
 
         let find_options = FindOptions::builder()
@@ -406,4 +351,80 @@ impl RewardsManager {
                 .collect()
         })
     }
+
+    fn build_rewards_filter_expr(
+        &self,
+        from: Option<u64>,
+        to: Option<u64>,
+        community: Option<&str>,
+    ) -> Result<Document, error::Error> {
+        let mut in_and_cond_doc = doc! {
+            "$and": []
+        };
+
+        let mut cond = doc! {};
+
+        if let Some(community) = community {
+            cond.insert("$eq", bson::to_bson(&["$$wallet.v.community", community])?);
+
+            in_and_cond_doc.get_array_mut("$and")?.push(
+                doc! {
+                    "$gt": [{ "$size": "$$entries" }, 0]
+                }
+                .into(),
+            );
+        }
+
+        if from.is_some() || to.is_some() {
+            if let Some(from) = from {
+                in_and_cond_doc.get_array_mut("$and")?.push(
+                    doc! {
+                        "$gte": ["$$timestamp", bson::to_bson(&from)?]
+                    }
+                    .into(),
+                );
+            }
+
+            if let Some(to) = to {
+                in_and_cond_doc.get_array_mut("$and")?.push(
+                    doc! {
+                        "$lt": ["$$timestamp", bson::to_bson(&to)?]
+                    }
+                    .into(),
+                );
+            }
+        }
+
+        Ok(doc! {
+            "$let":{
+                "vars":{
+                    "entries":{
+                        "$filter":{
+                            "input":{
+                                "$objectToArray":"$wallets"
+                            },
+                            "as":"wallet",
+                            "cond": cond
+                        }
+                    }
+                },
+                "in":{
+                    "$let": {
+                        "vars": {
+                            "timestamp":{
+                                "$arrayElemAt":[{
+                                    "$map":{
+                                        "input":"$$entries",
+                                        "as":"entry",
+                                        "in":"$$entry.v.timestamp"
+                                    }
+                                },0]
+                            }
+                        },
+                        "in": in_and_cond_doc
+                    }
+                }
+            }
+        })
+    }
 }
diff --git a/gov-portal-db/src/server.rs b/gov-portal-db/src/server.rs
index 6849a2a..f4b9209 100644
--- a/gov-portal-db/src/server.rs
+++ b/gov-portal-db/src/server.rs
@@ -1,7 +1,7 @@
 use axum::{extract::State, routing::post, Json, Router};
 use chrono::{DateTime, Utc};
 use ethereum_types::Address;
-use futures_util::{future, FutureExt};
+use futures_util::{future, FutureExt, TryFutureExt};
 use jsonwebtoken::TokenData;
 use serde::{Deserialize, Serialize};
 use std::{collections::HashMap, sync::Arc};
@@ -106,6 +106,7 @@ pub struct TokenResponse {
 
 /// JSON-serialized request passed as POST-data to `/rewards` endpoint
 #[derive(Debug, Deserialize)]
+#[serde(rename_all = "camelCase")]
 pub struct RewardsRequest {
     pub token: SessionToken,
     pub wallet: Option<Address>,
@@ -116,6 +117,13 @@ pub struct RewardsRequest {
     pub community: Option<String>,
 }
 
+#[derive(Debug, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct RewardsResponse {
+    pub data: Vec<Rewards>,
+    pub total: u64,
+}
+
 /// JSON-serialized request passed as POST-data to `/users` endpoint
 #[derive(Debug, Deserialize)]
 pub struct UsersRequest {
@@ -566,7 +574,7 @@ async fn update_reward_route(
 async fn rewards_route(
     State(state): State<AppState>,
     Json(req): Json<RewardsRequest>,
-) -> Result<Json<Vec<Rewards>>, String> {
+) -> Result<Json<RewardsResponse>, String> {
     tracing::debug!("[/rewards] Request {:?}", req);
 
     let res = match state
@@ -588,7 +596,18 @@ async fn rewards_route(
             },
         )) => state
             .rewards_manager
-            .get_rewards(&requestor, start, limit, from, to, community)
+            .count_rewards(&requestor, from, to, community.as_deref())
+            .and_then(|total| {
+                let manager = Arc::clone(&state.rewards_manager);
+                let community = community.as_deref();
+
+                async move {
+                    manager
+                        .get_rewards(&requestor, start, limit, from, to, community)
+                        .await
+                        .map(|data| RewardsResponse { data, total })
+                }
+            })
             .await
             .map_err(|e| format!("Unable to get rewards. Error: {e}")),
 
@@ -606,10 +625,22 @@ async fn rewards_route(
             },
         )) => state
             .rewards_manager
-            .get_rewards_by_wallet(&requestor, &wallet, start, limit, from, to, community)
+            .count_rewards_by_wallet(&requestor, &wallet, from, to, community.as_deref())
+            .and_then(|total| {
+                let manager = Arc::clone(&state.rewards_manager);
+                let community = community.as_deref();
+
+                async move {
+                    manager
+                        .get_rewards_by_wallet(
+                            &requestor, &wallet, start, limit, from, to, community,
+                        )
+                        .await
+                        .map(|data| RewardsResponse { data, total })
+                }
+            })
             .await
             .map_err(|e| format!("Unable to get rewards. Error: {e}")),
-
         Err(e) => Err(format!("Rewards request failure. Error: {e}")),
     };
 
diff --git a/gov-portal-db/tests/test_rewards_manager.rs b/gov-portal-db/tests/test_rewards_manager.rs
index b8254ff..5144e2d 100644
--- a/gov-portal-db/tests/test_rewards_manager.rs
+++ b/gov-portal-db/tests/test_rewards_manager.rs
@@ -247,7 +247,7 @@ async fn test_rewards_endpoint() -> Result<(), anyhow::Error> {
             None,
             None,
             None,
-            Some("3".into()),
+            Some("3"),
         )
         .await
         .unwrap()
@@ -490,7 +490,7 @@ async fn test_rewards_by_wallet() -> Result<(), anyhow::Error> {
                 None,
                 Some(now + 2 * 4 * 60 * 60 + 1),
                 None,
-                Some("0".into()),
+                Some("0"),
             )
             .await
             .unwrap()
@@ -507,7 +507,7 @@ async fn test_rewards_by_wallet() -> Result<(), anyhow::Error> {
                 None,
                 Some(now + 2 * 4 * 60 * 60 + 1),
                 None,
-                Some("1".into()),
+                Some("1"),
             )
             .await
             .unwrap()