Back to selected work
Technical implementation guidePeach

Selected technical writing sample

Authored the selected payment processing implementation guide.

Peach Processing Implementation

This guide walks you through implementing Peach's payment processing solution, which allows you to manage loan payments without direct relationships with payment processors or banks. You'll learn how to set up both API integration and borrower-facing components through a practical implementation example.

Overview

The Peach processing implementation enables:

We'll follow a sample lender's implementation through these stages:

  1. Initial setup and configuration
  2. Borrower portal implementation
  3. Payment instrument setup
  4. Payment processing configuration
  5. Transaction monitoring
  6. Additional feature integration

Prerequisites

Before starting this guide, ensure you have:

For setup guidance, refer to:

Borrower Portal Setup

You can set up Peach's Borrower Portal, which provides ready-to-use interfaces for:

  1. Payment Method Management
  1. Autopay Configuration
  1. Payment Processing

For detailed portal configuration, see our Borrower Portal Implementation Guide.

Payment Instrument Setup

Add Bank Account Payment Instrument

The following is an example Create Payment Instrument request. It directs Peach to add a checking account as a payment method for the borrower identified by the personId parameter.

This request includes Plaid integration details to enable account verification and future data syncing.

Let's examine the key components:

  1. The instrumentType field specifies this is a bank account payment method
  2. The account details include:
  1. Additional settings:

Request

POST /api/people/{person_id}/payment-instruments
Content-Type: application/json  
X-API-KEY: <YOUR-API-KEY>

{
   "accountHolderName": "John Doe",
   "accountHolderType": "personal",
   "accountNumber": "<EXAMPLE_ACCOUNT_NUMBER>",
   "accountType": "savings",
   "instrumentType": "bankAccount",
   "routingNumber": "<EXAMPLE_ROUTING_NUMBER>",
   "createdAt": "2023-01-01T00:00:00Z",
   "updatedAt": "2023-01-01T00:00:00Z",
   "deletedAt": null,
   "isExternal": false,
   "pendingAt": null,
   "externalId": "ext-123",
   "status": "pending",
   "inactiveReason": "updated",
   "verified": false,
   "nickname": "My Savings",
   "institutionName": "Example Bank",
   "sendNotice": true
}

Response

The response will include a unique payment instrument ID and mask sensitive data like the account number, showing only the last 4 digits.

{
    "status": 201,
    "data": [
        {
            "createdAt": "2025-03-05T20:59:47.765934+00:00",
            "updatedAt": "2025-03-05T20:59:47.782448+00:00",
            "deletedAt": null,
            "id": "PT-6JYD-EQ5J",
            "object": "bankAccount",
            "externalId": "ext-123",
            "companyId": "CP-L9BN-5J52",
            "instrumentType": "bankAccount",
            "status": "pending",
            "inactiveReason": null,
            "activeAt": null,
            "inactiveAt": null,
            "pendingAt": "2025-03-05T20:59:47.279838+00:00",
            "nickname": "My Savings",
            "verified": false,
            "isExternal": false,
            "failureReason": null,
            "failureDescriptionShort": null,
            "failureDescriptionLong": null,
            "accountNumber": "<EXAMPLE_ACCOUNT_NUMBER>",
            "accountNumberLastFour": "<LAST_FOUR>",
            "routingNumber": "<EXAMPLE_ROUTING_NUMBER>",
            "accountType": "savings",
            "accountHolderType": "personal",
            "accountHolderName": "John Doe",
            "institutionName": "Example Bank",
            "accountLink": null
        }
    ],
    "message": "Created payment instrument"
}

Setting Up Autopay

The following is an example Create Autopay request that schedules recurring weekly payments for Fridays using the bank account associated with paymentInstrumentId. Since isAlignedToDueDates is set to true, these payments will process on the loan's regular due dates.

The request configures:

Request

POST /api/people/{person_id}/loans/{loan_id}/autopay
Content-Type: application/json
X-API-KEY: <YOUR-API-KEY>

{
 "paymentInstrumentId": "PT-OB5R-M8QJ",
 "previewMode": true,
 "isAlignedToDueDates": true,
 "paymentFrequency": "monthly",
 "sendNotice": true
}

Response

The response includes the full autopay schedule with payment details. Note that the actual response may include many more scheduled payments than shown in this example. The deltaTerms object shows potential savings from more frequent payments.

{
  "status": 200,
  "data": {
    "id": "AP-VK2O-3QVB",
    "isLocked": false,
    "createdAt": "2025-03-05T22:37:18.473196+00:00",
    "type": "statementMinimumAmount",
    "extraAmount": 0,
    "isAlignedToDueDates": true,
    "paymentFrequency": "monthly",
    "specificDays": [
      15
    ],
    "paymentInstrumentId": "PT-OB5R-M8QJ",
    "agreementDocumentId": null,
    "schedule": [
      {
        "ids": [
          "AE-KGLQ-E7LB",
          "AE-BW14-LYMK"
        ],
        "amount": 415.25,
        "baseAmount": 0.0,
        "originalAmount": 415.25,
        "originalDate": null,
        "date": "2025-03-06",
        "interestAmount": 0,
        "interestBeforeDiscountAmount": 0,
        "paymentType": "periodicPayment",
        "principalAmount": 0,
        "status": "booked",
        "individualEntries": [
          {
            "date": "2025-03-06",
            "id": "AE-KGLQ-E7LB",
            "periodId": "PE-BM81-7V7V",
            "paymentType": "periodicPayment",
            "status": "booked",
            "amount": 315.25,
            "baseAmount": null,
            "originalAmount": 315.25,
            "originalDate": null,
            "principalAmount": 0.0,
            "interestAmount": 0.0,
            "interestBeforeDiscountAmount": 0.0,
            "dynamicFeeDetails": {
              "loanFeeId": null,
              "dynamicFeeTypeId": null,
              "apiName": null,
              "displayName": null
            },
            "specialFlag": null
          },
          {
            "date": "2025-03-06",
            "id": "AE-BW14-LYMK",
            "periodId": "PE-BM81-7V7V",
            "paymentType": "originationFee",
            "status": "booked",
            "amount": 100.0,
            "baseAmount": null,
            "originalAmount": 100.0,
            "originalDate": null,
            "principalAmount": null,
            "interestAmount": null,
            "interestBeforeDiscountAmount": null,
            "dynamicFeeDetails": {
              "loanFeeId": null,
              "dynamicFeeTypeId": null,
              "apiName": null,
              "displayName": null
            },
            "specialFlag": null
          }
        ]
      },
      {
        "ids": [
          "AE-KEY3-V77B"
        ],
        "amount": 315.25,
        "baseAmount": 0.0,
        "originalAmount": 315.25,
        "originalDate": null,
        "date": "2025-03-15",
        "interestAmount": 0,
        "interestBeforeDiscountAmount": 0,
        "paymentType": "periodicPayment",
        "principalAmount": 0,
        "status": "booked",
        "individualEntries": [
          {
            "date": "2025-03-15",
            "id": "AE-KEY3-V77B",
            "periodId": "PE-KG8Y-131E",
            "paymentType": "periodicPayment",
            "status": "booked",
            "amount": 315.25,
            "baseAmount": null,
            "originalAmount": 315.25,
            "originalDate": null,
            "principalAmount": 0.0,
            "interestAmount": 0.0,
            "interestBeforeDiscountAmount": 0.0,
            "dynamicFeeDetails": {
              "loanFeeId": null,
              "dynamicFeeTypeId": null,
              "apiName": null,
              "displayName": null
            },
            "specialFlag": null
          }
        ]
      }
// Additional payments truncated for brevity
    ],
    "deltaTerms": {
      "deltaInterestAmount": -659.15,
      "deltaFeeAmount": 0,
      "deltaDurationDays": -61,
      "deltaDueDatesNumber": -2
    },
    "offsetFromDueDate": null
  }
}

Payment Processing

Here's how to set up and monitor payment events:

1. Create Webhook Subscription

First, configure your endpoint to receive real-time payment events:

POST /api/webhooks
X-API-KEY: YOUR_API_KEY
Content-Type: application/json

{
 "webhookType": "direct",
 "eventTypes": [
   "payment.initiated",
   "payment.succeeded"
 ],
 "enabled": true,
 "hydrateData": false,
 "webhookDirectDetails": {
   "webhookUrl": "https://api.example.com/webhooks/peach-finance
"
 }
}

This response indicates a successful creation of a webhook subscription and will send notifications to the specified URL whenever payments are initiated or succeed.

{
    "status": 201,
    "data": {
        "createdAt": "2025-03-11T05:23:03.832491+00:00",
        "updatedAt": "2025-03-11T05:23:03.832503+00:00",
        "deletedAt": null,
        "id": "WH-LXX11-CC22",
        "object": "webhook",
        "companyId": "CP-LXX11-CC22",
        "eventTypes": [
            "payment.initiated",
            "payment.succeeded"
        ],
        "hydrateData": false,
        "webhookType": "direct",
        "enabled": true,
        "hmacSecretKey": "<WEBHOOK_SECRET>",
        "webhookDirectDetails": {
            "webhookUrl": "https://api.example.com/webhooks/peach-finance"
        }
    },
    "message": "Webhook created"
}

:

NACHA File Processing

For ACH payments, Peach manages the entire NACHA file process:

  1. Daily Generation (Morning)
  1. Processing Timeline

Transaction Monitoring

Track payment status and loan balances:

Balance Check

GET /api/people/{PERSON_ID}/loans/{LOAN_ID}/balances
X-API-KEY: YOUR_API_KEY

Transaction History

GET /api/people/{PERSON_ID}/loans/{LOAN_ID}/transactions
X-API-KEY: YOUR_API_KEY

Additional Features

Consider implementing these additional features:

  1. Payment Plans
  2. Promise to Pay