Skip to main content

Integration pattern

Reviewed 14 October 2026

A job that finds what the webhooks missed or doubled.payment reconciliation automation

Webhooks, imports and typing all feed the books, and any can miss or double. A job compares the books with the bank each night.

The demo matches bank lines to invoices in ERPNext. It does not show a webhook.

Use it when

  • Money is recorded in two places by different routes, such as a gateway and the ledger.
  • A missed or doubled event would not be noticed until month-end.
  • More entries arrive than a person can match by eye in one sitting.

Skip it when

  • You reconcile a few entries a month. ERPNext's manual Payment Reconciliation tool is enough.
  • The cause is a handler that drops events every day. Fix the handler; the job is the net, not the repair.
  • There is no outside record to compare with: no statement, no settlement list.

Try it

Run the reconciliation job

A sample ledger and a sample statement with five planted gaps. Run the job and see what is left for a person. Sample data. Not a measurement.

When it runs

Matched (4)

Same reference and amount.

pay_A1 ₹12,000pay_A2 ₹8,500pay_A3 ₹15,000pay_A4 ₹3,200

Probable: needs a person (1)

Same amount and day, no reference.

₹4,100, first on the list 17 Oct. Confirm it is pay_A7, then add the reference.

Exceptions (4)

Each with what to check.

Exceptions the job leaves for a person
WhatReferenceAmountWhat to doFirst on the list
Booked twicepay_A4₹3,200Cancel the duplicate receipt. Check the webhook handler for a missing key.16 Oct
Short or over by ₹50pay_A5₹9,700Ask the gateway why the settlement is short before you adjust anything.17 Oct
Never bookedpay_A6₹6,400Create the receipt. Then find why the webhook missed it.17 Oct
In the books, not on the statementpay_A8₹2,000Wait for the next statement. If it is still missing, check the payment.18 Oct
A nightly job puts each gap on the list the morning after: 16 to 18 Oct.

The books

Eight receipts booked by webhook, 14 to 17 October.

The books: receipts booked by webhook
ReferenceAmountDay
pay_A1₹12,00014 Oct
pay_A2₹8,50014 Oct
pay_A3₹15,00015 Oct
pay_A4₹3,20015 Oct
pay_A4₹3,20015 Oct
pay_A5₹9,75016 Oct
none₹4,10016 Oct
pay_A8₹2,00017 Oct

The statement

Seven lines: the outside record.

The statement: the outside record
ReferenceAmountDay
pay_A1₹12,00014 Oct
pay_A2₹8,50014 Oct
pay_A3₹15,00015 Oct
pay_A4₹3,20015 Oct
pay_A5₹9,70016 Oct
pay_A6₹6,40016 Oct
pay_A7₹4,10016 Oct

How long senders keep trying: Frappe Webhook: three tries, pauses of 1 s and 4 s. Shopify: 8 tries over 4 hours. Razorpay: 24 hours. Stripe: up to three days (live mode).

Frappe webhook.py, v15Shopify duplicate webhooksRazorpay best practicesStripe webhooks

What you give up, and how it fails.

What you give up

What you get and what it costs
What you getWhat it costs
Misses and doubles surface within a day, not at month-end.The job needs the scheduler running; if it is off, nothing runs.
People work a short exception list, not the whole ledger.Matching rules can be wrong, and accepting weak matches hides errors.
It catches what retries cannot: events that never arrived.It only finds differences against a record that exists. No statement, no check.

How it fails

How the pattern fails, why, and the evidence
What happensWhyEvidence
The sender stops sending.Shopify deletes an API-configured webhook subscription after eight failures in a row, and says delivery "isn't always guaranteed". Events stop until someone re-creates it.
One request tries to carry the whole ledger.ERPNext's Invoice Limit and Payment Limit default to 50, and the field says "System will fetch all the entries if limit value is zero". Large parties then time out; the background job works through queued documents instead.
The job never runs, and nothing says so.When Auto Reconcile Payments is off, or the scheduler is inactive, the trigger shows a message and does nothing.
"Submitted" is read as "reconciled".ERPNext's docs: submitting queues the process and "does not itself confirm that every entry was reconciled". Read the status and the log.
It matches the books to the books.Process Payment Reconciliation allocates payments to invoices that already exist. It does not import or match bank transactions, so a payment the bank has and the books lack is invisible to it.
The list is cleared instead of worked.Forcing or auto-accepting weak matches finishes the reconciliation and leaves the difference, disguised. (Our glossary: Bank statement.)
Follows from the design

Each failure is Documented, with the maker's own page or code, or it Follows from the design. None is a result from a MithTech client project.

In ERPNext and Frappe.

Read from Frappe v15.123.0 and v16.52.0, ERPNext v15.122.0 and Frappe's payments app at commit 9885a6e5 on 14 October 2026, with the file and line. Other systems' names and settings were not checked here.

Where each part lives

The pattern in ERPNext and Frappe: feature, where it lives, and what it does
FeatureWhereWhat it does
Payment Reconciliation (manual)Accounts › Payment Reconciliation
Allocates a party's unreconciled payments to its open invoices. Invoice Limit and Payment Limit default to 50; 0 fetches everything.ERPNext Payment Reconciliation, v15
Process Payment Reconciliationdoctype
Queues the same allocation as a background job per party. Statuses: Queued, Running, Paused, Completed, Partially Reconciled, Failed, Cancelled.ERPNext Process Payment Reconciliation, v15
Auto Reconcile PaymentsAccounts Settings › Payments
Turns the queue on. The trigger runs every 15 minutes by default (1 to 59). Queue size is 5 by default (5 to 100). Jobs run on the long queue with a 3,600-second timeout. Nothing runs if the scheduler is inactive.ERPNext Accounts Settings, v15ERPNext Process Payment Reconciliation, v15
Bank Transaction and Bank Reconciliation Tooldoctypes
The statement side: bank lines matched to Payment Entries and invoices. Statuses: Pending, Settled, Unreconciled, Reconciled, Cancelled.ERPNext Bank Transaction, v15
Bank Statement Importdoctype
Imports a statement file as new Bank Transactions.ERPNext Bank Transaction, v15
The schedulerbench scheduler
The job only runs when it does. Our scheduler check shows how to tell.

How to build it

  1. Pick the outside record: the bank statement, or the gateway's settlement list. Match on its reference first.

  2. Match in order: same reference and amount; then same amount and day with no reference (probable); then nothing (an exception).

  3. Never post a match you cannot explain. Probable matches go to a person.

  4. Run it on a schedule, and alert when the job has not run.

  5. Read the exceptions weekly. A gap that repeats is a handler bug: see idempotent webhooks.

Questions about reconciliation as a job