Skip to content
Back to Resources
Guide

Which Stripe payments have not been reconciled against the ledger

Skopx Team
August 5, 2026
12 min read

It is the fourth working day of the month. The controller at a thirty person software company has two windows open and a coffee going cold between them.

On the left, the Stripe Dashboard, Payments view, filtered to last month. 1,847 successful charges, three currencies, a payouts tab showing eleven deposits that hit the bank between the 2nd and the 31st. Every payout has a breakdown: gross charges, refunds, Stripe fees, adjustments, net amount transferred.

On the right, QuickBooks Online. The bank feed has pulled in those eleven deposits from the operating account. Nine of them are matched to something. Two are sitting in For Review with a suggested match the bookkeeper does not trust. The Undeposited Funds account, which should be near zero at month end, has $14,206 in it. The Stripe Clearing account the previous bookkeeper set up has a balance of $3,118 that nobody can explain and that has been quietly growing for five months.

The controller needs to close by Friday. The question she needs answered is not "how much did we collect" and not "what is in the bank." Both screens can tell her those. The question is: which specific payments taken in Stripe have not landed anywhere defensible in the ledger, and for each one, why not.

Nobody can answer that from either screen.

What Stripe shows on its own, and where it stops

Stripe's accounting reporting is genuinely good, and better than most people who complain about it realise. The Balance report reconciles activity to payout, with every charge, refund, dispute, fee and adjustment assigned to a payout or explicitly marked as still in the balance. The Payout reconciliation report gives you, per payout, the exact line items that summed to the deposit amount. Stripe Revenue Recognition will produce accrual-basis revenue schedules if you pay for it. You can export all of it to CSV, and the numbers foot.

Where Stripe stops is precise and it is not a shortcoming. Stripe knows what happened inside Stripe. It knows charge ch_3PqL2x for $4,200 succeeded on the 14th, was included in payout po_1PrM8v on the 17th, and that $126 of fee came out of it. It does not know whether that payout was recorded in QuickBooks, which account it landed in, whether the bookkeeper split it correctly between revenue and fees, or whether somebody categorised the whole deposit as revenue and left the fee expense unbooked.

Stripe has no read into your general ledger. It cannot, because it does not have one. Ask the Stripe Dashboard "is this reconciled" and the honest answer is that the word means something different on its side of the wall. Stripe means "assigned to a payout." Your controller means "traceable to a journal entry that survives an audit."

What QuickBooks shows on its own, and where it stops

QuickBooks knows the bank. The feed pulls a $47,318.44 deposit from the operating account on the 17th, described as STRIPE TRANSFER ST-A4K9. It offers matching rules, it will remember how you categorised the last one, and the reconciliation screen will happily tick that deposit off against the bank statement. Bank rec, in the strict sense, will pass.

What QuickBooks cannot see is the inside of that deposit. $47,318.44 is a net figure. Underneath it are 212 charges, nine refunds, one dispute reversal, $1,388 of processing fees and a $40 adjustment for a chargeback fee. If the deposit was booked as a single line to Sales, revenue is overstated by the fee amount and expenses are understated by the same. The books still balance. The bank still reconciles. The P&L is wrong, and nothing in QuickBooks flags it, because from the ledger's point of view a $47,318.44 deposit categorised to an income account is a perfectly well formed transaction.

The Stripe app for QuickBooks and third party syncs like Synder or A2X exist precisely to solve this, and when they are configured properly they solve it well. But the failure mode is not that people lack a sync. It is that the sync was set up two years ago, has drifted, covers one Stripe account and not the second one somebody opened for the EU entity, does not handle the manual journal entries the previous controller made to force a quarter closed, and stops importing silently when an OAuth token expires. The residue of all that drift is the $3,118 in the clearing account.

Why the gap exists structurally

Here is the part that matters, and it is not a feature request either company has failed to build.

One half of this evidence is a record. Charge IDs, payout IDs, amounts, timestamps, fee lines, journal entry numbers, account codes. Structured, keyed, queryable. Stripe has its half. QuickBooks has its half. Both halves are clean.

The other half of the evidence is a sentence somebody wrote.

It is the memo field on a journal entry that says "reclass Stripe Nov, per Dana, netting Oct refunds." It is the Slack message in #finance from the 3rd: "ignore the two Feb payouts in review, those are the ones I reversed when we changed the clearing account." It is a comment on the Notion close checklist reading "clearing account variance is the Shopify migration, do not chase." It is the email from the auditor asking why the September fee expense jumped, and the reply explaining it.

That sentence is what turns an unmatched payout from a discrepancy into a known, accepted, documented item. And it lives nowhere either system can reach. Stripe cannot index your Slack. QuickBooks cannot read your Notion. Not because they are behind, but because a payments processor and a general ledger are both, correctly, systems of record for their own transactions, and a system of record does not get to be a system of record for someone else's prose.

This is also why automation platforms do not close the gap. Zapier, Make and their peers are trigger based and excellent at it: a charge succeeds, so create a sales receipt; a payout arrives, so post a journal entry. They move records forward. They are built for the next thing that should happen. But "which payments were never reconciled" is a question about the past, about a state that accumulated across five months of things that did and did not happen, and there is no trigger for the absence of an event.

And it is why BI tools do not close it either. Looker, Power BI and their conversational layers connect to databases and modelled sources. Point them at a Stripe warehouse sync and a QuickBooks extract and they will build you a reconciliation dashboard that is genuinely useful. But the memo field explaining that the variance is intentional is either not in the warehouse at all, or it is a free text column nobody modelled. Evidence that is a sentence is outside what those tools can see, not something they see badly.

What the join actually requires

Two things. One is mechanical. One is not.

The key. The connection between the sides is the payout, not the charge. Charges do not appear in the bank; payouts do. So the join runs:

Stripe sideBridgeQuickBooks side
Charge, refund, dispute, feepayout_id on each balance transaction,
Payout: amount, arrival date, statement descriptorAmount plus arrival date, within a two day windowBank deposit or clearing account entry
,Deposit line categorisationJournal lines: income, fee expense, clearing

The messy part is that the bank descriptor is not a payout ID. Stripe puts a short reference in the statement descriptor, banks truncate it differently, and once you have two Stripe accounts or a currency conversion in the middle, the amount and date window is doing most of the work. Multi day payout schedules and same amount payouts in the same week produce genuine ambiguity.

The judgement. Once you have the unmatched set, roughly 20 to 40 payouts in a year for a company this size, the real question for each is: is this a problem or a known item? That is not a matching problem. Answering it requires reading the journal entry memo, the close checklist comment and the Slack thread from the week it happened, and deciding whether somebody already accounted for it in prose. A rule cannot do that. A person can, in about ninety seconds per item, if the prose is in front of them.

How you would answer it with Skopx

Skopx connects to nearly 1,000 tools plus your databases, including Stripe, QuickBooks, Slack, Notion, Gmail and Drive. You ask in chat and it answers across all of them with citations back to the source.

The realistic sentence someone types:

For the last six months, list every Stripe payout that does not have a matching entry in QuickBooks by amount and arrival date within two days, and for each one search Slack and our close checklists for any mention of that amount, date or the word clearing, and tell me which ones already have an explanation.

What comes back is a list. Each row is a payout with its amount and arrival date, its Stripe payout ID, whether a plausible QuickBooks entry exists, and, where one was found, the sentence somebody wrote about it with a link to the Slack message or the memo it came from. The eleven that have an explanation get labelled as such. The four that do not are the actual close blockers, and they are now four items instead of a $3,118 mystery.

The reading is the part that could not be automated before. Not the matching.

Once the controller has run that sentence a few times and trusts the shape of the answer, the natural next step is to stop retyping it. Ask for it as an internal app and Skopx builds a console from that description: an Unreconciled Payouts view with a row per open item, the Stripe detail on one side, the QuickBooks state on the other, the found explanation underneath, filters by month and by Stripe account, and a Post suggested journal entry button on rows where the correct entry is unambiguous. That button asks for confirmation before it writes anything to QuickBooks, and it is the only write on the page.

You open it, you read it, you close the four items. Team is $16 per seat per month with 2.3 million AI tokens included. Solo is $5.

Honest limits

Some things this does not do, stated plainly.

It is not a sync and it is not a replacement for one. If your Stripe activity is not flowing into QuickBooks at all, fix that first with the Stripe app or A2X or Synder. This tells you where the flow broke. It does not carry the water.

The console stores nothing. It reads Stripe and QuickBooks live each time you open it, and it reads your Slack and docs for the explanations. There is no database behind it, no saved reconciliation state, no record of which items you marked resolved last month. If you need that memory, it belongs in your close checklist, and the console will read it back to you next month.

Nothing runs on a schedule and nothing alerts you. It will not email you on the 3rd. You open it when you are closing. The one write is the button, and only when someone presses it and confirms.

The date window match is a heuristic, not a proof. Two payouts of the same amount in the same week will be flagged as ambiguous rather than guessed at. On multi currency accounts, expect to check FX affected rows by hand.

Reading prose means reading what is written. If the explanation for a variance only ever existed in someone's head or in a phone call, no search finds it. This surfaces evidence that exists. It does not manufacture it.

It is not an audit opinion and not a bookkeeper. It gets the controller from an unbounded question to a bounded list with the reasoning attached. The judgement, and the signature at the bottom of the close, stay with the human.

Security note: SOC 2 controls are in place, access follows your existing permissions in each connected tool, and a person only ever sees what their own Stripe and QuickBooks accounts allow them to see.

Share this article

Skopx Team

The Skopx engineering and product team

Related Articles

Stay Updated

Get the latest insights on AI-powered code intelligence delivered to your inbox.