Payor Management Overview
This guide provides a comprehensive overview of managing payors (customer payment profiles) and their saved payment methods. Understanding these concepts is essential for implementing recurring billing, subscription services, or any scenario where you need to store customer payment information securely.
What is a Payor?
A payor is a customer payment profile that can store one or more saved payment methods. Think of it as a digital wallet for a customer that can hold multiple credit cards and bank accounts.
Key Benefits of Payors
- Recurring Billing: Store payment methods for subscription or recurring payments
- One-Click Checkout: Enable fast checkout without re-entering card details
- Multiple Payment Options: Allow customers to manage multiple cards or bank accounts
- Payment Method Updates: Easy updates when cards expire or customers want to change their payment method
- PCI Compliance: Reduces your PCI scope by storing encrypted payment data securely
Payor and Saved Payment Method Relationship
Understanding the relationship between payors and saved payment methods is crucial:
- One Payor can have many Saved Payment Methods
- Each payor must have at least one saved payment method
- One saved payment method can be marked as the default
- Each saved payment method belongs to exactly one payor
Data Model
Payor
βββ Payor ID (system-generated)
βββ Customer Account ID (your system's customer ID)
βββ Customer Account Type (optional classification)
βββ Customer Data (custom key-value pairs)
βββ Sponsor Key (optional tracking code)
βββ Saved Payment Methods (1 to many)
βββ Saved Payment Method 1
β βββ Payment Method ID (system-generated)
β βββ Account Type (VISA, MASTERCARD, CHECKING, etc.)
β βββ Masked Account Number (e.g., ************1234)
β βββ Expiry Date (credit cards only)
β βββ Billing Address
β βββ Is Default (true/false)
β βββ Customer Data (custom key-value pairs)
βββ Saved Payment Method 2
βββ Saved Payment Method N
Integrator-Set ID Fields
The API provides several ID fields that you (the integrator) can set to link Payment Gateway entities to your own system's identifiers. These fields are critical for maintaining relationships between your data and the payment system.
customerAccountId
Description:
The customerAccountId is the most important integrator-set field. It should contain your system's
unique customer identifier (e.g., your database's customer ID, account number, or user ID). This field enables
you to look up payors using your own customer identifiers.
Best Practices:
- β Always set this field when creating payors
- β Use your system's primary customer identifier (database ID, account number, etc.)
- β Keep this value stableβdon't change it unless the customer changes in your system
- β Use this field to search for payors:
GET /payors?customerAccountId=YOUR-CUSTOMER-ID - β Store the returned payorId in your database for quick lookups
- β Don't use temporary or session-based IDs
- β Don't include sensitive information (SSN, full names, etc.)
Example Usage:
// Your system's customer ID
string yourCustomerId = "CUST-123456";
// Create payor with your customer ID
var request = new {
customerAccountId = yourCustomerId, // β Links to YOUR system
// ... other fields
};
// Later: Look up payor by your customer ID
var payors = await GetPayorsAsync($"?customerAccountId={yourCustomerId}");
customerAccountType
Description:
An optional field where you can store a customer classification or account type from your system. This could represent customer tiers, account types, business categories, or any other classification meaningful to your application.
Example Use Cases:
- Customer Tiers: "Premium", "Standard", "Basic", "VIP"
- Account Types: "Individual", "Business", "Enterprise", "Non-Profit"
- Service Plans: "Monthly", "Annual", "Pay-As-You-Go"
- Business Categories: "Retail", "Healthcare", "Education", "Daycare"
- Payment Plans: "Autopay", "Manual", "Invoice"
Best Practices:
- β Use consistent, standardized values across your application
- β Use this for filtering or grouping in reports and analytics
- β Document the possible values in your internal documentation
- β Don't use this for dynamic or frequently changing data (use customerData instead)
- β Don't store sensitive classification information
sponsorKey
Description:
A short code (up to 8 characters) that can be used to track which sponsor, program, campaign, or funding source is associated with this payor. This field is particularly useful for organizations that need to track payments by funding source or marketing campaign.
Example Use Cases:
- Funding Sources: "GRANT001", "STATE-CA", "FEDERAL"
- Marketing Campaigns: "SPRING24", "PROMO123", "REF-LINK"
- Sponsors/Partners: "CORP-A", "DONOR123", "PARTNER1"
- Programs: "DAYCARE", "AFTERSCH", "SUMMER"
- Referral Sources: "WEBSITE", "PHONE", "WALKIN"
Best Practices:
- β Use short, memorable codes (maximum 8 characters)
- β Establish a consistent coding scheme
- β Use uppercase for consistency
- β Track this in reports to analyze payment patterns by sponsor/program
- β Don't include spaces or special characters
- β Don't change this value frequentlyβit's meant to be stable
Custom Data (customerData)
The customerData field allows you to store arbitrary key-value pairs with both payors
and saved payment methods. This is your "scratch space" for storing any additional information you
need that doesn't fit into the standard fields.
What is customerData?
customerData is a flexible JSON object where you can store
custom key-value pairs. Both payors and saved payment methods have their own separate customerData fields.
Structure
{
"customerData": {
"key1": "value1",
"key2": "value2",
"key3": "value3",
// ... as many key-value pairs as needed
}
}
When to Use customerData
| Scenario | Use customerData? | Alternative |
|---|---|---|
| Link to your customer ID | β No | Use customerAccountId |
| Classify customer type | β No | Use customerAccountType |
| Track sponsor/program | β No | Use sponsorKey |
| Store billing address | β No | Use standard address fields |
| Store custom app data | β Yes | Perfect use case |
| Store temporary flags | β Yes | Good for dynamic data |
| Store metadata from external systems | β Yes | Ideal for integration data |
Example Use Cases for customerData
Use Case 1: Storing Integration Metadata
{
"customerData": {
"externalSystemId": "EXT-789456",
"externalAccountNumber": "ACC-2024-0123",
"syncStatus": "synced",
"lastSyncDate": "2024-04-07T10:30:00Z"
}
}
Use Case 2: Feature Flags and Preferences
{
"customerData": {
"autoPayEnabled": "true",
"emailReceiptsEnabled": "true",
"preferredPaymentDay": "1",
"notificationPreference": "email"
}
}
Use Case 3: Business-Specific Data (Daycare Example)
{
"customerData": {
"enrolledChildren": "2",
"primaryChildName": "Emma Smith",
"enrollmentDate": "2023-09-01",
"tuitionPlan": "weekly",
"pickupAuthCode": "1234"
}
}
Use Case 4: Payment Method Metadata
{
"customerData": {
"cardNickname": "Personal Visa",
"preferredForRecurring": "true",
"addedBy": "customer-portal",
"verifiedDate": "2024-03-15",
"notes": "Primary payment method for subscriptions"
}
}
Best Practices for customerData
- β Use descriptive key names that clearly indicate the purpose
- β Use camelCase or snake_case consistently
- β Store values as strings (even for numbers/booleans) for consistency
- β Keep key names reasonably short but descriptive
- β Document your custom fields in your internal documentation
- β Use namespacing for complex scenarios (e.g., "integration.salesforce.id")
- β Don't store sensitive data (passwords, SSNs, full credit card numbers)
- β Don't store large amounts of data (keep it lightweight)
- β Don't use special characters in keys (stick to alphanumeric and underscores)
- β Don't store data that changes frequently on every transaction
Common Payor Management Workflows
Workflow 1: First-Time Customer Setup
1. Customer signs up in your system
2. Your system generates customer ID: "CUST-123456"
3. Customer provides payment information through hosted payment page OR your secure form
4. Encrypt payment data (if using direct API)
5. Create payor with:
- customerAccountId = "CUST-123456"
- customerAccountType = "Premium" (optional)
- sponsorKey = "WEB" (optional)
- customerData = { "signupDate": "2024-04-07", "source": "website" }
- First saved payment method with setAsDefault: true
6. Store returned payorId and savedPaymentMethodId in your database
- Your DB: customers table, add columns: payor_id, default_payment_method_id
7. Customer can now make payments using saved payment method
Workflow 2: Looking Up Existing Payor
1. Customer logs into your system
2. Your system knows customer ID: "CUST-123456"
3. Option A: Query your database for stored payorId (fastest)
- SELECT payor_id FROM customers WHERE customer_id = 'CUST-123456'
4. Option B: Search API using customerAccountId
- GET /payors?customerAccountId=CUST-123456
5. Retrieve payment methods for the payor
- GET /payors/{payorId}/savedPaymentMethods
6. Display payment methods to customer
7. Customer selects payment method for transaction
8. Process payment using savedPaymentMethodId
Workflow 3: Adding New Payment Method to Existing Payor
1. Customer wants to add new card to their profile
2. Look up payorId (from your database or API search)
3. Customer provides new payment information
4. Encrypt payment data
5. POST /payors/{payorId}/savedPaymentMethods
- Include: setAsDefault (true/false)
- Include: customerData if needed (e.g., "nickname": "Work Card")
6. Store returned savedPaymentMethodId in your database
7. Optionally delete old payment method if customer requested
8. Update your database with new default payment method if changed
Workflow 4: Updating Expired Card
1. Customer's card is expiring soon (you track expiry dates)
2. Send notification to customer to update card
3. Customer provides new card information
4. Look up payorId
5. Option A: Update existing payment method (if same card, new expiry)
- PUT /payors/{payorId}/savedPaymentMethods/{paymentMethodId}
6. Option B: Add new payment method and delete old (if different card)
- POST /payors/{payorId}/savedPaymentMethods with setAsDefault: true
- DELETE old payment method
7. Update your database with new payment method ID
8. Send confirmation to customer
Workflow 5: Recurring Billing
1. Recurring billing job runs (daily/weekly/monthly)
2. Query your database for customers due for payment
3. For each customer:
a. Retrieve payorId and default savedPaymentMethodId from your database
b. Generate unique transaction ID for idempotency
c. POST /transactions (process sale) using savedPaymentMethodId
d. Record transaction result in your database
e. If payment fails:
- Log failure reason
- Send notification to customer
- Implement retry logic (if appropriate)
- Consider trying alternate payment method if available
f. If payment succeeds:
- Update customer account status
- Send receipt/confirmation
- Update next billing date
Best Practices
Data Synchronization
- Store Essential IDs: Always store payorId and savedPaymentMethodId in your database
- Cache Strategically: Cache payor and payment method data to reduce API calls, but refresh periodically
- Handle Deletions: Be prepared for payment methods or payors to be deletedβimplement proper error handling
- Sync Status: Track sync status in your database (e.g., "synced", "needs-update", "error")
Database Schema Recommendations
-- Customers Table (your existing table) customers βββ id (your primary key) βββ customer_account_id (your customer identifier) βββ payor_id (store Payment Gateway payor ID) βββ default_payment_method_id (store default payment method ID) βββ payor_last_synced (timestamp) βββ ... other customer fields -- Optional: Payment Methods Table (for multiple payment methods) customer_payment_methods βββ id (your primary key) βββ customer_id (foreign key to customers) βββ payor_id (Payment Gateway payor ID) βββ saved_payment_method_id (Payment Gateway payment method ID) βββ account_type (VISA, MASTERCARD, CHECKING, etc.) βββ last_four (last 4 digits for display) βββ expiry_date (for credit cards) βββ is_default (boolean) βββ nickname (optional, for customer to identify) βββ created_at βββ updated_at
Error Handling
- Payment Method Not Found (404): Customer may have deleted itβrefresh your cache and display current methods
- Payor Not Found (404): Rare, but handle gracefullyβmay need to recreate payor
- Validation Errors (400): Display clear error messages to customerβoften due to expired cards or invalid data
- Duplicate customerAccountId (400): A payor already exists for this customerβlook it up instead of creating
Security Considerations
- Never display full account numbersβonly show masked versions (e.g., ************1234)
- Never log or store payment method IDs in plain text logsβuse masked logging
- Validate that the payorId belongs to the correct customer before processing payments
- Implement proper authorization checksβcustomers should only access their own payors
- Use HTTPS for all API communications
- Never expose payorId or savedPaymentMethodId in URLs or client-side code unnecessarily
- Implement proper session management and CSRF protection
Performance Optimization
- Cache Payor IDs: Store payorId in your database to avoid lookup API calls
- Cache Payment Methods: Cache the list of payment methods, refresh when customer updates
- Batch Operations: When querying multiple payors, use the bulk search endpoint with multiple IDs
- Lazy Loading: Only fetch payment method details when neededβdon't load all details upfront
- Database Indexes: Index payorId and savedPaymentMethodId columns in your database
Customer Experience
- Display Friendly Names: Show card type and last 4 digits (e.g., "Visa ending in 1234")
- Allow Nicknames: Let customers nickname their payment methods (store in customerData)
- Show Expiry Warnings: Notify customers 30-60 days before card expiration
- Default Payment Method: Clearly indicate which is the default payment method
- Easy Management: Provide UI for adding, updating, deleting, and setting default payment methods
- Visual Indicators: Use card logos/icons to make payment methods easily recognizable
Testing Checklist
Before going to production, test these scenarios:
| Scenario | Expected Result |
|---|---|
| Create payor with customerAccountId | Payor created, payorId returned, can be found by customerAccountId |
| Create payor with duplicate customerAccountId | 400 error with clear message about duplicate |
| Add second payment method to payor | Payment method added, original default unchanged unless specified |
| Set new payment method as default | New method becomes default, old default flag removed automatically |
| Delete non-default payment method | Method deleted, default unchanged |
| Delete default payment method (only 1 exists) | Cannot delete last payment methodβmust keep at least one |
| Delete default payment method (multiple exist) | Method deleted, another is automatically set as default |
| Update payment method | Expiry date and billing address updated successfully |
| Process payment with saved method | Transaction processed, no need to re-enter card details |
| Process payment after method deleted | 404 error with clear message, handle gracefully in your app |
| Retrieve customerData | Custom fields returned exactly as stored |
| Update customerData | Fields updated, existing fields unchanged unless specified |
Related Documentation
Payor Endpoints
- List Payors - Search for payors by customerAccountId or payorIds
- Create Payor - Create new payor with first payment method
- Get Payor - Retrieve single payor details
- Delete Payor - Delete payor and all payment methods
Saved Payment Method Endpoints
- List Payment Methods - Get all payment methods for a payor
- Add Payment Method - Add new payment method to payor
- Get Payment Method - Retrieve single payment method details
- Update Payment Method - Update expiry date or billing address
- Delete Payment Method - Remove single payment method
- Delete All Methods - Remove all payment methods (deletes payor)
Related Topics
- Integration Best Practices - General integration guidelines
- Get PAN Key - Encryption key for card/account numbers
- Process Transaction - Use saved payment methods for transactions