How to reconcile Microsoft 365 licences without a PSA

Every paid reconciliation tool assumes the billing side is ConnectWise, Autotask, HaloPSA or Syncro. If you invoice out of QuickBooks or Xero, here is how to do it anyway.

The short answer. Download the licence-based reconciliation file from Partner Center, export your invoices for the same month from your accounting system, then compare them per client and per SKU, after collapsing the charge-type rows into one effective seat count. The step that catches everyone is that summing the Quantity column gives the wrong number, because one subscription produces several rows a month and some are negative.

Why there is no product for this

Reconciliation tools sell through PSA marketplaces, so they integrate PSAs first and accounting systems never. Checked in August 2026:

ToolFromReads QuickBooks / Xero?
BillingReconcile$129/moNot listed among its 13 integrations
Sync 365QuoteNo, requires ConnectWise, Autotask or HaloPSA
Syncro Universal Billing~$139/tech/moNo, requires Syncro
Gradient MSPQuoteNo accounting integrations at all

So if you have no PSA, the honest options are: do it by hand, buy a PSA you did not want, or use something that reads the two files directly. The full comparison is here, including the cases where buying one of the above genuinely is the right answer.

The manual method, step by step

  1. Get the reconciliation file. Partner Center → Billing → download the licence-based reconciliation file for the month. Not the usage-based one, which is Azure consumption and a different problem. It arrives as CSV with 28 columns; you need four of them: CustomerName, OfferName, ChargeType and Quantity.
  2. Export your invoices for the same month. In QuickBooks or Xero, export invoices with one row per line item, including the customer, the description, the quantity and the rate. The periods must match. Comparing July licences to June invoices produces a large and completely fictional number.
  3. Collapse the charge types. This is the step that matters. Group by client and SKU, then add only the charge types that change quantity: cycleCharge, new, renew, addQuantity, removeQuantity (which arrives negative), moveQuantity and convert.

    Exclude customerCredit, extendTerm and cancelImmediate. Those are money, not seats. A credit for an outage is not a licence going away.

    If you are mid-migration you may also see legacy strings: Cycle fee, Cycle instance prorate, Cancel fee can appear in the same file. Handle both vocabularies or you will silently drop rows, and a dropped row looks exactly like a client who owes you nothing.
  4. Match the SKU to your invoice line, which is the slow part. Your invoice does not say "Microsoft 365 Business Premium". It says M365 BP, or Bus. Prem., or a house name like Email & Office Bundle that shares no words with the Microsoft name at all. Build an alias list once and keep it; it is the only part of this that gets faster with time.

    Watch the 2020 renames while you do it. "Office 365 Business Premium" is Microsoft 365 Business Standard today, a cheaper product, while a different old plan became Business Premium. Pricing that line by its name rather than its SKU has been wrong for years in a lot of shops.
  5. Compare counts, and sanity-check before you invoice. For each client and SKU, effective seats minus invoiced quantity. Anything positive is money you paid Microsoft and never charged for.

    Before you act: if a lot of clients appear to have nothing invoiced at all, your export is incomplete or covers the wrong month. That is far more likely than fifteen clients you forgot to bill.
Realistically, how long? For 8–15 clients, the first pass takes an afternoon, mostly spent on step 4. Later months take about an hour once the alias list exists. That is the real reason it gets done annually instead of monthly, and why seats added in March get noticed in November.

Should you just buy a PSA?

If you are growing past roughly 10 technicians, probably yes, and take reconciliation as a side effect rather than buying a point solution you will discard. Syncro at around $139/tech/month and Atera at $99–149 both bundle PSA and RMM, and Syncro's March 2026 release added licence-count syncing onto recurring invoices directly.

If you are two or three people with a dozen clients, a PSA is a large operational change to solve a monthly arithmetic problem. Do the arithmetic.

Common questions

Can I do this with the Partner Center API instead of downloading a CSV?

Yes. Partner Center exposes billed and unbilled reconciliation data through its API and through Microsoft Graph, and Microsoft publishes code samples. Both require live CSP credentials and app registration, so it is real development work rather than a script you run in an afternoon. The CSV download requires nothing.

What is the difference between the licence-based and usage-based reconciliation file?

Licence-based covers seat subscriptions such as Microsoft 365 and Dynamics, billed per licence per month. Usage-based covers metered Azure consumption. For unbilled seats you want the licence-based file; they are separate downloads with different columns.

Why do my seat counts change mid-month?

Because they do. A client onboards three staff on the 14th and Partner Center prorates it as a separate addQuantity row. Your recurring invoice template does not know that happened. This is the exact mechanism by which the gap is created, and why the check is worth running monthly rather than annually.

Is there a free way to check?

Yes, if you already have the two CSVs. Both are exports you can produce today from systems you already pay for.

Or skip the afternoon

There is a page that does steps 3 to 5 for you: the charge-type collapse, the alias matching, the rename warnings, and the sanity check on whether the two files line up. It asks you about anything it cannot match confidently rather than guessing, because a confident wrong answer is worse than no answer when you are about to invoice a client.

It runs entirely in your browser, so nothing is uploaded and there is no account to make. And it is free.

Open it · or read what every ChargeType means first

Last updated 11 August 2026. Charge-type behaviour follows Microsoft's published reconciliation file documentation; competitor prices are from each vendor's own pricing page on that date and change without notice. SeatGap is our own tool, which is why this page tells you when a PSA is the better answer.

Check the names first: every Microsoft 365 rename since 2020, and the two that moved a name onto a different product.