NetSuite to Salesforce Lead-to-Cash Sync (n8n)

Automate the transition from Back-Office Finance to Front-Office Sales using n8n's robust node-based architecture.

Tools: NetSuiteSalesforce

Platform: n8n

Short Answer

A bi-directional flow where Salesforce Accounts are automatically updated with NetSuite financial data, and sales reps receive real-time notifications of payment issues or inventory changes directly in the CRM.

The Problem

Sales teams often lack visibility into back-office financial status, leading to manual data entry errors and 'blind' selling to credit-blocked customers. This integration bridges the gap between NetSuite ERP and Salesforce CRM by synchronizing customer health and transaction data.

The Outcome

A bi-directional flow where Salesforce Accounts are automatically updated with NetSuite financial data, and sales reps receive real-time notifications of payment issues or inventory changes directly in the CRM.

Step-by-Step Guide

1. **Establish Credentials**: In n8n, go to 'Credentials' and setup **NetSuite Restlet API** (Token-Based Authentication/OAuth 1.0) and **Salesforce OAuth2**. Ensure Salesforce 'Consumer Key' and 'Consumer Secret' are configured in a Connected App. 2. **Configure NetSuite Trigger**: Use an n8n **Webhook Node** as the entry point. In NetSuite, create a 'User Event Script' or 'Scheduled Script' to POST data to the n8n webhook URL whenever a record matches your criteria. 3. **Handle Data Structure**: Add an **Edit Fields Node** (formerly Set) to extract $node['Webhook'].json["body"] and normalize the NetSuite nested JSON structure. 4. **Verify Record Presence**: Add a **Salesforce Node** set to 'Search' for an existing Account using the NetSuite `Internal ID` as the `External ID` in Salesforce to prevent duplicates. 5. **Branching Logic (IF Node)**: Use an **If Node** to check if a match was found. This determines whether you call the 'Create' or 'Update' action. 6. **Map Financial Data**: Use n8n **Expressions** to transform NetSuite currency formats to Salesforce decimal fields. Example: `{{$json.balance.toString().replace(/[^0-9.]/g, '')}}`. 7. **Salesforce Upsert**: Configure the **Salesforce Node** (Action: Upsert) using the custom `NetSuite_ID__c` field as the lookup key to ensure data integrity without duplicate accounts. 8. **Implement Error Handling**: Create a separate 'Error Workflow' and link it in the original workflow's **Settings > Error Workflow** to catch API rate limits or field validation errors. 9. **Wait/Delay (Optional)**: If processing large batches of NetSuite Inventory, use the **Wait Node** or **Split In Batches Node** (set to 50 records) to avoid Salesforce API concurrency limits.

Data Mapping

| NetSuite Field | Salesforce Field | n8n Transformation Expression | Required? | | :--- | :--- | :--- | :--- | | Internal ID | NetSuite_ID__c (Ext ID) | `{{ $json.id }}` | Yes | | Company Name | Name | `{{ $json.companyname }}` | Yes | | Balance | AnnualRevenue | `{{ parseFloat($json.balance) }}` | No | | Is Inactive | IsActive__c | `{{ $json.isinactive === 'F' ? true : false }}` | No | | Terms | Account_Status__c | `{{ $json.terms.name }}` | No | | Email | PersonEmail / Email | `{{ $json.email.toLowerCase() }}` | Yes |

Gotchas & Failure Modes

• **NetSuite Complexity**: NetSuite returns sublists (e.g., addressbook) as nested objects; use n8n's **Item Lists Node** to flatten these if you need to update multiple Salesforce Contacts. • **API Limits**: Salesforce has strict 'Concurrent Request' limits. If syncing >1000 records, use the **Split In Batches** node with a batch size of 50. • **Type Conversion**: NetSuite numbers often arrive as strings in webhooks. Always use `parseFloat()` or `.toNumber()` in n8n expressions before sending to Salesforce numeric fields. • **TBA Expiry**: NetSuite Token-Based Auth tokens can expire or be revoked if the user's role permissions change. Ensure the NetSuite Service Account has 'Web Services Only' enabled.

Verification Checklist

- [ ] Trigger the NetSuite Webhook manually using a 'Preview' transaction. - [ ] Check n8n **Execution Log** to Ensure JSON structure matches Expected Salesforce input. - [ ] Verify globally unique `NetSuite_ID__c` field exists in Salesforce. - [ ] Test matching logic: Ensure an existing Salesforce account is updated rather than a new one created. - [ ] Trigger an intentional error (e.g., missing name) to verify the **Error Trigger** workflow initiates.

Ready to Automate?

Build this automation with n8n in minutes.