1
Point it at the database you already have
The Mapper agent reads the schema and a few masked sample rows, then proposes how customers, services, invoices, line items and recurring agreements become PayPal objects. Every choice comes with a reason. Nothing touches PayPal until you accept.
- SQLite, Postgres, or a folder of CSV exports
- Validated against the real schema; falls back to a deterministic mapper
- Editable later in the console
$ npx paypal-retrofit init --source sqlite:./fernhill.db
◇ Found 5 tables
table rows foreign keys
customers 12
invoice_items 66 service_id→services, invoice_id→invoices
invoices 40 customer_id→customers
retainers 4 customer_id→customers
services 8
◇ Claude is mapping your schema to PayPal objects
object from detail
Customer customers name=full_name, email=email
Catalog product services name=name, price=unit_price
Invoice invoices number=invoice_no, total=total
Invoice items invoice_items via invoice_id
Status meaning status open=[overdue,sent,draft] paid=[paid]
Send to PayPal status when status in [overdue,sent]
Write back invoices paypalId→paypal_invoice_id, …
Subscription retainers monthly_fee/month, when [pending]
? Use this mapping? Yes
└ Wrote retrofit.config.yaml and retrofit.map.json
3
Payments flow back on their own
When a customer pays, PayPal's webhook is checked with PayPal's own signature verification, stored once, and applied to the legacy record (status, paid date and amount) before PayPal is told it arrived. If a webhook is ever lost, the reconciler finds the payment and repairs it, and flags anything that needs a person.
- Verified with
verify-webhook-signature
- Disputes, refunds and failed renewals become discrepancies
- Reconciles every 5 minutes, or on demand