← All white papersBuild plan · October 2026

Batch Payments on Microsoft 365

The same standard, for a business that lives in Microsoft 365: each deposit and its remittance lines as SharePoint lists, exceptions decided in Teams, and one batch payment per deposit, equal to it.

9 min read·Free to implement·Published by AI Pathway

Used by

  • Bookkeeper
  • Microsoft 365 Administrator
  • Finance Manager

Microsoft 365 has the pieces this needs: a library to keep every remittance copy, lists to hold each line as written, and Teams for the person who decides an exception. The part that takes thought is the same as on any stack: the deposit comes from the bank, one bad line holds the whole deposit, and the batch is applied once per deposit however many copies of the remittance arrive.

In short

  • What this is

    A build plan for the Remittance Split standard on Microsoft 365. Five lists keyed on the deposit, three flows, and a person deciding every exception in Teams.

  • The core rule

    Flow 3 applies a batch only when every line for a deposit is matched or decided and the lines total the deposit. Batches.DepositId is unique, so a second batch cannot be recorded.

  • What it does not do

    No flow writes off a short payment, raises a credit, edits an invoice, or fills in the Decision column. Those stay with the bookkeeper.

  • The hard part

    Keeping the clean lines waiting while one line is decided, and making the batch unique on the deposit rather than on the file, because the portal copy has a different name.

Take the spec to Claude, ChatGPT or Copilot. The sentence to paste is one click away.

Want the whole thing by email?

This paper, plus the rest of the library. One click to stop them.

1. Before you start

Read the Remittance Split build standard first. It defines its objects, and the lists below are those objects with SharePoint types on them. Shared conventions are in building the standards on Microsoft 365.

Check that your ledger can apply one payment across many invoices through its API, and decide how Flow 3 reaches it. Xero has batch payments; MYOB and QuickBooks Online can apply one customer payment across several invoices. Power Automate reaches each through a connector or an HTTP action on a connection the business owns, not the builder’s own login.

Then decide where the deposit comes from: the ledger’s bank feed, or a statement export dropped in a folder. Either way, the amount in the Deposits list comes from the bank, never from the remittance.

2. The lists, with their columns

For your developer. Show the fields for your developer
Site: BatchPayments

LIST  Deposits              (one row per bank line, from the bank)
  DepositId       Text            indexed, UNIQUE, REQUIRED. the bank feed's id for the line
  Amount          Currency        REQUIRED. from the bank, never from the remittance
  DepositDate     DateTime
  Reference       Text            indexed. the statement narrative, with the payer's payment reference
  Payer           Text
  Status          Choice          no_remittance | held | ready | applied
                                  | taken_over

LIBRARY  Remittances        (every copy that arrived, kept)
  PaymentRef      Text            indexed, REQUIRED
  DepositId       Text            indexed. set once the matching bank line exists
  Source          Choice          email | portal
  Duplicate       Boolean         another copy of a remittance already read

LIST  RemittanceLines       (each line exactly as written)
  LineKey         Text            indexed, UNIQUE. DepositId + line number: one row per line
  DepositId       Text            indexed, REQUIRED
  LineNo          Number
  InvoiceAsWritten Text
  PayerRef        Text            participant or claim number, kept, never matched on
  NameAsWritten   Text            kept, never matched on
  AmountAsWritten Text            Text on purpose: an unreadable figure stays unreadable
  Amount          Currency        blank when the figure could not be read
  MatchedInvoice  Text            the ledger's invoice number, found by number only
  Result          Choice          matched | short_paid | over_paid
                                  | already_settled | no_such_invoice | unreadable

LIST  Exceptions            (a person decides; no flow does)
  DepositId       Text            indexed, REQUIRED
  LineNo          Number          blank when the whole deposit is held
  Kind            Choice          total_mismatch | short_paid | over_paid
                                  | already_settled | no_such_invoice | unreadable
  Detail          Note            the line, and both amounts where there are two
  Decision        Choice          undecided | apply_as_written | reassign
                                  | take_over
  ReassignTo      Text            the invoice a person says the line was for
  DecidedBy       Person
  DecidedAt       DateTime

LIST  Batches               (one per deposit. Never two.)
  DepositId       Text            indexed, UNIQUE, REQUIRED
  LedgerBatchId   Text            indexed. the id the ledger returned
  Total           Currency        equals Deposits.Amount, or the row is never written
  Lines           Note            invoice and amount per remittance line
  RemittanceFile  Hyperlink       the copy the batch was built from
  AppliedAt       DateTime

There is no write-off, credit or adjustment column anywhere, on purpose. A short payment either becomes a part payment because a person chose apply_as_written, or the person takes the deposit over and does it by hand in the ledger.

No flow writes Decision. If Decision is blank or undecided on any row for a deposit, nothing for that deposit is applied.

Unique values on Batches.DepositId is the line that holds check 10: a second batch for the same deposit cannot be recorded, whichever copy of the remittance started it. AmountAsWritten is Text so an unreadable figure stays unreadable.

3. Every rule, and what enforces it

The ruleEnforced byHow
The deposit comes from the bankFlow 1, DepositsFlow 1 creates Deposits rows from the bank feed or statement only. A remittance with no matching deposit sits in the library with DepositId blank and is not read further.
Each line is read exactly as writtenFlow 2, RemittanceLines.AmountAsWrittenFlow 2 copies each line's text into the AsWritten columns. If the amount does not parse, Amount stays blank and Result is unreadable.
Matched by invoice number, then the amount confirmedFlow 2, MatchedInvoice and ResultFlow 2 looks the invoice up by number only, then compares the amount with what is owing. PayerRef and NameAsWritten are never in the lookup.
One exception holds the whole depositFlow 3, Exceptions.DecisionFlow 3 skips any deposit with an Exceptions row whose Decision is undecided, so the clean lines wait with it.
Nothing is written off, credited or adjustedFlow 3 has one ledger actionThe only ledger action in any flow is the batch payment. There is no write-off, credit note or invoice update action to misuse.
One batch per deposit, equal to itBatches.DepositId, uniqueFlow 3 writes the Batches row first and applies the batch only if the write succeeds, and only if the line amounts total Deposits.Amount.

4. The three flows

For your developer. Show the fields for your developer
FLOW 1  A deposit lands, or a remittance arrives
  trigger  a new bank line in the feed or statement folder;
           a new file in the Remittances library
  logic    bank line -> Deposits row, Amount from the bank
           remittance -> find the Deposits row whose Reference
             carries its PaymentRef; set DepositId
           a second copy for a deposit already read -> Duplicate
  never    create a deposit from a remittance's own total.

FLOW 2  Read and match the lines
  trigger  a Remittances file gets a DepositId (not Duplicate)
  logic    one RemittanceLines row per line, AsWritten columns
           exactly as printed (AI Builder or a parser fills them;
           a person corrects a misread, never the flow)
           Amount unreadable or no invoice number -> unreadable
           invoice by number only; not found -> no_such_invoice
           paid or credited -> already_settled
           amount less or more than owing -> short_paid / over_paid
           lines total vs Deposits.Amount; differs -> total_mismatch
           each exception -> Exceptions row, posted to the
             bookkeeper in Teams with the line and both amounts
  never    look an invoice up by amount, name or PayerRef.

FLOW 3  Apply the batch
  trigger  a RemittanceLines or Exceptions row changes; hourly
  logic    per deposit: any Exceptions row undecided -> skip
           any decision take_over -> Status taken_over, stop
           reassign -> match that line again against ReassignTo
           build one batch: a payment per line, line amounts
           total must equal Deposits.Amount, else stop
           create Batches row (DepositId unique); if it exists, stop
           apply the batch in the ledger; write LedgerBatchId;
             attach or link the remittance file
  never    apply part of a deposit, or any payment not on a line.

No flow writes the Decision column. A person sets it in the Exceptions list, from the Teams card or directly, and Flow 3 reads it.

5. The order to build it in

  1. Create the five lists and the library from the schema, with Batches.DepositId and RemittanceLines.LineKey unique.
  2. Build Flow 1 and prove a remittance with no bank line yet waits with DepositId blank.
  3. Build Flow 2 and prove a line $10 short lands in Exceptions as short_paid with both amounts.
  4. Build Flow 3 against the ledger's demo company, and prove a deposit with an undecided exception applies nothing.
  5. Drop the same remittance in twice and prove Batches still has one row for the deposit.

6. Four traps specific to this build

Taking the deposit amount from the remittance

The remittance says what the payer meant to send. The bank says what arrived. Only the second reconciles.

Matching a line on its amount when the number fails

Two participants or two claims are often for the same amount. A payment on the wrong invoice is harder to find than an exception.

Applying the clean lines and leaving the rest for later

The bank line then half reconciles, and the remainder has to be found by hand. Hold the whole deposit until every line is decided.

Keying the batch on the file name

The emailed copy and the portal copy have different names. Key on the deposit, and let SharePoint's unique column refuse the second.

7. Where the automation stops

  • Deciding every exception: accept a short payment, name the right invoice, or take the deposit over.
  • Writing off a remainder, raising a credit note or recording an overpayment, by hand in the ledger.
  • Asking the payer for a corrected remittance.
  • Correcting a line the reader misread from the PDF.

The pass test. On the ledger’s demo company, or your own, take a real deposit and its remittance. Change one line on a copy so it is $10 short and drop it in the library: nothing is applied, and Exceptions names the line and both amounts. Restore the line: exactly one batch payment, equal to the deposit, with each invoice paid by its own line’s amount. Drop the same remittance in again: Batches still has one row for that deposit. Half an hour on your own tenant.

Related reading