← Insights

Business Systems

ERP Integration: What Flows In and How to Reconcile It

How to connect field, CRM, ecommerce and project systems to your ERP so master data has one owner, posting stays with finance, corrections keep their history and every transaction reconciles.

Published
Author
Cass & York Team
Series
Cass & York
Reading time
10 min read
0

Close week tells you how well your systems talk. The field app says 412 tickets were billed, the ERP shows 405 invoices, and someone spends Thursday hunting for the missing seven. ERP integration is supposed to end that week, and it can, as long as the integration follows the rules accounting already runs on.

ERP integration connects your operational systems (field service, CRM, ecommerce, project management) to the ERP so records move without rekeying. A safe ERP integration does four things. It gives each master record one owner, sends every transaction with a stable external ID so a retry can't create a duplicate, leaves approval and posting to the ERP, and sends corrections after posting as linked reversals or credit memos. A nightly count, sum and status check then proves both sides agree.

This guide is for the controller, CFO or operations director connecting those systems to NetSuite, Sage Intacct, Acumatica, Business Central or QuickBooks Enterprise. It includes one field ticket corrected after capture, traced through the ERP with its history intact.

What can safely flow into the ERP

Every record that crosses into an ERP belongs to one of four groups, and each group needs its own rule.

Four kinds of data in ERP systems integration, and what the integration may do with each

Data

Examples

Owner

What the integration may do

Master data

Customers, items, jobs, cost codes, vendors

One named system per object

Create or update by external ID. Deactivate only in the owning system.

Transactions

Invoices, sales orders, field tickets, timesheets, receipts

Source system until posting, ERP after

Create as a draft or pending document. Update freely until it posts.

Approval state

Customer signed, manager approved, on hold

The system where the approver works

Carry as a field. Leave ERP approval rules switched on.

Posting

Posted invoice, journal entry, ledger impact

ERP only

Read back status and document numbers.

Operational systems propose, and the ERP decides what reaches the ledger. Once something posts, any change arrives as a new document that points at the old one.

Master data: one owner and one key per object

Master data is the customers, items, jobs and codes that every transaction refers to. If the CRM and the ERP can both create customers, you will have ACME Corp and Acme Corporation within a month, and invoices will split across both. We covered the wider version of this problem in building a single source of truth.

Assign one owner per object and write it down. A common split for a contractor: the CRM owns customers and contacts, the ERP owns items, cost codes and the chart of accounts, and the project system owns jobs once a contract is signed. A manufacturer or distributor might let the ecommerce platform own web customers while the ERP owns items, prices and inventory.

Then give every record a key both systems understand. NetSuite lets you key a record by an external ID in place of its internal ID, and its help center names synchronization with outside data as the main use (Using External IDs). In REST you address the record as eid:CID001, and the upsert operation creates the record when the external ID is new and updates it when one already exists. Business Central's API has an externalDocumentNumber field on sales invoices, which is where we store the source key (salesInvoice resource type).

We prefix keys with the source system, such as fs_10482 for a field service ticket (NetSuite external IDs accept letters, numbers, underscores and hyphens). Anyone looking at the ERP record can tell where it came from and which screen to open.

Transactions, approval state and the posting boundary

The posting boundary is the moment a document stops being editable and becomes ledger history. In Business Central, a sales invoice has statuses such as Draft, In Review, Open, Paid, Canceled and Corrective, and a separate post action carries a draft across the line (salesInvoice resource type).

We design integrations to stop on the near side of that line by default. The integration creates the invoice or journal as a draft, attaches the source key, and lets the ERP's own approval and posting rules run. NetSuite is explicit about this: with journal approvals required, entries post only after someone with Journal Approval permission approves them (Journal Entry Approval Overview).

Approval state from the source system still travels as a field. A ticket the customer signed or a quote a manager approved tells the billing clerk which batch is clean to post. In the commercial roofing quote platform we built, quotes move through review and approval stages inside the portal, and state like that is worth sending downstream. Our guide to human in the loop automation covers how to decide which steps need a person.

Posting periods are a second boundary

Business Central limits posting to the dates in Allow Posting From and Allow Posting To, set for the whole company and overridable per user (Specify posting periods). NetSuite locks A/R, A/P, payroll or the entire period during close (Locking and Unlocking Accounting Periods).

Your integration needs a written rule for a transaction dated into a closed period. Either it waits in the error queue for finance, or it posts to the first open period with the original date kept in a memo field. Finance picks the rule before launch.

Retries, idempotency and the error queue

An API call can time out after the ERP already saved the invoice, and a careless retry creates a second one. Idempotency fixes this: sending the same request twice has the effect of sending it once. Stripe documents the pattern well. A client sends an idempotency key, and retries with that key return the saved result of the first request (Idempotent requests).

With an ERP, the external ID usually does this job. A PUT to eid:fs_10482 in NetSuite updates the same record every time, so a retry is harmless.

Some records will still fail: a customer missing from the ERP, a closed period, an item nobody mapped. Those go to an error queue. Azure Service Bus calls its version a dead letter queue, and its docs note that messages stay there until code retrieves and settles them (Service Bus documentation on dead letter queues). For finance, that means a failed record waits in a visible place until a person resolves it.

Each entry in our error queues carries five things:

  • The source key and version, so the fix starts from the right record.
  • A reason a bookkeeper can act on, such as "Customer 2231 has no match in the ERP."
  • An owner: billing, AP or the operations admin.
  • An age, so anything older than two days shows up on the close checklist.
  • A replay action that resends with the same external ID.

On the customer operations platform we built, synchronization with Zoho CRM and Zoho Inventory covered invoices, payments, sales orders and subscriptions, and the data synchronization work tracked integration state, retries and processing logs. We build ERP integrations the same way, with a log finance can open during close.

Walkthrough: a field ticket corrected after capture

Say a 40 person specialty contractor runs field service software and Business Central. On Tuesday a foreman closes field ticket 10482: 8 labor hours at $95 plus $340 of materials, $1,100 in total. The ticket flows to Business Central as a draft sales invoice. On Thursday the office notices the foreman logged a helper twice. Real labor was 6.5 hours, so the correct total is $957.50.

Here is the event log the integration keeps, shown for two timings of the same fix.

Event log for field ticket 10482, corrected before posting (2a) or after posting (2b). Example figures.

Step

Source event

Integration action

ERP result

1

Ticket 10482 version 1 closed, $1,100

Create draft invoice with external document number FT10482. Log key fs_10482_v1.

Draft sales invoice for $1,100

2a, before posting

Ticket edited to version 2, $957.50

Update the same draft by key. Log old and new values, user and time.

Same draft, now $957.50. Log holds both versions.

2b, after posting

Ticket edited to version 2, $957.50

Call cancel on the posted invoice, then create and post a new invoice for version 2. Log all three document numbers.

Corrective credit memo for $1,100 applied to the original. New invoice for $957.50.

3

Nightly reconciliation

Compare the ticket total with the net ERP amount for FT10482.

$957.50 on both sides. Check passes.

Before posting, an edit in place is safe because nothing has reached the ledger. The integration still logs both versions, with who changed the ticket and when, so an auditor asking why the invoice dropped $142.50 gets the answer from one screen.

After posting: cancel, credit and reissue

After posting, every change arrives as a new document. Business Central's documentation describes the behavior we rely on: where cancel is allowed, canceling an unpaid posted invoice creates and posts a corrective credit memo, marks the original as canceled, and keeps the credit memo as the audit trail (Correct or cancel unpaid sales invoices). The API exposes cancel as an action on the invoice (salesInvoice resource type). If the customer already paid, Business Central blocks the cancel, so finance issues a sales credit memo for $142.50 and the log records why.

Journal entries work the same way. A Business Central reversal carries the same document number and posting date as the original, and each entry can be reversed one time (Reverse journal postings). Sage Intacct links the reversal to the original, shows a Reversed on date, allows reversals in open periods, and sends subledger entries such as AP back to the originating application to be voided (Reverse journal entries).

Every ERP document carries the ticket number in its external document number, and every log row carries the ticket version. From any ERP document you can open the ticket version that created it, and from any ticket you can list every ERP document it touched: the version 1 invoice, the credit memo and the version 2 invoice.

How to reconcile transactions between source systems and the ERP

Reconciliation answers one question: does every source record have exactly one live ERP record with the same amount and the right status? Run three checks every night and month end becomes a review of a short list.

  1. Completeness. Count source records closed yesterday and ERP documents carrying those keys. Every gap must sit in the error queue with a reason.
  2. Amount. Sum by day, customer and job on both sides, net of credit memos and reversals. Ticket 10482 nets to $957.50 on both sides even with three ERP documents behind it.
  3. Status. Compare states. Approved in the source should mean posted or pending approval in the ERP. Voided in the source should mean reversed or credited in the ERP.

Records that fail a check become exceptions, and exceptions are where the close hours go. That makes the exception rate the number to manage.

Enter last month's numbers to see how many hours your exception rate costs at month end.

Set transactions per month, exception rate, minutes per exception and loaded hourly cost; the chart shows month end matching hours across every exception rate, with your rate and half your rate marked.

The line is straight, so every point of exception rate you remove gives back the same hours. Start with causes you can fix during setup: master data ownership, unmapped items and the closed period rule.

ERP integration software vs custom ERP integration services

The right build depends on how unusual your transactions are, how many systems feed the ERP, and who owns the integration after launch.

Comparing ERP integration solutions

Option

Fits when

Watch for

Prebuilt connector or iPaaS (ERP integration software such as Boomi, Workato or a native app)

Standard objects and common pairs, such as an ecommerce store feeding NetSuite

Fixed mappings that skip field tickets or retainage. Error screens built for IT that finance never sees.

iPaaS plus custom mapping

Mostly standard objects with a few custom fields or approval rules

Logic spread across dozens of flows, with nobody owning reconciliation

Custom integration service

Custom transactions such as field tickets, progress billing or job cost, strict correction history, several sources feeding one ERP

Needs a named owner, monitoring and documentation, or the code itself becomes the risk

Whichever you pick, hold every option to the same four tests. Does it key every record by external ID? Can it stop at draft? Does it send corrections as reversals or credit memos? Does finance get an error queue and a nightly reconciliation report? We compared the tradeoffs in more depth in API integration platforms vs custom code.

What finance must validate before launch

Finance owns the ledger, so finance approves the integration. Before go live, test each of these with real records in a sandbox company:

  1. Each master object has one owner, and the integration queues records from any other system.
  2. Send the same transaction twice, including after a forced timeout. Exactly one ERP document should exist.
  3. Confirm which documents arrive as drafts, which post automatically, and who approves them.
  4. Send a transaction dated into a locked period and confirm it lands where finance decided.
  5. Change a transaction before posting and again after posting. Check the edit, the reversal or credit memo, and the link back to the source version.
  6. Compare line totals and tax on 50 real transactions to the cent.
  7. Check that every failure in the error queue has a reason, an owner and a replay that reuses the external ID.
  8. Run the three nightly checks on a full month of history and clear every exception before cutover.

If you can, run one close in parallel, old process and integration side by side, until the report shows zero unexplained differences.

Where to start

A good ERP integration makes month end boring. Source systems propose, the ERP posts, corrections arrive as linked documents, and a nightly report names the few records that need a person. Finance can trace any ledger line back to the field ticket or order that created it.

If you are connecting field, CRM, ecommerce or project systems to your ERP and want the posting rules and reconciliation designed before anyone writes code, show us your workflow. We will map what should flow in, where it should stop, and how you will prove it matches. Our systems integration page explains how we run these projects.

For who owns customers, orders and invoices before they reach the ERP, see our CRM and ERP integration guide. See our systems integration services.

Sources

Share this article

Show us the workflow your existing software can't handle.

You don't need a technical specification. Walk us through the process, the systems involved, and where your team is losing time.

Book a Workflow Call →
Systems involved