API Integration & Workflow Automation
CRM and ERP integration: who owns customers, orders and invoices?
CRM and ERP integration, field by field: which system owns customers, orders and invoices, how to stop sync loops, and how to reconcile changed orders.
- Published
- Author
- Cass & York Team
- Series
- Cass & York
- Reading time
- 12 min read
A rep marks a $48,000 deal Closed Won on Tuesday. On Thursday the customer drops five units, the rep edits the opportunity, and the integration pushes the new amount into the ERP, where the order has already shipped and been billed. At month end the controller has three numbers for one sale and loses a morning working out which one is real.
CRM and ERP integration breaks in the same place almost every time: both systems believe they own the same field. The fix is a field ownership map. Every field gets one owner, one sync direction, and one moment when it passes from sales to operations and finance.
This guide is for COOs, controllers and ops leads running HubSpot or Salesforce alongside NetSuite, QuickBooks Enterprise, Sage Intacct or a similar ERP. It covers the handoff from a closed deal to fulfillment and invoicing, the identifiers that keep records matched, sync loops, cancellations and changed orders, and the daily check that proves the totals agree. We use one sample customer and order throughout and finish on the conflict most teams get wrong.
Short answer: the CRM owns the relationship and the deal until the customer commits. The ERP owns the billing identity, the sales order, fulfillment and every invoice from the moment the order exists. Each field syncs in one direction, the receiving system keeps a read only copy, and any change after the handoff goes through the ERP as a change order or a credit memo.
Why CRM and ERP integrations break at the handoff
Both systems store a customer, an amount and a status, and each was built for a different team. Sales edits the CRM all day because the deal is still moving. Finance needs ERP records to hold still once they post, because tax, revenue and receivables depend on them. In DATAVERSITY's 2024 Trends in Data Management survey, 68% of 334 respondents named data silos as a problem in their organization and 56% named data quality.
Connectors make the overlap easy to create. HubSpot's Salesforce integration has a two way rule where the most recent value will always overwrite the other side. HubSpot's data sync asks you to pick a default app that overwrites the other when values differ.
Both settings work as designed. Applied to an order amount, they let a rep's late edit beat an invoiced figure, so the decision has to be made field by field.
The field ownership map for a sample customer and order
Our sample is fictional. Harbor Point Facilities, a property management company, buys 40 commercial water filtration units at $1,200 each from a distributor running HubSpot and NetSuite. The deal closes at $48,000. Swap in Salesforce, Sage Intacct or QuickBooks Enterprise and the map holds with different field names.
The diagram shows which system writes each group of fields and the single event that moves the order across.
Record | Field | Owner | Direction | When it syncs | In the other system |
|---|---|---|---|---|---|
Customer | CRM company ID | CRM | CRM to ERP, stored as external ID | Customer creation | Locked |
Customer | ERP customer ID | ERP | ERP to CRM | Customer creation | Locked |
Customer | Company name, website, industry | CRM | CRM to ERP once | Customer creation | ERP keeps its own legal name |
Customer | Legal name, billing address, billing contact | ERP | ERP to CRM | On change | Read only; sales files a change request |
Customer | Ship to addresses | ERP after the first order | CRM to ERP on the first order, then ERP to CRM | Order creation, then on change | Read only |
Customer | Payment terms, credit limit, tax exemption | ERP | ERP to CRM | On change | Read only |
Customer | Account owner, lifecycle stage, marketing consent | CRM | Account owner copied to ERP for commission reports | On change | Hidden or read only |
Customer | Open balance, days overdue | ERP | ERP to CRM | Daily and on payment | Read only |
Deal | Quote lines, discount, close date | CRM | Copied into the sales order once | Closed Won | Order lines live in the ERP after this |
Deal | Booked amount ($48,000) | CRM, locked at Closed Won | Stays in the CRM | Locked at Closed Won | Reported beside ERP totals |
Sales order | Order number, lines, quantities, prices | ERP | ERP to CRM | On change | Read only |
Sales order | Order status, ship date, tracking | ERP | ERP to CRM | On change | Read only fulfillment fields on the deal |
Invoice | Number, total, due date, amount paid | ERP | ERP to CRM | On posting and on payment | Read only |
Credit memo | Number, amount, reason, applied invoice | ERP | ERP to CRM | On posting | Read only |
Deal | Order total, net invoiced | ERP | ERP to CRM | On change | Read only, beside booked amount |
Read the table top to bottom and one pattern repeats. Before Closed Won the CRM writes; once the sales order exists the ERP writes and the CRM reads. The two ID rows are the exception on purpose, because each system needs the other's key to find the matching record.
Sage Intacct's own Salesforce integration splits the work this way. Its component overview says the Salesforce objects reflect data contained in Intacct, and in the classic workflow synced documents are read only in Salesforce. Admins can also block Salesforce users from entering invoices while still letting them create quotes and orders.
Design the handoff from sales to fulfillment and invoicing
The handoff is one event with six steps. We design it so a retry at any step lands on the same records.
- Require complete data before Closed Won. The CRM blocks the stage until the deal has a billing contact email, a ship to address, requested payment terms, tax status, and line items that exist in the ERP item list. An incomplete deal stays open in the CRM where sales can fix it.
- Find or create the customer by ID. The integration looks up the ERP customer using the CRM company ID stored as its external ID. NetSuite REST supports upsert with PUT on an external ID: the record is added if missing and updated if it exists, so a second attempt finds the first.
- Create the sales order with the deal ID as its external ID. Harbor Point's deal becomes sales order SO5531, starting at Pending Approval if your account uses order approvals.
- Write the ERP IDs back. The ERP customer ID lands on the company and SO5531 lands on the deal. From this point the deal's line items lock in the CRM.
- Mirror status forward. Each ERP status change updates a read only fulfillment status on the deal.
- Mirror invoices and payments. Invoice number, total, due date and amount paid appear on the deal and the company, so a rep can see an account is 40 days late before calling about a renewal.
NetSuite's sales order statuses are set by the system, which makes them a clean source for the CRM picklist. This mapping assumes Advanced Shipping is on.
NetSuite status | What NetSuite means | CRM fulfillment status | What sales can request |
|---|---|---|---|
Pending Approval | Order not yet approved | Booked, awaiting approval | Line edits, applied in the ERP |
Pending Fulfillment | Approved, waiting to ship | In fulfillment | Change request |
Partially Fulfilled | Some items shipped | Partially shipped | Changes to unshipped lines |
Pending Billing | Waiting for an invoice | Shipped, awaiting invoice | Change request to finance |
Billed | Shipped and invoiced | Invoiced | Credit memo or a new linked order |
Closed | Will not be fulfilled or billed | Closed | None |
Canceled | Terminal; NetSuite says it cannot be undone | Canceled | A new order copied from the old one |
Sage Intacct and QuickBooks Enterprise use their own labels. Map them into the same CRM picklist so a pipeline report reads the same whichever ERP sits behind it. Spell every value exactly: when HubSpot syncs the NetSuite customer status, the dropdown labels must match NetSuite's values exactly, including case.
Identifiers that keep customers and orders matched
Names drift and IDs hold. Once a record exists in both systems, match it by ID every time.
- Store each system's ID in the other. The CRM company ID becomes the ERP customer's external ID, and the ERP customer ID goes into a locked CRM field. The deal ID becomes the sales order's external ID.
- Retire name and domain matching after the first sync. HubSpot's data sync matches companies by name or domain by default. A parent company with three billing entities on one domain will collapse into one record.
- Make Salesforce external IDs unique. Salesforce upsert creates a record when nothing matches, updates on one match, and returns an error on several. Marking the field Unique stops duplicates at the source.
- Check the characters. NetSuite external IDs accept letters, numbers, underscores and hyphens, and a pipe character breaks REST lookups. Raw HubSpot and Salesforce record IDs fit those rules.
- Add the subsidiary when you run several. HubSpot's NetSuite integration adds a NetSuite Subsidiary property to companies, deals, invoices and orders. With more than one subsidiary, the customer key is the CRM company ID plus the subsidiary.
Our customer data integration guide covers the harder case: deciding whether two existing records are the same customer before either ID exists.
How to avoid sync loops between CRM and ERP
A sync loop starts when the integration writes a field into the ERP, the ERP reports a change, and the integration copies that "change" back to the CRM, which reports its own change. Every pass refreshes the modified timestamp, so a most recent value rule always sees a fresh edit. The loop burns API calls and can bounce an old value back over a correct one.
Four controls stop it:
- Give every field one owner. A field that syncs in one direction has no path back. The ownership map removes most loops before any code runs.
- Tag your own writes and skip them. Salesforce Change Data Capture puts the API client ID in the changeOrigin header field when your calls set one, and Salesforce documents it for exactly this check. A dedicated integration user gives you a second filter through commitUser.
- Skip writes that change nothing. Store the last value synced for each field and write only when the incoming value differs.
- Process each event once. Shopify says your app might receive the same webhook more than once, after a timeout or a retry, and points to the
X-Shopify-Event-Idheader for spotting repeats. Our Shopify integrations consulting included Salesforce and event integrations, and we design every event handler to record the event ID and skip one it has already processed. The same rule applies to NetSuite and HubSpot events.
For the case where a create request times out and nobody knows whether it succeeded, see our walkthrough of following a sale through CRM, operations, accounting and marketing.
Sync timing: what needs minutes and what can wait
Decide timing by who acts on the data next. A warehouse waiting on an order needs minutes. A rep checking an overdue balance can live with a daily refresh.
Flow | Timing we design for | Who is waiting |
|---|---|---|
Closed Won to sales order | Event driven, minutes | Fulfillment |
Order status and shipment to CRM | Event driven or a short schedule | Reps answering customer calls |
Billing address and terms changes | On change | AR and tax |
Invoices and payments to CRM | Hourly or daily | Account managers and collections |
Reconciliation | Daily, plus a run before month end close | Controller |
Check what your connector actually does. HubSpot's data sync says records sync within 10 minutes of a change after the initial sync, and an initial sync of a large database can take several days. When you map a new property in the HubSpot NetSuite integration, existing records sync only after they're updated in either system, so plan a backfill.
QuickBooks Enterprise connectors that run through the Web Connector sync while the Web Connector is open, on an interval the vendor sets (MyWorks ranges from 5 to 60 minutes by plan). Sage Intacct syncs Salesforce order entry documents manually or on its scheduler. Our piece on how fast customer data needs to update works through the same question for customer messages.
Cancellations and changed orders after the handoff
Once the sales order exists, the CRM requests and the ERP executes. Sales submits a change request on the deal with a reason code (quantity change, product swap, price concession, customer canceled), the requested amount and the requester. Operations or finance applies it in the ERP, and the result flows back like any other ERP field.
What the ERP does depends on where the order is:
Order stage | Customer cancels | Customer changes quantity or product |
|---|---|---|
Pending Approval | Cancel the sales order | Edit the order lines |
Approved, nothing shipped | Cancel the sales order | Change order on the open lines |
Partially shipped | Close the unshipped lines and invoice what shipped | Change the unshipped lines; shipped lines stay |
Invoiced | Credit memo against the invoice | Decrease: credit memo. Increase: a new sales order linked to the original |
Canceled in NetSuite | Final | Copy into a new order with a new external ID |
NetSuite describes a credit memo as a transaction that decreases what a customer owes and can reverse a charge. A credit memo keeps the invoice and the reversal side by side, which is what an auditor and your reconciliation both need.
Keep the CRM history intact. A deal canceled after booking stays Closed Won with a "Canceled after booking" flag and a reason. Win rates stay honest, and commission clawbacks run from a recorded field.
The hardest conflict: one amount field, three true numbers
The amount field causes more trouble than every other field combined, because three different numbers are each correct for someone.
- Booked amount is what sales won. Pipeline, quota and commission run on it. Harbor Point: $48,000.
- Order total is what operations will ship. It moves with change orders and may include freight. After the customer drops five units: $42,000 in product.
- Net invoiced is invoices minus credit memos. Revenue and receivables run on it. Harbor Point was invoiced $45,550 including $850 freight and $2,700 sales tax, then received a $1,500 credit for a late delivery: $44,050.
Both default fixes fail. Sync the CRM amount into the ERP and the rep's edit rewrites a billed order or spawns a second one. Sync the ERP total onto the CRM amount and last quarter's closed won report changes after the quarter closed, commissions shift without anyone approving it, and tax and freight inflate bookings.
Sage Intacct's connector offers this second path deliberately: admins can include tax and add ons in the quote amount or replace it with the order amount. Choose it with your sales leader in the room.
Our rule is three fields with three owners. Booked amount lives in the CRM and locks at Closed Won. Order total and net invoiced live in the ERP and appear on the deal as read only fields. Every dollar between booked and invoiced carries a reason code from a change order, freight, tax or a credit memo.
Plug in a deal of your own to see whether every dollar between booked and invoiced has a reason.
Reconciliation: proving CRM and ERP totals agree
Events get missed, people edit records by hand, and connectors fail quietly. A daily reconciliation job catches all three. We run four checks:
- Orphans. Every Closed Won deal since go live has exactly one sales order carrying its deal ID, and every sales order points back to one deal. A deal with no order is revenue nobody is fulfilling, so we build this check first.
- Amount bridge. Booked amount, plus coded change orders, freight and tax, minus credit memos, equals net invoiced. Whatever is left is unexplained variance.
- Status match. The CRM fulfillment status equals the ERP status for every open order.
- Balance match. The open balance on each CRM company equals the ERP receivables aging for that customer.
Each exception lands in a queue with the deal ID, order number, expected value, actual value and an owner: sales ops for orphans, AR for invoice gaps, an ops lead for stuck statuses. Run the full set before month end close so the controller starts with a short list. Our article on building a single source of truth covers how to report two correct measures side by side once they reconcile.
What to check in a CRM ERP integration tool
Whether you connect CRM, ERP and accounting through a native connector, an integration platform or custom code, the tool has to follow the map. Before you pick one, confirm it can do the following:
- Set direction per field. HubSpot's Salesforce integration offers prefer Salesforce unless blank, always use Salesforce, two way, and don't sync.
- Map custom fields at a price you accept. HubSpot's NetSuite integration requires a Data Hub subscription for custom field mappings.
- Upsert by external ID and write the ERP IDs back to the CRM.
- Recognize and skip its own writes.
- Hold failed records in a queue someone owns, with a reconciliation report beside it.
Gaps in that list usually decide between configuring a connector and adding code around it. Our comparison of integration platforms and custom code walks through where that line falls.
Get one set of numbers from deal to invoice
A finished CRM and ERP integration gives you one sales order per deal, one owner per field, and a daily list of every dollar between booked and invoiced with a reason beside it. Your controller closes the month from that list, and sales sees order status and overdue balances without asking finance.
If you run HubSpot or Salesforce with NetSuite, Sage Intacct or QuickBooks Enterprise and the totals disagree, send us one order that went sideways. Through a free workflow review we will draw your field ownership map, find the field causing the drift, and estimate what closing the gap is worth. You keep the findings either way. You can see the rest of our systems integration and reporting services or contact us directly.
Related reading: following a sale through CRM, operations, accounting and marketing and our customer operations platform case study. For the posting and reconciliation rules once records reach the ERP, see our ERP integration guide. See our systems integration services or get in touch.
Sources
- Using External IDs, Oracle NetSuite Help Center, accessed November 3, 2026
- Using the Upsert Operation, Oracle NetSuite Help Center, accessed November 3, 2026
- Viewing the Status of Sales Orders, Oracle NetSuite Help Center, accessed November 3, 2026
- Credit Memo Use Cases, Oracle NetSuite Help Center, accessed November 3, 2026
- upsert(), Salesforce SOAP API Developer Guide, accessed November 3, 2026
- Change Event Header Fields, Salesforce Change Data Capture Developer Guide, accessed November 3, 2026
- Use HubSpot's integration with NetSuite, HubSpot Knowledge Base, accessed November 3, 2026
- Sync the status field between HubSpot and NetSuite, HubSpot Knowledge Base, accessed November 3, 2026
- Connect and use HubSpot data sync, HubSpot Knowledge Base, accessed November 3, 2026
- Map HubSpot properties to Salesforce fields, HubSpot Knowledge Base, accessed November 3, 2026
- Advanced CRM Integration components, Sage Intacct Help, accessed November 3, 2026
- Sync sales transactions, Sage Intacct Help, accessed November 3, 2026
- Sync Order Entry, Sage Intacct Help, accessed November 3, 2026
- Ignore duplicate webhooks, Shopify Developer Documentation, accessed November 3, 2026
- Using the QuickBooks Web Connector to sync with Shopify (QuickBooks Desktop), MyWorks Software, accessed November 3, 2026
- Trends in Data Management 2024, DATAVERSITY, 2024
Share this article