Skip to main content
Version: RK Auto

Admin Payment History API

Author(s)

  • Amarnath Garai

Last Updated Date

2026-06-03


Feature Overview

Admin users need a paginated payment history view that is grouped by invoice. Each invoice record includes invoice totals, invoice line items, all payment attempts for that invoice, customer basic information, and service request basic information.

This API is intended for admin payment history screens, reconciliation support, and operational review of failed, expired, processing, and successful payment attempts.


Endpoint

EndpointMethodAuth ScopeResponse
/payments/historyGETadmin_userServerPaginatedData<PaymentHistoryResponse>

Authorization

Requires JWT bearer authentication and both admin scopes:

Authorization: Bearer <access_token>

Query Parameters

The endpoint uses AdminPaymentHistoryFilter as query parameters.

ParameterTypeRequiredDefaultDescription
invoiceIdGuid?No-Filter by a specific invoice ID.
serviceRequestIdGuid?No-Filter by a specific service request ID.
customerIdGuid?No-Filter by a specific customer ID.
invoicePaymentStatusPaymentStatus?No-Filter by invoice-level payment status.
paymentStatusTransactionStatus?No-Filter invoices that have at least one payment attempt with this status.
searchKeywordstring?No-Searches invoice number, request number, customer code, customer name/email, payment reference number, trace ID, and transaction ID.
fromDateDateTime?No-Filter invoices created on or after this date.
toDateDateTime?No-Filter invoices created on or before this date.
rowsPerPageintNo10Number of invoices per page. Values below 1 are reset to 10.
pageNumberintNo1Page number to return. Values below 1 are reset to 1.

Enum Values

PaymentStatus is the invoice-level payment status:

Pending
Paid
PartiallyPaid
Refunded
PartiallyRefunded
Failed

TransactionStatus is the individual payment attempt status:

Initiated
Processing
Success
Failed
Expired
Cancelled
Refunded
PartiallyRefunded

Other response enums:

PaymentMethod: NewCard, SavedCard
RequestStatus: Pending, Assigned, EnRoute, InProgress, Stopped, Completed, Canceled, Accepted, Ringing
ServiceScheduleType: OnDemand, Scheduled
LocationPreference: CustomerLocation, ServiceCenter
Gender: Male, Female, Others

DTOs

AdminPaymentHistoryFilter

public record AdminPaymentHistoryFilter
{
public Guid? InvoiceId { get; init; }
public Guid? ServiceRequestId { get; init; }
public Guid? CustomerId { get; init; }
public PaymentStatus? InvoicePaymentStatus { get; init; }
public TransactionStatus? PaymentStatus { get; init; }
public string? SearchKeyword { get; init; }
public DateTime? FromDate { get; init; }
public DateTime? ToDate { get; init; }
public int RowsPerPage { get; init; } = 10;
public int PageNumber { get; init; } = 1;
}

ServerPaginatedData

public class ServerPaginatedData<T>
{
public List<T> Data { get; set; } = [];
public int TotalNumber { get; set; }
public bool HasPreviousPage { get; set; }
public bool HasNextPage { get; set; }
public int TotalPages { get; set; }
public int PageNumber { get; set; }
public int RowsPerPage { get; set; }
}

PaymentHistoryResponse

public record PaymentHistoryResponse
{
public Guid InvoiceId { get; init; }
public string InvoiceNumber { get; init; } = string.Empty;
public Guid ServiceRequestId { get; init; }
public decimal SubTotal { get; init; }
public decimal TaxAmount { get; init; }
public decimal DiscountAmount { get; init; }
public decimal TotalAmount { get; init; }
public decimal PaidAmount { get; init; }
public decimal DueAmount { get; init; }
public PaymentStatus InvoicePaymentStatus { get; init; }
public string? TransactionNo { get; init; }
public DateTime CreatedAt { get; init; }
public DateTime? UpdatedAt { get; init; }
public required CustomerBasicInfo Customer { get; init; }
public required PaymentServiceRequestBasicInfo ServiceRequest { get; init; }
public List<InvoiceItemResponse> InvoiceItems { get; init; } = new();
public List<PaymentAttemptResponse> Payments { get; init; } = new();
}

CustomerBasicInfo

public record CustomerBasicInfo
{
public Guid UserId { get; init; }
public Guid CustomerId { get; init; }
public string CustomerCode { get; init; } = string.Empty;
public string Email { get; init; } = string.Empty;
public string FirstName { get; init; } = string.Empty;
public string LastName { get; init; } = string.Empty;
public string PhoneNumber { get; init; } = string.Empty;
public string? ProfileImageUrl { get; set; }
public Gender? Gender { get; init; }
public bool? IsDeleted { get; init; } = false;
}

PaymentServiceRequestBasicInfo

public record PaymentServiceRequestBasicInfo
{
public Guid RequestId { get; init; }
public string RequestNumber { get; init; } = string.Empty;
public RequestStatus RequestStatus { get; init; }
public ServiceScheduleType ServiceScheduleType { get; init; }
public LocationPreference LocationPreference { get; init; }
public DateTime RequestedAt { get; init; }
public DateTime? ScheduledAt { get; init; }
public DateTime? CompletedAt { get; init; }
public string? Location { get; init; }
public decimal? EstimatedPrice { get; init; }
}

InvoiceItemResponse

public record InvoiceItemResponse
{
public Guid InvoiceItemId { get; init; }
public Guid? ServiceId { get; init; }
public string? ServiceCode { get; init; }
public string ServiceName { get; init; } = string.Empty;
public decimal UnitPrice { get; init; }
public int Quantity { get; init; }
public decimal SubTotal { get; init; }
public decimal TaxAmount { get; init; }
public decimal DiscountAmount { get; init; }
public decimal TotalAmount { get; init; }
}

PaymentAttemptResponse

public record PaymentAttemptResponse
{
public Guid PaymentId { get; init; }
public PaymentMethod PaymentMethod { get; init; }
public TransactionStatus PaymentStatus { get; init; }
public decimal TotalAmount { get; init; }
public string ReferenceNumber { get; init; } = string.Empty;
public string? TraceId { get; init; }
public string? TransactionId { get; init; }
public DateTime? ExpireAt { get; init; }
public DateTime? InitiatedAt { get; init; }
public DateTime? CompletedAt { get; init; }
public DateTime? FailedAt { get; init; }
public string? Message { get; init; }
public string? AuthCode { get; init; }
public string? CardBrand { get; init; }
public string? Last4 { get; init; }
public bool SaveTokenRequested { get; init; }
public string? GatewayRequest { get; init; }
public string? GatewayResponse { get; init; }
public string? WebhookPayload { get; init; }
public DateTime CreatedAt { get; init; }
public DateTime UpdatedAt { get; init; }
}

Error Response

public record CommonResponse
{
public int Status { get; init; }
public string? Message { get; init; }
}

Example Requests

Fetch Failed Payment Attempts

GET /payments/history?paymentStatus=Failed&pageNumber=1&rowsPerPage=10
Authorization: Bearer <access_token>

Fetch Paid Invoices for a Customer

GET /payments/history?customerId=7bc33308-4a95-49ab-b209-9f102f1774d4&invoicePaymentStatus=Paid&pageNumber=1&rowsPerPage=10
Authorization: Bearer <access_token>

Search by Invoice, Request, Customer, or Gateway Reference

GET /payments/history?searchKeyword=INV-20260603-00012&pageNumber=1&rowsPerPage=10
Authorization: Bearer <access_token>

Example Success Response

{
"data": [
{
"invoiceId": "f79f2366-5d79-4c06-9ae5-4f1d2c3e35b5",
"invoiceNumber": "INV-20260603-00012",
"serviceRequestId": "4a3b1e93-1b58-4e8f-a0fd-55a130e5a77a",
"subTotal": 175.00,
"taxAmount": 14.00,
"discountAmount": 0.00,
"totalAmount": 189.00,
"paidAmount": 189.00,
"dueAmount": 0.00,
"invoicePaymentStatus": "Paid",
"transactionNo": "TXN-RKA-20260603-00001",
"createdAt": "2026-06-03T09:15:12Z",
"updatedAt": "2026-06-03T09:20:31Z",
"customer": {
"userId": "3d951196-5f56-4a6f-bd10-73237a48699d",
"customerId": "7bc33308-4a95-49ab-b209-9f102f1774d4",
"customerCode": "CUST-00045",
"email": "customer@example.com",
"firstName": "Alex",
"lastName": "Morgan",
"phoneNumber": "+14155552671",
"profileImageUrl": null,
"gender": "Male",
"isDeleted": false
},
"serviceRequest": {
"requestId": "4a3b1e93-1b58-4e8f-a0fd-55a130e5a77a",
"requestNumber": "RKA-26-A000836",
"requestStatus": "Completed",
"serviceScheduleType": "OnDemand",
"locationPreference": "CustomerLocation",
"requestedAt": "2026-06-03T08:30:00Z",
"scheduledAt": null,
"completedAt": "2026-06-03T09:05:00Z",
"location": "124 Cherry Drive, St. Louis, MO",
"estimatedPrice": 175.00
},
"invoiceItems": [
{
"invoiceItemId": "7db0ae2f-5a35-41a6-8e3d-d3555307e42c",
"serviceId": "21f5681c-0206-482a-85c0-bbcfa0e1c179",
"serviceCode": "OIL-CHANGE",
"serviceName": "Oil Change",
"unitPrice": 75.00,
"quantity": 1,
"subTotal": 75.00,
"taxAmount": 6.00,
"discountAmount": 0.00,
"totalAmount": 81.00
},
{
"invoiceItemId": "e13aacfa-c729-42d5-8a32-0e8615e33388",
"serviceId": "f0790ff3-2bc8-4843-a990-35f556879d73",
"serviceCode": "BRAKE-INSP",
"serviceName": "Brake Inspection",
"unitPrice": 100.00,
"quantity": 1,
"subTotal": 100.00,
"taxAmount": 8.00,
"discountAmount": 0.00,
"totalAmount": 108.00
}
],
"payments": [
{
"paymentId": "95d16a16-c2c2-4aaf-9d01-b2b5aaac810e",
"paymentMethod": "NewCard",
"paymentStatus": "Success",
"totalAmount": 189.00,
"referenceNumber": "RKA-26-A000836",
"traceId": "trace-92f42",
"transactionId": "DP-99887766",
"expireAt": "2026-06-03T09:25:00Z",
"initiatedAt": "2026-06-03T09:16:00Z",
"completedAt": "2026-06-03T09:20:31Z",
"failedAt": null,
"message": null,
"authCode": "A12345",
"cardBrand": "Visa",
"last4": "4242",
"saveTokenRequested": false,
"gatewayRequest": "{\"amount\":189.00,\"currency\":\"USD\"}",
"gatewayResponse": "{\"status\":\"approved\",\"authCode\":\"A12345\"}",
"webhookPayload": "{\"event\":\"payment.success\",\"paymentId\":\"95d16a16-c2c2-4aaf-9d01-b2b5aaac810e\"}",
"createdAt": "2026-06-03T09:16:00Z",
"updatedAt": "2026-06-03T09:20:31Z"
},
{
"paymentId": "94cc7347-013f-4eb7-a4bc-a597cc60e504",
"paymentMethod": "NewCard",
"paymentStatus": "Failed",
"totalAmount": 189.00,
"referenceNumber": "RKA-26-A000836",
"traceId": "trace-80ac1",
"transactionId": null,
"expireAt": "2026-06-03T09:10:00Z",
"initiatedAt": "2026-06-03T09:05:00Z",
"completedAt": null,
"failedAt": "2026-06-03T09:08:42Z",
"message": "Card declined",
"authCode": null,
"cardBrand": "Visa",
"last4": "1111",
"saveTokenRequested": false,
"gatewayRequest": "{\"amount\":189.00,\"currency\":\"USD\"}",
"gatewayResponse": "{\"status\":\"declined\",\"reason\":\"Card declined\"}",
"webhookPayload": null,
"createdAt": "2026-06-03T09:05:00Z",
"updatedAt": "2026-06-03T09:08:42Z"
}
]
}
],
"totalNumber": 1,
"hasPreviousPage": false,
"hasNextPage": false,
"totalPages": 1,
"pageNumber": 1,
"rowsPerPage": 10
}

Error Responses

400 Bad Request

Returned for invalid filter values, such as fromDate greater than toDate.

{
"status": 2,
"message": "FromDate cannot be greater than ToDate"
}

403 Forbidden

Returned when the caller does not have the required admin scopes.

{
"status": 401,
"message": "Forbidden"
}

500 Internal Server Error

Returned when the service or database layer fails unexpectedly.

{
"status": 500,
"message": "Failed to retrieve payment history"
}

Data Loading Notes

  • Pagination is invoice-based, not payment-attempt-based.
  • Each returned invoice includes all payment attempts for that invoice.
  • Filtering by paymentStatus returns invoices that have at least one payment attempt with that status.
  • The response intentionally excludes checkout URL and async processing ID.
  • Payment attempts are ordered newest first.