Embedded Finance Tracking: How to Account for Stripe Connect, Square Payouts, and Platform-Based Revenue in Beancount

Hey folks! I’ve been tracking my marketplace business in Beancount for about 3 years now, and I wanted to share my experience with embedded finance accounting since I’ve seen several recent questions about Stripe Connect and Square payouts.

Background: Why This Matters

Embedded finance—where payment processing, payouts, and banking are integrated into platforms—is becoming the norm for online businesses. But it creates some serious accounting complexity:

  • Multi-step revenue flow: Customer → Platform → Your Bank (with fees at each step)
  • Timing delays: 2-day settlement lag between transaction and deposit
  • Batch settlements: Today’s $10K deposit might represent 100+ transactions from 2 days ago
  • Complex adjustments: Refunds, chargebacks, reserves, and fees all mixed together

My Setup: Marketplace on Stripe Connect

Here’s what I’m tracking for my marketplace:

  • Customers pay for products (gross revenue)
  • Stripe Connect takes 2.9% + 30¢ processing fee
  • My platform takes 2% commission
  • Stripe holds reserves for potential chargebacks
  • Net proceeds deposited 2 days later

The Reconciliation Challenge

Early on, I was spending 5+ hours per week just trying to match bank deposits to individual transactions. The problems:

  1. Stripe batches everything—one bank deposit = 137 separate transactions
  2. Refunds reduce future payouts rather than reversing original deposits
  3. Reserves are released 30-90 days after original transaction
  4. Fees vary by transaction type (domestic card vs international vs ACH)

What I’ve Learned

After 3 years of refinement, I’ve developed a system that’s working well. I’ll share my account structure and automation approach in the replies below, but first I want to hear:

What are others doing for embedded finance tracking in Beancount?

Specifically:

  • How do you structure your accounts (Assets:Stripe vs Assets:Bank)?
  • Do you track reserves separately?
  • Any automation for pulling Stripe/Square data?
  • How do you handle the 2-day settlement timing?

I’ve got a pretty solid system now, but I’m always curious to see how others approach this problem. Plus I know several newcomers have been asking about this lately, so hopefully this thread can be a resource.

Looking forward to the discussion!

This is exactly what I’ve been struggling with! I’m running a similar marketplace setup and the reconciliation is killing me.

My Current Account Structure (Still Messy)

Here’s what I’ve cobbled together so far:

Assets:Stripe:Pending          ; Revenue received but not yet deposited
Assets:Stripe:Reserve           ; Money held for chargebacks
Assets:Bank:Checking            ; Actual deposits
Revenue:Marketplace:GrossSales  ; What customers paid
Expenses:Processing:Stripe      ; All Stripe fees
Expenses:Platform:Commission    ; Platform takes

The Daily Workflow I’m Trying

  1. Download Stripe CSV daily
  2. Import transactions with @stripe-transfer-id metadata
  3. Tag each transaction with settlement date
  4. When bank deposit hits, match it to the batch

The Problems I’m Hitting

Problem 1: Batch matching is manual

  • Stripe says “Payout ID: po_abc123” includes 147 charges
  • I have to manually sum up all transactions with that payout ID
  • Takes 20-30 minutes per payout to verify the math

Problem 2: Refunds mess everything up

  • Customer refund doesn’t create a reverse bank transaction
  • It just reduces tomorrow’s payout
  • My account balances don’t reconcile until I manually adjust

Problem 3: Reserves are a black box

  • Stripe holds $2,000 in reserves right now
  • Released 30-90 days after original transaction
  • I can’t easily track which original transactions those reserves correspond to

Questions

@helpful_veteran - You mentioned you’ve got this working well after 3 years. Do you:

  1. Import Stripe data automatically or manually?
  2. Track each individual transaction or just the batched payouts?
  3. Have a way to automate the batch matching?

For my sanity, I need to get this down from 4-5 hours per week to under 1 hour. The business is growing and I can’t keep scaling manual reconciliation!

Would love to see what account structure and metadata strategy others are using. Especially interested in any Python scripts or importers people have built.

Great topic! I’ve got 3 clients now using Stripe Connect, and we’ve worked through most of these pain points. Let me share what’s working for us.

The Account Structure We Use

I set up a similar structure to what Fred mentioned, but with a bit more detail:

Assets:StripeConnect:Available         ; Money ready for payout
Assets:StripeConnect:Pending           ; Money from recent charges (within 2-day window)
Assets:StripeConnect:Reserve           ; Held for potential disputes
Assets:Bank:BusinessChecking           ; Actual cash in bank

Revenue:Sales:Gross                    ; What customers actually paid
Expenses:Fees:Processing:Stripe        ; 2.9% + 30¢ fees
Expenses:Fees:Platform:Commission      ; Platform cut (if applicable)
Expenses:Fees:Refunds                  ; When we have to refund customers

Our Daily Workflow (Takes About 45 Minutes/Week Now)

Monday-Friday morning routine:

  1. Log into Stripe dashboard
  2. Export yesterday’s transactions (Charges + Refunds + Payouts)
  3. Run our Beancount importer script (I’ll explain below)
  4. Quick visual check in Fava to ensure everything balanced
  5. Done!

The key insight: Track EVERY transaction individually with proper metadata, then reconciliation happens automatically.

Metadata Strategy (This Is Critical)

Every transaction gets these tags:

  • @stripe-charge-id - The unique charge ID (ch_abc123)
  • @stripe-payout-id - The payout batch this will be part of (po_xyz789)
  • @customer-name - Who bought (helpful for disputes later)
  • @settlement-date - When the payout will hit the bank
  • @gross-amount - Original charge amount (even though fees were deducted)

Example Transaction

Here’s what a typical charge looks like in our books:

2026-03-20 * "Customer purchase via Stripe" ^stripe-charge-id:"ch_abc123" ^stripe-payout-id:"po_xyz789"
  Assets:StripeConnect:Pending           97.00 USD
  Expenses:Fees:Processing:Stripe         3.00 USD
  Revenue:Sales:Gross                  -100.00 USD
  
; Then 2 days later when payout hits:
2026-03-22 * "Stripe payout" ^stripe-payout-id:"po_xyz789"
  Assets:Bank:BusinessChecking         1,247.38 USD
  Assets:StripeConnect:Pending        -1,247.38 USD

Handling Refunds

You’re right that refunds are tricky! Here’s how we handle it:

2026-03-21 * "Refund to customer" ^stripe-refund-id:"re_def456"
  Revenue:Sales:Gross                    100.00 USD  ; Reverse the sale
  Expenses:Fees:Refunds                    3.00 USD  ; Fees aren't refunded by Stripe\!
  Assets:StripeConnect:Available       -103.00 USD  ; Comes out of available balance

The trick is that Stripe DOES NOT refund their processing fees. So a $100 sale that you later refund costs you $3 in non-recoverable fees. That’s why we track Expenses:Fees:Refunds separately.

Reconciliation Trick

Here’s the magic: Since every transaction has @stripe-payout-id metadata, I can run a BQL query:

SELECT sum(position) WHERE 
  any_meta('stripe-payout-id') = 'po_xyz789' 
  AND account ~ 'StripeConnect:Pending'

This tells me: “What’s the total amount that should be in payout po_xyz789?”

Then I compare that to the actual bank deposit. If they match → we’re good. If they don’t → there’s a discrepancy to investigate.

Time Savings

Before this system: 6 hours/week per client
After this system: 45 minutes/week per client (mostly just spot-checking)

The upfront investment was about 3-4 hours to set up the importer script and account structure, but it’s paid for itself many times over.

For @finance_fred

Your account structure looks good! The main things I’d suggest:

  1. Split Stripe:Pending into Pending/Available/Reserve - Makes it clearer what money is in what state
  2. Add comprehensive metadata - Every transaction needs @stripe-payout-id at minimum
  3. Track individual transactions, not batches - Let Beancount sum them for you
  4. Don’t forget Stripe doesn’t refund fees - Track this separately

Happy to share more details about the importer script if folks are interested. I wrote it in Python using the Stripe API, and it’s been rock solid for 6 months now.

Excellent discussion! As a CPA, I want to add the tax and compliance perspective because this is where many businesses get into trouble with embedded finance accounting.

Critical Tax Issue #1: Gross Revenue vs Net Deposits

The IRS doesn’t care what hit your bank account. They care about gross revenue.

If you only track the net deposits ($94.80 in Fred’s example), but Stripe reports $100 in gross charges on your 1099-K, you’ve got a mismatch that will trigger audit flags.

What You MUST Track

  • Gross sales: $100 (what customer paid)
  • Processing fees: $3.20 (deductible expense on Schedule C line 10)
  • Platform commission: $2.00 (deductible expense)
  • Net deposit: $94.80 (what hits your bank)

Your books need to show all four numbers clearly, with an audit trail connecting them.

Critical Tax Issue #2: Revenue Recognition Timing

This depends on your accounting method:

Cash Basis (most small businesses):

  • Record revenue when customer pays Stripe (March 20)
  • NOT when you receive the bank deposit (March 22)
  • Why? Because the money is legally yours on March 20, even though it’s in Stripe’s custody

Accrual Basis:

  • Record revenue when customer commits to purchase (potentially even earlier)
  • The 2-day settlement lag is just a cash flow timing issue

Most of my embedded finance clients are cash basis, so I tell them: Revenue date = Stripe charge date, NOT bank deposit date.

Critical Tax Issue #3: Platform Reserves Create Timing Problems

This is subtle but important for year-end tax:

If Stripe is holding $2,000 in reserves on December 31st:

  • That $2,000 is YOUR money (you owe tax on it)
  • Even though you can’t access it yet
  • It should show as Assets:StripeConnect:Reserve on your balance sheet
  • The revenue was recognized when customers paid (potentially months ago)

Common mistake: Only recognizing revenue when reserves are released. This defers taxable income artificially and will cause problems in an audit.

Critical Tax Issue #4: 1099-K Reconciliation

Stripe will send you (and the IRS) a 1099-K showing gross payment volume. For 2026, the threshold is $5,000 (it changed from $20,000 in previous years).

Your tax return needs to reconcile:

  • Line 1 (Gross receipts): Should match your Revenue:Sales:Gross account
  • Should match the 1099-K (or explain differences)
  • Processing fees go on Line 10 (Contract labor)
  • Net effect: Taxable income = Gross - Fees

If your books only show net deposits, you can’t complete this reconciliation.

Recommended Beancount Structure (CPA Perspective)

; When customer makes purchase (charge date = revenue date)
2026-03-20 * "Stripe Connect sale" ^charge-id:"ch_abc123" ^payout-id:"po_xyz789"
  Assets:StripeConnect:Pending           94.80 USD  ; What you'll receive
  Expenses:Fees:Processing:Stripe         3.00 USD  ; Deductible
  Expenses:Fees:Platform                  2.20 USD  ; Deductible
  Revenue:Sales:Gross                  -100.00 USD  ; Matches 1099-K
  
; When payout settles to bank (2 days later)
2026-03-22 * "Stripe payout batch po_xyz789"
  Assets:Bank:BusinessChecking         1,247.38 USD
  Assets:StripeConnect:Pending        -1,247.38 USD
  
; Year-end: Reserves still held by Stripe
2026-12-31 * "Document Stripe reserves for balance sheet"
  Assets:StripeConnect:Reserve         2,000.00 USD
  Assets:StripeConnect:Available      -2,000.00 USD

For Tax Season Prep

Make sure your system can generate these reports:

  1. Total gross revenue (must match 1099-K)
  2. Total processing fees (Schedule C deduction)
  3. Reserve balance at year-end (balance sheet)
  4. Reconciliation showing: Bank Deposits + Reserves = Gross Revenue - Fees

Pro Tip: Quarterly Estimated Taxes

Don’t forget: You owe tax on revenue held in Stripe reserves, even if you haven’t received the cash yet.

If you have $2,000 in reserves on March 31, you need to include that revenue in your Q1 estimated tax payment. I see a lot of businesses get surprised by this.

Bob’s Refund Handling Note

@bookkeeper_bob is spot on about non-refundable fees! One addition:

2026-03-21 * "Customer refund" ^refund-id:"re_def456"
  Revenue:Sales:Gross                    100.00 USD  ; Reverse revenue
  Expenses:Fees:Processing:NonRefundable   3.00 USD  ; Stripe keeps this\!
  Assets:StripeConnect:Available       -103.00 USD

For tax purposes, the $3 non-refundable fee stays as a deductible expense. You gave back $100 in revenue but permanently lost $3 to Stripe.

Bottom Line

The key to audit-proof books:

  1. Track gross revenue (matches 1099-K)
  2. Track all fees separately (deductible expenses)
  3. Revenue date = charge date (not deposit date)
  4. Document reserves clearly

Happy to answer any specific tax questions about embedded finance scenarios!

Alice covered the big tax issues beautifully. I want to add a few real-world audit and compliance scenarios I’ve dealt with as an EA:

Audit Scenario #1: IRS Questions Your Gross Revenue

What happened:

  • Client received 1099-K from Stripe showing $287,000 in gross payments
  • Their tax return showed $268,000 in gross receipts
  • IRS sent CP2000 notice (underreported income)

The problem:

  • They only tracked net deposits in their books
  • Didn’t account for December reserves ($19,000 still held by Stripe)
  • IRS assumed the $19K difference was unreported income

How we fixed it:

  • Reconstructed Beancount records showing reserve balances monthly
  • Proved the $19K was included in the 1099-K but held by Stripe
  • Provided balance sheet showing Assets:StripeConnect:Reserve

Lesson: Your books MUST show reserves as an asset, with revenue already recognized. Otherwise IRS will think you hid income.

Audit Scenario #2: Quarterly Estimated Tax Underpayment Penalty

What happened:

  • Client with strong Q4 sales (holiday season)
  • $45K in reserves at year-end
  • Didn’t include reserve revenue in Q4 estimated payment
  • Hit with underpayment penalty + interest

The problem:

  • Revenue: $45K (taxable in current year)
  • Cash received: $0 (still in reserves)
  • Estimated tax paid: $0 (based on cash flow, not revenue)

Result:

  • Owed $12K in tax on the $45K
  • Plus 6% annualized underpayment penalty ($360)
  • Plus interest from January 15 until they paid in April

Lesson: You owe estimated tax on revenue in reserves, even if Stripe hasn’t paid you yet. Plan your cash flow accordingly!

Audit Scenario #3: Refund Documentation

What happened:

  • Client claimed $12,000 in “refunds” as negative revenue
  • IRS requested documentation for all refunds
  • Client couldn’t provide Stripe transaction IDs for each refund

What saved them:

  • Beancount transactions with ^refund-id metadata
  • Each refund linked to original charge ID
  • Stripe dashboard exports matched Beancount penny-for-penny
  • Generated PDF showing: Original charge → Refund → Net effect

Lesson: Metadata isn’t just for your convenience—it’s your audit defense. Link every refund to the original transaction.

State Sales Tax Complication

One more thing nobody’s mentioned yet:

If you’re selling physical goods, you might owe state sales tax on those transactions. This gets complicated fast:

2026-03-20 * "Stripe sale (California customer)" ^charge-id:"ch_abc123"
  Assets:StripeConnect:Pending           87.75 USD  ; Net after fees
  Expenses:Fees:Processing:Stripe         3.25 USD
  Liabilities:SalesTax:California         9.25 USD  ; 9.25% CA sales tax
  Revenue:Sales:Gross                   -90.75 USD  ; Gross before tax
  ; Note: Customer paid $100 = $90.75 goods + $9.25 tax

Critical: The 1099-K includes the sales tax (customer paid $100 total). But:

  • Your taxable revenue is only $90.75
  • $9.25 is a liability you’ll remit to California
  • Your tax return needs to show $90.75, not $100

If you’re in multiple states (marketplace facilitator rules), this gets even more complex.

Crypto Payments via Stripe

Quick note for anyone accepting crypto through Stripe:

  • Stripe converts crypto to USD instantly
  • From IRS perspective, you received USD revenue
  • No crypto tax complications (Stripe handles the conversion)
  • Just track the USD amounts

Quarterly Tax Planning Recommendation

For embedded finance businesses, I recommend this quarterly routine:

End of each quarter:

  1. Run BQL query: Total revenue (including reserves)
  2. Calculate: Reserve balance change from last quarter
  3. Estimate: Tax owed on revenue not yet received
  4. Set aside: Enough cash to cover tax on reserves

Example calculation:

  • Q1 revenue: $75,000
  • Q1 reserves increased: $5,000
  • Effective tax rate: 30% (federal + state + SE)
  • Tax on reserves: $5,000 × 30% = $1,500

Set aside that $1,500 in a separate account, even though Stripe hasn’t paid you yet. When the reserve is released in Q2 or Q3, you’ll have cash ready for the tax bill.

For Fred & Bob

Your account structures look solid. Just make sure you can generate:

  1. Monthly reserve balance report

    • Beginning reserve balance
    • New amounts added to reserve
    • Reserve releases
    • Ending reserve balance
  2. Gross revenue report (must match 1099-K)

    • Total charges
    • Minus: Refunds
    • Equals: Net revenue reported to IRS
  3. Fee deduction report (Schedule C backup)

    • Processing fees by month
    • Platform commissions
    • Non-refundable fees on refunds
    • Total deductible fees

If your Beancount system can generate those three reports, you’re 95% ready for tax season.

Alice’s Point About Revenue Recognition

@accountant_alice is absolutely right about cash vs accrual basis. I’ll add one nuance:

Even on cash basis, the “constructive receipt” doctrine says you have income when:

  1. Money is credited to your account
  2. Set apart for you
  3. Made available without restriction

When Stripe charges a customer, that money is “set apart for you” (in your Stripe account). The 2-day settlement delay doesn’t change the revenue date—you already have constructive receipt.

This is why revenue date = charge date, not deposit date.

Bottom Line for Tax Compliance

  • Track gross revenue (matches 1099-K)
  • Recognize revenue on charge date (not deposit date)
  • Document reserves as assets (not deferred revenue)
  • Pay estimated tax on reserves (even if cash not received)
  • Link every transaction with metadata (audit defense)

Happy to answer any specific tax questions about embedded finance!