Why an accounting integration must be safe to run twice
Every integration retries sometimes. In most systems a duplicate is untidy. In your accounts it is a figure that is simply wrong.
Networks time out. Processes restart. Someone re-runs yesterday's job because they are not sure it finished. These are not unusual events; they are the normal operating conditions of any integration.
In most places the consequence is a duplicate record somebody tidies up. In accounting the consequence is an invoice that was never owed, a figure that no longer matches the bank, and a conversation with your accountant. So accounting integrations need to be designed for repetition from the beginning, not hardened against it later.
What idempotency means here
An operation is idempotent when performing it twice leaves the same result as performing it once. Applied to invoicing: if the same instruction arrives twice, you want one invoice, not two.
That requires a stable identifier derived from the source record — the order, booking, or usage period the invoice represents — rather than from the attempt. The integration then asks whether this thing already exists before creating it, and the answer is reliable because the identifier does not change between attempts.
The failure mode to design for is partial success
The hardest case is not a request that failed. It is one that succeeded while the response was lost. From the caller's point of view those look identical, and the natural reaction — retry — is what creates the duplicate.
This is why the check has to be a lookup against the accounting system rather than a flag in your own database. Your flag may not have been written. The invoice was still created.
Batches need to be resumable
A run over several hundred records will sometimes stop halfway. If resuming means starting again, every already-processed record is a duplicate risk.
Each item should therefore be independently identifiable and independently checkable, so a resumed run can skip what it already did. It is slower to build than a single sweep and it is the difference between a job you can safely re-run and one that needs a careful human every time it fails.
Leave closed periods alone
Once a period is reconciled or closed, an integration that rewrites history creates work only an accountant can undo, and it undermines trust in every number around it.
Corrections belong in the current period, where they are visible and explainable. This is worth agreeing with whoever does your books before anything is built, because it shapes how the integration handles late-arriving changes.
Decide tax treatment before structure
Rates, treatments, and cross-border rules are not details to settle afterwards. They determine how records are shaped, so retrofitting them tends to mean rebuilding.
The practical approach is to agree the treatment with your accountant first and build to it, rather than making a reasonable guess and reconciling the difference later.
Matching is where the effort actually goes
Creating records is the straightforward half. The harder half is linking a payment to the right invoice when the two systems carry different references for the same transaction — one uses your order number, another a platform reference, a third whatever the customer typed.
Anything that cannot be matched with confidence should go to an exception queue rather than being allocated on a best guess. A short list someone reviews each week is far better than a set of confident-looking allocations that are quietly wrong.
Multi-currency needs decisions, not defaults
If you invoice or receive in more than one currency, somebody has to decide which rate applies, at what moment it is captured, and how the difference between invoice and settlement is treated.
These are accounting decisions rather than technical ones, and they need to be consistent across every record the integration creates. Left to a library default, they produce small discrepancies that are tedious to unpick months later.
How you know it works
Not because the calls returned successfully. An accounting integration is working when the totals in the accounts match the payments received and the invoices issued, with no duplicates and nothing missing.
That means a reconciliation check alongside the integration, and an alert when it stops running. An accounting sync that quietly stopped three weeks ago is worse than not having one, because by then you have been trusting it.