Bug: [FEATURE]: Add Payments - List to v2



`Payments - List` endpoint is needed for the dashboard
diff --git a/api-reference-v2/api-reference/payments/payments--list.mdx b/api-reference-v2/api-reference/payments/payments--list.mdx
new file mode 100644
index 00000000000..80350a5705e
--- /dev/null
+++ b/api-reference-v2/api-reference/payments/payments--list.mdx
@@ -0,0 +1,3 @@
+---
+openapi: get /v2/payments/list
+---
\ No newline at end of file
diff --git a/api-reference-v2/mint.json b/api-reference-v2/mint.json
index 8fd3b64230b..d935ec84a61 100644
--- a/api-reference-v2/mint.json
+++ b/api-reference-v2/mint.json
@@ -43,7 +43,8 @@
         "api-reference/payments/payments--payment-methods-list",
         "api-reference/payments/payments--confirm-intent",
         "api-reference/payments/payments--get",
-        "api-reference/payments/payments--create-and-confirm-intent"
+        "api-reference/payments/payments--create-and-confirm-intent",
+        "api-reference/payments/payments--list"
       ]
     },
     {
diff --git a/api-reference-v2/openapi_spec.json b/api-reference-v2/openapi_spec.json
index cedd4abcca6..4d68da7cec7 100644
--- a/api-reference-v2/openapi_spec.json
+++ b/api-reference-v2/openapi_spec.json
@@ -2258,6 +2258,341 @@
         ]
       }
     },
+    "/v2/payments/list": {
+      "get": {
+        "tags": [
+          "Payments"
+        ],
+        "summary": "Payments - List",
+        "description": "To list the *payments*",
+        "operationId": "List all Payments",
+        "parameters": [
+          {
+            "name": "payment_id",
+            "in": "path",
+            "description": "The identifier for payment",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "nullable": true
+            },
+            "example": "pay_fafa124123"
+          },
+          {
+            "name": "profile_id",
+            "in": "path",
+            "description": "The identifier for business profile",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "nullable": true
+            },
+            "example": "pay_fafa124123"
+          },
+          {
+            "name": "customer_id",
+            "in": "path",
+            "description": "The identifier for customer",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "nullable": true,
+              "maxLength": 64,
+              "minLength": 1
+            },
+            "example": "cus_y3oqhf46pyzuxjbcn2giaqnb44"
+          },
+          {
+            "name": "starting_after",
+            "in": "path",
+            "description": "A cursor for use in pagination, fetch the next list after some object",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "nullable": true
+            },
+            "example": "pay_fafa124123"
+          },
+          {
+            "name": "ending_before",
+            "in": "path",
+            "description": "A cursor for use in pagination, fetch the previous list before some object",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "nullable": true
+            },
+            "example": "pay_fafa124123"
+          },
+          {
+            "name": "limit",
+            "in": "path",
+            "description": "limit on the number of objects to return",
+            "required": true,
+            "schema": {
+              "type": "integer",
+              "format": "int32",
+              "default": 10,
+              "maximum": 100,
+              "minimum": 0
+            }
+          },
+          {
+            "name": "offset",
+            "in": "path",
+            "description": "The starting point within a list of objects",
+            "required": true,
+            "schema": {
+              "type": "integer",
+              "format": "int32",
+              "nullable": true,
+              "minimum": 0
+            }
+          },
+          {
+            "name": "created",
+            "in": "path",
+            "description": "The time at which payment is created",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "date-time",
+              "nullable": true
+            },
+            "example": "2022-09-10T10:11:12Z"
+          },
+          {
+            "name": "created.lt",
+            "in": "path",
+            "description": "Time less than the payment created time",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "date-time",
+              "nullable": true
+            },
+            "example": "2022-09-10T10:11:12Z"
+          },
+          {
+            "name": "created.gt",
+            "in": "path",
+            "description": "Time greater than the payment created time",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "date-time",
+              "nullable": true
+            },
+            "example": "2022-09-10T10:11:12Z"
+          },
+          {
+            "name": "created.lte",
+            "in": "path",
+            "description": "Time less than or equals to the payment created time",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "date-time",
+              "nullable": true
+            },
+            "example": "2022-09-10T10:11:12Z"
+          },
+          {
+            "name": "created.gte",
+            "in": "path",
+            "description": "Time greater than or equals to the payment created time",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "format": "date-time",
+              "nullable": true
+            },
+            "example": "2022-09-10T10:11:12Z"
+          },
+          {
+            "name": "start_amount",
+            "in": "path",
+            "description": "The start amount to filter list of transactions which are greater than or equal to the start amount",
+            "required": true,
+            "schema": {
+              "type": "integer",
+              "format": "int64",
+              "nullable": true
+            }
+          },
+          {
+            "name": "end_amount",
+            "in": "path",
+            "description": "The end amount to filter list of transactions which are less than or equal to the end amount",
+            "required": true,
+            "schema": {
+              "type": "integer",
+              "format": "int64",
+              "nullable": true
+            }
+          },
+          {
+            "name": "connector",
+            "in": "path",
+            "description": "The connector to filter payments list",
+            "required": true,
+            "schema": {
+              "allOf": [
+                {
+                  "$ref": "#/components/schemas/Connector"
+                }
+              ],
+              "nullable": true
+            }
+          },
+          {
+            "name": "currency",
+            "in": "path",
+            "description": "The currency to filter payments list",
+            "required": true,
+            "schema": {
+              "allOf": [
+                {
+                  "$ref": "#/components/schemas/Currency"
+                }
+              ],
+              "nullable": true
+            }
+          },
+          {
+            "name": "status",
+            "in": "path",
+            "description": "The payment status to filter payments list",
+            "required": true,
+            "schema": {
+              "allOf": [
+                {
+                  "$ref": "#/components/schemas/IntentStatus"
+                }
+              ],
+              "nullable": true
+            }
+          },
+          {
+            "name": "payment_method_type",
+            "in": "path",
+            "description": "The payment method type to filter payments list",
+            "required": true,
+            "schema": {
+              "allOf": [
+                {
+                  "$ref": "#/components/schemas/PaymentMethod"
+                }
+              ],
+              "nullable": true
+            }
+          },
+          {
+            "name": "payment_method_subtype",
+            "in": "path",
+            "description": "The payment method subtype to filter payments list",
+            "required": true,
+            "schema": {
+              "allOf": [
+                {
+                  "$ref": "#/components/schemas/PaymentMethodType"
+                }
+              ],
+              "nullable": true
+            }
+          },
+          {
+            "name": "authentication_type",
+            "in": "path",
+            "description": "The authentication type to filter payments list",
+            "required": true,
+            "schema": {
+              "allOf": [
+                {
+                  "$ref": "#/components/schemas/AuthenticationType"
+                }
+              ],
+              "nullable": true
+            }
+          },
+          {
+            "name": "merchant_connector_id",
+            "in": "path",
+            "description": "The merchant connector id to filter payments list",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "nullable": true
+            }
+          },
+          {
+            "name": "order_on",
+            "in": "path",
+            "description": "The field on which the payments list should be sorted",
+            "required": true,
+            "schema": {
+              "$ref": "#/components/schemas/SortOn"
+            }
+          },
+          {
+            "name": "order_by",
+            "in": "path",
+            "description": "The order in which payments list should be sorted",
+            "required": true,
+            "schema": {
+              "$ref": "#/components/schemas/SortBy"
+            }
+          },
+          {
+            "name": "card_network",
+            "in": "path",
+            "description": "The card networks to filter payments list",
+            "required": true,
+            "schema": {
+              "allOf": [
+                {
+                  "$ref": "#/components/schemas/CardNetwork"
+                }
+              ],
+              "nullable": true
+            }
+          },
+          {
+            "name": "merchant_order_reference_id",
+            "in": "path",
+            "description": "The identifier for merchant order reference id",
+            "required": true,
+            "schema": {
+              "type": "string",
+              "nullable": true
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "Successfully retrieved a payment list",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/PaymentListResponse"
+                }
+              }
+            }
+          },
+          "404": {
+            "description": "No payments found"
+          }
+        },
+        "security": [
+          {
+            "api_key": []
+          },
+          {
+            "jwt_key": []
+          }
+        ]
+      }
+    },
     "/v2/payment-methods": {
       "post": {
         "tags": [
@@ -7931,14 +8266,6 @@
         "type": "object",
         "description": "Details of customer attached to this payment",
         "properties": {
-          "id": {
-            "type": "string",
-            "description": "The identifier for the customer.",
-            "example": "cus_y3oqhf46pyzuxjbcn2giaqnb44",
-            "nullable": true,
-            "maxLength": 64,
-            "minLength": 1
-          },
           "name": {
             "type": "string",
             "description": "The customer's name",
@@ -12346,10 +12673,25 @@
           }
         }
       },
-      "OrderDetailsWithAmount": {
+      "Order": {
         "type": "object",
         "required": [
-          "product_name",
+          "on",
+          "by"
+        ],
+        "properties": {
+          "on": {
+            "$ref": "#/components/schemas/SortOn"
+          },
+          "by": {
+            "$ref": "#/components/schemas/SortBy"
+          }
+        }
+      },
+      "OrderDetailsWithAmount": {
+        "type": "object",
+        "required": [
+          "product_name",
           "quantity",
           "amount"
         ],
@@ -13546,74 +13888,32 @@
           }
         }
       },
-      "PaymentListConstraints": {
+      "PaymentListResponse": {
         "type": "object",
+        "required": [
+          "count",
+          "total_count",
+          "data"
+        ],
         "properties": {
-          "customer_id": {
-            "type": "string",
-            "description": "The identifier for customer",
-            "example": "cus_y3oqhf46pyzuxjbcn2giaqnb44",
-            "nullable": true,
-            "maxLength": 64,
-            "minLength": 1
-          },
-          "starting_after": {
-            "type": "string",
-            "description": "A cursor for use in pagination, fetch the next list after some object",
-            "example": "pay_fafa124123",
-            "nullable": true
-          },
-          "ending_before": {
-            "type": "string",
-            "description": "A cursor for use in pagination, fetch the previous list before some object",
-            "example": "pay_fafa124123",
-            "nullable": true
-          },
-          "limit": {
+          "count": {
             "type": "integer",
-            "format": "int32",
-            "description": "limit on the number of objects to return",
-            "default": 10,
-            "maximum": 100,
+            "description": "The number of payments included in the current response",
             "minimum": 0
           },
-          "created": {
-            "type": "string",
-            "format": "date-time",
-            "description": "The time at which payment is created",
-            "example": "2022-09-10T10:11:12Z",
-            "nullable": true
-          },
-          "created.lt": {
-            "type": "string",
-            "format": "date-time",
-            "description": "Time less than the payment created time",
-            "example": "2022-09-10T10:11:12Z",
-            "nullable": true
-          },
-          "created.gt": {
-            "type": "string",
-            "format": "date-time",
-            "description": "Time greater than the payment created time",
-            "example": "2022-09-10T10:11:12Z",
-            "nullable": true
-          },
-          "created.lte": {
-            "type": "string",
-            "format": "date-time",
-            "description": "Time less than or equals to the payment created time",
-            "example": "2022-09-10T10:11:12Z",
-            "nullable": true
+          "total_count": {
+            "type": "integer",
+            "format": "int64",
+            "description": "The total number of available payments for given constraints"
           },
-          "created.gte": {
-            "type": "string",
-            "format": "date-time",
-            "description": "Time greater than or equals to the payment created time",
-            "example": "2022-09-10T10:11:12Z",
-            "nullable": true
+          "data": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/PaymentsListResponseItem"
+            },
+            "description": "The list of payments response objects"
           }
-        },
-        "additionalProperties": false
+        }
       },
       "PaymentMethod": {
         "type": "string",
@@ -15774,6 +16074,217 @@
         },
         "additionalProperties": false
       },
+      "PaymentsListResponseItem": {
+        "type": "object",
+        "required": [
+          "id",
+          "merchant_id",
+          "profile_id",
+          "status",
+          "amount",
+          "created",
+          "attempt_count",
+          "return_url"
+        ],
+        "properties": {
+          "id": {
+            "type": "string",
+            "description": "Unique identifier for the payment",
+            "example": "12345_pay_01926c58bc6e77c09e809964e72af8c8",
+            "maxLength": 64,
+            "minLength": 32
+          },
+          "merchant_id": {
+            "type": "string",
+            "description": "This is an identifier for the merchant account. This is inferred from the API key\nprovided during the request",
+            "example": "merchant_1668273825",
+            "maxLength": 255
+          },
+          "profile_id": {
+            "type": "string",
+            "description": "The business profile that is associated with this payment"
+          },
+          "customer_id": {
+            "type": "string",
+            "description": "The identifier for the customer",
+            "example": "12345_cus_01926c58bc6e77c09e809964e72af8c8",
+            "nullable": true,
+            "maxLength": 64,
+            "minLength": 32
+          },
+          "payment_method_id": {
+            "type": "string",
+            "description": "Identifier for Payment Method used for the payment",
+            "nullable": true
+          },
+          "status": {
+            "allOf": [
+              {
+                "$ref": "#/components/schemas/IntentStatus"
+              }
+            ],
+            "default": "requires_confirmation"
+          },
+          "amount": {
+            "$ref": "#/components/schemas/PaymentAmountDetailsResponse"
+          },
+          "created": {
+            "type": "string",
+            "format": "date-time",
+            "description": "Time when the payment was created",
+            "example": "2022-09-10T10:11:12Z"
+          },
+          "payment_method_type": {
+            "allOf": [
+              {
+                "$ref": "#/components/schemas/PaymentMethod"
+              }
+            ],
+            "nullable": true
+          },
+          "payment_method_subtype": {
+            "allOf": [
+              {
+                "$ref": "#/components/schemas/PaymentMethodType"
+              }
+            ],
+            "nullable": true
+          },
+          "connector": {
+            "allOf": [
+              {
+                "$ref": "#/components/schemas/Connector"
+              }
+            ],
+            "nullable": true
+          },
+          "merchant_connector_id": {
+            "type": "string",
+            "description": "Identifier of the connector ( merchant connector account ) which was chosen to make the payment",
+            "nullable": true
+          },
+          "customer": {
+            "allOf": [
+              {
+                "$ref": "#/components/schemas/CustomerDetailsResponse"
+              }
+            ],
+            "nullable": true
+          },
+          "merchant_reference_id": {
+            "type": "string",
+            "description": "The reference id for the order in the merchant's system. This value can be passed by the merchant.",
+            "nullable": true
+          },
+          "connector_payment_id": {
+            "type": "string",
+            "description": "A unique identifier for a payment provided by the connector",
+            "example": "993672945374576J",
+            "nullable": true
+          },
+          "connector_response_reference_id": {
+            "type": "string",
+            "description": "Reference to the capture at connector side",
+            "nullable": true
+          },
+          "metadata": {
+            "type": "object",
+            "description": "Metadata is useful for storing additional, unstructured information on an object.",
+            "nullable": true
+          },
+          "description": {
+            "type": "string",
+            "description": "A description of the payment",
+            "example": "It's my first payment request",
+            "nullable": true
+          },
+          "authentication_type": {
+            "allOf": [
+              {
+                "$ref": "#/components/schemas/AuthenticationType"
+              }
+            ],
+            "default": "three_ds",
+            "nullable": true
+          },
+          "capture_method": {
+            "allOf": [
+              {
+                "$ref": "#/components/schemas/CaptureMethod"
+              }
+            ],
+            "nullable": true
+          },
+          "setup_future_usage": {
+            "allOf": [
+              {
+                "$ref": "#/components/schemas/FutureUsage"
+              }
+            ],
+            "nullable": true
+          },
+          "attempt_count": {
+            "type": "integer",
+            "format": "int32",
+            "description": "Total number of attempts associated with this payment"
+          },
+          "error": {
+            "allOf": [
+              {
+                "$ref": "#/components/schemas/ErrorDetails"
+              }
+            ],
+            "nullable": true
+          },
+          "cancellation_reason": {
+            "type": "string",
+            "description": "If the payment was cancelled the reason will be provided here",
+            "nullable": true
+          },
+          "order_details": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/OrderDetailsWithAmount"
+            },
+            "description": "Information about the product , quantity and amount for connectors. (e.g. Klarna)",
+            "example": "[{\n        \"product_name\": \"gillete creme\",\n        \"quantity\": 15,\n        \"amount\" : 900\n    }]",
+            "nullable": true
+          },
+          "return_url": {
+            "type": "string",
+            "description": "The URL to redirect after the completion of the operation",
+            "example": "https://hyperswitch.io"
+          },
+          "statement_descriptor": {
+            "type": "string",
+            "description": "For non-card charges, you can use this value as the complete description that appears on your customers’ statements. Must contain at least one letter, maximum 22 characters.",
+            "example": "Hyperswitch Router",
+            "nullable": true,
+            "maxLength": 255
+          },
+          "allowed_payment_method_types": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/PaymentMethodType"
+            },
+            "description": "Allowed Payment Method Types for a given PaymentIntent",
+            "nullable": true
+          },
+          "authorization_count": {
+            "type": "integer",
+            "format": "int32",
+            "description": "Total number of authorizations happened in an incremental_authorization payment",
+            "nullable": true
+          },
+          "modified_at": {
+            "type": "string",
+            "format": "date-time",
+            "description": "Date time at which payment was updated",
+            "example": "2022-09-10T10:11:12Z",
+            "nullable": true
+          }
+        }
+      },
       "PaymentsRequest": {
         "type": "object",
         "required": [
@@ -20352,6 +20863,20 @@
           "contain"
         ]
       },
+      "SortBy": {
+        "type": "string",
+        "enum": [
+          "asc",
+          "desc"
+        ]
+      },
+      "SortOn": {
+        "type": "string",
+        "enum": [
+          "amount",
+          "created"
+        ]
+      },
       "SplitPaymentsRequest": {
         "oneOf": [
           {
diff --git a/crates/api_models/src/events/payment.rs b/crates/api_models/src/events/payment.rs
index 4e672927284..ccda5fd402d 100644
--- a/crates/api_models/src/events/payment.rs
+++ b/crates/api_models/src/events/payment.rs
@@ -11,7 +11,7 @@ use super::{
 ))]
 use crate::payment_methods::CustomerPaymentMethodsListResponse;
 #[cfg(feature = "v1")]
-use crate::payments::{PaymentListResponse, PaymentListResponseV2};
+use crate::payments::{PaymentListFilterConstraints, PaymentListResponseV2};
 #[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
 use crate::{events, payment_methods::CustomerPaymentMethodsListResponse};
 use crate::{
@@ -23,16 +23,15 @@ use crate::{
         PaymentMethodUpdate,
     },
     payments::{
-        self, ExtendedCardInfoResponse, PaymentIdType, PaymentListConstraints,
-        PaymentListFilterConstraints, PaymentListFilters, PaymentListFiltersV2,
-        PaymentsAggregateResponse, PaymentsApproveRequest, PaymentsCancelRequest,
-        PaymentsCaptureRequest, PaymentsCompleteAuthorizeRequest,
-        PaymentsDynamicTaxCalculationRequest, PaymentsDynamicTaxCalculationResponse,
-        PaymentsExternalAuthenticationRequest, PaymentsExternalAuthenticationResponse,
-        PaymentsIncrementalAuthorizationRequest, PaymentsManualUpdateRequest,
-        PaymentsManualUpdateResponse, PaymentsPostSessionTokensRequest,
-        PaymentsPostSessionTokensResponse, PaymentsRejectRequest, PaymentsResponse,
-        PaymentsRetrieveRequest, PaymentsSessionResponse, PaymentsStartRequest,
+        self, ExtendedCardInfoResponse, PaymentIdType, PaymentListConstraints, PaymentListFilters,
+        PaymentListFiltersV2, PaymentListResponse, PaymentsAggregateResponse,
+        PaymentsApproveRequest, PaymentsCancelRequest, PaymentsCaptureRequest,
+        PaymentsCompleteAuthorizeRequest, PaymentsDynamicTaxCalculationRequest,
+        PaymentsDynamicTaxCalculationResponse, PaymentsExternalAuthenticationRequest,
+        PaymentsExternalAuthenticationResponse, PaymentsIncrementalAuthorizationRequest,
+        PaymentsManualUpdateRequest, PaymentsManualUpdateResponse,
+        PaymentsPostSessionTokensRequest, PaymentsPostSessionTokensResponse, PaymentsRejectRequest,
+        PaymentsResponse, PaymentsRetrieveRequest, PaymentsSessionResponse, PaymentsStartRequest,
         RedirectionResponse,
     },
 };
@@ -350,6 +349,7 @@ impl ApiEventMetric for PaymentMethodCollectLinkResponse {
     }
 }
 
+#[cfg(feature = "v1")]
 impl ApiEventMetric for PaymentListFilterConstraints {
     fn get_api_event_type(&self) -> Option<ApiEventsType> {
         Some(ApiEventsType::ResourceListAPI)
@@ -373,7 +373,6 @@ impl ApiEventMetric for PaymentListConstraints {
     }
 }
 
-#[cfg(feature = "v1")]
 impl ApiEventMetric for PaymentListResponse {
     fn get_api_event_type(&self) -> Option<ApiEventsType> {
         Some(ApiEventsType::ResourceListAPI)
diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs
index f996de726e4..222373f538f 100644
--- a/crates/api_models/src/payments.rs
+++ b/crates/api_models/src/payments.rs
@@ -8,8 +8,6 @@ use cards::CardNumber;
 #[cfg(feature = "v2")]
 use common_enums::enums::PaymentConnectorTransmission;
 use common_enums::ProductType;
-#[cfg(feature = "v2")]
-use common_utils::id_type::GlobalPaymentId;
 use common_utils::{
     consts::default_payments_list_limit,
     crypto,
@@ -97,6 +95,7 @@ pub struct CustomerDetails {
     pub phone_country_code: Option<String>,
 }
 
+#[cfg(feature = "v1")]
 /// Details of customer attached to this payment
 #[derive(
     Debug, Default, serde::Serialize, serde::Deserialize, Clone, ToSchema, PartialEq, Setter,
@@ -123,6 +122,27 @@ pub struct CustomerDetailsResponse {
     pub phone_country_code: Option<String>,
 }
 
+#[cfg(feature = "v2")]
+/// Details of customer attached to this payment
+#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, ToSchema, PartialEq, Setter)]
+pub struct CustomerDetailsResponse {
+    /// The customer's name
+    #[schema(max_length = 255, value_type = Option<String>, example = "John Doe")]
+    pub name: Option<Secret<String>>,
+
+    /// The customer's email address
+    #[schema(max_length = 255, value_type = Option<String>, example = "johntest@test.com")]
+    pub email: Option<Email>,
+
+    /// The customer's phone number
+    #[schema(value_type = Option<String>, max_length = 10, example = "9123456789")]
+    pub phone: Option<Secret<String>>,
+
+    /// The country code for the customer's phone number
+    #[schema(max_length = 2, example = "+1")]
+    pub phone_country_code: Option<String>,
+}
+
 // Serialize is required because the api event requires Serialize to be implemented
 #[derive(Debug, serde::Serialize, serde::Deserialize, Clone, ToSchema)]
 #[serde(deny_unknown_fields)]
@@ -4862,6 +4882,139 @@ pub struct PaymentsResponse {
     pub card_discovery: Option<enums::CardDiscovery>,
 }
 
+#[cfg(feature = "v2")]
+#[derive(Clone, Debug, serde::Serialize, ToSchema)]
+pub struct PaymentsListResponseItem {
+    /// Unique identifier for the payment
+    #[schema(
+        min_length = 32,
+        max_length = 64,
+        example = "12345_pay_01926c58bc6e77c09e809964e72af8c8",
+        value_type = String,
+    )]
+    pub id: id_type::GlobalPaymentId,
+
+    /// This is an identifier for the merchant account. This is inferred from the API key
+    /// provided during the request
+    #[schema(max_length = 255, example = "merchant_1668273825", value_type = String)]
+    pub merchant_id: id_type::MerchantId,
+
+    /// The business profile that is associated with this payment
+    #[schema(value_type = String)]
+    pub profile_id: id_type::ProfileId,
+
+    /// The identifier for the customer
+    #[schema(
+        min_length = 32,
+        max_length = 64,
+        example = "12345_cus_01926c58bc6e77c09e809964e72af8c8",
+        value_type = Option<String>
+    )]
+    pub customer_id: Option<id_type::GlobalCustomerId>,
+
+    /// Identifier for Payment Method used for the payment
+    #[schema(value_type = Option<String>)]
+    pub payment_method_id: Option<id_type::GlobalPaymentMethodId>,
+
+    /// Status of the payment
+    #[schema(value_type = IntentStatus, example = "failed", default = "requires_confirmation")]
+    pub status: api_enums::IntentStatus,
+
+    /// Amount related information for this payment and attempt
+    pub amount: PaymentAmountDetailsResponse,
+
+    /// Time when the payment was created
+    #[schema(example = "2022-09-10T10:11:12Z")]
+    #[serde(with = "common_utils::custom_serde::iso8601")]
+    pub created: PrimitiveDateTime,
+
+    /// The payment method type for this payment attempt
+    #[schema(value_type = Option<PaymentMethod>, example = "wallet")]
+    pub payment_method_type: Option<api_enums::PaymentMethod>,
+
+    #[schema(value_type = Option<PaymentMethodType>, example = "apple_pay")]
+    pub payment_method_subtype: Option<api_enums::PaymentMethodType>,
+
+    /// The connector used for the payment
+    #[schema(value_type = Option<Connector>, example = "stripe")]
+    pub connector: Option<String>,
+
+    /// Identifier of the connector ( merchant connector account ) which was chosen to make the payment
+    #[schema(value_type = Option<String>)]
+    pub merchant_connector_id: Option<id_type::MerchantConnectorAccountId>,
+
+    /// Details of the customer
+    pub customer: Option<CustomerDetailsResponse>,
+
+    /// The reference id for the order in the merchant's system. This value can be passed by the merchant.
+    #[schema(value_type = Option<String>)]
+    pub merchant_reference_id: Option<id_type::PaymentReferenceId>,
+
+    /// A unique identifier for a payment provided by the connector
+    #[schema(value_type = Option<String>, example = "993672945374576J")]
+    pub connector_payment_id: Option<String>,
+
+    /// Reference to the capture at connector side
+    pub connector_response_reference_id: Option<String>,
+
+    /// Metadata is useful for storing additional, unstructured information on an object.
+    #[schema(value_type = Option<Object>, example = r#"{ "udf1": "some-value", "udf2": "some-value" }"#)]
+    pub metadata: Option<Secret<serde_json::Value>>,
+
+    /// A description of the payment
+    #[schema(example = "It's my first payment request")]
+    pub description: Option<String>,
+
+    /// The transaction authentication can be set to undergo payer authentication. By default, the authentication will be marked as NO_THREE_DS
+    #[schema(value_type = Option<AuthenticationType>, example = "no_three_ds", default = "three_ds")]
+    pub authentication_type: Option<api_enums::AuthenticationType>,
+
+    /// This is the instruction for capture/ debit the money from the users' card. On the other hand authorization refers to blocking the amount on the users' payment method.
+    #[schema(value_type = Option<CaptureMethod>, example = "automatic")]
+    pub capture_method: Option<api_enums::CaptureMethod>,
+
+    /// Indicates that you intend to make future payments with this Payment’s payment method. Providing this parameter will attach the payment method to the Customer, if present, after the Payment is confirmed and any required actions from the user are complete.
+    #[schema(value_type = Option<FutureUsage>, example = "off_session")]
+    pub setup_future_usage: Option<api_enums::FutureUsage>,
+
+    /// Total number of attempts associated with this payment
+    pub attempt_count: i16,
+
+    /// Error details for the payment if any
+    pub error: Option<ErrorDetails>,
+
+    /// If the payment was cancelled the reason will be provided here
+    pub cancellation_reason: Option<String>,
+
+    /// Information about the product , quantity and amount for connectors. (e.g. Klarna)
+    #[schema(value_type = Option<Vec<OrderDetailsWithAmount>>, example = r#"[{
+        "product_name": "gillete creme",
+        "quantity": 15,
+        "amount" : 900
+    }]"#)]
+    pub order_details: Option<Vec<Secret<OrderDetailsWithAmount>>>,
+
+    /// The URL to redirect after the completion of the operation
+    #[schema(value_type = String, example = "https://hyperswitch.io")]
+    pub return_url: Option<common_utils::types::Url>,
+
+    /// For non-card charges, you can use this value as the complete description that appears on your customers’ statements. Must contain at least one letter, maximum 22 characters.
+    #[schema(value_type = Option<String>, max_length = 255, example = "Hyperswitch Router")]
+    pub statement_descriptor: Option<common_utils::types::StatementDescriptor>,
+
+    /// Allowed Payment Method Types for a given PaymentIntent
+    #[schema(value_type = Option<Vec<PaymentMethodType>>)]
+    pub allowed_payment_method_types: Option<Vec<common_enums::PaymentMethodType>>,
+
+    /// Total number of authorizations happened in an incremental_authorization payment
+    pub authorization_count: Option<i32>,
+
+    /// Date time at which payment was updated
+    #[schema(example = "2022-09-10T10:11:12Z")]
+    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
+    pub modified_at: Option<PrimitiveDateTime>,
+}
+
 // Serialize is implemented because, this will be serialized in the api events.
 // Usually request types should not have serialize implemented.
 //
@@ -5417,6 +5570,7 @@ pub struct ExternalAuthenticationDetailsResponse {
     pub error_message: Option<String>,
 }
 
+#[cfg(feature = "v1")]
 #[derive(Clone, Debug, serde::Deserialize, ToSchema, serde::Serialize)]
 #[serde(deny_unknown_fields)]
 pub struct PaymentListConstraints {
@@ -5481,6 +5635,131 @@ pub struct PaymentListConstraints {
     pub created_gte: Option<PrimitiveDateTime>,
 }
 
+#[cfg(feature = "v2")]
+#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, utoipa::IntoParams)]
+#[serde(deny_unknown_fields)]
+pub struct PaymentListConstraints {
+    /// The identifier for payment
+    #[param(example = "pay_fafa124123", value_type = Option<String>)]
+    pub payment_id: Option<id_type::GlobalPaymentId>,
+
+    /// The identifier for business profile
+    #[param(example = "pay_fafa124123", value_type = Option<String>)]
+    pub profile_id: Option<id_type::ProfileId>,
+
+    /// The identifier for customer
+    #[param(
+        max_length = 64,
+        min_length = 1,
+        example = "cus_y3oqhf46pyzuxjbcn2giaqnb44",
+        value_type = Option<String>,
+    )]
+    pub customer_id: Option<id_type::GlobalCustomerId>,
+
+    /// A cursor for use in pagination, fetch the next list after some object
+    #[param(example = "pay_fafa124123", value_type = Option<String>)]
+    pub starting_after: Option<id_type::GlobalPaymentId>,
+
+    /// A cursor for use in pagination, fetch the previous list before some object
+    #[param(example = "pay_fafa124123", value_type = Option<String>)]
+    pub ending_before: Option<id_type::GlobalPaymentId>,
+
+    /// limit on the number of objects to return
+    #[param(default = 10, maximum = 100)]
+    #[serde(default = "default_payments_list_limit")]
+    pub limit: u32,
+
+    /// The starting point within a list of objects
+    pub offset: Option<u32>,
+
+    /// The time at which payment is created
+    #[param(example = "2022-09-10T10:11:12Z")]
+    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
+    pub created: Option<PrimitiveDateTime>,
+
+    /// Time less than the payment created time
+    #[param(example = "2022-09-10T10:11:12Z")]
+    #[serde(
+        default,
+        with = "common_utils::custom_serde::iso8601::option",
+        rename = "created.lt"
+    )]
+    pub created_lt: Option<PrimitiveDateTime>,
+
+    /// Time greater than the payment created time
+    #[param(example = "2022-09-10T10:11:12Z")]
+    #[serde(
+        default,
+        with = "common_utils::custom_serde::iso8601::option",
+        rename = "created.gt"
+    )]
+    pub created_gt: Option<PrimitiveDateTime>,
+
+    /// Time less than or equals to the payment created time
+    #[param(example = "2022-09-10T10:11:12Z")]
+    #[serde(
+        default,
+        with = "common_utils::custom_serde::iso8601::option",
+        rename = "created.lte"
+    )]
+    pub created_lte: Option<PrimitiveDateTime>,
+
+    /// Time greater than or equals to the payment created time
+    #[param(example = "2022-09-10T10:11:12Z")]
+    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
+    #[serde(rename = "created.gte")]
+    pub created_gte: Option<PrimitiveDateTime>,
+
+    /// The start amount to filter list of transactions which are greater than or equal to the start amount
+    pub start_amount: Option<i64>,
+    /// The end amount to filter list of transactions which are less than or equal to the end amount
+    pub end_amount: Option<i64>,
+    /// The connector to filter payments list
+    #[param(value_type = Option<Connector>)]
+    pub connector: Option<api_enums::Connector>,
+    /// The currency to filter payments list
+    #[param(value_type = Option<Currency>)]
+    pub currency: Option<enums::Currency>,
+    /// The payment status to filter payments list
+    #[param(value_type = Option<IntentStatus>)]
+    pub status: Option<enums::IntentStatus>,
+    /// The payment method type to filter payments list
+    #[param(value_type = Option<PaymentMethod>)]
+    pub payment_method_type: Option<enums::PaymentMethod>,
+    /// The payment method subtype to filter payments list
+    #[param(value_type = Option<PaymentMethodType>)]
+    pub payment_method_subtype: Option<enums::PaymentMethodType>,
+    /// The authentication type to filter payments list
+    #[param(value_type = Option<AuthenticationType>)]
+    pub authentication_type: Option<enums::AuthenticationType>,
+    /// The merchant connector id to filter payments list
+    #[param(value_type = Option<String>)]
+    pub merchant_connector_id: Option<id_type::MerchantConnectorAccountId>,
+    /// The field on which the payments list should be sorted
+    #[serde(default)]
+    pub order_on: SortOn,
+    /// The order in which payments list should be sorted
+    #[serde(default)]
+    pub order_by: SortBy,
+    /// The card networks to filter payments list
+    #[param(value_type = Option<CardNetwork>)]
+    pub card_network: Option<enums::CardNetwork>,
+    /// The identifier for merchant order reference id
+    pub merchant_order_reference_id: Option<String>,
+}
+
+#[cfg(feature = "v2")]
+impl PaymentListConstraints {
+    pub fn has_no_attempt_filters(&self) -> bool {
+        self.connector.is_none()
+            && self.payment_method_type.is_none()
+            && self.payment_method_subtype.is_none()
+            && self.authentication_type.is_none()
+            && self.merchant_connector_id.is_none()
+            && self.card_network.is_none()
+    }
+}
+
 #[cfg(feature = "v1")]
 #[derive(Clone, Debug, serde::Serialize, ToSchema)]
 pub struct PaymentListResponse {
@@ -5490,6 +5769,16 @@ pub struct PaymentListResponse {
     pub data: Vec<PaymentsResponse>,
 }
 
+#[cfg(feature = "v2")]
+#[derive(Clone, Debug, serde::Serialize, ToSchema)]
+pub struct PaymentListResponse {
+    /// The number of payments included in the current response
+    pub count: usize,
+    /// The total number of available payments for given constraints
+    pub total_count: i64,
+    /// The list of payments response objects
+    pub data: Vec<PaymentsListResponseItem>,
+}
 #[derive(Setter, Clone, Default, Debug, PartialEq, serde::Serialize, ToSchema)]
 pub struct IncrementalAuthorizationResponse {
     /// The unique identifier of authorization
@@ -5519,6 +5808,7 @@ pub struct PaymentListResponseV2 {
     pub data: Vec<PaymentsResponse>,
 }
 
+#[cfg(feature = "v1")]
 #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
 pub struct PaymentListFilterConstraints {
     /// The identifier for payment
@@ -5562,6 +5852,7 @@ pub struct PaymentListFilterConstraints {
     pub card_discovery: Option<Vec<enums::CardDiscovery>>,
 }
 
+#[cfg(feature = "v1")]
 impl PaymentListFilterConstraints {
     pub fn has_no_attempt_filters(&self) -> bool {
         self.connector.is_none()
diff --git a/crates/diesel_models/src/query/payment_attempt.rs b/crates/diesel_models/src/query/payment_attempt.rs
index 60393211968..cfcbc2bd199 100644
--- a/crates/diesel_models/src/query/payment_attempt.rs
+++ b/crates/diesel_models/src/query/payment_attempt.rs
@@ -412,6 +412,64 @@ impl PaymentAttempt {
         ))
     }
 
+    #[cfg(feature = "v2")]
+    #[allow(clippy::too_many_arguments)]
+    pub async fn get_total_count_of_attempts(
+        conn: &PgPooledConn,
+        merchant_id: &common_utils::id_type::MerchantId,
+        active_attempt_ids: &[String],
+        connector: Option<String>,
+        payment_method_type: Option<enums::PaymentMethod>,
+        payment_method_subtype: Option<enums::PaymentMethodType>,
+        authentication_type: Option<enums::AuthenticationType>,
+        merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
+        card_network: Option<enums::CardNetwork>,
+    ) -> StorageResult<i64> {
+        let mut filter = <Self as HasTable>::table()
+            .count()
+            .filter(dsl::merchant_id.eq(merchant_id.to_owned()))
+            .filter(dsl::id.eq_any(active_attempt_ids.to_owned()))
+            .into_boxed();
+
+        if let Some(connector) = connector {
+            filter = filter.filter(dsl::connector.eq(connector));
+        }
+
+        if let Some(payment_method_type) = payment_method_type {
+            filter = filter.filter(dsl::payment_method_type_v2.eq(payment_method_type));
+        }
+        if let Some(payment_method_subtype) = payment_method_subtype {
+            filter = filter.filter(dsl::payment_method_subtype.eq(payment_method_subtype));
+        }
+        if let Some(authentication_type) = authentication_type {
+            filter = filter.filter(dsl::authentication_type.eq(authentication_type));
+        }
+        if let Some(merchant_connector_id) = merchant_connector_id {
+            filter = filter.filter(dsl::merchant_connector_id.eq(merchant_connector_id))
+        }
+        if let Some(card_network) = card_network {
+            filter = filter.filter(dsl::card_network.eq(card_network))
+        }
+
+        router_env::logger::debug!(query = %debug_query::<Pg, _>(&filter).to_string());
+
+        // TODO: Remove these logs after debugging the issue for delay in count query
+        let start_time = std::time::Instant::now();
+        router_env::logger::debug!("Executing count query start_time: {:?}", start_time);
+        let result = db_metrics::track_database_call::<<Self as HasTable>::Table, _, _>(
+            filter.get_result_async::<i64>(conn),
+            db_metrics::DatabaseOperation::Filter,
+        )
+        .await
+        .change_context(DatabaseError::Others)
+        .attach_printable("Error filtering count of payments");
+
+        let duration = start_time.elapsed();
+        router_env::logger::debug!("Completed count query in {:?}", duration);
+
+        result
+    }
+
     #[cfg(feature = "v1")]
     #[allow(clippy::too_many_arguments)]
     pub async fn get_total_count_of_attempts(
diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs
index af462443cdf..ce586408fc3 100644
--- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs
+++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs
@@ -199,6 +199,21 @@ pub trait PaymentAttemptInterface {
         card_discovery: Option<Vec<storage_enums::CardDiscovery>>,
         storage_scheme: storage_enums::MerchantStorageScheme,
     ) -> error_stack::Result<i64, errors::StorageError>;
+
+    #[cfg(all(feature = "v2", feature = "olap"))]
+    #[allow(clippy::too_many_arguments)]
+    async fn get_total_count_of_filtered_payment_attempts(
+        &self,
+        merchant_id: &id_type::MerchantId,
+        active_attempt_ids: &[String],
+        connector: Option<api_models::enums::Connector>,
+        payment_method_type: Option<storage_enums::PaymentMethod>,
+        payment_method_subtype: Option<storage_enums::PaymentMethodType>,
+        authentication_type: Option<storage_enums::AuthenticationType>,
+        merchant_connector_id: Option<id_type::MerchantConnectorAccountId>,
+        card_network: Option<storage_enums::CardNetwork>,
+        storage_scheme: storage_enums::MerchantStorageScheme,
+    ) -> error_stack::Result<i64, errors::StorageError>;
 }
 
 #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)]
diff --git a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs
index b2335550cf5..be7e55e45ab 100644
--- a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs
+++ b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs
@@ -120,6 +120,30 @@ pub trait PaymentIntentInterface {
         storage_scheme: common_enums::MerchantStorageScheme,
     ) -> error_stack::Result<Vec<(PaymentIntent, PaymentAttempt)>, errors::StorageError>;
 
+    #[cfg(all(feature = "v2", feature = "olap"))]
+    async fn get_filtered_payment_intents_attempt(
+        &self,
+        state: &KeyManagerState,
+        merchant_id: &id_type::MerchantId,
+        constraints: &PaymentIntentFetchConstraints,
+        merchant_key_store: &MerchantKeyStore,
+        storage_scheme: common_enums::MerchantStorageScheme,
+    ) -> error_stack::Result<
+        Vec<(
+            PaymentIntent,
+            Option<super::payment_attempt::PaymentAttempt>,
+        )>,
+        errors::StorageError,
+    >;
+
+    #[cfg(all(feature = "v2", feature = "olap"))]
+    async fn get_filtered_active_attempt_ids_for_total_count(
+        &self,
+        merchant_id: &id_type::MerchantId,
+        constraints: &PaymentIntentFetchConstraints,
+        storage_scheme: common_enums::MerchantStorageScheme,
+    ) -> error_stack::Result<Vec<Option<String>>, errors::StorageError>;
+
     #[cfg(all(feature = "v1", feature = "olap"))]
     async fn get_filtered_active_attempt_ids_for_total_count(
         &self,
@@ -1077,6 +1101,7 @@ impl From<PaymentIntentUpdateInternal> for diesel_models::PaymentIntentUpdateInt
     }
 }
 
+#[cfg(feature = "v1")]
 pub enum PaymentIntentFetchConstraints {
     Single {
         payment_intent_id: id_type::PaymentId,
@@ -1084,6 +1109,7 @@ pub enum PaymentIntentFetchConstraints {
     List(Box<PaymentIntentListParams>),
 }
 
+#[cfg(feature = "v1")]
 impl PaymentIntentFetchConstraints {
     pub fn get_profile_id_list(&self) -> Option<Vec<id_type::ProfileId>> {
         if let Self::List(pi_list_params) = self {
@@ -1094,6 +1120,26 @@ impl PaymentIntentFetchConstraints {
     }
 }
 
+#[cfg(feature = "v2")]
+pub enum PaymentIntentFetchConstraints {
+    Single {
+        payment_intent_id: id_type::GlobalPaymentId,
+    },
+    List(Box<PaymentIntentListParams>),
+}
+
+#[cfg(feature = "v2")]
+impl PaymentIntentFetchConstraints {
+    pub fn get_profile_id(&self) -> Option<id_type::ProfileId> {
+        if let Self::List(pi_list_params) = self {
+            pi_list_params.profile_id.clone()
+        } else {
+            None
+        }
+    }
+}
+
+#[cfg(feature = "v1")]
 pub struct PaymentIntentListParams {
     pub offset: u32,
     pub starting_at: Option<PrimitiveDateTime>,
@@ -1117,6 +1163,30 @@ pub struct PaymentIntentListParams {
     pub merchant_order_reference_id: Option<String>,
 }
 
+#[cfg(feature = "v2")]
+pub struct PaymentIntentListParams {
+    pub offset: u32,
+    pub starting_at: Option<PrimitiveDateTime>,
+    pub ending_at: Option<PrimitiveDateTime>,
+    pub amount_filter: Option<api_models::payments::AmountFilter>,
+    pub connector: Option<api_models::enums::Connector>,
+    pub currency: Option<common_enums::Currency>,
+    pub status: Option<common_enums::IntentStatus>,
+    pub payment_method_type: Option<common_enums::PaymentMethod>,
+    pub payment_method_subtype: Option<common_enums::PaymentMethodType>,
+    pub authentication_type: Option<common_enums::AuthenticationType>,
+    pub merchant_connector_id: Option<id_type::MerchantConnectorAccountId>,
+    pub profile_id: Option<id_type::ProfileId>,
+    pub customer_id: Option<id_type::GlobalCustomerId>,
+    pub starting_after_id: Option<id_type::GlobalPaymentId>,
+    pub ending_before_id: Option<id_type::GlobalPaymentId>,
+    pub limit: Option<u32>,
+    pub order: api_models::payments::Order,
+    pub card_network: Option<common_enums::CardNetwork>,
+    pub merchant_order_reference_id: Option<String>,
+}
+
+#[cfg(feature = "v1")]
 impl From<api_models::payments::PaymentListConstraints> for PaymentIntentFetchConstraints {
     fn from(value: api_models::payments::PaymentListConstraints) -> Self {
         let api_models::payments::PaymentListConstraints {
@@ -1155,6 +1225,73 @@ impl From<api_models::payments::PaymentListConstraints> for PaymentIntentFetchCo
     }
 }
 
+#[cfg(feature = "v2")]
+impl From<api_models::payments::PaymentListConstraints> for PaymentIntentFetchConstraints {
+    fn from(value: api_models::payments::PaymentListConstraints) -> Self {
+        let api_models::payments::PaymentListConstraints {
+            customer_id,
+            starting_after,
+            ending_before,
+            limit,
+            created,
+            created_lt,
+            created_gt,
+            created_lte,
+            created_gte,
+            payment_id,
+            profile_id,
+            start_amount,
+            end_amount,
+            connector,
+            currency,
+            status,
+            payment_method_type,
+            payment_method_subtype,
+            authentication_type,
+            merchant_connector_id,
+            order_on,
+            order_by,
+            card_network,
+            merchant_order_reference_id,
+            offset,
+        } = value;
+        if let Some(payment_intent_id) = payment_id {
+            Self::Single { payment_intent_id }
+        } else {
+            Self::List(Box::new(PaymentIntentListParams {
+                offset: offset.unwrap_or_default(),
+                starting_at: created_gte.or(created_gt).or(created),
+                ending_at: created_lte.or(created_lt).or(created),
+                amount_filter: (start_amount.is_some() || end_amount.is_some()).then_some({
+                    api_models::payments::AmountFilter {
+                        start_amount,
+                        end_amount,
+                    }
+                }),
+                connector,
+                currency,
+                status,
+                payment_method_type,
+                payment_method_subtype,
+                authentication_type,
+                merchant_connector_id,
+                profile_id,
+                customer_id,
+                starting_after_id: starting_after,
+                ending_before_id: ending_before,
+                limit: Some(std::cmp::min(limit, PAYMENTS_LIST_MAX_LIMIT_V1)),
+                order: api_models::payments::Order {
+                    on: order_on,
+                    by: order_by,
+                },
+                card_network,
+                merchant_order_reference_id,
+            }))
+        }
+    }
+}
+
+#[cfg(feature = "v1")]
 impl From<common_utils::types::TimeRange> for PaymentIntentFetchConstraints {
     fn from(value: common_utils::types::TimeRange) -> Self {
         Self::List(Box::new(PaymentIntentListParams {
@@ -1182,6 +1319,7 @@ impl From<common_utils::types::TimeRange> for PaymentIntentFetchConstraints {
     }
 }
 
+#[cfg(feature = "v1")]
 impl From<api_models::payments::PaymentListFilterConstraints> for PaymentIntentFetchConstraints {
     fn from(value: api_models::payments::PaymentListFilterConstraints) -> Self {
         let api_models::payments::PaymentListFilterConstraints {
@@ -1233,6 +1371,7 @@ impl From<api_models::payments::PaymentListFilterConstraints> for PaymentIntentF
     }
 }
 
+#[cfg(feature = "v1")]
 impl<T> TryFrom<(T, Option<Vec<id_type::ProfileId>>)> for PaymentIntentFetchConstraints
 where
     Self: From<T>,
diff --git a/crates/openapi/src/openapi_v2.rs b/crates/openapi/src/openapi_v2.rs
index e5c9c6fa81f..12e42320b40 100644
--- a/crates/openapi/src/openapi_v2.rs
+++ b/crates/openapi/src/openapi_v2.rs
@@ -127,6 +127,7 @@ Never share your secret api keys. Keep them guarded and secure.
         routes::payments::payments_create_and_confirm_intent,
         routes::payments::payments_connector_session,
         routes::payments::list_payment_methods,
+        routes::payments::payments_list,
 
         //Routes for payment methods
         routes::payment_method::create_payment_method_api,
@@ -375,6 +376,7 @@ Never share your secret api keys. Keep them guarded and secure.
         api_models::payments::ConnectorTokenDetails,
         api_models::payments::PaymentsRequest,
         api_models::payments::PaymentsResponse,
+        api_models::payments::PaymentsListResponseItem,
         api_models::payments::PaymentRetrieveBody,
         api_models::payments::PaymentsRetrieveRequest,
         api_models::payments::PaymentsCaptureRequest,
@@ -437,7 +439,7 @@ Never share your secret api keys. Keep them guarded and secure.
         api_models::payments::SamsungPayCardBrand,
         api_models::payments::SamsungPayTokenData,
         api_models::payments::PaymentsCancelRequest,
-        api_models::payments::PaymentListConstraints,
+        api_models::payments::PaymentListResponse,
         api_models::payments::CashappQr,
         api_models::payments::BankTransferData,
         api_models::payments::BankTransferNextStepsData,
@@ -493,6 +495,9 @@ Never share your secret api keys. Keep them guarded and secure.
         api_models::payments::PaymentsConfirmIntentResponse,
         api_models::payments::AmountDetailsResponse,
         api_models::payments::BankCodeResponse,
+        api_models::payments::Order,
+        api_models::payments::SortOn,
+        api_models::payments::SortBy,
         api_models::payments::PaymentMethodListResponseForPayments,
         api_models::payments::ResponsePaymentMethodTypesForPayments,
         api_models::payment_methods::RequiredFieldInfo,
diff --git a/crates/openapi/src/routes/payments.rs b/crates/openapi/src/routes/payments.rs
index ceccd53c4dd..633e0685e60 100644
--- a/crates/openapi/src/routes/payments.rs
+++ b/crates/openapi/src/routes/payments.rs
@@ -457,6 +457,7 @@ pub fn payments_cancel() {}
 /// Payments - List
 ///
 /// To list the *payments*
+#[cfg(feature = "v1")]
 #[utoipa::path(
     get,
     path = "/payments/list",
@@ -846,3 +847,21 @@ pub(crate) enum ForceSync {
     security(("publishable_key" = []))
 )]
 pub fn list_payment_methods() {}
+
+/// Payments - List
+///
+/// To list the *payments*
+#[cfg(feature = "v2")]
+#[utoipa::path(
+    get,
+    path = "/v2/payments/list",
+    params(api_models::payments::PaymentListConstraints),
+    responses(
+        (status = 200, description = "Successfully retrieved a payment list", body = PaymentListResponse),
+        (status = 404, description = "No payments found")
+    ),
+    tag = "Payments",
+    operation_id = "List all Payments",
+    security(("api_key" = []), ("jwt_key" = []))
+)]
+pub fn payments_list() {}
diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs
index 6edd2b7c65d..fdead461448 100644
--- a/crates/router/src/core/payments.rs
+++ b/crates/router/src/core/payments.rs
@@ -5214,6 +5214,82 @@ pub async fn list_payments(
     ))
 }
 
+#[cfg(all(feature = "v2", feature = "olap"))]
+pub async fn list_payments(
+    state: SessionState,
+    merchant: domain::MerchantAccount,
+    key_store: domain::MerchantKeyStore,
+    constraints: api::PaymentListConstraints,
+) -> RouterResponse<payments_api::PaymentListResponse> {
+    common_utils::metrics::utils::record_operation_time(
+        async {
+            let limit = &constraints.limit;
+            helpers::validate_payment_list_request_for_joins(*limit)?;
+            let db: &dyn StorageInterface = state.store.as_ref();
+            let fetch_constraints = constraints.clone().into();
+            let list: Vec<(storage::PaymentIntent, Option<storage::PaymentAttempt>)> = db
+                .get_filtered_payment_intents_attempt(
+                    &(&state).into(),
+                    merchant.get_id(),
+                    &fetch_constraints,
+                    &key_store,
+                    merchant.storage_scheme,
+                )
+                .await
+                .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
+            let data: Vec<api_models::payments::PaymentsListResponseItem> =
+                list.into_iter().map(ForeignFrom::foreign_from).collect();
+
+            let active_attempt_ids = db
+                .get_filtered_active_attempt_ids_for_total_count(
+                    merchant.get_id(),
+                    &fetch_constraints,
+                    merchant.storage_scheme,
+                )
+                .await
+                .to_not_found_response(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("Error while retrieving active_attempt_ids for merchant")?;
+
+            let total_count = if constraints.has_no_attempt_filters() {
+                i64::try_from(active_attempt_ids.len())
+                    .change_context(errors::ApiErrorResponse::InternalServerError)
+                    .attach_printable("Error while converting from usize to i64")
+            } else {
+                let active_attempt_ids = active_attempt_ids
+                    .into_iter()
+                    .flatten()
+                    .collect::<Vec<String>>();
+
+                db.get_total_count_of_filtered_payment_attempts(
+                    merchant.get_id(),
+                    &active_attempt_ids,
+                    constraints.connector,
+                    constraints.payment_method_type,
+                    constraints.payment_method_subtype,
+                    constraints.authentication_type,
+                    constraints.merchant_connector_id,
+                    constraints.card_network,
+                    merchant.storage_scheme,
+                )
+                .await
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("Error while retrieving total count of payment attempts")
+            }?;
+
+            Ok(services::ApplicationResponse::Json(
+                api_models::payments::PaymentListResponse {
+                    count: data.len(),
+                    total_count,
+                    data,
+                },
+            ))
+        },
+        &metrics::PAYMENT_LIST_LATENCY,
+        router_env::metric_attributes!(("merchant_id", merchant.get_id().clone())),
+    )
+    .await
+}
+
 #[cfg(all(feature = "olap", feature = "v1"))]
 pub async fn apply_filters_on_payments(
     state: SessionState,
diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs
index 7302831e509..03998e135d1 100644
--- a/crates/router/src/core/payments/transformers.rs
+++ b/crates/router/src/core/payments/transformers.rs
@@ -2770,6 +2770,54 @@ impl ForeignFrom<(storage::PaymentIntent, storage::PaymentAttempt)> for api::Pay
     }
 }
 
+#[cfg(feature = "v2")]
+impl ForeignFrom<(storage::PaymentIntent, Option<storage::PaymentAttempt>)>
+    for api_models::payments::PaymentsListResponseItem
+{
+    fn foreign_from((pi, pa): (storage::PaymentIntent, Option<storage::PaymentAttempt>)) -> Self {
+        Self {
+            id: pi.id,
+            merchant_id: pi.merchant_id,
+            profile_id: pi.profile_id,
+            customer_id: pi.customer_id,
+            payment_method_id: pa.as_ref().and_then(|p| p.payment_method_id.clone()),
+            status: pi.status,
+            amount: api_models::payments::PaymentAmountDetailsResponse::foreign_from((
+                &pi.amount_details,
+                pa.as_ref().map(|p| &p.amount_details),
+            )),
+            created: pi.created_at,
+            payment_method_type: pa.as_ref().and_then(|p| p.payment_method_type.into()),
+            payment_method_subtype: pa.as_ref().and_then(|p| p.payment_method_subtype.into()),
+            connector: pa.as_ref().and_then(|p| p.connector.clone()),
+            merchant_connector_id: pa.as_ref().and_then(|p| p.merchant_connector_id.clone()),
+            customer: None,
+            merchant_reference_id: pi.merchant_reference_id,
+            connector_payment_id: pa.as_ref().and_then(|p| p.connector_payment_id.clone()),
+            connector_response_reference_id: pa
+                .as_ref()
+                .and_then(|p| p.connector_response_reference_id.clone()),
+            metadata: pi.metadata,
+            description: pi.description.map(|val| val.get_string_repr().to_string()),
+            authentication_type: pi.authentication_type,
+            capture_method: Some(pi.capture_method),
+            setup_future_usage: Some(pi.setup_future_usage),
+            attempt_count: pi.attempt_count,
+            error: pa
+                .as_ref()
+                .and_then(|p| p.error.as_ref())
+                .map(|e| api_models::payments::ErrorDetails::foreign_from(e.clone())),
+            cancellation_reason: pa.as_ref().and_then(|p| p.cancellation_reason.clone()),
+            order_details: None,
+            return_url: pi.return_url,
+            statement_descriptor: pi.statement_descriptor,
+            allowed_payment_method_types: pi.allowed_payment_method_types,
+            authorization_count: pi.authorization_count,
+            modified_at: pa.as_ref().map(|p| p.modified_at),
+        }
+    }
+}
+
 #[cfg(feature = "v1")]
 impl ForeignFrom<ephemeral_key::EphemeralKey> for api::ephemeral_key::EphemeralKeyCreateResponse {
     fn foreign_from(from: ephemeral_key::EphemeralKey) -> Self {
diff --git a/crates/router/src/db/kafka_store.rs b/crates/router/src/db/kafka_store.rs
index d21c345b5fe..a8189468b16 100644
--- a/crates/router/src/db/kafka_store.rs
+++ b/crates/router/src/db/kafka_store.rs
@@ -1735,6 +1735,34 @@ impl PaymentAttemptInterface for KafkaStore {
             .await
     }
 
+    #[cfg(feature = "v2")]
+    async fn get_total_count_of_filtered_payment_attempts(
+        &self,
+        merchant_id: &id_type::MerchantId,
+        active_attempt_ids: &[String],
+        connector: Option<api_models::enums::Connector>,
+        payment_method_type: Option<common_enums::PaymentMethod>,
+        payment_method_subtype: Option<common_enums::PaymentMethodType>,
+        authentication_type: Option<common_enums::AuthenticationType>,
+        merchant_connector_id: Option<id_type::MerchantConnectorAccountId>,
+        card_network: Option<common_enums::CardNetwork>,
+        storage_scheme: MerchantStorageScheme,
+    ) -> CustomResult<i64, errors::DataStorageError> {
+        self.diesel_store
+            .get_total_count_of_filtered_payment_attempts(
+                merchant_id,
+                active_attempt_ids,
+                connector,
+                payment_method_type,
+                payment_method_subtype,
+                authentication_type,
+                merchant_connector_id,
+                card_network,
+                storage_scheme,
+            )
+            .await
+    }
+
     #[cfg(feature = "v1")]
     async fn find_attempts_by_merchant_id_payment_id(
         &self,
@@ -1914,6 +1942,32 @@ impl PaymentIntentInterface for KafkaStore {
             .await
     }
 
+    #[cfg(all(feature = "olap", feature = "v2"))]
+    async fn get_filtered_payment_intents_attempt(
+        &self,
+        state: &KeyManagerState,
+        merchant_id: &id_type::MerchantId,
+        constraints: &hyperswitch_domain_models::payments::payment_intent::PaymentIntentFetchConstraints,
+        key_store: &domain::MerchantKeyStore,
+        storage_scheme: MerchantStorageScheme,
+    ) -> CustomResult<
+        Vec<(
+            hyperswitch_domain_models::payments::PaymentIntent,
+            Option<hyperswitch_domain_models::payments::payment_attempt::PaymentAttempt>,
+        )>,
+        errors::DataStorageError,
+    > {
+        self.diesel_store
+            .get_filtered_payment_intents_attempt(
+                state,
+                merchant_id,
+                constraints,
+                key_store,
+                storage_scheme,
+            )
+            .await
+    }
+
     #[cfg(all(feature = "olap", feature = "v1"))]
     async fn get_filtered_active_attempt_ids_for_total_count(
         &self,
@@ -1952,6 +2006,21 @@ impl PaymentIntentInterface for KafkaStore {
             )
             .await
     }
+    #[cfg(all(feature = "olap", feature = "v2"))]
+    async fn get_filtered_active_attempt_ids_for_total_count(
+        &self,
+        merchant_id: &id_type::MerchantId,
+        constraints: &hyperswitch_domain_models::payments::payment_intent::PaymentIntentFetchConstraints,
+        storage_scheme: MerchantStorageScheme,
+    ) -> CustomResult<Vec<Option<String>>, errors::DataStorageError> {
+        self.diesel_store
+            .get_filtered_active_attempt_ids_for_total_count(
+                merchant_id,
+                constraints,
+                storage_scheme,
+            )
+            .await
+    }
 }
 
 #[async_trait::async_trait]
diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs
index 3da65e968b6..ea8e978fab7 100644
--- a/crates/router/src/routes/app.rs
+++ b/crates/router/src/routes/app.rs
@@ -572,6 +572,7 @@ impl Payments {
                 web::resource("/create-intent")
                     .route(web::post().to(payments::payments_create_intent)),
             )
+            .service(web::resource("/list").route(web::get().to(payments::payments_list)))
             .service(
                 web::resource("/aggregate").route(web::get().to(payments::get_payments_aggregates)),
             )
diff --git a/crates/router/src/routes/payments.rs b/crates/router/src/routes/payments.rs
index dd15079efed..1faaf9cc5ae 100644
--- a/crates/router/src/routes/payments.rs
+++ b/crates/router/src/routes/payments.rs
@@ -1234,6 +1234,35 @@ pub async fn payments_list(
     .await
 }
 
+#[instrument(skip_all, fields(flow = ?Flow::PaymentsList))]
+#[cfg(all(feature = "olap", feature = "v2"))]
+pub async fn payments_list(
+    state: web::Data<app::AppState>,
+    req: actix_web::HttpRequest,
+    payload: web::Query<payment_types::PaymentListConstraints>,
+) -> impl Responder {
+    let flow = Flow::PaymentsList;
+    let payload = payload.into_inner();
+    Box::pin(api::server_wrap(
+        flow,
+        state,
+        &req,
+        payload,
+        |state, auth: auth::AuthenticationData, req, _| {
+            payments::list_payments(state, auth.merchant_account, auth.key_store, req)
+        },
+        auth::auth_type(
+            &auth::HeaderAuth(auth::ApiKeyAuth),
+            &auth::JWTAuth {
+                permission: Permission::MerchantPaymentRead,
+            },
+            req.headers(),
+        ),
+        api_locking::LockAction::NotApplicable,
+    ))
+    .await
+}
+
 #[instrument(skip_all, fields(flow = ?Flow::PaymentsList))]
 #[cfg(all(feature = "olap", feature = "v1"))]
 pub async fn profile_payments_list(
diff --git a/crates/router/src/types/api/payments.rs b/crates/router/src/types/api/payments.rs
index 58159fc5688..74329844a76 100644
--- a/crates/router/src/types/api/payments.rs
+++ b/crates/router/src/types/api/payments.rs
@@ -1,5 +1,7 @@
 #[cfg(feature = "v1")]
-pub use api_models::payments::{PaymentListResponse, PaymentListResponseV2};
+pub use api_models::payments::{
+    PaymentListFilterConstraints, PaymentListResponse, PaymentListResponseV2,
+};
 #[cfg(feature = "v2")]
 pub use api_models::payments::{
     PaymentsConfirmIntentRequest, PaymentsCreateIntentRequest, PaymentsIntentResponse,
@@ -14,9 +16,8 @@ pub use api_models::{
         CryptoData, CustomerAcceptance, CustomerDetailsResponse, MandateAmountData, MandateData,
         MandateTransactionType, MandateType, MandateValidationFields, NextActionType,
         OnlineMandate, OpenBankingSessionToken, PayLaterData, PaymentIdType,
-        PaymentListConstraints, PaymentListFilterConstraints, PaymentListFilters,
-        PaymentListFiltersV2, PaymentMethodData, PaymentMethodDataRequest,
-        PaymentMethodDataResponse, PaymentOp, PaymentRetrieveBody,
+        PaymentListConstraints, PaymentListFilters, PaymentListFiltersV2, PaymentMethodData,
+        PaymentMethodDataRequest, PaymentMethodDataResponse, PaymentOp, PaymentRetrieveBody,
         PaymentRetrieveBodyWithCredentials, PaymentsAggregateResponse, PaymentsApproveRequest,
         PaymentsCancelRequest, PaymentsCaptureRequest, PaymentsCompleteAuthorizeRequest,
         PaymentsDynamicTaxCalculationRequest, PaymentsDynamicTaxCalculationResponse,
diff --git a/crates/storage_impl/src/mock_db/payment_attempt.rs b/crates/storage_impl/src/mock_db/payment_attempt.rs
index c9d250d306b..f460bb99491 100644
--- a/crates/storage_impl/src/mock_db/payment_attempt.rs
+++ b/crates/storage_impl/src/mock_db/payment_attempt.rs
@@ -59,6 +59,22 @@ impl PaymentAttemptInterface for MockDb {
         Err(StorageError::MockDbError)?
     }
 
+    #[cfg(all(feature = "v2", feature = "olap"))]
+    async fn get_total_count_of_filtered_payment_attempts(
+        &self,
+        _merchant_id: &id_type::MerchantId,
+        _active_attempt_ids: &[String],
+        _connector: Option<api_models::enums::Connector>,
+        _payment_method_type: Option<common_enums::PaymentMethod>,
+        _payment_method_subtype: Option<common_enums::PaymentMethodType>,
+        _authentication_type: Option<common_enums::AuthenticationType>,
+        _merchanat_connector_id: Option<id_type::MerchantConnectorAccountId>,
+        _card_network: Option<storage_enums::CardNetwork>,
+        _storage_scheme: storage_enums::MerchantStorageScheme,
+    ) -> CustomResult<i64, StorageError> {
+        Err(StorageError::MockDbError)?
+    }
+
     #[cfg(feature = "v1")]
     async fn find_payment_attempt_by_attempt_id_merchant_id(
         &self,
diff --git a/crates/storage_impl/src/mock_db/payment_intent.rs b/crates/storage_impl/src/mock_db/payment_intent.rs
index 6a46702e525..3c90ecbdc7f 100644
--- a/crates/storage_impl/src/mock_db/payment_intent.rs
+++ b/crates/storage_impl/src/mock_db/payment_intent.rs
@@ -28,6 +28,24 @@ impl PaymentIntentInterface for MockDb {
         Err(StorageError::MockDbError)?
     }
 
+    #[cfg(all(feature = "v2", feature = "olap"))]
+    async fn get_filtered_payment_intents_attempt(
+        &self,
+        state: &KeyManagerState,
+        merchant_id: &common_utils::id_type::MerchantId,
+        constraints: &hyperswitch_domain_models::payments::payment_intent::PaymentIntentFetchConstraints,
+        merchant_key_store: &MerchantKeyStore,
+        storage_scheme: storage_enums::MerchantStorageScheme,
+    ) -> error_stack::Result<
+        Vec<(
+            PaymentIntent,
+            Option<hyperswitch_domain_models::payments::payment_attempt::PaymentAttempt>,
+        )>,
+        StorageError,
+    > {
+        Err(StorageError::MockDbError)?
+    }
+
     #[cfg(all(feature = "v1", feature = "olap"))]
     async fn filter_payment_intents_by_time_range_constraints(
         &self,
@@ -63,6 +81,17 @@ impl PaymentIntentInterface for MockDb {
         Err(StorageError::MockDbError)?
     }
 
+    #[cfg(all(feature = "v2", feature = "olap"))]
+    async fn get_filtered_active_attempt_ids_for_total_count(
+        &self,
+        _merchant_id: &common_utils::id_type::MerchantId,
+        _constraints: &hyperswitch_domain_models::payments::payment_intent::PaymentIntentFetchConstraints,
+        _storage_scheme: storage_enums::MerchantStorageScheme,
+    ) -> error_stack::Result<Vec<Option<String>>, StorageError> {
+        // [#172]: Implement function for `MockDb`
+        Err(StorageError::MockDbError)?
+    }
+
     #[cfg(all(feature = "v1", feature = "olap"))]
     async fn get_filtered_payment_intents_attempt(
         &self,
diff --git a/crates/storage_impl/src/payments/payment_attempt.rs b/crates/storage_impl/src/payments/payment_attempt.rs
index 7fb1d3ab80d..183470a87e1 100644
--- a/crates/storage_impl/src/payments/payment_attempt.rs
+++ b/crates/storage_impl/src/payments/payment_attempt.rs
@@ -507,6 +507,44 @@ impl<T: DatabaseStore> PaymentAttemptInterface for RouterStore<T> {
             er.change_context(new_err)
         })
     }
+    #[cfg(all(feature = "v2", feature = "olap"))]
+    #[instrument(skip_all)]
+    async fn get_total_count_of_filtered_payment_attempts(
+        &self,
+        merchant_id: &common_utils::id_type::MerchantId,
+        active_attempt_ids: &[String],
+        connector: Option<api_models::enums::Connector>,
+        payment_method_type: Option<common_enums::PaymentMethod>,
+        payment_method_subtype: Option<common_enums::PaymentMethodType>,
+        authentication_type: Option<common_enums::AuthenticationType>,
+        merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
+        card_network: Option<common_enums::CardNetwork>,
+        _storage_scheme: MerchantStorageScheme,
+    ) -> CustomResult<i64, errors::StorageError> {
+        let conn = self
+            .db_store
+            .get_replica_pool()
+            .get()
+            .await
+            .change_context(errors::StorageError::DatabaseConnectionError)?;
+
+        DieselPaymentAttempt::get_total_count_of_attempts(
+            &conn,
+            merchant_id,
+            active_attempt_ids,
+            connector.map(|val| val.to_string()),
+            payment_method_type,
+            payment_method_subtype,
+            authentication_type,
+            merchant_connector_id,
+            card_network,
+        )
+        .await
+        .map_err(|er| {
+            let new_err = diesel_error_to_data_error(*er.current_context());
+            er.change_context(new_err)
+        })
+    }
 }
 
 #[async_trait::async_trait]
@@ -1424,6 +1462,34 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
             )
             .await
     }
+    #[cfg(all(feature = "v2", feature = "olap"))]
+    #[instrument(skip_all)]
+    async fn get_total_count_of_filtered_payment_attempts(
+        &self,
+        merchant_id: &common_utils::id_type::MerchantId,
+        active_attempt_ids: &[String],
+        connector: Option<api_models::enums::Connector>,
+        payment_method_type: Option<common_enums::PaymentMethod>,
+        payment_method_subtype: Option<common_enums::PaymentMethodType>,
+        authentication_type: Option<common_enums::AuthenticationType>,
+        merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
+        card_network: Option<common_enums::CardNetwork>,
+        storage_scheme: MerchantStorageScheme,
+    ) -> CustomResult<i64, errors::StorageError> {
+        self.router_store
+            .get_total_count_of_filtered_payment_attempts(
+                merchant_id,
+                active_attempt_ids,
+                connector,
+                payment_method_type,
+                payment_method_subtype,
+                authentication_type,
+                merchant_connector_id,
+                card_network,
+                storage_scheme,
+            )
+            .await
+    }
 }
 
 impl DataModelExt for MandateAmountData {
diff --git a/crates/storage_impl/src/payments/payment_intent.rs b/crates/storage_impl/src/payments/payment_intent.rs
index b64d1aee364..e53a72c8734 100644
--- a/crates/storage_impl/src/payments/payment_intent.rs
+++ b/crates/storage_impl/src/payments/payment_intent.rs
@@ -164,6 +164,27 @@ impl<T: DatabaseStore> PaymentIntentInterface for KVRouterStore<T> {
         }
     }
 
+    #[cfg(all(feature = "v2", feature = "olap"))]
+    #[instrument(skip_all)]
+    async fn get_filtered_payment_intents_attempt(
+        &self,
+        state: &KeyManagerState,
+        merchant_id: &common_utils::id_type::MerchantId,
+        constraints: &PaymentIntentFetchConstraints,
+        merchant_key_store: &MerchantKeyStore,
+        storage_scheme: MerchantStorageScheme,
+    ) -> error_stack::Result<Vec<(PaymentIntent, Option<PaymentAttempt>)>, StorageError> {
+        self.router_store
+            .get_filtered_payment_intents_attempt(
+                state,
+                merchant_id,
+                constraints,
+                merchant_key_store,
+                storage_scheme,
+            )
+            .await
+    }
+
     #[cfg(feature = "v1")]
     #[instrument(skip_all)]
     async fn update_payment_intent(
@@ -459,6 +480,23 @@ impl<T: DatabaseStore> PaymentIntentInterface for KVRouterStore<T> {
             )
             .await
     }
+
+    #[cfg(all(feature = "v2", feature = "olap"))]
+    async fn get_filtered_active_attempt_ids_for_total_count(
+        &self,
+        merchant_id: &common_utils::id_type::MerchantId,
+        constraints: &PaymentIntentFetchConstraints,
+        storage_scheme: MerchantStorageScheme,
+    ) -> error_stack::Result<Vec<Option<String>>, StorageError> {
+        self.router_store
+            .get_filtered_active_attempt_ids_for_total_count(
+                merchant_id,
+                constraints,
+                storage_scheme,
+            )
+            .await
+    }
+
     #[cfg(feature = "v2")]
     async fn find_payment_intent_by_merchant_reference_id_profile_id(
         &self,
@@ -1086,6 +1124,303 @@ impl<T: DatabaseStore> PaymentIntentInterface for crate::RouterStore<T> {
             .await
     }
 
+    #[cfg(all(feature = "v2", feature = "olap"))]
+    #[instrument(skip_all)]
+    async fn get_filtered_payment_intents_attempt(
+        &self,
+        state: &KeyManagerState,
+        merchant_id: &common_utils::id_type::MerchantId,
+        constraints: &PaymentIntentFetchConstraints,
+        merchant_key_store: &MerchantKeyStore,
+        storage_scheme: MerchantStorageScheme,
+    ) -> error_stack::Result<Vec<(PaymentIntent, Option<PaymentAttempt>)>, StorageError> {
+        use diesel::NullableExpressionMethods as _;
+        use futures::{future::try_join_all, FutureExt};
+
+        use crate::DataModelExt;
+
+        let conn = connection::pg_connection_read(self).await.switch()?;
+        let conn = async_bb8_diesel::Connection::as_async_conn(&conn);
+        let mut query = DieselPaymentIntent::table()
+            .filter(pi_dsl::merchant_id.eq(merchant_id.to_owned()))
+            .left_join(
+                payment_attempt_schema::table
+                    .on(pi_dsl::active_attempt_id.eq(pa_dsl::id.nullable())),
+            )
+            // Filtering on merchant_id for payment_attempt is not required for v2 as payment_attempt_ids are globally unique
+            .into_boxed();
+
+        query = match constraints {
+            PaymentIntentFetchConstraints::Single { payment_intent_id } => {
+                query.filter(pi_dsl::id.eq(payment_intent_id.to_owned()))
+            }
+            PaymentIntentFetchConstraints::List(params) => {
+                query = match params.order {
+                    Order {
+                        on: SortOn::Amount,
+                        by: SortBy::Asc,
+                    } => query.order(pi_dsl::amount.asc()),
+                    Order {
+                        on: SortOn::Amount,
+                        by: SortBy::Desc,
+                    } => query.order(pi_dsl::amount.desc()),
+                    Order {
+                        on: SortOn::Created,
+                        by: SortBy::Asc,
+                    } => query.order(pi_dsl::created_at.asc()),
+                    Order {
+                        on: SortOn::Created,
+                        by: SortBy::Desc,
+                    } => query.order(pi_dsl::created_at.desc()),
+                };
+
+                if let Some(limit) = params.limit {
+                    query = query.limit(limit.into());
+                }
+
+                if let Some(customer_id) = &params.customer_id {
+                    query = query.filter(pi_dsl::customer_id.eq(customer_id.clone()));
+                }
+
+                if let Some(merchant_order_reference_id) = &params.merchant_order_reference_id {
+                    query = query.filter(
+                        pi_dsl::merchant_reference_id.eq(merchant_order_reference_id.clone()),
+                    )
+                }
+
+                if let Some(profile_id) = &params.profile_id {
+                    query = query.filter(pi_dsl::profile_id.eq(profile_id.clone()));
+                }
+
+                query = match (params.starting_at, &params.starting_after_id) {
+                    (Some(starting_at), _) => query.filter(pi_dsl::created_at.ge(starting_at)),
+                    (None, Some(starting_after_id)) => {
+                        // TODO: Fetch partial columns for this query since we only need some columns
+                        let starting_at = self
+                            .find_payment_intent_by_id(
+                                state,
+                                starting_after_id,
+                                merchant_key_store,
+                                storage_scheme,
+                            )
+                            .await?
+                            .created_at;
+                        query.filter(pi_dsl::created_at.ge(starting_at))
+                    }
+                    (None, None) => query,
+                };
+
+                query = match (params.ending_at, &params.ending_before_id) {
+                    (Some(ending_at), _) => query.filter(pi_dsl::created_at.le(ending_at)),
+                    (None, Some(ending_before_id)) => {
+                        // TODO: Fetch partial columns for this query since we only need some columns
+                        let ending_at = self
+                            .find_payment_intent_by_id(
+                                state,
+                                ending_before_id,
+                                merchant_key_store,
+                                storage_scheme,
+                            )
+                            .await?
+                            .created_at;
+                        query.filter(pi_dsl::created_at.le(ending_at))
+                    }
+                    (None, None) => query,
+                };
+
+                query = query.offset(params.offset.into());
+
+                query = match params.amount_filter {
+                    Some(AmountFilter {
+                        start_amount: Some(start),
+                        end_amount: Some(end),
+                    }) => query.filter(pi_dsl::amount.between(start, end)),
+                    Some(AmountFilter {
+                        start_amount: Some(start),
+                        end_amount: None,
+                    }) => query.filter(pi_dsl::amount.ge(start)),
+                    Some(AmountFilter {
+                        start_amount: None,
+                        end_amount: Some(end),
+                    }) => query.filter(pi_dsl::amount.le(end)),
+                    _ => query,
+                };
+
+                query = match &params.currency {
+                    Some(currency) => query.filter(pi_dsl::currency.eq(*currency)),
+                    None => query,
+                };
+
+                query = match &params.connector {
+                    Some(connector) => query.filter(pa_dsl::connector.eq(*connector)),
+                    None => query,
+                };
+
+                query = match &params.status {
+                    Some(status) => query.filter(pi_dsl::status.eq(*status)),
+                    None => query,
+                };
+
+                query = match &params.payment_method_type {
+                    Some(payment_method_type) => {
+                        query.filter(pa_dsl::payment_method_type_v2.eq(*payment_method_type))
+                    }
+                    None => query,
+                };
+
+                query = match &params.payment_method_subtype {
+                    Some(payment_method_subtype) => {
+                        query.filter(pa_dsl::payment_method_subtype.eq(*payment_method_subtype))
+                    }
+                    None => query,
+                };
+
+                query = match &params.authentication_type {
+                    Some(authentication_type) => {
+                        query.filter(pa_dsl::authentication_type.eq(*authentication_type))
+                    }
+                    None => query,
+                };
+
+                query = match &params.merchant_connector_id {
+                    Some(merchant_connector_id) => query
+                        .filter(pa_dsl::merchant_connector_id.eq(merchant_connector_id.clone())),
+                    None => query,
+                };
+
+                if let Some(card_network) = &params.card_network {
+                    query = query.filter(pa_dsl::card_network.eq(card_network.clone()));
+                }
+                query
+            }
+        };
+
+        logger::debug!(filter = %diesel::debug_query::<diesel::pg::Pg,_>(&query).to_string());
+
+        query
+            .get_results_async::<(
+                DieselPaymentIntent,
+                Option<diesel_models::payment_attempt::PaymentAttempt>,
+            )>(conn)
+            .await
+            .change_context(StorageError::DecryptionError)
+            .async_and_then(|output| async {
+                try_join_all(output.into_iter().map(
+                    |(pi, pa): (_, Option<diesel_models::payment_attempt::PaymentAttempt>)| async {
+                        let payment_intent = PaymentIntent::convert_back(
+                            state,
+                            pi,
+                            merchant_key_store.key.get_inner(),
+                            merchant_id.to_owned().into(),
+                        );
+                        let payment_attempt = pa
+                            .async_map(|val| {
+                                PaymentAttempt::convert_back(
+                                    state,
+                                    val,
+                                    merchant_key_store.key.get_inner(),
+                                    merchant_id.to_owned().into(),
+                                )
+                            })
+                            .map(|val| val.transpose());
+
+                        let output = futures::try_join!(payment_intent, payment_attempt);
+                        output.change_context(StorageError::DecryptionError)
+                    },
+                ))
+                .await
+            })
+            .await
+            .change_context(StorageError::DecryptionError)
+    }
+
+    #[cfg(all(feature = "v2", feature = "olap"))]
+    #[instrument(skip_all)]
+    async fn get_filtered_active_attempt_ids_for_total_count(
+        &self,
+        merchant_id: &common_utils::id_type::MerchantId,
+        constraints: &PaymentIntentFetchConstraints,
+        _storage_scheme: MerchantStorageScheme,
+    ) -> error_stack::Result<Vec<Option<String>>, StorageError> {
+        let conn = connection::pg_connection_read(self).await.switch()?;
+        let conn = async_bb8_diesel::Connection::as_async_conn(&conn);
+        let mut query = DieselPaymentIntent::table()
+            .select(pi_dsl::active_attempt_id)
+            .filter(pi_dsl::merchant_id.eq(merchant_id.to_owned()))
+            .order(pi_dsl::created_at.desc())
+            .into_boxed();
+
+        query = match constraints {
+            PaymentIntentFetchConstraints::Single { payment_intent_id } => {
+                query.filter(pi_dsl::id.eq(payment_intent_id.to_owned()))
+            }
+            PaymentIntentFetchConstraints::List(params) => {
+                if let Some(customer_id) = &params.customer_id {
+                    query = query.filter(pi_dsl::customer_id.eq(customer_id.clone()));
+                }
+                if let Some(merchant_order_reference_id) = &params.merchant_order_reference_id {
+                    query = query.filter(
+                        pi_dsl::merchant_reference_id.eq(merchant_order_reference_id.clone()),
+                    )
+                }
+                if let Some(profile_id) = &params.profile_id {
+                    query = query.filter(pi_dsl::profile_id.eq(profile_id.clone()));
+                }
+
+                query = match params.starting_at {
+                    Some(starting_at) => query.filter(pi_dsl::created_at.ge(starting_at)),
+                    None => query,
+                };
+
+                query = match params.ending_at {
+                    Some(ending_at) => query.filter(pi_dsl::created_at.le(ending_at)),
+                    None => query,
+                };
+
+                query = match params.amount_filter {
+                    Some(AmountFilter {
+                        start_amount: Some(start),
+                        end_amount: Some(end),
+                    }) => query.filter(pi_dsl::amount.between(start, end)),
+                    Some(AmountFilter {
+                        start_amount: Some(start),
+                        end_amount: None,
+                    }) => query.filter(pi_dsl::amount.ge(start)),
+                    Some(AmountFilter {
+                        start_amount: None,
+                        end_amount: Some(end),
+                    }) => query.filter(pi_dsl::amount.le(end)),
+                    _ => query,
+                };
+
+                query = match &params.currency {
+                    Some(currency) => query.filter(pi_dsl::currency.eq(*currency)),
+                    None => query,
+                };
+
+                query = match &params.status {
+                    Some(status) => query.filter(pi_dsl::status.eq(*status)),
+                    None => query,
+                };
+
+                query
+            }
+        };
+
+        db_metrics::track_database_call::<<DieselPaymentIntent as HasTable>::Table, _, _>(
+            query.get_results_async::<Option<String>>(conn),
+            db_metrics::DatabaseOperation::Filter,
+        )
+        .await
+        .map_err(|er| {
+            StorageError::DatabaseError(
+                error_stack::report!(diesel_models::errors::DatabaseError::from(er))
+                    .attach_printable("Error filtering payment records"),
+            )
+            .into()
+        })
+    }
+
     #[cfg(all(feature = "v1", feature = "olap"))]
     #[instrument(skip_all)]
     async fn get_filtered_active_attempt_ids_for_total_count(

## 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 -->
Added `Payments - List` endpoint for v2

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

- Request:

```
curl --location 'http://localhost:8080/v2/payments/list?profile_id=pro_4jOKADI7FmJF09Sp30bM' \
--header 'Content-Type: application/json' \
--header 'x-profile-id: pro_syRDLhwbDPVbVgrDQDN5' \
--header 'api-key: dev_S529hQ8b0xLFAC4WvYFOgM9VFvUkxB8btBfmxVh83pejCCBmB33wK7ujJYoVcKAe'
```

- Response:

```json
{
    "count": 3,
    "total_count": 3,
    "data": [
        {
            "id": "12345_pay_0195129a6d6b79c0b0fc459fc0fc4ba8",
            "merchant_id": "cloth_seller_VbtyEBrzigIhWiWgxQWr",
            "profile_id": "pro_4jOKADI7FmJF09Sp30bM",
            "customer_id": "12345_cus_01951299cc277621a6c26053d1f98145",
            "payment_method_id": null,
            "status": "requires_payment_method",
            "amount": {
                "order_amount": 100,
                "currency": "USD",
                "shipping_cost": null,
                "order_tax_amount": null,
                "external_tax_calculation": "skip",
                "surcharge_calculation": "skip",
                "surcharge_amount": null,
                "tax_on_surcharge": null,
                "net_amount": 100,
                "amount_to_capture": null,
                "amount_capturable": 0,
                "amount_captured": null
            },
            "created": "2025-02-17T06:31:05.333Z",
            "payment_method_type": null,
            "payment_method_subtype": null,
            "connector": null,
            "merchant_connector_id": null,
            "customer": null,
            "merchant_reference_id": null,
            "connector_payment_id": null,
            "connector_response_reference_id": null,
            "metadata": null,
            "description": null,
            "authentication_type": "no_three_ds",
            "capture_method": "manual",
            "setup_future_usage": "on_session",
            "attempt_count": 0,
            "error": null,
            "cancellation_reason": null,
            "order_details": null,
            "return_url": null,
            "statement_descriptor": null,
            "allowed_payment_method_types": null,
            "authorization_count": 0,
            "modified_at": null
        },
        {
            "id": "12345_pay_0195129973837d138240f54b307544f6",
            "merchant_id": "cloth_seller_VbtyEBrzigIhWiWgxQWr",
            "profile_id": "pro_4jOKADI7FmJF09Sp30bM",
            "customer_id": null,
            "payment_method_id": null,
            "status": "requires_payment_method",
            "amount": {
                "order_amount": 100,
                "currency": "USD",
                "shipping_cost": null,
                "order_tax_amount": null,
                "external_tax_calculation": "skip",
                "surcharge_calculation": "skip",
                "surcharge_amount": null,
                "tax_on_surcharge": null,
                "net_amount": 100,
                "amount_to_capture": null,
                "amount_capturable": 0,
                "amount_captured": null
            },
            "created": "2025-02-17T06:30:01.356Z",
            "payment_method_type": null,
            "payment_method_subtype": null,
            "connector": null,
            "merchant_connector_id": null,
            "customer": null,
            "merchant_reference_id": null,
            "connector_payment_id": null,
            "connector_response_reference_id": null,
            "metadata": null,
            "description": null,
            "authentication_type": "no_three_ds",
            "capture_method": "manual",
            "setup_future_usage": "on_session",
            "attempt_count": 0,
            "error": null,
            "cancellation_reason": null,
            "order_details": null,
            "return_url": null,
            "statement_descriptor": null,
            "allowed_payment_method_types": null,
            "authorization_count": 0,
            "modified_at": null
        },
        {
            "id": "12345_pay_019512991b037d12b1a6c6be6e9ec825",
            "merchant_id": "cloth_seller_VbtyEBrzigIhWiWgxQWr",
            "profile_id": "pro_4jOKADI7FmJF09Sp30bM",
            "customer_id": null,
            "payment_method_id": null,
            "status": "requires_capture",
            "amount": {
                "order_amount": 100,
                "currency": "USD",
                "shipping_cost": null,
                "order_tax_amount": null,
                "external_tax_calculation": "skip",
                "surcharge_calculation": "skip",
                "surcharge_amount": null,
                "tax_on_surcharge": null,
                "net_amount": 100,
                "amount_to_capture": null,
                "amount_capturable": 100,
                "amount_captured": 0
            },
            "created": "2025-02-17T06:29:38.704Z",
            "payment_method_type": "card",
            "payment_method_subtype": "credit",
            "connector": "stripe",
            "merchant_connector_id": "mca_ONJ7YPf8ct3Mnvxir8d3",
            "customer": null,
            "merchant_reference_id": null,
            "connector_payment_id": "pi_3QtNq2EKQ8UQWeo41P082tvk",
            "connector_response_reference_id": null,
            "metadata": null,
            "description": null,
            "authentication_type": "no_three_ds",
            "capture_method": "manual",
            "setup_future_usage": "on_session",
            "attempt_count": 0,
            "error": null,
            "cancellation_reason": null,
            "order_details": null,
            "return_url": null,
            "statement_descriptor": null,
            "allowed_payment_method_types": null,
            "authorization_count": 0,
            "modified_at": "2025-02-17T06:29:55.623Z"
        }
    ]
}
```

## 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`
- [x] I reviewed the submitted code
- [ ] I added unit tests for my changes where possible
