A working sample, not a mock up

Two hundred payments on one ACH, and every invoice ticked off by hand

A customer wires one lump and sends a spreadsheet saying which invoices it covers. The spreadsheet has two hundred lines. The invoices have to be marked paid one at a time, and the list cannot be sorted by the thing you need to sort it by. That is the job this page does.

It is running right now, in this browser tab, on a sample remittance and a sample open invoice list. Every number below is computed when the page loads. Nothing is uploaded and nothing is stored. Scroll to the bottom to drop in your own two files instead.

01What the two files are

One is what the payer sends. One is what QuickBooks Desktop gives you. Neither is designed to meet the other, which is the whole problem.

The remittance advice, as payers actually send it

loading

Look at what is wrong with it, because all of it is normal. One reference carries an INV prefix and the rest do not. Excel has turned one into a decimal. Several rows have no reference at all. Two are a single amount covering more than one invoice. One is a short payment with the reason typed in the notes column. Further down the file some amounts are a couple of cents out, and a few references are mistyped, one of them onto the number of a different invoice that is also open.

The open invoice list, exported from QuickBooks Desktop

loading

One practical note on getting this out of QuickBooks. The obvious report is Open Invoices, but it puts the customer in a grouping header row rather than in a column, which means the export needs un grouping before anything can read it. A/R Aging Detail carries Name as a real column and saves that step, which is the shape shown here. Either export also interleaves subtotal and blank rows, and Excel eats leading zeros off invoice numbers; the reader below drops the first and ignores the second.

02What came out

Running.

03How each match was made

Nothing is matched on a hunch. Every application belongs to one of six rules, applied in this order, and the order matters: a line with a good reference claims its invoice before any line without one is allowed to guess at it.

RuleLinesConfidenceWhat it means

A few of them, in full

LineReferencePaidInvoiceAppliedRuleNote

04What a person still has to decide

This is the honest half, and it is the reason to trust the other half. Every line here could have been forced into a match by lowering the bar. None of them were. The list is short, each item says what is wrong, and where there were candidates they are all shown rather than one being picked.

    05Three things you can change and watch recompute

    These are not display filters. Changing one re runs the whole match from the two files.

    The tolerance is the one worth playing with. Set it to zero and six lines stop settling cleanly: three become part payments and three become overpayments, over a cent or two, because the payer's system rounded and yours did not. Three invoices that were closed are now open for a penny. Set it to a dollar instead and you start closing invoices that are genuinely a dollar short. The right number is a decision about the account rather than about the software, which is why it is a knob and not a constant. Whatever you change, the line under the controls says what moved.

    The last checkbox is a guard worth understanding. Invoice numbers here run in one dense sequential block, so a single mistyped digit lands on some other real invoice more often than it lands on nothing. A matcher that simply trusts the reference posts that money against the wrong invoice at full confidence and nobody finds out until two balances are wrong. With the guard on, a reference whose amount points somewhere else is refused and sent to the list above.

    06Getting it back into QuickBooks Desktop

    This is the part where it is worth being precise about which step is demonstrated here and which step is a build.

    What this page does. It answers the question that is slow by hand: which invoice does each of these lines belong to. That answer comes out as a review sheet, a short exceptions list, and an import file in the layout the tools below want.

    What it does not do. It does not reach into a company file. Nothing here has touched QuickBooks.

    The part that is already solved, and worth saying first

    Applying payments to invoices in bulk is not an unsolved problem. Transaction Pro Importer, Zed Axis, SaasAnt and Business Importer all do it, and they do it properly, at invoice level. Transaction Pro is the one with a published price, at a couple of hundred dollars one time per user rather than a subscription. They take a spreadsheet with an apply to invoice column, one row per invoice, and rows sharing a reference number become a single payment across several invoices. Some of them need a switch turned on before that mode is even available, so it is worth reading their notes before buying.

    What none of them do is work out which invoice a line belongs to. They need the answer already in the sheet. So if the remittance arrived with clean invoice numbers in every row, one of those tools is the whole solution and this page has nothing to add. It earns its ground on the other case, which is the one that produces a two hundred line spreadsheet with typos, blanks, lumped amounts and short pays in it.

    That is why the first file below is the one to look at. It is the same match, laid out in the shape those importers read.

    The IIF file, and the thing it genuinely cannot do

    IIF is the plain text format QuickBooks Desktop has always accepted, and the file below is a real one. It creates the payment transactions and drops the customer balance. What it will not do is attach a payment to an invoice, because the format has no field for that. Intuit states it plainly in their own import documentation: importing IIF does not link transactions, and you still have to link an invoice and its payment afterwards.

    What you actually get is the cash in and the invoices still open, with the payments sitting as unapplied credits, showing up as negative lines on the same Open Invoices report the input came from. It is offered here because the cash side in one step is still worth having, and because being shown the file beats being told about it. The invoice numbers ride in the memo column so the trail stays readable.

    Worth knowing about the neighbouring shortcut too. QuickBooks has an Auto Apply Payment button, and a preference that does the same thing automatically. Its rule is: look for an invoice whose amount exactly matches, and failing that apply oldest first until the money runs out. That is fine on a tidy account and wrong in exactly the places the exceptions list above is about, because two invoices at the same amount, a short pay and a lumped payment all defeat it quietly.

    The route that attaches payments to invoices without buying anything

    Underneath, those importer tools all talk to the Desktop SDK. The request is ReceivePaymentAdd carrying an AppliedToTxnAdd block per invoice, and that is the thing that actually removes the clicking. The sample below is generated from this same match. It needs one input a spreadsheet cannot give it: each invoice's internal TxnID, which is not the invoice number and has to be read back from the company file first with an invoice query. The placeholders carry the invoice number so the substitution is mechanical, and no identifier in the file is invented.

    That read back plus write is a small program that runs on the same Windows machine as QuickBooks and is authorised once from inside it. Nothing has to be exposed to the internet and no web connector is involved unless you want the logic to live somewhere else. It is a build rather than a download, and it is the honest shape of the finished thing: a folder you drop the remittance into, and the invoices are ticked off when you look.

    One number to check before importing anything

    The payment files do not add up to the advice total, on purpose.

    Nothing here invents a credit or pushes money onto an invoice to make a total agree, so the difference is exactly the lines that were not matched plus whatever was paid over and above what the named invoices were open for. Both are itemised in the exceptions file, and the readme that comes with the download opens with the same three numbers so it travels with the files rather than living only on this page.

    Files are assembled in this tab and saved by the browser. Nothing is sent anywhere.

    07Try it on your own two files

    Everything happens in this tab. No upload, no server, no storage. Reload the page and it is gone. If you would rather check that claim than take it on trust, open the network tab first, or pull the wire out.

    Open invoices

    Needs a column of invoice numbers and a column of balances. It looks for Num, Invoice, Open Balance, Amount, Name, Customer, Date and a few obvious variants, in any order.

    Remittance advice

    Needs an amount column. A reference column, a date, a site or job and a notes column are all used if present. Looks for Amount Paid, Amount, Invoice Reference, Reference, Site, Notes and similar.

    The payer name has to match the customer name on the invoice list, because amount matching is scoped to one customer. If your remittance has its own customer column, that wins and this field is ignored.

    08What this is not

    • It is not connected to QuickBooks. It reads two files and writes several.
    • It does not learn. Every rule is written down and every match says which one it used. That is deliberate: a matcher you cannot audit is one you have to check by hand anyway, which puts you back where you started.
    • It does not resolve the exceptions. Those need someone who knows the account, and pretending otherwise is how wrong money gets posted quietly.
    • The combination search is bounded, at three invoices deep and a fixed amount of work. On a list this size an unbounded search does not fail loudly, it just finds several readings of the same number, which is worse than finding none.
    • The sample data is invented. Every customer, site, invoice number, amount and date on this page was generated for it.