Delete Payor
Description: Deletes the payor profile and all associated saved payment methods for a merchant with the given IDs. This is a soft delete operation - the payor record is marked as deleted but remains in the system for historical and audit purposes.
Path Parameters
Authentication
This endpoint requires bearer token authentication using the Authorization header.
Code Examples
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
public class PayorClient
{
private readonly HttpClient _httpClient;
private readonly string _baseUrl = "https://your-api-domain.com"; // Replace with actual base URL
private readonly string _bearerToken;
public PayorClient(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> DeletePayorAsync(
string merchantId,
string payorId)
{
try
{
// Construct the endpoint URL
string endpoint = $"/v1/rest/merchants/{merchantId}/payors/{payorId}";
// Make the DELETE request
HttpResponseMessage response = await _httpClient.DeleteAsync(endpoint);
// 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;
}
}
public async Task<bool> DeletePayorWithConfirmationAsync(
string merchantId,
string payorId)
{
try
{
Console.WriteLine("WARNING: This will delete the payor and all saved payment methods.");
Console.Write("Are you sure you want to proceed? (yes/no): ");
string confirmation = Console.ReadLine();
if (confirmation?.ToLower() != "yes")
{
Console.WriteLine("Delete operation cancelled.");
return false;
}
// Proceed with deletion
string endpoint = $"/v1/rest/merchants/{merchantId}/payors/{payorId}";
HttpResponseMessage response = await _httpClient.DeleteAsync(endpoint);
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Payor deleted successfully.");
return true;
}
else if (response.StatusCode == System.Net.HttpStatusCode.Conflict)
{
Console.WriteLine("Payor was already deleted.");
return false;
}
else
{
Console.WriteLine($"Delete failed with status code: {response.StatusCode}");
return false;
}
}
catch (HttpRequestException e)
{
Console.WriteLine($"Request error: {e.Message}");
throw;
}
}
}
// Example usage: Simple delete
var client = new PayorClient("your-bearer-token-here");
string result = await client.DeletePayorAsync(
"12345678901", // merchantId
"5513027774438108364" // payorId
);
Console.WriteLine(result);
// Example usage: Delete with confirmation
bool wasDeleted = await client.DeletePayorWithConfirmationAsync(
"12345678901", // merchantId
"5513027774438108364" // payorId
);
Imports System
Imports System.Net.Http
Imports System.Net.Http.Headers
Imports System.Threading.Tasks
Public Class PayorClient
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 DeletePayorAsync(
merchantId As String,
payorId As String) As Task(Of String)
Try
' Construct the endpoint URL
Dim endpoint As String = $"/v1/rest/merchants/{merchantId}/payors/{payorId}"
' Make the DELETE request
Dim response As HttpResponseMessage = Await _httpClient.DeleteAsync(endpoint)
' 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
Public Async Function DeletePayorWithConfirmationAsync(
merchantId As String,
payorId As String) As Task(Of Boolean)
Try
Console.WriteLine("WARNING: This will delete the payor and all saved payment methods.")
Console.Write("Are you sure you want to proceed? (yes/no): ")
Dim confirmation As String = Console.ReadLine()
If confirmation?.ToLower() <> "yes" Then
Console.WriteLine("Delete operation cancelled.")
Return False
End If
' Proceed with deletion
Dim endpoint As String = $"/v1/rest/merchants/{merchantId}/payors/{payorId}"
Dim response As HttpResponseMessage = Await _httpClient.DeleteAsync(endpoint)
If response.IsSuccessStatusCode Then
Console.WriteLine("Payor deleted successfully.")
Return True
ElseIf response.StatusCode = Net.HttpStatusCode.Conflict Then
Console.WriteLine("Payor was already deleted.")
Return False
Else
Console.WriteLine($"Delete failed with status code: {response.StatusCode}")
Return False
End If
Catch e As HttpRequestException
Console.WriteLine($"Request error: {e.Message}")
Throw
End Try
End Function
End Class
' Example usage: Simple delete
Dim client As New PayorClient("your-bearer-token-here")
Dim result As String = Await client.DeletePayorAsync(
"12345678901", ' merchantId
"5513027774438108364" ' payorId
)
Console.WriteLine(result)
' Example usage: Delete with confirmation
Dim wasDeleted As Boolean = Await client.DeletePayorWithConfirmationAsync(
"12345678901", ' merchantId
"5513027774438108364" ' payorId
)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class PayorClient {
private final HttpClient httpClient;
private final String baseUrl;
private final String bearerToken;
public PayorClient(String baseUrl, String bearerToken) {
this.baseUrl = baseUrl;
this.bearerToken = bearerToken;
this.httpClient = HttpClient.newHttpClient();
}
public String deletePayor(String merchantId, String payorId)
throws IOException, InterruptedException {
try {
// Construct the endpoint URL
String endpoint = String.format("%s/v1/rest/merchants/%s/payors/%s",
baseUrl, merchantId, payorId);
// Build the HTTP request
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(endpoint))
.header("Authorization", "Bearer " + bearerToken)
.header("Accept", "application/json")
.DELETE()
.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;
}
}
public boolean deletePayorWithConfirmation(String merchantId, String payorId)
throws IOException, InterruptedException {
try {
System.out.println("WARNING: This will delete the payor and all saved payment methods.");
System.out.print("Are you sure you want to proceed? (yes/no): ");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String confirmation = reader.readLine();
if (!"yes".equalsIgnoreCase(confirmation)) {
System.out.println("Delete operation cancelled.");
return false;
}
// Proceed with deletion
String endpoint = String.format("%s/v1/rest/merchants/%s/payors/%s",
baseUrl, merchantId, payorId);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(endpoint))
.header("Authorization", "Bearer " + bearerToken)
.header("Accept", "application/json")
.DELETE()
.build();
HttpResponse<String> response = httpClient.send(request,
HttpResponse.BodyHandlers.ofString());
if (response.statusCode() >= 200 && response.statusCode() < 300) {
System.out.println("Payor deleted successfully.");
return true;
} else if (response.statusCode() == 409) {
System.out.println("Payor was already deleted.");
return false;
} else {
System.out.println("Delete failed with status code: " + response.statusCode());
return false;
}
} catch (IOException | InterruptedException e) {
System.err.println("Request error: " + e.getMessage());
throw e;
}
}
// Example usage
public static void main(String[] args) {
try {
PayorClient client = new PayorClient(
"https://your-api-domain.com",
"your-bearer-token-here"
);
// Simple delete
String result = client.deletePayor("12345678901", "5513027774438108364");
System.out.println(result);
// Delete with confirmation
boolean wasDeleted = client.deletePayorWithConfirmation(
"12345678901",
"5513027774438108364"
);
System.out.println("Was deleted: " + wasDeleted);
} catch (Exception e) {
e.printStackTrace();
}
}
}
require 'net/http'
require 'uri'
require 'json'
class PayorClient
def initialize(base_url, bearer_token)
@base_url = base_url
@bearer_token = bearer_token
end
def delete_payor(merchant_id, payor_id)
# Construct the endpoint URL
endpoint = "#{@base_url}/v1/rest/merchants/#{merchant_id}/payors/#{payor_id}"
uri = URI(endpoint)
# Create HTTP request
request = Net::HTTP::Delete.new(uri)
request['Authorization'] = "Bearer #{@bearer_token}"
request['Accept'] = 'application/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
def delete_payor_with_confirmation(merchant_id, payor_id)
puts 'WARNING: This will delete the payor and all saved payment methods.'
print 'Are you sure you want to proceed? (yes/no): '
confirmation = gets.chomp
unless confirmation.downcase == 'yes'
puts 'Delete operation cancelled.'
return false
end
# Proceed with deletion
endpoint = "#{@base_url}/v1/rest/merchants/#{merchant_id}/payors/#{payor_id}"
uri = URI(endpoint)
request = Net::HTTP::Delete.new(uri)
request['Authorization'] = "Bearer #{@bearer_token}"
request['Accept'] = 'application/json'
response = Net::HTTP.start(uri.hostname, uri.port,
use_ssl: uri.scheme == 'https') do |http|
http.request(request)
end
case response
when Net::HTTPSuccess
puts 'Payor deleted successfully.'
true
when Net::HTTPConflict
puts 'Payor was already deleted.'
false
else
puts "Delete failed with status code: #{response.code}"
false
end
rescue StandardError => e
puts "Request error: #{e.message}"
raise
end
end
# Example usage
begin
client = PayorClient.new(
'https://your-api-domain.com',
'your-bearer-token-here'
)
# Simple delete
result = client.delete_payor('12345678901', '5513027774438108364')
puts result
# Delete with confirmation
was_deleted = client.delete_payor_with_confirmation(
'12345678901',
'5513027774438108364'
)
puts "Was deleted: #{was_deleted}"
rescue => e
puts "Error: #{e.message}"
end
Response Format
The response returns the deleted payor's information with the isDeleted flag set to true and the deletedDate populated. The response follows the same PayorResponse schema as the GET endpoint.
Success Response (HTTP 200)
{
"responseStatus": "Accepted",
"responseMessage": "Payor deleted successfully",
"responseCode": "200",
"responseReason": null,
"responseResult": "success",
"legacyResponseCode": "A",
"correlationId": "delete-123-456-789",
"customAttributes": null,
"payorId": "5513027774438108364",
"payorIdLimitedBitFlag": true,
"applicationId": "14",
"customerAccountId": "CUST-12345",
"createdDate": "2024-01-15T10:30:00Z",
"isDeleted": true,
"accountStatus": "Deleted",
"deletedDate": "2026-04-02T14:23:45Z",
"defaultSavedPaymentMethodId": null,
"savedPaymentMethodIds": [],
"savedPaymentMethods": [],
"customerData": {
"originalAccountType": "Premium",
"deletedBy": "CustomerService"
}
}
Response Fields
The response contains all standard PayorResponse fields. Key fields to note after deletion:
| Field | Type | Description |
|---|---|---|
| responseStatus | string | Typically "Accepted" for successful deletion |
| isDeleted | boolean | Set to true after successful deletion |
| deletedDate | string (date-time) | The timestamp when the payor was deleted (UTC) |
| accountStatus | string | Changed to indicate deleted status |
| savedPaymentMethodIds | array | Empty array - all payment methods are deleted |
| savedPaymentMethods | array | Empty array - all payment methods are deleted |
| defaultSavedPaymentMethodId | string | Set to null - no default payment method after deletion |
| correlationId | string | Logging correlation ID for troubleshooting |
HTTP Status Codes
| Status Code | Description |
|---|---|
| 200 | Success - Payor and all associated payment methods deleted successfully |
| 400 | Bad Request - Invalid merchantId or payorId format |
| 404 | Not Found - Payor with the specified ID does not exist for this merchant |
| 409 | Conflict - Payor has already been deleted (idempotent operation detected) |
| 500 | Internal Server Error - Server encountered an unexpected error |
Error Responses
Already Deleted Error (HTTP 409)
{
"responseStatus": "Error",
"responseMessage": "Payor has already been deleted",
"responseCode": "409",
"responseReason": "The payor was previously deleted and cannot be deleted again",
"responseResult": "failure",
"correlationId": "error-409-123-456",
"payorId": "5513027774438108364",
"isDeleted": true,
"deletedDate": "2026-03-15T10:00:00Z"
}
Not Found Error (HTTP 404)
{
"responseStatus": "NotFound",
"responseMessage": "Payor not found",
"responseCode": "404",
"responseReason": "No payor exists with the specified ID for this merchant",
"responseResult": "failure",
"correlationId": "error-404-789-012"
}
What Gets Deleted
When you delete a payor, the following are affected:
- Payor Profile: The payor record is soft-deleted (marked as deleted but retained in the database)
- All Saved Payment Methods: All credit cards and ACH accounts associated with this payor are deleted (marked as deleted but retained in the database)
- Default Payment Method: The default payment method designation is removed
- Historical Data: Transaction history remains intact for reporting and audit purposes
What is NOT deleted:
- Historical transaction records - these are preserved for accounting and compliance
- The payor record itself (soft delete) - it's marked as deleted but remains in the database
- The saved payment records (soft delete) - all are marked as deleted but remain in the database
Soft Delete vs Hard Delete
This endpoint performs a soft delete, which means:
| Aspect | Soft Delete (This Endpoint) | Hard Delete |
|---|---|---|
| Data Retention | Record remains in database, marked as deleted | Record permanently removed from database |
| Audit Trail | Full audit trail preserved | Audit trail lost |
| Recovery | Possible to restore (with support assistance) | Not recoverable |
| Historical Reports | Payor still appears in historical reports | Payor missing from all reports |
| Compliance | Meets regulatory retention requirements | May violate retention policies |
Best Practices
1. Always Confirm Before Deleting
Implement a confirmation dialog or step to ensure the user really wants to delete the payor. Consider requiring explicit user action (typing "DELETE" or clicking a confirmation button).
// Example confirmation pattern
public async Task<bool> SafeDeletePayorAsync(string merchantId, string payorId)
{
// First, retrieve the payor to show user what will be deleted
var payor = await GetPayorByIdAsync(merchantId, payorId);
Console.WriteLine($"You are about to delete:");
Console.WriteLine($" Payor ID: {payor.PayorId}");
Console.WriteLine($" Customer Account: {payor.CustomerAccountId}");
Console.WriteLine($" Payment Methods: {payor.SavedPaymentMethodIds?.Count ?? 0}");
Console.WriteLine();
Console.Write("Type 'DELETE' to confirm: ");
if (Console.ReadLine() == "DELETE")
{
await DeletePayorAsync(merchantId, payorId);
return true;
}
return false;
}
2. Check for Active Subscriptions or Pending Transactions
Before deleting a payor, verify there are no active subscriptions or pending transactions that rely on this payor's payment methods.
3. Handle the 409 Conflict Status Gracefully
A 409 status means the payor was already deleted. This is not necessarily an error - treat it as idempotent and inform the user that the payor is already deleted.
if (response.StatusCode == HttpStatusCode.Conflict)
{
Console.WriteLine("This payor was already deleted.");
// Don't throw an exception - this is an acceptable state
}
4. Log All Deletion Requests
Maintain an audit log of all payor deletions, including who requested the deletion, when it occurred, and the reason (if available).
await AuditLog.LogAsync(new AuditEntry
{
Action = "DeletePayor",
UserId = currentUserId,
MerchantId = merchantId,
PayorId = payorId,
Timestamp = DateTime.UtcNow,
Reason = deletionReason,
CorrelationId = response.CorrelationId
});
5. Notify Affected Users
If appropriate for your application, send a notification to the account holder confirming their payment profile has been removed.
6. Handle Cascading Effects
Consider what else in your system depends on this payor:
- Cancel any scheduled/recurring payments
- Update any UI that displays this payor
- Invalidate any cached payor data
- Check for any saved references to the deleted payment methods
Common Use Cases
1. Customer Account Closure
When a customer closes their account and wants all payment information removed:
// Complete account closure workflow await CancelAllScheduledPayments(merchantId, payorId); await DeletePayorAsync(merchantId, payorId); await SendAccountClosureEmail(customerEmail); await UpdateCustomerAccountStatus(customerAccountId, "Closed");
2. Data Privacy Compliance (GDPR, CCPA)
When a customer requests deletion of their personal data:
// Right to be forgotten / data deletion request await DeletePayorAsync(merchantId, payorId); await AnonymizeTransactionHistory(payorId); await LogDataDeletionRequest(customerId, "GDPR Request");
3. Duplicate Account Cleanup
When duplicate payor profiles are identified and need to be consolidated:
// Merge and cleanup duplicate accounts await MigrateTransactionHistory(duplicatePayorId, primaryPayorId); await DeletePayorAsync(merchantId, duplicatePayorId); await LogAccountMerge(primaryPayorId, duplicatePayorId);
4. Test Data Cleanup
When cleaning up test or demo accounts from production:
// Batch cleanup of test accounts
var testPayors = await GetTestPayorsAsync(merchantId);
foreach (var testPayorId in testPayors)
{
try
{
await DeletePayorAsync(merchantId, testPayorId);
Console.WriteLine($"Deleted test payor: {testPayorId}");
}
catch (Exception ex)
{
Console.WriteLine($"Failed to delete {testPayorId}: {ex.Message}");
}
}
Idempotency
This endpoint exhibits idempotent behavior for already-deleted payors. If you attempt to delete a payor that was already deleted, you'll receive a 409 Conflict response. This allows you to safely retry delete operations without worrying about causing errors.
First delete: Returns 200 Success
Subsequent deletes: Returns 409 Conflict (already deleted)
Recovery from Accidental Deletion
- Contact Procare Pay support immediately
- Provide the
correlationIdfrom the delete response - Provide the
merchantIdandpayorId - Support may be able to restore the payor profile, but this is not guaranteed
- Time is critical - contact support as soon as possible
Troubleshooting
- This means the payor was already deleted - this is normal for repeated delete requests
- Check the
isDeletedflag anddeletedDatein the response to see when it was deleted - This is not an error condition - treat as a successful idempotent operation
- Update your UI to reflect that the payor is already deleted
- Verify the payorId is correct and exists for the specified merchant
- Check that the merchantId is correct (must be exactly 11 digits)
- The payor may have never existed or was hard-deleted (rare)
- Verify you have the correct environment (production vs. sandbox)
- The payor is soft-deleted and may still appear in historical queries
- Check the
isDeletedflag when retrieving payors - Filter out deleted payors in your application logic:
where !isDeleted - Clear any cached data after deletion
- Contact Procare Pay support immediately with the correlationId
- Provide merchantId, payorId, and approximate deletion time
- Support may be able to restore the payor (not guaranteed)
- The sooner you contact support, the better chance of recovery
Security Considerations
- Authorization: Ensure the user has permission to delete payors for this merchant
- Audit Logging: Always log who deleted the payor, when, and why
- Confirmation: Require explicit user confirmation before deleting
- Rate Limiting: Monitor for unusual deletion patterns that might indicate abuse
- Notification: Consider notifying the account holder when their profile is deleted
- Data Retention: Understand your organization's data retention policies before implementing deletion
Additional Notes
- The
merchantIdmust be exactly 11 digits. Requests with invalid formats will return a 400 Bad Request error. - All saved payment methods associated with the payor are automatically deleted as part of this operation.
- Transaction history is preserved even after payor deletion for compliance and reporting purposes.
- Deleted payors cannot be used for new transactions but remain visible in historical reports.
- The
correlationIdin the response is crucial for troubleshooting and should be logged. - This is a soft delete - the record remains in the database with
isDeleted: true. - You cannot create a new payor with the same ID as a deleted payor.
- Attempting to update or retrieve a deleted payor may return the deleted record with
isDeleted: true.
Related Endpoints
- GET /v1/rest/merchants/{merchantId}/payors/{payorId} - Retrieve payor details (may return deleted payors)
- GET /v1/rest/merchants/{merchantId}/payors - List payors (may include deleted payors based on filters)
- DELETE /v1/rest/merchants/{merchantId}/payors/{payorId}/savedPaymentMethods/{savedPaymentMethodId} - Delete individual payment methods without deleting the payor