Get Saved Payment Methods List
GET
/v1/rest/merchants/{merchantId}/payors/{payorId}/savedPaymentMethods
Description: Retrieves all saved payment methods (credit cards and bank accounts) for a specific payor (customer payment profile).
What is this endpoint used for?
This endpoint lists all payment methods a customer has on file. Think of it like viewing all the cards in someone's wallet:
- Checkout Display: Show customers their saved cards/accounts during payment
- Payment Method Management: Let customers view all their saved payment options
- Default Selection: Identify which payment method is set as default
- Account Dashboard: Display payment methods in customer account settings
- Subscription Management: Show which card is being used for recurring payments
Path Parameters
merchantId (required)
Type: string
Pattern: Must be an 11-digit number
Description: The unique 11-digit merchant identifier
payorId (required)
Type: string
Description: The unique payor (payment profile) identifier
Authentication
This endpoint requires bearer token authentication using the Authorization header.
Note: The bearer token must be a valid Cognito token obtained through the OAuth2 authentication flow.
Code Examples
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Newtonsoft.Json;
public class SavedPaymentMethodResponse
{
[JsonProperty("savedPaymentMethodId")]
public string SavedPaymentMethodId { get; set; }
[JsonProperty("accountType")]
public string AccountType { get; set; }
[JsonProperty("maskedAccountNumber")]
public string MaskedAccountNumber { get; set; }
[JsonProperty("lastFour")]
public string LastFour { get; set; }
[JsonProperty("cardExpiry")]
public string CardExpiry { get; set; }
[JsonProperty("abaRoutingNumber")]
public string AbaRoutingNumber { get; set; }
[JsonProperty("accountHolderFirstName")]
public string AccountHolderFirstName { get; set; }
[JsonProperty("accountHolderLastName")]
public string AccountHolderLastName { get; set; }
[JsonProperty("accountHolderEmail")]
public string AccountHolderEmail { get; set; }
[JsonProperty("isDeleted")]
public bool IsDeleted { get; set; }
[JsonProperty("isDefaultAccount")]
public bool? IsDefaultAccount { get; set; }
[JsonProperty("createdDate")]
public DateTime? CreatedDate { get; set; }
[JsonProperty("sponsorKey")]
public string SponsorKey { get; set; }
}
public class SavedPaymentMethodsClient
{
private readonly HttpClient _httpClient;
private readonly string _baseUrl = "https://your-api-domain.com";
private readonly string _bearerToken;
public SavedPaymentMethodsClient(string bearerToken)
{
_bearerToken = bearerToken;
_httpClient = new HttpClient();
_httpClient.BaseAddress = new Uri(_baseUrl);
_httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", _bearerToken);
_httpClient.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
}
public async Task> GetSavedPaymentMethodsAsync(
string merchantId,
string payorId)
{
try
{
string endpoint = $"/v1/rest/merchants/{merchantId}/payors/{payorId}/savedPaymentMethods";
HttpResponseMessage response = await _httpClient.GetAsync(endpoint);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject>(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Request error: {e.Message}");
throw;
}
}
// Helper: Get only active (non-deleted) payment methods
public async Task> GetActivePaymentMethodsAsync(
string merchantId,
string payorId)
{
var allMethods = await GetSavedPaymentMethodsAsync(merchantId, payorId);
return allMethods.Where(m => !m.IsDeleted).ToList();
}
// Helper: Get default payment method
public async Task GetDefaultPaymentMethodAsync(
string merchantId,
string payorId)
{
var allMethods = await GetSavedPaymentMethodsAsync(merchantId, payorId);
return allMethods.FirstOrDefault(m => m.IsDefaultAccount == true && !m.IsDeleted);
}
}
// Example usage 1: Get all payment methods
var client = new SavedPaymentMethodsClient("your-bearer-token-here");
List paymentMethods =
await client.GetSavedPaymentMethodsAsync("12345678901", "payor123");
foreach (var method in paymentMethods)
{
if (!method.IsDeleted)
{
Console.WriteLine($"{method.AccountType} ending in {method.LastFour}");
if (method.IsDefaultAccount == true)
{
Console.WriteLine(" [Default]");
}
}
}
// Example usage 2: Get default payment method
SavedPaymentMethodResponse defaultMethod =
await client.GetDefaultPaymentMethodAsync("12345678901", "payor123");
if (defaultMethod != null)
{
Console.WriteLine($"Default: {defaultMethod.AccountType} ****{defaultMethod.LastFour}");
}
Imports System.Collections.Generic
Imports System.Linq
Imports System.Net.Http
Imports System.Net.Http.Headers
Imports System.Threading.Tasks
Imports Newtonsoft.Json
Public Class SavedPaymentMethodResponse
<JsonProperty("savedPaymentMethodId")>
Public Property SavedPaymentMethodId As String
<JsonProperty("accountType")>
Public Property AccountType As String
<JsonProperty("maskedAccountNumber")>
Public Property MaskedAccountNumber As String
<JsonProperty("lastFour")>
Public Property LastFour As String
<JsonProperty("cardExpiry")>
Public Property CardExpiry As String
<JsonProperty("isDeleted")>
Public Property IsDeleted As Boolean
<JsonProperty("isDefaultAccount")>
Public Property IsDefaultAccount As Boolean?
End Class
Public Class SavedPaymentMethodsClient
Private ReadOnly _httpClient As HttpClient
Private ReadOnly _baseUrl As String = "https://your-api-domain.com"
Private ReadOnly _bearerToken As String
Public Sub New(bearerToken As String)
_bearerToken = bearerToken
_httpClient = New HttpClient()
_httpClient.BaseAddress = New Uri(_baseUrl)
_httpClient.DefaultRequestHeaders.Authorization = _
New AuthenticationHeaderValue("Bearer", _bearerToken)
End Sub
Public Async Function GetSavedPaymentMethodsAsync(
merchantId As String,
payorId As String) As Task(Of List(Of SavedPaymentMethodResponse))
Try
Dim endpoint As String = $"/v1/rest/merchants/{merchantId}/payors/{payorId}/savedPaymentMethods"
Dim response As HttpResponseMessage = Await _httpClient.GetAsync(endpoint)
response.EnsureSuccessStatusCode()
Dim responseBody As String = Await response.Content.ReadAsStringAsync()
Return JsonConvert.DeserializeObject(Of List(Of SavedPaymentMethodResponse))(responseBody)
Catch ex As HttpRequestException
Console.WriteLine($"Request error: {ex.Message}")
Throw
End Try
End Function
' Helper: Get only active payment methods
Public Async Function GetActivePaymentMethodsAsync(
merchantId As String,
payorId As String) As Task(Of List(Of SavedPaymentMethodResponse))
Dim allMethods = Await GetSavedPaymentMethodsAsync(merchantId, payorId)
Return allMethods.Where(Function(m) Not m.IsDeleted).ToList()
End Function
End Class
' Example usage
Dim client As New SavedPaymentMethodsClient("your-bearer-token-here")
Dim paymentMethods As List(Of SavedPaymentMethodResponse) = _
Await client.GetSavedPaymentMethodsAsync("12345678901", "payor123")
For Each method In paymentMethods
If Not method.IsDeleted Then
Console.WriteLine($"{method.AccountType} ending in {method.LastFour}")
If method.IsDefaultAccount Then
Console.WriteLine(" [Default]")
End If
End If
Next
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.List;
import java.util.stream.Collectors;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
class SavedPaymentMethodResponse {
@SerializedName("savedPaymentMethodId")
private String savedPaymentMethodId;
@SerializedName("accountType")
private String accountType;
@SerializedName("maskedAccountNumber")
private String maskedAccountNumber;
@SerializedName("lastFour")
private String lastFour;
@SerializedName("cardExpiry")
private String cardExpiry;
@SerializedName("isDeleted")
private boolean isDeleted;
@SerializedName("isDefaultAccount")
private Boolean isDefaultAccount;
// Getters
public String getSavedPaymentMethodId() { return savedPaymentMethodId; }
public String getAccountType() { return accountType; }
public String getMaskedAccountNumber() { return maskedAccountNumber; }
public String getLastFour() { return lastFour; }
public String getCardExpiry() { return cardExpiry; }
public boolean isDeleted() { return isDeleted; }
public Boolean getIsDefaultAccount() { return isDefaultAccount; }
}
public class SavedPaymentMethodsClient {
private final HttpClient httpClient;
private final String baseUrl;
private final String bearerToken;
private final Gson gson;
public SavedPaymentMethodsClient(String bearerToken) {
this.bearerToken = bearerToken;
this.baseUrl = "https://your-api-domain.com";
this.httpClient = HttpClient.newHttpClient();
this.gson = new Gson();
}
public List getSavedPaymentMethods(
String merchantId,
String payorId) throws Exception {
String endpoint = baseUrl + "/v1/rest/merchants/" + merchantId +
"/payors/" + payorId + "/savedPaymentMethods";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(endpoint))
.header("Authorization", "Bearer " + bearerToken)
.header("Accept", "application/json")
.GET()
.build();
HttpResponse response = httpClient.send(
request,
HttpResponse.BodyHandlers.ofString()
);
if (response.statusCode() == 200) {
return gson.fromJson(response.body(),
new TypeToken>(){}.getType());
} else if (response.statusCode() == 404) {
throw new Exception("Payor not found");
} else {
throw new Exception("Request failed with status: " + response.statusCode());
}
}
// Helper: Get only active payment methods
public List getActivePaymentMethods(
String merchantId,
String payorId) throws Exception {
List allMethods =
getSavedPaymentMethods(merchantId, payorId);
return allMethods.stream()
.filter(m -> !m.isDeleted())
.collect(Collectors.toList());
}
// Helper: Get default payment method
public SavedPaymentMethodResponse getDefaultPaymentMethod(
String merchantId,
String payorId) throws Exception {
List allMethods =
getSavedPaymentMethods(merchantId, payorId);
return allMethods.stream()
.filter(m -> !m.isDeleted() && Boolean.TRUE.equals(m.getIsDefaultAccount()))
.findFirst()
.orElse(null);
}
public static void main(String[] args) {
try {
SavedPaymentMethodsClient client =
new SavedPaymentMethodsClient("your-bearer-token-here");
List methods =
client.getSavedPaymentMethods("12345678901", "payor123");
for (SavedPaymentMethodResponse method : methods) {
if (!method.isDeleted()) {
System.out.println(method.getAccountType() +
" ending in " + method.getLastFour());
if (Boolean.TRUE.equals(method.getIsDefaultAccount())) {
System.out.println(" [Default]");
}
}
}
// Get default method
SavedPaymentMethodResponse defaultMethod =
client.getDefaultPaymentMethod("12345678901", "payor123");
if (defaultMethod != null) {
System.out.println("\nDefault: " + defaultMethod.getAccountType() +
" ****" + defaultMethod.getLastFour());
}
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
}
require 'net/http'
require 'uri'
require 'json'
class SavedPaymentMethodsClient
def initialize(bearer_token, base_url = 'https://your-api-domain.com')
@bearer_token = bearer_token
@base_url = base_url
end
def get_saved_payment_methods(merchant_id, payor_id)
uri = URI("#{@base_url}/v1/rest/merchants/#{merchant_id}/payors/#{payor_id}/savedPaymentMethods")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true if uri.scheme == 'https'
request = Net::HTTP::Get.new(uri.path)
request['Authorization'] = "Bearer #{@bearer_token}"
request['Accept'] = 'application/json'
response = http.request(request)
case response.code.to_i
when 200
JSON.parse(response.body)
when 404
raise "Payor not found: #{payor_id}"
else
raise "Request failed with status: #{response.code} - #{response.message}"
end
rescue StandardError => e
puts "Request error: #{e.message}"
raise
end
# Helper: Get only active payment methods
def get_active_payment_methods(merchant_id, payor_id)
all_methods = get_saved_payment_methods(merchant_id, payor_id)
all_methods.reject { |m| m['isDeleted'] }
end
# Helper: Get default payment method
def get_default_payment_method(merchant_id, payor_id)
all_methods = get_saved_payment_methods(merchant_id, payor_id)
all_methods.find { |m| m['isDefaultAccount'] && !m['isDeleted'] }
end
end
# Example usage
client = SavedPaymentMethodsClient.new('your-bearer-token-here')
payment_methods = client.get_saved_payment_methods('12345678901', 'payor123')
payment_methods.each do |method|
unless method['isDeleted']
puts "#{method['accountType']} ending in #{method['lastFour']}"
puts ' [Default]' if method['isDefaultAccount']
end
end
# Get default method
default_method = client.get_default_payment_method('12345678901', 'payor123')
if default_method
puts "\nDefault: #{default_method['accountType']} ****#{default_method['lastFour']}"
end
rescue StandardError => e
puts "Request error: #{e.message}"
raise
end
# Helper: Get only active payment methods
def get_active_payment_methods(merchant_id, payor_id)
all_methods = get_saved_payment_methods(merchant_id, payor_id)
all_methods.reject { |m| m['isDeleted'] }
end
# Helper: Get default payment method
def get_default_payment_method(merchant_id, payor_id)
all_methods = get_saved_payment_methods(merchant_id, payor_id)
all_methods.find { |m| m['isDefaultAccount'] && !m['isDeleted'] }
end
end
# Example usage
client = SavedPaymentMethodsClient.new('your-bearer-token-here')
payment_methods = client.get_saved_payment_methods('12345678901', 'payor123')
payment_methods.each do |method|
unless method['isDeleted']
puts "#{method['accountType']} ending in #{method['lastFour']}"
puts ' [Default]' if method['isDefaultAccount']
end
end
# Get default method
default_method = client.get_default_payment_method('12345678901', 'payor123')
if default_method
puts "\nDefault: #{default_method['accountType']} ****#{default_method['lastFour']}"
end
Response Structure
The response is an array of saved payment method objects:
| Field | Type | Description |
|---|---|---|
| savedPaymentMethodId | string | Unique identifier for this payment method |
| accountType | string | Type of account: VISA, MC, AMEX, DISC, ECHK (checking), SAV (savings) |
| maskedAccountNumber | string | Masked card/account number (e.g., "************1234") |
| lastFour | string | Last 4 digits of the card/account number |
| cardExpiry | string | Card expiration date (for credit cards only) |
| abaRoutingNumber | string | Bank routing number (for ACH accounts only) |
| accountHolderFirstName | string | First name on the account |
| accountHolderLastName | string | Last name on the account |
| accountHolderEmail | string | Email address associated with the payment method |
| isDeleted | boolean | Whether this payment method has been deleted |
| isDefaultAccount | boolean | Whether this is the default payment method |
| createdDate | string (date-time) | When the payment method was added |
| deletedDate | string (date-time) | When the payment method was deleted (null if active) |
| sponsorKey | string | Sponsor key associated with this payment method |
Example Response
[
{
"savedPaymentMethodId": "5513027774438108365",
"accountType": "VISA",
"maskedAccountNumber": "************1234",
"lastFour": "1234",
"cardExpiry": "1225",
"accountHolderFirstName": "John",
"accountHolderLastName": "Doe",
"accountHolderEmail": "john.doe@example.com",
"accountHolderStreetLine1": "123 Main St",
"accountHolderCity": "Springfield",
"accountHolderRegion": "IL",
"accountHolderPostalCode": "62701",
"isDeleted": false,
"isDefaultAccount": true,
"createdDate": "2024-01-15T10:30:00Z",
"deletedDate": null,
"sponsorKey": "SPONS123"
},
{
"savedPaymentMethodId": "5513027774438108366",
"accountType": "ECHK",
"maskedAccountNumber": "******7890",
"lastFour": "7890",
"abaRoutingNumber": "123456789",
"accountHolderFirstName": "John",
"accountHolderLastName": "Doe",
"isDeleted": false,
"isDefaultAccount": false,
"createdDate": "2024-02-01T14:20:00Z",
"deletedDate": null
},
{
"savedPaymentMethodId": "5513027774438108367",
"accountType": "MC",
"maskedAccountNumber": "************5678",
"lastFour": "5678",
"cardExpiry": "0626",
"accountHolderFirstName": "John",
"accountHolderLastName": "Doe",
"isDeleted": true,
"isDefaultAccount": false,
"createdDate": "2023-12-10T09:15:00Z",
"deletedDate": "2024-03-01T11:00:00Z"
}
]
HTTP Status Codes
| Status Code | Description |
|---|---|
| 200 | Success - Payment methods retrieved (may be empty array if none exist) |
| 400 | Bad Request - Invalid merchant ID or payor ID format |
| 401 | Unauthorized - Missing or invalid authentication token |
| 404 | Not Found - Payor not found for this merchant |
| 500 | Internal Server Error - Server encountered an unexpected error |
Common Use Cases
1. Display Payment Methods at Checkout
// Show customer their saved cards Listmethods = await client.GetActivePaymentMethodsAsync(merchantId, payorId); if (methods.Any()) { Console.WriteLine("Select a payment method:"); foreach (var method in methods) { string displayName = $"{method.AccountType} ending in {method.LastFour}"; if (!string.IsNullOrEmpty(method.CardExpiry)) { displayName += $" (Exp: {method.CardExpiry})"; } if (method.IsDefaultAccount == true) { displayName += " [Default]"; } Console.WriteLine(displayName); } } else { Console.WriteLine("No saved payment methods. Add one?"); }
2. Show Account Management Page
// Display all payment methods in customer's account settings ListallMethods = await client.GetSavedPaymentMethodsAsync(merchantId, payorId); Console.WriteLine("Your Payment Methods:"); Console.WriteLine("===================="); foreach (var method in allMethods) { if (!method.IsDeleted) { Console.WriteLine($"\n{method.AccountType} ****{method.LastFour}"); Console.WriteLine($"Added: {method.CreatedDate:MM/dd/yyyy}"); if (method.IsDefaultAccount == true) { Console.WriteLine("Status: Default Payment Method"); } Console.WriteLine($"ID: {method.SavedPaymentMethodId}"); Console.WriteLine("[Edit] [Delete] [Set as Default]"); } }
3. Find Default Payment Method for Recurring Billing
// Get default card for subscription charge
SavedPaymentMethodResponse defaultMethod =
await client.GetDefaultPaymentMethodAsync(merchantId, payorId);
if (defaultMethod != null)
{
Console.WriteLine("Charging subscription to:");
Console.WriteLine($"{defaultMethod.AccountType} ****{defaultMethod.LastFour}");
// Process recurring payment
await ProcessRecurringPayment(
merchantId,
payorId,
defaultMethod.SavedPaymentMethodId,
subscriptionAmount
);
}
else
{
Console.WriteLine("No default payment method set. Please select one.");
}
4. Check if Customer Has ACH Account
// See if customer has bank account on file Listmethods = await client.GetActivePaymentMethodsAsync(merchantId, payorId); var achAccounts = methods.Where(m => m.AccountType == "ECHK" || m.AccountType == "SAV" ).ToList(); if (achAccounts.Any()) { Console.WriteLine("ACH payment available:"); foreach (var account in achAccounts) { Console.WriteLine($"{account.AccountType} ****{account.LastFour}"); } }
5. Validate Payment Method Before Transaction
// Before processing, check if payment method exists and is active string selectedPaymentMethodId = GetUserSelection(); Listmethods = await client.GetSavedPaymentMethodsAsync(merchantId, payorId); var selectedMethod = methods.FirstOrDefault(m => m.SavedPaymentMethodId == selectedPaymentMethodId ); if (selectedMethod == null) { Console.WriteLine("Payment method not found"); } else if (selectedMethod.IsDeleted) { Console.WriteLine("This payment method has been deleted"); } else { // Check if card is expired if (!string.IsNullOrEmpty(selectedMethod.CardExpiry)) { if (IsCardExpired(selectedMethod.CardExpiry)) { Console.WriteLine("This card has expired. Please update it."); return; } } // Process transaction await ProcessTransaction(merchantId, payorId, selectedPaymentMethodId, amount); }
Best Practices
- Filter out deleted methods: By default, hide deleted payment methods from customers
- Highlight default method: Clearly indicate which payment method is the default
- Check expiration dates: Warn customers if their credit card is expired or expiring soon
- Cache appropriately: Cache for the duration of a session, but refresh before processing payments
- Handle empty results: Some payors may have no payment methods (all deleted)
- Display card brands: Use
accountTypeto show appropriate card logos (VISA, MC, etc.) - Security consideration: Only show last 4 digits - never display full card numbers
Understanding Deleted Payment Methods
Why are deleted methods still returned?
Deleted payment methods appear in the response for historical and auditing purposes. They allow you to:
- Track which payment methods were previously used
- Maintain transaction history linkage
- Comply with record-keeping requirements
- Provide customer support with complete payment history
Always filter by isDeleted: false when displaying payment options to customers.
Account Type Reference
| Account Type | Description | Additional Fields |
|---|---|---|
| VISA | Visa credit card | cardExpiry, maskedAccountNumber |
| MC | Mastercard credit card | cardExpiry, maskedAccountNumber |
| AMEX | American Express card | cardExpiry, maskedAccountNumber |
| DISC | Discover card | cardExpiry, maskedAccountNumber |
| ECHK | Checking account (ACH) | abaRoutingNumber, maskedAccountNumber |
| SAV | Savings account (ACH) | abaRoutingNumber, maskedAccountNumber |
Troubleshooting
404 Not Found - "Payor not found"
- The payor ID doesn't exist for this merchant
- Verify the payor ID is correct
- Confirm the merchant ID matches the payor's merchant
- Check if payor was deleted
Empty Array Returned
- Payor exists but has no saved payment methods
- All payment methods may have been deleted
- This is normal for newly created payors
- Prompt user to add a payment method
All Methods Show isDeleted: true
- Customer has deleted all their payment methods
- Filter active methods returns empty list
- Prompt customer to add a new payment method
Related Endpoints
- GET /v1/rest/merchants/{merchantId}/payors/{payorId}/savedPaymentMethods/{id} - Get single payment method details
- POST /v1/rest/merchants/{merchantId}/payors/{payorId}/savedPaymentMethods - Add a new payment method
- PUT /v1/rest/merchants/{merchantId}/payors/{payorId}/savedPaymentMethods/{id} - Update a payment method
- DELETE /v1/rest/merchants/{merchantId}/payors/{payorId}/savedPaymentMethods/{id} - Delete a payment method
Additional Notes
- The response includes both active and deleted payment methods by default
- Only one payment method can be marked as default at a time
- The
maskedAccountNumberis safe to display - it contains no sensitive information - For credit cards, check the
cardExpiryfield to warn about expired cards - For ACH, the
abaRoutingNumberis not masked (it's not considered sensitive) - The
sponsorKeycan be used to track which sponsor/program the payment method belongs to - Billing address fields (street, city, region, postal code) are included if they were provided during creation
- The response order is not guaranteed - sort by
isDefaultAccountandcreatedDateas needed