Monitor Automatic Payments
Track automatic payment activity and handle failures
Monitor automatic payment activity to track collection success rates, identify failed payments, and implement recovery strategies. Query automatic payment transactions, watch for failed attempts, set up webhook notifications for real-time monitoring, and build processes to handle payment failures gracefully. Effective monitoring improves collection rates and customer experience.
Automatic payments have trigger: "automatic" in the transaction record. Use this field to
filter and report on autopay activity. Failed automatic payments create zero-amount payment
allocations on invoices, allowing you to track failed attempts and trigger recovery processes.
Prerequisites
Before monitoring automatic payments, ensure you understand:
Autopay overview
Understand how automatic payments work and the retry logic.
Enable autopay
See how autopay is configured to understand what you're monitoring.
Querying Automatic Payments
Find and analyze automatic payment transactions.
Filtering automatic payments:
- Use
trigger == "automatic"to find autopay transactions - Combine with
type == "payment"to filter payment types - Use
created_atdate filters to find recent payments - Check
statusfield for payment success or failure
Transaction statuses:
-
completed- Payment successful -
failed- Payment failed (will retry automatically) -
pending- Payment being processed -
cancelled- Payment was cancelled
Monitor specific customer
# Find all automatic payments for a customer
customer_payments = pl.Transaction.filter_by(
q='type == "payment" && trigger == "automatic" && sender.account_id == "acct_customer123"',
order_by="desc(created_at)"
).all()
print(f"Customer automatic payments: {len(customer_payments)}")
total_paid = 0
successful_count = 0
failed_count = 0
for payment in customer_payments:
if payment.status == "completed":
total_paid += payment.amount
successful_count += 1
elif payment.status == "failed":
failed_count += 1
print(f"Successful: {successful_count}")
print(f"Failed: {failed_count}")
print(f"Total collected: ${total_paid}")Daily automatic payment summary
# Get today's automatic payment activity
from datetime import date
today = date.today().isoformat()
todays_payments = pl.Transaction.filter_by(
q=f'type == "payment" && trigger == "automatic" && created_at >= "{today}T00:00:00Z"',
order_by="desc(created_at)"
).all()
successful = [p for p in todays_payments if p.status == "completed"]
failed = [p for p in todays_payments if p.status == "failed"]
total_amount = sum(p.amount for p in successful)
print("Today's Automatic Payments:")
print(f" Attempts: {len(todays_payments)}")
print(f" Successful: {len(successful)}")
print(f" Failed: {len(failed)}")
print(f" Amount Collected: ${total_amount}")
if todays_payments:
print(f" Success Rate: {(len(successful) / len(todays_payments)) * 100:.1f}%")Success Rate Tracking: Monitor your autopay success rate daily or weekly. A declining success rate may indicate issues with customer payment methods, pricing problems, or customer satisfaction issues requiring attention.
Monitoring Failed Payments
Identify and track invoices with failed automatic payment attempts.
Failed automatic payments create zero-amount payment allocations on invoices for tracking.
Identifying failed attempts:
- Zero-amount payment allocations indicate failed attempts
- Invoice remains in
unpaidorpartially_paidstatus - Automatic retry continues for up to 5 days
- After 5 days, invoice requires manual intervention
# Check invoice payment history including failed attempts
invoice = pl.Invoice.get("inv_abc123")
print("Payment attempts:", len(invoice.payments))
print("Current status:", invoice.status)
print("Balance due:", invoice.totals["balance_due"])
for index, payment in enumerate(invoice.payments):
print(f"\nAttempt {index + 1}:")
print(" Amount:", payment.amount)
print(" Date:", payment.created_at)
if payment.amount == 0:
print(" Status: Failed attempt - will retry")
else:
print(" Status: Successful payment")
# Check if invoice is in retry period
from datetime import date
due_date = date.fromisoformat(invoice.due_date)
today = date.today()
days_since_due = (today - due_date).days
if 0 <= days_since_due <= 5 and invoice.status == "unpaid":
print(f"\nIn retry period - day {days_since_due} of 5")Tracking payment attempts:
- Each payment attempt creates a payment allocation on the invoice
- Failed attempts are marked with zero amount
- Successful payments show the actual amount charged
- Check retry period status to determine if invoice will auto-retry
# Find invoices with recent failed automatic payments
from datetime import date, timedelta
five_days_ago = (date.today() - timedelta(days=5)).isoformat()
invoices = pl.Invoice.filter_by(
q=f'status == "unpaid" && autopay_settings.allowed == true && due_date >= "{five_days_ago}"',
order_by="asc(due_date)"
).all()
failed_invoices = [
inv for inv in invoices
if any(p.amount == 0 for p in inv.payments)
]
print(f"Found {len(failed_invoices)} invoices with failed autopay")
for invoice in failed_invoices:
print(f"Invoice {invoice.id}: ${invoice.totals['balance_due']} due")
print(f" Customer: {invoice.payer['account_id']}")
print(f" Due date: {invoice.due_date}")Bulk monitoring approach:
- Query all unpaid invoices with autopay enabled
- Filter by recent due dates (within retry window)
- Check for zero-amount payment allocations
- Identify customers requiring notification
Customer Communication: Always notify customers immediately when automatic payments fail. Give them clear instructions on how to resolve the issue and provide easy ways to update payment methods or pay manually.
Webhook Monitoring
Receive real-time notifications for automatic payment events.
Setup webhook for automatic payments
# Webhook handler for automatic payments
from flask import Flask, request
app = Flask(__name__)
@app.route("/webhooks/payload", methods=["POST"])
def handle_webhook():
event = request.json
if (
event["type"] == "transaction.created"
and event["data"]["trigger"] == "automatic"
and event["data"]["type"] == "payment"
):
transaction = event["data"]
print("Automatic payment processed:")
print(f" Transaction: {transaction['id']}")
print(f" Amount: ${transaction['amount']}")
print(f" Status: {transaction['status']}")
print(f" Customer: {transaction['sender']['account_id']}")
if transaction["status"] == "completed":
handle_successful_autopay(transaction)
elif transaction["status"] == "failed":
handle_failed_autopay(transaction)
return "", 200
def handle_successful_autopay(transaction):
print("Payment successful - sending confirmation")
def handle_failed_autopay(transaction):
print("Payment failed - notifying customer")Invoice status webhooks
# Monitor invoice status changes from autopay
from flask import Flask, request
app = Flask(__name__)
@app.route("/webhooks/payload", methods=["POST"])
def handle_webhook():
event = request.json
if event["type"] == "invoice.updated":
invoice = event["data"]
if invoice["status"] == "paid" and invoice["autopay_settings"]["allowed"]:
print(f"Invoice {invoice['id']} paid via autopay")
print(f"Amount: ${invoice['totals']['total']}")
return "", 200Webhook Subscriptions: Subscribe to transaction.created webhook events with a filter for
trigger == "automatic" to receive real-time notifications of all automatic payment attempts.
This enables immediate response to payment success or failure.
Handling Failed Automatic Payments
Implement strategies for recovering from failed autopay attempts.
Disable automatic payments
Turn off autopay for specific invoices or billing schedules.
Payment requests
Generate payment links for customers to pay manually.
Payment methods
Manage customer payment methods and default settings.
Invoice statuses
Understanding invoice lifecycle and payment states.
Automated Recovery: Build automated workflows that detect failed payments, notify customers, and provide easy paths to resolution. The faster customers can fix payment issues, the higher your recovery rate will be.
Schema Reference
Fields relevant to monitoring automatic payments:
Transaction Trigger
typepayment, deposit, withdraw, refund, payoutstatuscodeapproved, card_expired, duplicate_attempt, exceeded_limit, general_decline, insufficient_bal, invalid_card_code, invalid_card_number, invalid_zip, invalid_address, invalid_account_number, suspicious_activity, too_many_attempts, processing_issue, issue_reading_card, not_supported, general_reject, general_adjustment, payment_stopped"Undocumented"messagevalueprocessing, authorized, processed, declined, rejected, voided, adjustedcreated_atNext Steps
Improve automatic payment operations and analytics
Configure Autopay
Set up automatic payments with Enable Autopay to configure default payment methods and collection rules, stop automatic payments when needed with Disable Autopay for customer requests or policy changes, and understand payment processing with Autopay Overview for eligibility and retry logic.
Handle Manual Payments
Process manual invoice payments with Payment API for programmatic payment processing, send payment links to customers with Payment Requests via email or SMS, and record offline payments with External Payments for cash, check, and wire transfers.
Analyze Performance
Set up real-time monitoring with Webhook Events to receive notifications for automatic payment events, understand payment processing with Transaction Status for tracking payment lifecycle, and build custom reports with Reporting Overview for revenue and collection analytics.
Related articles
- Enable Autopay - Set up automatic payments
- Disable Autopay - Stop automatic payments
- Autopay Overview - How automatic payments work
- Webhook Events - Real-time automatic payment notifications
- Transaction Status - Understanding payment processing
- Invoice Statuses - Invoice lifecycle and status transitions