Reconcile
Handling Batched Payments

Batched Payments

Trace paying transactions to funding payouts and reconcile batched settlements


Payment transactions from customers are batched and settled as deposit transactions to merchant bank accounts. Understanding this relationship is essential for reconciliation, accounting, and financial reporting. Use transfers to trace from individual payments to their funding deposit and vice versa.

Prerequisites

Before working with batched payments, understand:


Understanding Batching


How payment transactions are batched into funding transactions.

Netted funding flow

How payments, payouts, and refunds batch together in netted funding style:

Scenario: Three payments processed, batched into one netted deposit.

Paying transactions (Credits):

Payment A: $150 (type: payment, status: processed)
Payment B: $200 (type: payment, status: processed)
Payment C: $175 (type: payment, status: processed)
Total credits: $525

Funding transaction:

Deposit: $525 (type: deposit)
  ← Transfer from Payment A: $150
  ← Transfer from Payment B: $200
  ← Transfer from Payment C: $175

Bank statement:

Deposit: $525

Netted funding combines all credits into a single deposit that appears on the merchant's bank statement.

Scenario: Payments and refunds processed, netted together into one deposit.

Paying transactions:

Credits:
  Payment A: $150 (type: payment, status: processed)
  Payment B: $200 (type: payment, status: processed)
  Payment C: $175 (type: payment, status: processed)
  Total credits: $525

Debits:
  Refund A: -$50 (type: refund, status: processed)
  Total debits: -$50

Net amount: $475

Funding transaction:

Deposit: $475 (type: deposit)
  ← Transfer from Payment A: $150
  ← Transfer from Payment B: $200
  ← Transfer from Payment C: $175
  ← Transfer from Refund A: -$50

Bank statement:

Deposit: $475

Netted funding combines all credits and debits into a single net deposit amount.

Scenario: More debits than credits results in a net withdrawal.

Paying transactions:

Credits:
  Payment A: $100 (type: payment, status: processed)
  Total credits: $100

Debits:
  Refund A: -$200 (type: refund, status: processed)
  Refund B: -$150 (type: refund, status: processed)
  Total debits: -$350

Net amount: -$250

Funding transaction:

Withdrawal: $250 (type: withdrawal, amount is positive value)
  ← Transfer from Payment A: $100
  ← Transfer from Refund A: -$200
  ← Transfer from Refund B: -$150

Bank statement:

Withdrawal: $250 (funds pulled from merchant account)

When debits exceed credits, netted funding creates a withdrawal from the merchant's bank account.

Scenario: Payment rejected after initial processing, excluded from batch.

Paying transactions:

Payment A: $150 (type: payment, status: processed)
Payment B: $200 (type: payment, status: rejected) ← Rejected
Payment C: $175 (type: payment, status: processed)

Funding transaction:

Deposit: $325 (type: deposit)
  ← Transfer from Payment A: $150
  ← Transfer from Payment C: $175
  (Payment B has no transfer - rejected before funding)

Bank statement:

Deposit: $325

Rejected payments are excluded from the funding batch. If a funding transaction itself is rejected by the bank, no deposit appears and all associated payments remain unfunded until the next batch.

Gross funding flow

How payments and refunds batch separately in gross funding style:

Scenario: Three payments processed, batched into one gross deposit.

Paying transactions (Credits):

Payment A: $150 (type: payment, status: processed)
Payment B: $200 (type: payment, status: processed)
Payment C: $175 (type: payment, status: processed)
Total credits: $525

Funding transaction:

Deposit: $525 (type: deposit)
  ← Transfer from Payment A: $150
  ← Transfer from Payment B: $200
  ← Transfer from Payment C: $175

Bank statement:

Deposit: $525

Gross funding batches all credits into one deposit, similar to netted.

Scenario: Payments and refunds processed, batched into separate transactions.

Paying transactions:

Credits:
  Payment A: $150 (type: payment, status: processed)
  Payment B: $200 (type: payment, status: processed)
  Payment C: $175 (type: payment, status: processed)
  Total credits: $525

Debits:
  Refund A: -$50 (type: refund, status: processed)
  Total debits: -$50

Funding transactions:

Deposit: $525 (type: deposit)
  ← Transfer from Payment A: $150
  ← Transfer from Payment B: $200
  ← Transfer from Payment C: $175

Withdrawal: $50 (type: withdrawal)
  ← Transfer from Refund A: -$50

Bank statement:

Deposit: $525
Withdrawal: $50

Gross funding creates separate deposit and withdrawal transactions, appearing as two entries on the bank statement.

Scenario: Only refunds processed, creating a withdrawal.

Paying transactions (Debits):

Refund A: -$200 (type: refund, status: processed)
Refund B: -$150 (type: refund, status: processed)
Total debits: -$350

Funding transaction:

Withdrawal: $350 (type: withdrawal)
  ← Transfer from Refund A: -$200
  ← Transfer from Refund B: -$150

Bank statement:

Withdrawal: $350

When only debits exist, gross funding creates a withdrawal that pulls funds from the merchant's bank account.

Scenario: Refund rejected after processing, excluded from withdrawal batch.

Paying transactions:

Credits:
  Payment A: $150 (type: payment, status: processed)
  Payment B: $200 (type: payment, status: processed)
  Total credits: $350

Debits:
  Refund A: -$50 (type: refund, status: processed)
  Refund B: -$25 (type: refund, status: rejected) ← Rejected
  Total processed debits: -$50

Funding transactions:

Deposit: $350 (type: deposit)
  ← Transfer from Payment A: $150
  ← Transfer from Payment B: $200

Withdrawal: $50 (type: withdrawal)
  ← Transfer from Refund A: -$50
  (Refund B has no transfer - rejected before funding)

Bank statement:

Deposit: $350
Withdrawal: $50

Rejected refunds are excluded from the withdrawal batch. Credits and debits batch separately regardless of rejections.

Itemized funding flow

How each transaction creates its own funding transaction in itemized style:

Scenario: Three payments processed, each creating its own deposit.

Paying transactions:

Payment A: $150 (type: payment, status: processed)
Payment B: $200 (type: payment, status: processed)
Payment C: $175 (type: payment, status: processed)

Funding transactions:

Deposit A: $150 (type: deposit)
  ← Transfer from Payment A: $150

Deposit B: $200 (type: deposit)
  ← Transfer from Payment B: $200

Deposit C: $175 (type: deposit)
  ← Transfer from Payment C: $175

Bank statement:

Deposit: $150
Deposit: $200
Deposit: $175

Itemized funding creates a one-to-one relationship between payments and deposits. Each deposit traces to exactly one payment via transfers.

Scenario: Payments and refunds processed, each creating separate funding transactions.

Paying transactions:

Payment A: $150 (type: payment, status: processed)
Payment B: $200 (type: payment, status: processed)
Refund A: -$50 (type: refund, status: processed)
Payment C: $175 (type: payment, status: processed)

Funding transactions:

Deposit A: $150 (type: deposit)
  ← Transfer from Payment A: $150

Deposit B: $200 (type: deposit)
  ← Transfer from Payment B: $200

Withdrawal A: $50 (type: withdrawal)
  ← Transfer from Refund A: -$50

Deposit C: $175 (type: deposit)
  ← Transfer from Payment C: $175

Bank statement:

Deposit: $150
Deposit: $200
Withdrawal: $50
Deposit: $175

Each payment creates a deposit, each refund creates a withdrawal. All appear as separate bank statement entries.

Scenario: Merchant pays out to a customer, creating a withdrawal.

Paying transaction:

Payout A: $300 (type: payout, status: processed)

Funding transaction:

Withdrawal: $300 (type: withdrawal)
  ← Transfer from Payout A: $300

Bank statement:

Withdrawal: $300

Payouts create withdrawals that pull funds from the merchant's bank account to send to a customer.

Scenario: Payment rejected before funding, no deposit created.

Paying transactions:

Payment A: $150 (type: payment, status: processed)
Payment B: $200 (type: payment, status: rejected) ← Rejected
Payment C: $175 (type: payment, status: processed)

Funding transactions:

Deposit A: $150 (type: deposit)
  ← Transfer from Payment A: $150

(No funding transaction for Payment B - rejected before funding)

Deposit C: $175 (type: deposit)
  ← Transfer from Payment C: $175

Bank statement:

Deposit: $150
Deposit: $175

Rejected payments never create funding transactions. If a funding deposit itself is rejected by the bank, the associated payment remains unfunded and will be retried in a new deposit transaction.

Transfers


Transfers represent a balance transfer from one transaction to another, linking payment transactions to deposit transactions. Each transfer contains the source and destination transaction IDs, enabling bidirectional tracing between paying transactions and their funding transactions.

Transfer found in a payment transaction, linking to its funding deposit:

{
  "id": "xfer_abc123",
 
  // The payment transaction this transfer belongs to
  "transaction_id": "txn_payment456",
 
  // The deposit transaction this payment funded
  "assoc_transaction_id": "txn_deposit789",
 
  "amount": 150.00,
  "type": "deposit",
 
  "sender": {
    "account_id": "acct_customer"  // Customer paying
  },
 
  "receiver": {
    "account_id": "acct_merchant"  // Merchant receiving payment
  }
}

Tracing forward:

  1. Get payment transaction with transfers field
  2. Find transfer with assoc_transaction_id populated
  3. Fetch deposit using assoc_transaction_id
  4. Verify deposit contains this payment in batch

Transfer found in a deposit transaction, linking back to a component payment:

{
  "id": "xfer_abc123",
 
  // The deposit transaction this transfer belongs to
  "transaction_id": "txn_deposit789",
 
  // The payment transaction that funded this deposit
  "assoc_transaction_id": "txn_payment456",
 
  "amount": 150.00,
  "type": "payment",
 
  "sender": {
    "account_id": "acct_customer"  // Customer who paid
  },
 
  "receiver": {
    "account_id": "acct_merchant"  // Merchant who received deposit
  }
}

Tracing backward:

  1. Get deposit transaction with transfers field
  2. Extract all assoc_transaction_id values from transfers array
  3. Fetch all payment transactions
  4. Calculate totals and verify batch composition

Tracing Batched Payments


Trace from payments to funding and vice versa.

import payload
pl = payload.Session('secret_key_3bW9...', api_version='v2')
 
# Trace payment transactions to their funding deposit
 
# Get a payment transaction and trace to funding
def trace_payment_to_funding(payment_transaction_id):
    # Get the payment transaction with transfers
    payment = pl.Transaction.get(payment_transaction_id, fields='id,type,amount,created_at,transfers')
 
    print('Payment Transaction:')
    print(f'  ID: {payment.id}')
    print(f'  Amount: ${payment.amount}')
    print(f'  Date: {payment.created_at}')
    print(f'  Transfers: {len(payment.transfers)}')
 
    # Find the funding transfer (links to deposit transaction)
    funding_transfer = next(
        (xfer for xfer in payment.transfers
         if xfer.assoc_transaction_id and xfer.assoc_transaction_id.startswith('txn_')),
        None
    )
 
    if funding_transfer:
        # Get the associated deposit transaction
        deposit = pl.Transaction.get(funding_transfer.assoc_transaction_id)
 
        print('\nFunding Deposit Transaction:')
        print(f'  ID: {deposit.id}')
        print(f'  Type: {deposit.type}')
        print(f'  Amount: ${deposit.amount}')
        print(f'  Date: {deposit.created_at}')
        print(f'  Descriptor: {deposit.descriptor}')
 
        return {
            'payment': payment,
            'funding_transfer': funding_transfer,
            'deposit': deposit
        }
    else:
        print('\nNo funding deposit found (may not be settled yet)')
        return {'payment': payment, 'funding_transfer': None, 'deposit': None}
 
# Reverse: Get a deposit and find all payments it includes
def trace_deposits_to_payments(deposit_transaction_id):
    # Get the deposit transaction with transfers
    deposit = pl.Transaction.get(
        deposit_transaction_id,
        fields='id,type,amount,created_at,descriptor,transfers'
    )
 
    print('Deposit Transaction:')
    print(f'  ID: {deposit.id}')
    print(f'  Amount: ${deposit.amount}')
    print(f'  Date: {deposit.created_at}')
    print(f'  Descriptor: {deposit.descriptor}')
    print(f'  Transfers: {len(deposit.transfers)}')
 
    # Get all associated payment transactions
    payment_transaction_ids = [
        xfer.assoc_transaction_id
        for xfer in deposit.transfers
        if xfer.assoc_transaction_id
    ]
 
    if len(payment_transaction_ids) > 0:
        # Fetch all payment transactions
        payments = [pl.Transaction.get(txn_id) for txn_id in payment_transaction_ids]
 
        print(f'\nIncluded Payments: {len(payments)}')
        for index, payment in enumerate(payments, 1):
            print(f'  {index}. {payment.id} - ${payment.amount} - {payment.description}')
 
        # Verify total
        total_payments = sum(p.amount for p in payments)
        print(f'\nTotal payments: ${total_payments:.2f}')
        print(f'Deposit amount: ${deposit.amount:.2f}')
        print(f'Match: {"YES" if abs(total_payments - deposit.amount) < 0.01 else "NO"}')
 
        return {
            'deposit': deposit,
            'payments': payments,
            'total_payments': total_payments
        }
    else:
        print('\nNo associated payment transactions found')
        return {'deposit': deposit, 'payments': [], 'total_payments': 0}
 
# Example usage
payment_id = 'txn_payment123'
trace_payment_to_funding(payment_id)

Follow a payment transaction to its funding deposit.

Process:

  1. Fetch payment transaction with transfers field
  2. Find transfer with assoc_transaction_id pointing to deposit
  3. Fetch associated deposit transaction
  4. Verify amounts and timing

Use cases:

  • Customer asks which bank deposit includes their payment
  • Accounting needs to match payment to settlement
  • Reconciling specific transaction
  • Auditing payment-to-funding flow

Example result:

Payment: txn_payment123 - $150.00
  → Transfer: xfer_abc456
  → Deposit: txn_deposit789 - $525.00 (netted batch)

Follow a funding deposit back to all included payments.

Process:

  1. Fetch deposit transaction with transfers field
  2. Extract all assoc_transaction_id values from transfers
  3. Fetch all associated payment transactions
  4. Calculate totals and verify

Use cases:

  • Bank deposit needs breakdown
  • Reconciling deposit to component payments
  • Accounting period close
  • Verifying batch composition

Example result:

Deposit: txn_deposit789 - $525.00
  ← Payment 1: txn_payment123 - $150.00
  ← Payment 2: txn_payment456 - $200.00
  ← Payment 3: txn_payment789 - $175.00
  Total: $525.00 ✓

Reconciliation Patterns


Common reconciliation scenarios for batched payments.

Reconcile a day's batched funding to component payments.

Scenario: Bank statement shows $15,000 deposit from yesterday's batch.

Process:

  1. Match bank deposit to deposit transaction ($15,000)
  2. Get deposit transaction with transfers
  3. Trace to all payment transactions
  4. Verify total matches bank deposit
  5. Mark all payments as reconciled

Query pattern:

# Find deposit matching bank statement
deposits = pl.Transaction.filter_by(
    q='type == "deposit" && amount == 15000 && est_cleared_date == date("2024-01-15")'
).all()
 
# Get breakdown
deposit = pl.Transaction.select("object", "id", "amount", "transfers").get(deposits[0].id)
 
# Calculate component payments
payment_ids = [xfer.assoc_transaction_id for xfer in deposit.transfers]

Reconcile multiple funding deposits for a period.

Scenario: Weekly accounting close requires matching all deposits to payments.

Process:

  1. Query all deposits for the week
  2. For each deposit, trace to payments
  3. Build complete payment list
  4. Verify no duplicate payments
  5. Match total to bank activity

Benefits:

  • Complete period coverage
  • Identifies missing settlements
  • Ensures all payments funded
  • Supports financial reporting

Match individual deposits to specific payments (itemized funding).

Scenario: Each payment creates separate bank deposit.

Process:

  1. For each bank deposit, find matching deposit transaction
  2. Trace deposit to single payment (1:1 relationship)
  3. Verify amounts match
  4. Mark payment and deposit as reconciled

Characteristics:

  • One-to-one deposit-to-payment relationship
  • Simpler reconciliation
  • More bank statement entries
  • Clear transaction-level visibility

Reconcile netted funding that includes fees or adjustments.

Scenario: Bank deposit is less than total payments due to fees.

Process:

  1. Find deposit transaction
  2. Trace to all component payments
  3. Calculate gross payment total
  4. Identify adjustment transactions (fees, refunds)
  5. Verify: (payments) - (refunds) - (fees) = (bank deposit)

Example:

Payments: $15,000
Refunds:  -$500
Fees:     -$250
Deposit:  $14,250 (matches bank)

Common Scenarios


Typical batching scenarios and how to handle them.

Question: "When will payment txn_payment123 be deposited to my bank?"

Solution:

  1. Get payment transaction
  2. Check for associated deposit in transfers
  3. If exists, check deposit's est_cleared_date
  4. If no deposit yet, payment not settled
payment = pl.Transaction.select("object", "id", "amount", "transfers").get("txn_payment123")
 
funding_transfer = next(
    (xfer for xfer in payment.transfers if xfer.assoc_transaction_id),
    None
)
 
if funding_transfer:
    deposit = pl.Transaction.get(funding_transfer.assoc_transaction_id)
    print(f"Will be deposited: {deposit.est_cleared_date}")
    print(f"Deposit amount: ${deposit.amount}")
else:
    print("Not yet settled - funding pending")

Question: "What payments are in my $15,000 bank deposit?"

Solution:

  1. Match bank deposit to deposit transaction
  2. Get deposit with transfers
  3. Fetch all associated payments
  4. Display breakdown
# Find deposit transaction
deposits = pl.Transaction.filter_by(
    q='amount == 15000 && type == "deposit" && est_cleared_date == date("2024-01-15")'
).all()
 
deposit = pl.Transaction.select("object", "id", "amount", "transfers").get(deposits[0].id)
 
# Get all payments
payment_ids = [
    xfer.assoc_transaction_id
    for xfer in deposit.transfers
    if xfer.assoc_transaction_id
]
 
payments = [pl.Transaction.get(pid) for pid in payment_ids]
 
print("Deposit breakdown:")
for p in payments:
    print(f"  {p.id}: ${p.amount} - {p.description}")

Question: "Reconcile all deposits for January 2024."

Solution:

  1. Query all deposits for period
  2. For each deposit, trace to payments
  3. Build comprehensive report
  4. Verify totals
# Get all deposits for January
deposits = pl.Transaction.filter_by(
    q='type == "deposit" && created_at >= date("2024-01-01") && created_at < date("2024-02-01")',
    order_by="asc(created_at)"
).all()
 
print(f"Deposits in January: {len(deposits)}")
 
total_deposits = 0
total_payments = 0
 
for deposit in deposits:
    # Get full deposit with transfers
    full_deposit = pl.Transaction.select("object", "id", "amount", "created_at", "transfers").get(deposit.id)
 
    # Get payments
    payment_ids = [
        xfer.assoc_transaction_id
        for xfer in full_deposit.transfers
        if xfer.assoc_transaction_id
    ]
 
    payments = [pl.Transaction.get(pid) for pid in payment_ids]
 
    payment_sum = sum(p.amount for p in payments)
 
    print(
        f"Deposit {full_deposit.id}: ${full_deposit.amount} ({len(payments)} payments: ${payment_sum})"
    )
 
    total_deposits += full_deposit.amount
    total_payments += payment_sum
 
print(f"\nTotal deposits: ${total_deposits:.2f}")
print(f"Total payments: ${total_payments:.2f}")

Schema Reference


Fields relevant to batched payments and transfers.

Transaction fields

transfersTransfer
array
No description
type
enum[string]Immutable
The type of transaction being processed. This determines the direction and nature of funds movement, such as payment collection, refund issuance, credit disbursement, or account funding operations.
Values: payment, deposit, withdraw, refund, payout

Transfer fields

transaction_id ID of Transaction
string
ID of the transaction object (ID prefix: txn)
Pattern: ^txn_[A-Za-z0-9]+$
assoc_transaction_id ID of Transaction
string
ID of the associated transaction object. (ID prefix: txn)
Pattern: ^txn_[A-Za-z0-9]+$
Required if:
receiver=null
sender=null
amount
number (double)Immutable
The monetary amount of this transfer. Positive amounts represent credits (funds received), while negative amounts represent debits (funds sent). This amount contributes to account balance calculations.
type
stringRead-only
The type of transfer. Possible values include payment, deposit, reversal, refund, reject, adjustment, credit, or transfer. This is automatically determined based on the associated transaction types and amounts.
Max length: 20

Next Steps

Improve batch reconciliation and automate payment tracing workflows


Match Deposits to Bank Statements

Match funding transactions to bank activity with Match Funding Transactions guide, complete your bank reconciliation with Bank Reconciliation documentation, and understand Funding styles and settlement timing.

Track Reconciliation Status

Add custom reconciliation metadata with Custom Attributes for tracking deposit associations, build comprehensive financial reports with Reporting guide, and explore complete transaction documentation in Transactions.

Configure Funding Settings

Optimize your funding style for easier reconciliation with Processing Settings configuration, understand Automated Funding behavior, and learn about transfer relationships in Transfers API documentation.

Automate Reconciliation Workflows

Build automated batch reconciliation tools using API Reference documentation, receive real-time notifications via Webhooks for automatic processing, and integrate with external accounting systems using System Integration best practices.