Customer Refunds on the Income Tab
Yes — outgoing peer-to-peer payments to someone who previously paid you are detected automatically and written as a negative-amount row on your Income (Beta) tab. Net income on Schedule C / T2125 reflects the refund correctly without any manual adjustment.
How it works
Four payment platforms are covered today: Cash App, Venmo, Zelle, Interac e-Transfer. When ExpenseBot's Gmail scan sees an outgoing payment from one of these platforms (e.g. a Cash App email titled "You sent $200 to Tj Carter") and the recipient has a prior incoming payment from the same person on your Income tab, the refund flow triggers:
- A negative-amount row is written to your Income tab (e.g.
-$200) - The new row's Reference # column is set to
refund-of:<original_record_id>so you can trace it back to the original income event - Net rent / income in any year-end report (Schedule C, T2125, Schedule E for rental refunds) sums all rows on the Income tab including the negative — so a $1,000 receipt followed by a $200 refund nets to $800
The original incoming row is left untouched — you keep both the receipt and the refund as audit evidence for your books.
Why this approach (vs. just deleting the original)
IRS Schedule C, Line 2 (Returns and allowances) and CRA T2125 Line 8290 (Returns, allowances, and discounts) both expect refunds to be reported as separate adjustments, not by reducing the gross receipts line. Keeping the original receipt and adding a negative offset row mirrors that accounting convention exactly. Your accountant gets a clean audit trail without having to ask "did this $1,000 come in or not?"
The mirror approach also matches how ExpenseBot handles expense refunds (Amazon return-of-purchase): a negative row is added to the Expense tab, the original purchase row stays. Income refunds work the same way on the Income side.
Which platforms are detected
Live today:
- Cash App — outgoing P2P payments
- Venmo — outgoing P2P payments
- Zelle — outgoing P2P payments
- Interac e-Transfer — outgoing transfers (Canada)
Not yet detected automatically:
- PayPal personal sends — coming soon
- Wire transfers — manual entry only (no Gmail signal)
- ATM cash withdrawal handed to a customer — manual entry only
For platforms not yet detected, log the refund through any of these manual paths — all three produce the same negative-amount Refund-issued row with the right refund-of:<original_record_id> reference:
- Add Income → manual entry → set category = "Refund issued" and enter a negative amount
- Add Income → From CSV — drop in a CSV that contains refund rows. The AI auto-detects refunds (negative amounts or "refund" descriptions), tags them as Refund issued, and resolves the cross-link to the original income row by payer match
- Add Income → From screenshot or PDF — same behavior: refund rows in a Cash App / Stripe / PayPal monthly statement get extracted as negative-amount Refund issued rows
All three paths run the same dedup as the Gmail-scan refund detector — if the same refund event later shows up in your Gmail and we already wrote the row from a CSV import, the email-side scan skips it instead of creating a duplicate. Same in reverse. You won't get double-counted regardless of which path the refund came in through.
What if the recipient never paid me before?
A peer-to-peer outgoing payment to someone who has no prior incoming row doesn't create any sheet entry. The Gmail email is processed and labeled but neither tab gets a row. This is intentional: most outgoing peer payments are personal (paying a friend back, splitting a bill, sending money to family) and don't belong on a business books spreadsheet at all.
What if I refund part of the payment?
The negative row matches the outgoing amount — not the original incoming amount. If a customer paid you $1,000 and you refund $300, you'll see:
- Original row:
+$1,000 - Refund row:
-$300 - Net to Schedule C / T2125: $700
This matches IRS reporting convention (returns are reported at the actual amount returned, not the full original receipt).
Disabling automatic refund detection
If you want to handle refunds manually instead of having ExpenseBot create the rows, you can opt out via Settings → Gmail Automation → uncheck "Also track income emails (beta)". Note this also disables incoming income detection — there's no separate toggle for refunds alone. For most users the automatic detection saves time and keeps the books accurate without intervention.
Audit trail
Every detected refund logs a Cloud Run line:
💰← Refund of income detected: <user> / <subject> → matched payer "Tj Carter" → row 47
Plus a row in your incomeDetections Firestore subcollection with method: "refund_candidate" for support troubleshooting if a refund didn't catch.
