SCROLL FOR MORE
Three-way match, run overnight.
Three-way match, run overnight.
Three-way match, run overnight.
MatchRail reconciles the purchase order, the receipt and the bill against the QuickBooks or Xero ledger you already close on, overnight — and queues only the ones that disagree.
>
ORDERED
ORDERED
ORDERED
//
//
//
RECEIVED
RECEIVED
RECEIVED
//
//
//
BILLED
BILLED
BILLED
<
[n.
01
/
10
]
> Why MatchRail
[n.
01
/
10
]
> Why MatchRail
[n.
01
/
10
]
> Why MatchRail
Built to show you
less, not more
Every other tool in this category hands you a dashboard of everything. MatchRail hands you the exceptions, and clears the rest on a tolerance you can read in the source.
Built to show you
less, not more
Every other tool in this category hands you a dashboard of everything. MatchRail hands you the exceptions, and clears the rest on a tolerance you can read in the source.
Built to show you
less, not more
Every other tool in this category hands you a dashboard of everything. MatchRail hands you the exceptions, and clears the rest on a tolerance you can read in the source.
//
001
Only the exceptions
The queue holds disagreements. A clean match never appears in it.
//
002
Three documents, side by side
The order, the receipt and the bill, with the disputed line marked in all three.
//
003
The receipt your ledger lacks
Neither QuickBooks nor Xero has a goods receipt. MatchRail owns that document.
//
001
Only the exceptions
The queue holds disagreements. A clean match never appears in it.
//
002
Three documents, side by side
The order, the receipt and the bill, with the disputed line marked in all three.
//
003
The receipt your ledger lacks
Neither QuickBooks nor Xero has a goods receipt. MatchRail owns that document.
//
001
Only the exceptions
The queue holds disagreements. A clean match never appears in it.
//
002
Three documents, side by side
The order, the receipt and the bill, with the disputed line marked in all three.
//
003
The receipt your ledger lacks
Neither QuickBooks nor Xero has a goods receipt. MatchRail owns that document.
[n.
02
/
10
]
> Numbers
[n.
02
/
10
]
> Numbers
[n.
02
/
10
]
> Numbers
Three documents a bill,
and every figure checked against the other two
Three documents a bill,
and every figure checked against the other two
Three documents a bill,
and every figure checked against the other two
3 rails
QuickBooks and Xero for the documents, Stripe for the payments.
$39/mo
The whole matcher. No per-invoice tier, no revenue band.
500 a day
The ceiling on auto-clears per book. Past it the pass queues everything, whatever the tolerance says.
0 units
Quantity tolerance. A unit is on the dock or it is not — there is no small shortfall.
// The tolerance
1%
Of the purchase order's own figure — with a $25 cash ceiling that also has to hold. The tighter band always binds.
// The kill window
60s
Minimum, between your approval and the correction reaching your ledger. The dispatcher sweeps every 15 minutes, so it is a floor and never a deadline.
[n.
03
/
10
]
> Core Features
Three documents,
one verdict a night
Orders and bills come out of QuickBooks and Xero since each rail's own watermark. A rail that does not answer never advances it.
Quantities, unit prices and totals compared as integers, so a floating-point rounding error can never invent or hide a variance.
Clean if and only if there are no variances — a test, not a comment. A clean match in the queue would mean the matcher is wrong.
- 01Pull
- 02Match
- 03Queue
- 04Correct
A clean match never reaches the queue. If one does, the matcher is wrong.
Keep the ledger
MatchRail reads purchase orders and bills out of QuickBooks and Xero and payments out of Stripe. The one document neither ledger has — the goods receipt — is recorded in MatchRail.
- Orders and billsPulled from QuickBooks and Xero, incrementally, against a watermark.
- The receiptRecorded here, because no ledger in this category carries one.
- PaymentsStripe, so money that left before a match passed is flagged.
- Write-backAn approved correction posts to QuickBooks — deferred, audited, undoable.
Corrections are deferred, never posted
An approved correction is queued with an expiry, writes its own audit row, and is re-checked against the documents before it writes.
1% and $25, and both have to hold
The tighter band always binds. Outside it, nothing is ever cleared or posted without you.
[n.
04
/
10
]
> The loop
[n.
04
/
10
]
> The loop
[n.
04
/
10
]
> The loop
It matches overnight.
You look at what disagrees.
It matches overnight.
You look at what disagrees.
It matches overnight.
You look at what disagrees.
// 01
The pass pulls what changed on each connected rail since its last watermark, matches every bill against its purchase order and its receipt, and clears what agrees. No export, no second system of record, no new place to enter a bill.
Overnight, on your own ledger
3 rails — QuickBooks and Xero for the orders and the bills, Stripe for the payments that settled them. The pass is incremental against a stored watermark, and a rail that does not answer does NOT advance it: an empty answer from a ledger is indistinguishable from "nothing was billed", so the window is re-read tomorrow rather than skipped forever.
// 02
What lands is the exceptions — each one naming its reason in words, with the purchase order, the receipt and the bill in three columns and the disputed line marked in all three. Everything that agreed is already closed.
A morning queue of only what disagrees
A match is queued only when it falls outside BOTH tolerance bands — 1% of the purchase order's own figure AND $25 in cash, with the tighter one binding. Quantity carries a tolerance of 0: a unit is on the dock or it is not. The matcher's invariant — clean if and only if there are no variances — is a test, not a comment.
// 03
Every cleared match, queued exception, approved correction and posted write goes to an append-only audit trail with the figures it acted on. An approved correction is not posted when you tap it — it is queued with an expiry.
A receipt on every action, and a window to take it back
60-second kill window on an approved correction: the dispatcher's own WHERE clause will not pick a row up before it elapses, and undo is a single conditional UPDATE that races the dispatcher's claim with exactly one winner. It sweeps every 15 minutes, so the window is a floor and never a deadline.
// 04
When a check does not pass, MatchRail does less rather than more: it queues instead of clearing, and it holds instead of posting. There is no flag anywhere that makes it proceed anyway.
Gates fail closed
Nothing outside tolerance is ever auto-posted. Past 500 auto-clears in a day the pass stops clearing and queues everything else regardless of tolerance. Past 50 posts in a day the dispatcher stops writing to your ledger and the corrections wait. And it refuses to post a figure that changed after you approved it.
[n.
05
/
10
]
> The artifact
[n.
05
/
10
]
> The artifact
[n.
05
/
10
]
> The artifact
"Corrugated case, 12 x 9 x 6": ordered at $12.50, billed at $14.10.
Re-price the bill line to the price the purchase order agreed.
This is the thing
you actually get.
Not a dashboard tour — one exception out of the morning queue, exactly as the matcher hands it over. The order, the receipt and the bill side by side, the field they disagree on marked in all three, the reason in the matcher's own words, and what it proposes doing about it.
[n.
06
/
10
]
> What you get
[n.
06
/
10
]
> What you get
[n.
06
/
10
]
> What you get
Everything a match needs,
checked for you
Everything a match needs,
checked for you
Everything a match needs,
checked for you
From the purchase order to the posted correction, MatchRail runs the whole comparison against your own ledger — you only look at what disagrees.
[n.
07
/
10
]
> Pricing
One flat price. No per-invoice tier.
Includes:
Record what arrived against a purchase order
The three documents, side by side
No credit card required
Import orders and bills by hand
Not in this tier — Nightly pull from QuickBooks and Xero
Not in this tier — Automatic three-way match on a tolerance
Not in this tier — Deferred, audited corrections posted back
Includes:
Everything in Free
Nightly pull from QuickBooks and Xero
Automatic three-way match on a tolerance
Only exceptions reach the queue
Stripe payments cross-checked against the match
Deferred, audited corrections posted back
Not in this tier — Many books from one console
Includes:
Everything in Pro
For bookkeepers and accounting firms
Many books from one console
Per-book tolerance and caps
Append-only audit trail, exportable
QuickBooks, Xero and Stripe on every book
Same gates, unwaivable, on every book
[n.
08
/
10
]
> Changelog
[n.
08
/
10
]
> Changelog
[n.
08
/
10
]
> Changelog
Aug 14, 2026
The receipt your ledger does not have
Aug 14, 2026
QuickBooks Online has no goods-receipt entity, and Xero's /Receipts endpoint is expense claims.
Aug 14, 2026
Corrections wait behind a kill window
Aug 14, 2026
Approving a correction queues it with an expiry rather than posting it.
Aug 14, 2026
Only exceptions reach the queue
Aug 14, 2026
A match is clean if and only if it carries no variances, and the queue renders exceptions and nothing else.
[n.
09
/
10
]
> Blog
[n.
09
/
10
]
> Blog
[n.
09
/
10
]
> Blog
Closing the month, minus the sampling
Closing the month, minus the sampling
Closing the month, minus the sampling
[n.
10
/
10
]
> FAQ
The things bookkeepers ask first.
How the match works, what it connects to, what it will and will not do to your ledger, and what stops it doing something you did not ask for.
//
001
It reconciles the purchase order, the receipt and the bill against each other overnight, and hands you only the ones that disagree. A bill that matches its order and its receipt inside tolerance is cleared and you never see it. The queue is the exceptions, and nothing else.
//
002
A variance clears only when it is inside BOTH bands: 1% of the figure on the purchase order AND $25 in cash. The tighter one always binds, so a small bill is governed by the percentage and a large one by the dollar ceiling. Quantity has no tolerance at all — a unit is on the dock or it is not.
//
003
No. A correction is queued when you approve it, not posted. It waits 60 seconds behind a kill window, writes its own audit row, and the dispatcher re-checks the figure against the current documents before it writes anything. Anything outside tolerance is never auto-posted at all.
//
004
Three columns: the purchase order, the receipt and the bill, side by side, with the disputed line marked in all three and the reason written out in words — “billed 24, received 21”, “ordered at $12.50, billed at $14.10”. You are reading the disagreement, not taking our word for it.
//
005
No, and it never asks to be. MatchRail has no bills of its own, no payment run and no chart of accounts. It reads the documents in the ledger you already close on and hands back a short list. If you switch it off tomorrow, your books are exactly where you left them.
//
006
A bookkeeper closing the month on QuickBooks or Xero, for a business that raises purchase orders and takes deliveries — anyone whose close currently involves opening three documents per bill and checking they agree, or quietly sampling because there is not time to check them all.
//
007
Four things, all in code. The tolerance decides whether one match is the agent's to clear. The auto-clear cap stops it clearing more than 500 in a day — past that, everything queues for you regardless. The post cap stops it writing more than 50 corrections into your ledger in a day. And the dispatcher refuses to post a figure that has moved since you approved it.
//
008
No, and that is deliberate. There is no --force, no allowlist and no known-issues file anywhere in MatchRail. A gate that can be waived is a gate that gets waived, usually at the worst possible moment, and every one of these gates fails toward showing you more rather than less.
//
009
No. The matcher is arithmetic — quantities compared, unit prices compared against the order, totals compared against price times quantity received, all in integer cents so a floating-point rounding error can never invent or hide a variance. A model that is right 99% of the time is the wrong tool for a control an auditor will ask about.
//
010
Only ones it can derive from the three documents in front of it: re-price a line to the order's price, re-quantity a line to what arrived, void a second copy of a bill. Where two disagreements overlap it proposes nothing and says so, because a guess written into a ledger is worse than no guess.
//
011
Close it. The exception becomes “closed” rather than “clean” — its variances stay attached to it forever, and the audit trail records who overruled the matcher and when. Marking it clean would destroy the evidence of what was overruled, which is exactly what an auditor is looking for.
//
012
Yes, for at least 60 seconds. Approving queues the correction with an expiry stamped on it; the dispatcher will not pick it up before that expiry, and undo is a single conditional database update that races the dispatcher's claim with exactly one winner. If undo wins, nothing was ever written.
//
013
Purchase orders and bills come out of QuickBooks or Xero. Payments come from Stripe, so a bill that was paid before its match passed is flagged. The receipt is recorded in MatchRail — because neither QuickBooks Online nor Xero has a goods-receipt document at all.
//
014
Because they do not have them. QuickBooks Online's Accounting API carries no item-receipt entity of any name — item receipts are a QuickBooks Desktop feature — and Xero's /Receipts endpoint is, in its own specification's words, draft expense claim receipts, meaning employee expenses. Xero purchase orders go from authorised straight to billed with no received state. That gap is exactly why a bookkeeper on either ledger cannot do a three-way match today.
//
015
The narrowest grant that does the job. Xero is connected read-only; Stripe is connected read-only. Only QuickBooks is asked for write access, and only so an approved correction can be posted back. Tokens are encrypted at rest in a table with row-level security on and no policies, so nothing but the server ever reads them.
//
016
The match runs nightly against what changed on each rail since its last watermark, so it reads a night's worth of documents rather than your whole ledger. You can also pull and re-match on demand from the Rails page when you want an answer before tomorrow morning.
//
017
The pass records the failure and does NOT advance its watermark, so tomorrow re-reads that window instead of skipping it forever. An empty answer from a ledger is indistinguishable from “nothing was billed”, and a matcher that accepted one would quietly clear a book on the strength of an outage.
//
018
The stored token is deleted, not flagged. A row marked disconnected that still holds a live refresh token is a standing write grant on your general ledger sitting in a database, and “we stopped using it” is not the same as “we no longer have it”. The documents already pulled stay in your account until you delete them.
Questions
Need help with something? We are a small team too. Write to us and a person answers.
Email us »//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
Only what disagrees.
The demo book is live — free, no card. Fifty-one bills went in and nine reached the queue.
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
Only what disagrees.
The demo book is live — free, no card. Fifty-one bills went in and nine reached the queue.
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
Only what disagrees.
The demo book is live — free, no card. Fifty-one bills went in and nine reached the queue.
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]
//
[#received]
&
[#billed]