External Payment Processing with Peach allows you to handle all payment processing through your own payment processor while keeping Peach's system updated about payment statuses.
With this approach, you'll process payments outside of Peach's system, and then update Peach about the status of those payments through API calls. Peach is responsible for overall loan servicing management, and will apply payments to loan balances based on your payment updates via API calls, and according to your configured payment waterfall, providing borrowers with a consistent portal experience.
- CVV Storage: Peach cannot store card CVV numbers due to PCI compliance. Some card processors can process cards without CVV, while others cannot.
- Borrower Experience: Borrowers will still use Peach's Borrower Portal to schedule payments, but the actual processing happens through your system.
- Troubleshooting Complexity: Since payment processing happens outside Peach, troubleshooting payment issues may require coordination between systems.
- Engineering Resources: Implementing external payment processing requires significant engineering resources compared to using Peach's direct processing options.
First, you'll need to inform Peach that you'll be processing payments externally.
Contact Peach to update your configuration:
- Reach out to your Peach implementation engineer
- Request that your account be configured for external payment processing
- Confirm the change has been applied to your account
Payment instruments in Peach represent the methods borrowers use to make payments (bank accounts, debit/credit cards, etc.). For external processing, these instruments must be marked as external.
POST /api/people/{personId}/payment-instruments
Content-Type: application/json
X-API-KEY: <YOUR-API-KEY>
{
"accountHolderName": "John Doe",
"accountHolderType": "personal",
"accountNumber": "4995672067",
"accountType": "savings",
"instrumentType": "bankAccount",
"routingNumber": "123456789",
"createdAt": "2023-01-01T00:00:00Z",
"updatedAt": "2023-01-01T00:00:00Z",
"deletedAt": null,
"isExternal": true,
"pendingAt": null,
"externalId": "ext-123",
"status": "pending",
"inactiveReason": "updated",
"verified": false,
"nickname": "My Savings",
"institutionName": "Example Bank",
"sendNotice": true
}
Response
The following response shows a successful creation of an external payment instrument (status code 201). The created bank account has ID "PT-MJ1O-WMRJ", is marked as active, verified, and configured for external processing (isExternal:true).
{
"status": 201,
"data": [
{
"createdAt": "2025-03-13T03:17:43.416082+00:00",
"updatedAt": "2025-03-13T03:17:43.429024+00:00",
"deletedAt": null,
"id": "PT-MJ1O-WMRJ",
"object": "bankAccount",
"externalId": null,
"companyId": "CP-L9BN-5J52",
"instrumentType": "bankAccount",
"status": "active",
"inactiveReason": null,
"activeAt": "2025-03-13T03:17:42.934412+00:00",
"inactiveAt": null,
"pendingAt": null,
"nickname": "Personal Bank Account",
"verified": true,
"isExternal": true,
"failureReason": null,
"failureDescriptionShort": null,
"failureDescriptionLong": null,
"accountNumber": "cv94slu8dsjs73900l20",
"accountNumberLastFour": "2323",
"routingNumber": "021313103",
"accountType": "checking",
"accountHolderType": "personal",
"accountHolderName": "Jane Borrower",
"institutionName": "CITIZENS BANK NA",
"accountLink": null
}
],
"message": "Created payment instrument"
}For existing payment instruments, update them to mark them as external:
PUT https://api.peachfinance.com/api/people/{personId}/payment-instruments/{instrumentId}
Content-Type: application/json
X-API-KEY: <YOUR-API-KEY>
{
"isExternal": true
}Note: Peach can help bulk update existing payment instruments to isExternal=true upon request.
When borrowers add payment methods through the Borrower Portal, they'll be created with:
- isExternal=true
- status=pending (for manually entered methods)
- status=active (for bank accounts added via Plaid)
For manually added payment instruments, you'll need to verify and activate them:
PUT https://api.peachfinance.com/api/people/{personId}/payment-instruments/{instrumentId}
Content-Type: application/json
X-API-KEY: <YOUR-API-KEY>
{
"status": "active",
"verified": true
}To know when to process payments, you'll need to listen for events from Peach, such as:
- payment.scheduled - When a payment is first scheduled
- payment.due.today - When a scheduled payment is due
POST https://api.peachfinance.com/api/webhooks
Content-Type: application/json
X-API-KEY: <YOUR-API-KEY>
{
"webhookType": "direct",
"eventTypes": [
"payment.scheduled",
"payment.due.today"
],
"enabled": true,
"hydrateData": false,
"webhookDirectDetails": {
"webhookUrl": "https://webhook.site/bbdfd6e1-ce89-4995-8e73-379ebd0464b1"
}
}Your webhook endpoint should:
- Validate the webhook signature
- Parse the webhook payload
- Process the event based on its type
When you receive a payment.due.today event, you'll need to process the payment with your payment processor.
From the webhook payload, extract:
- Loan ID
- Payment amount
- Payment instrument details
- Due date
Use your payment processor's API to process the payment:
- Submit the payment to your processor
- Capture the processor's reference ID
- Store the mapping between Peach's transaction ID and your processor's reference ID
As the payment moves through its lifecycle with your processor, update its status in Peach.
Note: External transactions created with status initiated, pending, or succeeded are immediately applied to the loan balance.
PUT https://api.peachfinance.com/api/people/{personId}/loans/{loanId}/transactions/{transactionId}
Content-Type: application/json
X-API-KEY: <YOUR-API-KEY>
{
"amount": 150.00,
"paymentInstrumentId": "PT-MJ1O-WMRJ",
"type": "oneTime",
"status": "initiated"
}PUT https://api.peachfinance.com/api/people/{personId}/loans/{loanId}/transactions/{transactionId}
Content-Type: application/json
X-API-KEY: <YOUR-API-KEY>
{
"amount": 150.00,
"paymentInstrumentId": "PT-MJ1O-WMRJ",
"type": "oneTime",
"status": "pending"
}PUT https://api.peachfinance.com/api/people/{personId}/loans/{loanId}/transactions/{transactionId}
Content-Type: application/json
X-API-KEY: <YOUR-API-KEY>
{
"amount": 150.00,
"paymentInstrumentId": "PT-MJ1O-WMRJ",
"type": "oneTime",
"status": "succeeded"
}PUT https://api.peachfinance.com/api/people/{personId}/loans/{loanId}/transactions/{transactionId}
Content-Type: application/json
X-API-KEY: <YOUR-API-KEY>
{
"amount": 150.00,
"paymentInstrumentId": "PT-MJ1O-WMRJ",
"type": "oneTime",
"status": "failed"
}Important: When a payment fails, Peach will automatically trigger a replay to adjust the loan balance, removing the payment's impact on balances, and recalculating interest as if the payment never happened.
The response will include an associated transactionId (TX-1A1A-2B2B) for each status change.
For borrowers enrolled in Autopay, Peach will generate scheduled transactions according to the Autopay schedule. When these transactions are due, Peach will send a payment.due.today event:
- Receive the payment.due.today event for an Autopay payment
- Process the payment with your payment processor
- Update the transaction status in Peach as the payment progresses
You can also create new transactions to record payments that were processed outside Peach:
POST https://api.peachfinance.com/api/people/{personId}/loans/{loanId}/transactions
Content-Type: application/json
X-API-KEY: <YOUR-API-KEY>
{
"amount": 100.0,
"type": "oneTime",
"isExternal": true,
"externalId": "your-external-transaction-id",
"paymentInstrumentId": "payment-instrument-id",
"status": "succeeded"
}maybe: When a borrower makes a payment, the transaction may pass through one or more of the below statuses as it's processed:
- scheduled - Payment is scheduled for a future date; not yet applied to the loan balance
- initiated - Payment has been initiated with the processor; applied to the loan balance
- pending - Payment is being processed; applied to the loan balance
- succeeded - Payment was successfully completed; remains applied to the loan balance
- failed - Payment failed; removed from the loan balance with a loan replay
- inDispute - Payment is in dispute; removed from the loan balance with a loan replay
- canceled - Payment was canceled before processing (only available for scheduled status)
- chargeback - Payment was disputed and ruled against the lender; removed from the loan balance
- Payment Instrument Not Found: Ensure the payment instrument exists and is marked as external
- Invalid Transaction Status Transition: Check that you're following the allowed status transition flows
- Missing Required Fields: Verify all required fields are included in your requests
- Authentication Failures: Confirm your API key is valid and has the necessary permissions
If your Peach account is configured with Galileo for third-party notification:
- Make createPayment() API calls to Galileo when receiving payment.created or payment.initiated webhooks
- Make createAdjustment() API calls to Galileo when receiving payment.reversed webhooks
- Make these calls regardless of payment instrument type or isExternal status
- BYOB Processing — An alternative where Peach generates NACHA files but your bank settles.
- Payment Processing Overview — Index of payment processing options and concepts.