Update Saved Payment Method
Description: Updates a saved payment method for the specified merchant, payor, and payment method. This endpoint allows you to update account holder information, billing address, and other payment method details.
Path Parameters
Authentication
This endpoint requires bearer token authentication using the Authorization header.
Request Body Fields
| Field | Type | Required | Description |
|---|---|---|---|
| idLimitedBitFlag | boolean | Optional | Indicates whether IDs use 64-bit integer format (true) or GUID format (false) |
| paymentMethodType | string | Optional | The payment method type: "Checking", "Saving", "CreditCard", or "Null". Used when updating to specify the account type. |
| customerAccountType | string | Optional | User-defined external account type (e.g., "Primary", "Backup", "Business") |
| customerAccountId | string | Optional | The external customer ID for the payor profile |
| encryptedAccountNumber | string | Optional | Encrypted account number (credit card or bank account). If you need to change the account number, create a new payment method instead of updating. |
| cardExpiry | string | Optional | Credit card expiration in MMyy, MMyyyy, or yyyyMMdd format. Required for credit cards, not applicable for ACH. |
| abaRoutingNumber | string | Optional | Bank routing (ABA) number for ACH accounts. Required for ACH, not applicable for credit cards. |
| accountHolderFirstName | string | Optional | The first name of the account holder |
| accountHolderLastName | string | Optional | The last name of the account holder |
| accountHolderStreetLine1 | string | Optional | The first line of the billing street address |
| accountHolderStreetLine2 | string | Optional | The second line of the billing street address (apartment, suite, etc.) |
| accountHolderCity | string | Optional | The billing address city |
| accountHolderRegion | string | Optional | The billing address region/state/province |
| accountHolderPostalCode | string | Optional | The billing address postal/ZIP code |
| accountHolderPhoneNumber | string | Optional | The account holder's phone number |
| accountHolderEmail | string | Optional | The account holder's email address |
| setAsDefaultPaymentMethod | boolean | Optional | Set to true to make this payment method the default for this payor. Default: false |
| customerData | object | Optional | Key-value pairs for storing custom metadata (e.g., {"notes": "Updated card", "priority": "high"}) |
| sponsorKey | string | Optional | Sponsor key (max 8 characters). Must not be empty string if provided. |
| allowTransactionalEmails | boolean | Optional | Whether to allow transactional emails. Automatically set to false if email is null/empty. |
Code Examples
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
public class SavedPaymentMethodUpdateRequest
{
[JsonProperty("cardExpiry")]
public string CardExpiry { get; set; }
[JsonProperty("accountHolderFirstName")]
public string AccountHolderFirstName { get; set; }
[JsonProperty("accountHolderLastName")]
public string AccountHolderLastName { get; set; }
[JsonProperty("accountHolderStreetLine1")]
public string AccountHolderStreetLine1 { get; set; }
[JsonProperty("accountHolderStreetLine2")]
public string AccountHolderStreetLine2 { get; set; }
[JsonProperty("accountHolderCity")]
public string AccountHolderCity { get; set; }
[JsonProperty("accountHolderRegion")]
public string AccountHolderRegion { get; set; }
[JsonProperty("accountHolderPostalCode")]
public string AccountHolderPostalCode { get; set; }
[JsonProperty("accountHolderPhoneNumber")]
public string AccountHolderPhoneNumber { get; set; }
[JsonProperty("accountHolderEmail")]
public string AccountHolderEmail { get; set; }
[JsonProperty("setAsDefaultPaymentMethod")]
public bool SetAsDefaultPaymentMethod { get; set; }
[JsonProperty("customerData")]
public Dictionary<string, string> CustomerData { get; set; }
[JsonProperty("sponsorKey")]
public string SponsorKey { get; set; }
[JsonProperty("allowTransactionalEmails")]
public bool AllowTransactionalEmails { get; set; }
}
public class SavedPaymentMethodClient
{
private readonly HttpClient _httpClient;
private readonly string _baseUrl = "https://your-api-domain.com"; // Replace with actual base URL
private readonly string _bearerToken;
public SavedPaymentMethodClient(string bearerToken)
{
_bearerToken = bearerToken;
_httpClient = new HttpClient();
_httpClient.BaseAddress = new Uri(_baseUrl);
// Set the Authorization header with bearer token
_httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", _bearerToken);
// Set Accept header to request JSON
_httpClient.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
}
public async Task<string> UpdateSavedPaymentMethodAsync(
string merchantId,
string payorId,
string savedPaymentMethodId,
SavedPaymentMethodUpdateRequest updateRequest)
{
try
{
// Construct the endpoint URL
string endpoint = $"/v1/rest/merchants/{merchantId}/payors/{payorId}" +
$"/savedPaymentMethods/{savedPaymentMethodId}";
// Serialize the request object to JSON
string jsonContent = JsonConvert.SerializeObject(
updateRequest,
Formatting.None,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
var content = new StringContent(
jsonContent,
Encoding.UTF8,
"application/json");
// Make the PUT request
HttpResponseMessage response = await _httpClient.PutAsync(endpoint, content);
// Ensure the request was successful
response.EnsureSuccessStatusCode();
// Read and return the response content as a string
string responseBody = await response.Content.ReadAsStringAsync();
return responseBody;
}
catch (HttpRequestException e)
{
Console.WriteLine($"Request error: {e.Message}");
throw;
}
}
}
// Example usage: Update credit card expiration date and billing address
var updateRequest = new SavedPaymentMethodUpdateRequest
{
CardExpiry = "1227", // December 2027
AccountHolderFirstName = "John",
AccountHolderLastName = "Doe",
AccountHolderStreetLine1 = "456 New Address Ave",
AccountHolderStreetLine2 = "Suite 100",
AccountHolderCity = "Chicago",
AccountHolderRegion = "IL",
AccountHolderPostalCode = "60601",
AccountHolderPhoneNumber = "555-987-6543",
AccountHolderEmail = "john.doe@newdomain.com",
SetAsDefaultPaymentMethod = true,
CustomerData = new Dictionary<string, string>
{
{ "notes", "Updated card expiration and address" },
{ "lastModifiedBy", "CustomerService" }
},
AllowTransactionalEmails = true
};
var client = new SavedPaymentMethodClient("your-bearer-token-here");
string result = await client.UpdateSavedPaymentMethodAsync(
"12345678901", // merchantId
"5513027774438108364", // payorId
"5513027774438108365", // savedPaymentMethodId
updateRequest
);
Console.WriteLine(result);
Imports System
Imports System.Net.Http
Imports System.Net.Http.Headers
Imports System.Text
Imports System.Threading.Tasks
Imports System.Collections.Generic
Imports Newtonsoft.Json
Public Class SavedPaymentMethodUpdateRequest
<JsonProperty("cardExpiry")>
Public Property CardExpiry As String
<JsonProperty("accountHolderFirstName")>
Public Property AccountHolderFirstName As String
<JsonProperty("accountHolderLastName")>
Public Property AccountHolderLastName As String
<JsonProperty("accountHolderStreetLine1")>
Public Property AccountHolderStreetLine1 As String
<JsonProperty("accountHolderStreetLine2")>
Public Property AccountHolderStreetLine2 As String
<JsonProperty("accountHolderCity")>
Public Property AccountHolderCity As String
<JsonProperty("accountHolderRegion")>
Public Property AccountHolderRegion As String
<JsonProperty("accountHolderPostalCode")>
Public Property AccountHolderPostalCode As String
<JsonProperty("accountHolderPhoneNumber")>
Public Property AccountHolderPhoneNumber As String
<JsonProperty("accountHolderEmail")>
Public Property AccountHolderEmail As String
<JsonProperty("setAsDefaultPaymentMethod")>
Public Property SetAsDefaultPaymentMethod As Boolean
<JsonProperty("customerData")>
Public Property CustomerData As Dictionary(Of String, String)
<JsonProperty("sponsorKey")>
Public Property SponsorKey As String
<JsonProperty("allowTransactionalEmails")>
Public Property AllowTransactionalEmails As Boolean
End Class
Public Class SavedPaymentMethodClient
Private ReadOnly _httpClient As HttpClient
Private ReadOnly _baseUrl As String = "https://your-api-domain.com" ' Replace with actual base URL
Private ReadOnly _bearerToken As String
Public Sub New(bearerToken As String)
_bearerToken = bearerToken
_httpClient = New HttpClient()
_httpClient.BaseAddress = New Uri(_baseUrl)
' Set the Authorization header with bearer token
_httpClient.DefaultRequestHeaders.Authorization = _
New AuthenticationHeaderValue("Bearer", _bearerToken)
' Set Accept header to request JSON
_httpClient.DefaultRequestHeaders.Accept.Add( _
New MediaTypeWithQualityHeaderValue("application/json"))
End Sub
Public Async Function UpdateSavedPaymentMethodAsync(
merchantId As String,
payorId As String,
savedPaymentMethodId As String,
updateRequest As SavedPaymentMethodUpdateRequest) As Task(Of String)
Try
' Construct the endpoint URL
Dim endpoint As String = $"/v1/rest/merchants/{merchantId}/payors/{payorId}" & _
$"/savedPaymentMethods/{savedPaymentMethodId}"
' Serialize the request object to JSON
Dim jsonContent As String = JsonConvert.SerializeObject(
updateRequest,
Formatting.None,
New JsonSerializerSettings With {
.NullValueHandling = NullValueHandling.Ignore
})
Dim content = New StringContent(
jsonContent,
Encoding.UTF8,
"application/json")
' Make the PUT request
Dim response As HttpResponseMessage = Await _httpClient.PutAsync(endpoint, content)
' Ensure the request was successful
response.EnsureSuccessStatusCode()
' Read and return the response content as a string
Dim responseBody As String = Await response.Content.ReadAsStringAsync()
Return responseBody
Catch e As HttpRequestException
Console.WriteLine($"Request error: {e.Message}")
Throw
End Try
End Function
End Class
' Example usage: Update credit card expiration date and billing address
Dim updateRequest As New SavedPaymentMethodUpdateRequest With {
.CardExpiry = "1227",
.AccountHolderFirstName = "John",
.AccountHolderLastName = "Doe",
.AccountHolderStreetLine1 = "456 New Address Ave",
.AccountHolderStreetLine2 = "Suite 100",
.AccountHolderCity = "Chicago",
.AccountHolderRegion = "IL",
.AccountHolderPostalCode = "60601",
.AccountHolderPhoneNumber = "555-987-6543",
.AccountHolderEmail = "john.doe@newdomain.com",
.SetAsDefaultPaymentMethod = True,
.CustomerData = New Dictionary(Of String, String) From {
{"notes", "Updated card expiration and address"},
{"lastModifiedBy", "CustomerService"}
},
.AllowTransactionalEmails = True
}
Dim client As New SavedPaymentMethodClient("your-bearer-token-here")
Dim result As String = Await client.UpdateSavedPaymentMethodAsync(
"12345678901", ' merchantId
"5513027774438108364", ' payorId
"5513027774438108365", ' savedPaymentMethodId
updateRequest
)
Console.WriteLine(result)
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
class SavedPaymentMethodUpdateRequest {
@JsonProperty("cardExpiry")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String cardExpiry;
@JsonProperty("accountHolderFirstName")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String accountHolderFirstName;
@JsonProperty("accountHolderLastName")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String accountHolderLastName;
@JsonProperty("accountHolderStreetLine1")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String accountHolderStreetLine1;
@JsonProperty("accountHolderStreetLine2")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String accountHolderStreetLine2;
@JsonProperty("accountHolderCity")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String accountHolderCity;
@JsonProperty("accountHolderRegion")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String accountHolderRegion;
@JsonProperty("accountHolderPostalCode")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String accountHolderPostalCode;
@JsonProperty("accountHolderPhoneNumber")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String accountHolderPhoneNumber;
@JsonProperty("accountHolderEmail")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String accountHolderEmail;
@JsonProperty("setAsDefaultPaymentMethod")
private boolean setAsDefaultPaymentMethod;
@JsonProperty("customerData")
@JsonInclude(JsonInclude.Include.NON_NULL)
private Map<String, String> customerData;
@JsonProperty("sponsorKey")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String sponsorKey;
@JsonProperty("allowTransactionalEmails")
private boolean allowTransactionalEmails;
// Getters and setters
public void setCardExpiry(String cardExpiry) { this.cardExpiry = cardExpiry; }
public void setAccountHolderFirstName(String name) { this.accountHolderFirstName = name; }
public void setAccountHolderLastName(String name) { this.accountHolderLastName = name; }
public void setAccountHolderStreetLine1(String street) { this.accountHolderStreetLine1 = street; }
public void setAccountHolderStreetLine2(String street) { this.accountHolderStreetLine2 = street; }
public void setAccountHolderCity(String city) { this.accountHolderCity = city; }
public void setAccountHolderRegion(String region) { this.accountHolderRegion = region; }
public void setAccountHolderPostalCode(String postalCode) { this.accountHolderPostalCode = postalCode; }
public void setAccountHolderPhoneNumber(String phone) { this.accountHolderPhoneNumber = phone; }
public void setAccountHolderEmail(String email) { this.accountHolderEmail = email; }
public void setSetAsDefaultPaymentMethod(boolean isDefault) { this.setAsDefaultPaymentMethod = isDefault; }
public void setCustomerData(Map<String, String> data) { this.customerData = data; }
public void setSponsorKey(String key) { this.sponsorKey = key; }
public void setAllowTransactionalEmails(boolean allow) { this.allowTransactionalEmails = allow; }
}
public class SavedPaymentMethodClient {
private final HttpClient httpClient;
private final String baseUrl;
private final String bearerToken;
private final ObjectMapper objectMapper;
public SavedPaymentMethodClient(String baseUrl, String bearerToken) {
this.baseUrl = baseUrl;
this.bearerToken = bearerToken;
this.httpClient = HttpClient.newHttpClient();
this.objectMapper = new ObjectMapper();
}
public String updateSavedPaymentMethod(
String merchantId,
String payorId,
String savedPaymentMethodId,
SavedPaymentMethodUpdateRequest updateRequest)
throws IOException, InterruptedException {
try {
// Construct the endpoint URL
String endpoint = String.format("%s/v1/rest/merchants/%s/payors/%s/savedPaymentMethods/%s",
baseUrl, merchantId, payorId, savedPaymentMethodId);
// Serialize the request object to JSON
String jsonContent = objectMapper.writeValueAsString(updateRequest);
// Build the HTTP request
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(endpoint))
.header("Authorization", "Bearer " + bearerToken)
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.PUT(HttpRequest.BodyPublishers.ofString(jsonContent))
.build();
// Send the request and get response
HttpResponse<String> response = httpClient.send(request,
HttpResponse.BodyHandlers.ofString());
// Check if request was successful (status code 200-299)
if (response.statusCode() < 200 || response.statusCode() >= 300) {
throw new RuntimeException("HTTP Error: " + response.statusCode() +
" - " + response.body());
}
// Return the response body
return response.body();
} catch (IOException | InterruptedException e) {
System.err.println("Request error: " + e.getMessage());
throw e;
}
}
// Example usage
public static void main(String[] args) {
try {
SavedPaymentMethodClient client = new SavedPaymentMethodClient(
"https://your-api-domain.com",
"your-bearer-token-here"
);
SavedPaymentMethodUpdateRequest updateRequest = new SavedPaymentMethodUpdateRequest();
updateRequest.setCardExpiry("1227");
updateRequest.setAccountHolderFirstName("John");
updateRequest.setAccountHolderLastName("Doe");
updateRequest.setAccountHolderStreetLine1("456 New Address Ave");
updateRequest.setAccountHolderStreetLine2("Suite 100");
updateRequest.setAccountHolderCity("Chicago");
updateRequest.setAccountHolderRegion("IL");
updateRequest.setAccountHolderPostalCode("60601");
updateRequest.setAccountHolderPhoneNumber("555-987-6543");
updateRequest.setAccountHolderEmail("john.doe@newdomain.com");
updateRequest.setSetAsDefaultPaymentMethod(true);
Map<String, String> customerData = new HashMap<>();
customerData.put("notes", "Updated card expiration and address");
customerData.put("lastModifiedBy", "CustomerService");
updateRequest.setCustomerData(customerData);
updateRequest.setAllowTransactionalEmails(true);
String result = client.updateSavedPaymentMethod(
"12345678901", // merchantId
"5513027774438108364", // payorId
"5513027774438108365", // savedPaymentMethodId
updateRequest
);
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
require 'net/http'
require 'uri'
require 'json'
class SavedPaymentMethodClient
def initialize(base_url, bearer_token)
@base_url = base_url
@bearer_token = bearer_token
end
def update_saved_payment_method(merchant_id, payor_id, saved_payment_method_id, update_request)
# Construct the endpoint URL
endpoint = "#{@base_url}/v1/rest/merchants/#{merchant_id}/payors/#{payor_id}" \
"/savedPaymentMethods/#{saved_payment_method_id}"
uri = URI(endpoint)
# Create HTTP request
request = Net::HTTP::Put.new(uri)
request['Authorization'] = "Bearer #{@bearer_token}"
request['Accept'] = 'application/json'
request['Content-Type'] = 'application/json'
# Serialize request to JSON, removing nil values
request.body = update_request.compact.to_json
# Make the request
response = Net::HTTP.start(uri.hostname, uri.port,
use_ssl: uri.scheme == 'https') do |http|
http.request(request)
end
# Check response status
unless response.is_a?(Net::HTTPSuccess)
raise "HTTP Error: #{response.code} - #{response.message}\n#{response.body}"
end
# Return the response body
response.body
rescue StandardError => e
puts "Request error: #{e.message}"
raise
end
end
# Example usage: Update credit card expiration date and billing address
begin
client = SavedPaymentMethodClient.new(
'https://your-api-domain.com',
'your-bearer-token-here'
)
update_request = {
cardExpiry: '1227',
accountHolderFirstName: 'John',
accountHolderLastName: 'Doe',
accountHolderStreetLine1: '456 New Address Ave',
accountHolderStreetLine2: 'Suite 100',
accountHolderCity: 'Chicago',
accountHolderRegion: 'IL',
accountHolderPostalCode: '60601',
accountHolderPhoneNumber: '555-987-6543',
accountHolderEmail: 'john.doe@newdomain.com',
setAsDefaultPaymentMethod: true,
customerData: {
notes: 'Updated card expiration and address',
lastModifiedBy: 'CustomerService'
},
allowTransactionalEmails: true
}
result = client.update_saved_payment_method(
'12345678901', # merchantId
'5513027774438108364', # payorId
'5513027774438108365', # savedPaymentMethodId
update_request
)
puts result
rescue => e
puts "Error: #{e.message}"
end
Example Request Bodies
Example 1: Update Credit Card Expiration Date
{
"cardExpiry": "1227",
"accountHolderFirstName": "John",
"accountHolderLastName": "Doe",
"accountHolderEmail": "john.doe@example.com"
}
Example 2: Update Billing Address
{
"accountHolderStreetLine1": "789 Oak Street",
"accountHolderStreetLine2": "Apartment 5C",
"accountHolderCity": "Boston",
"accountHolderRegion": "MA",
"accountHolderPostalCode": "02101",
"accountHolderPhoneNumber": "555-111-2222"
}
Example 3: Set as Default Payment Method
{
"setAsDefaultPaymentMethod": true,
"customerData": {
"reason": "Customer requested primary card change",
"changedBy": "CustomerService"
}
}
Example 4: Update Contact Information
{
"accountHolderEmail": "newemail@example.com",
"accountHolderPhoneNumber": "555-999-8888",
"allowTransactionalEmails": true,
"customerData": {
"contactPreference": "email",
"timezone": "America/Chicago"
}
}
Example 5: Update ACH Account Holder Name
{
"accountHolderFirstName": "Jane",
"accountHolderLastName": "Smith-Johnson",
"customerAccountType": "Joint Account",
"customerData": {
"accountOwnership": "joint",
"secondaryHolder": "John Johnson"
}
}
Response Format
The response follows the same format as the GET endpoint, returning the complete updated payment method details. See the Get Saved Payment Method documentation for full response field descriptions.
Success Response (HTTP 200)
{
"responseStatus": "SavedPaymentMethodUpdated",
"responseMessage": "Payment method updated successfully",
"responseCode": "200",
"responseReason": null,
"responseResult": "success",
"legacyResponseCode": "A",
"correlationId": "xyz789-abc123-def456",
"payorId": "5513027774438108364",
"savedPaymentMethodId": "5513027774438108365",
"savedPaymentMethodIdLimitedBitFlag": true,
"createdDate": "2024-01-15T10:30:00Z",
"accountType": "VISA",
"customerAccountId": "CUST-12345",
"customerAccountType": "Primary",
"binId": "dGVzdC1iaW4taWQ",
"maskedAccountNumber": "************1234",
"lastFour": "1234",
"cardExpiry": "1227",
"abaRoutingNumber": null,
"accountHolderFirstName": "John",
"accountHolderLastName": "Doe",
"accountHolderStreetLine1": "456 New Address Ave",
"accountHolderStreetLine2": "Suite 100",
"accountHolderCity": "Chicago",
"accountHolderRegion": "IL",
"accountHolderPostalCode": "60601",
"accountHolderPhoneNumber": "555-987-6543",
"accountHolderEmail": "john.doe@newdomain.com",
"binInformation": {
"binId": "dGVzdC1iaW4taWQ",
"cardType": "Credit",
"brandName": "Visa",
"fundingSource": "Credit",
"bin": "45678901",
"issuerInformation": {
"name": "Example Bank",
"country": "US",
"phoneNumber": "1-800-555-0100"
},
"surcharge": "Allowed"
},
"isDeleted": false,
"deletedDate": null,
"customerData": {
"notes": "Updated card expiration and address",
"lastModifiedBy": "CustomerService"
},
"isDefaultAccount": true,
"sponsorKey": "SPONSOR1",
"allowTransactionalEmails": true
}
HTTP Status Codes
| Status Code | Description |
|---|---|
| 200 | Success - Saved payment method updated successfully |
| 400 | Bad Request - Validation error (invalid data format, missing required fields, or invalid parameter values) |
| 401 | Unauthorized - Invalid or expired bearer token |
| 404 | Not Found - Saved payment method with the specified ID does not exist for this payor and merchant |
| 500 | Internal Server Error - Server encountered an unexpected error |
Common Error Scenarios
Validation Error (HTTP 400)
{
"responseStatus": "SavedPaymentValidationError",
"responseMessage": "Validation failed",
"responseCode": "400",
"responseReason": "Card expiry must be in MMyy, MMyyyy, or yyyyMMdd format",
"responseResult": "failure",
"correlationId": "error-123-456-789"
}
Not Found Error (HTTP 404)
{
"responseStatus": "NotFound",
"responseMessage": "Saved payment method not found",
"responseCode": "404",
"responseReason": "No saved payment method exists with the specified ID for this payor",
"responseResult": "failure",
"correlationId": "error-987-654-321"
}
Data Encryption Requirements
If you need to update the account number itself (which is rare), you must encrypt it before sending:
- Credit Card Numbers (PAN): Must be encrypted using the public key obtained from the
/keys/panendpoint - Bank Account Numbers: Must be encrypted using the public key obtained from the
/keys/sadendpoint - The encrypted value should be placed in the
encryptedAccountNumberfield - In most update scenarios, you should NOT send the account number - only update other fields like expiration, name, or address
Best Practices
1. Partial Updates
Only include fields you want to update in the request body. However, be cautious as some implementations may treat missing fields as "clear this field". It's safest to include all current values and only change the specific fields you need to update.
2. Update Card Expiration Dates Proactively
Monitor card expiration dates and prompt customers to update expiring cards before they expire. This prevents transaction failures and improves customer experience.
3. Verify Updates
After updating a payment method, consider making a GET request to verify the changes were applied correctly.
// After updating, verify the changes
var verifyResult = await client.GetSavedPaymentMethodByIdAsync(
merchantId,
payorId,
savedPaymentMethodId
);
4. Handle Default Payment Method Changes
When setting setAsDefaultPaymentMethod: true, the system will automatically unset the
previous default payment method. Only one payment method can be the default at a time.
5. Preserve Custom Data
If you have existing customerData, merge new values with existing ones rather than replacing
the entire object, unless you intentionally want to clear old custom data.
6. Email Validation
If you set allowTransactionalEmails: true, ensure the accountHolderEmail field
contains a valid email address. The system will automatically set allowTransactionalEmails
to false if the email is null or empty.
Common Use Cases
1. Update Expiring Credit Card
When a customer receives a new card with a new expiration date but the same account number:
{
"cardExpiry": "0328" // March 2028
}
2. Update Billing Address After Move
When a customer moves to a new address:
{
"accountHolderStreetLine1": "123 New Street",
"accountHolderStreetLine2": null,
"accountHolderCity": "New City",
"accountHolderRegion": "NY",
"accountHolderPostalCode": "10001"
}
3. Update Contact Information
When a customer changes their email or phone number:
{
"accountHolderEmail": "newemail@example.com",
"accountHolderPhoneNumber": "555-123-9999",
"allowTransactionalEmails": true
}
4. Mark as Default Payment Method
When a customer wants to change their default payment method:
{
"setAsDefaultPaymentMethod": true
}
5. Update After Name Change
When a customer legally changes their name (marriage, etc.):
{
"accountHolderFirstName": "Jane",
"accountHolderLastName": "NewLastName"
}
Troubleshooting
- Check that
cardExpiryis in the correct format (MMyy, MMyyyy, or yyyyMMdd) - Verify that
sponsorKeyis not an empty string and does not exceed 8 characters - Ensure email addresses are in valid format if provided
- Check that all required fields for the payment method type are included
- Verify the response body to confirm the changes were applied
- Some fields may have validation rules that prevent certain values
- Check if you have proper permissions to update the payment method
- Ensure you're updating the correct savedPaymentMethodId
- Verify the savedPaymentMethodId exists and belongs to the specified payorId
- Check that the merchantId is correct and matches the payor's merchant
- The payment method may have been deleted (check isDeleted status)
Additional Notes
- The
merchantIdmust be exactly 11 digits. Requests with invalid formats will return a 400 Bad Request error. - You cannot change the account number through an update - to use a different account number, delete the old payment method and create a new one.
- Setting a payment method as default will automatically unset any previous default payment method for that payor.
- The
correlationIdin the response is useful for troubleshooting and should be provided when contacting support. - All timestamps in the response are in UTC format.
- The response includes the complete updated payment method details, including any fields that weren't changed.
- Custom attributes in
customerDataare merged with existing data unless you explicitly overwrite the entire object. - Changes take effect immediately and will be used for subsequent transactions.
Security Considerations
- Always use HTTPS for API requests containing sensitive payment information
- Never log or store the full account number in plain text
- Implement proper access controls to ensure only authorized users can update payment methods
- Consider implementing an audit log to track payment method changes
- Validate all input data before sending to the API
- Use the
correlationIdfor tracking and debugging without exposing sensitive data