How to Sync Adobe Commerce Orders to NetSuite
Connect Adobe Commerce (Magento 2) to NetSuite for automated order processing.
What This Integration Does
Adobe Commerce is where the order is captured, but accounting, fulfillment, and inventory all live in NetSuite. Hand-keying orders into NetSuite is slow and error-prone, and any lag means warehouse staff are working from stale data. This workflow polls Adobe Commerce for new orders, normalises them into NetSuite sales orders with the right customer and item lines, and posts them as soon as they're ready to ship.
The workflow runs on a schedule (or via webhook), only picks up orders in a chosen status (typically pending or processing), and writes one NetSuite sales order per Adobe Commerce order. The Adobe Commerce order number is stored on the NetSuite record so re-runs are idempotent and you can trace a NetSuite SO back to its original Magento order.
Prerequisites
- An Adobe Commerce REST connection with integration token granting read access to orders, customers, and products.
- A NetSuite connection with permission to create sales orders and customers and run SuiteQL.
- Decisions made up front on item mapping (Magento SKU to NetSuite internal item id) and customer mapping (email to NetSuite entity id).
Step 1: Schedule Trigger
Drop a Trigger node onto the canvas and set its type to Schedule. Every 10-15 minutes is a sensible cadence for most stores. Capture the previous run's high-water-mark timestamp in a variable named since so each run only picks up new orders.
Step 2: List Orders from Adobe Commerce
Add a Connector node pointing at the adobe-commerce-rest connector and pick the list-orders tool. Filter by status and updated-at:
searchCriteria[filter_groups][0][filters][0][field]=status
searchCriteria[filter_groups][0][filters][0][value]=processing
searchCriteria[filter_groups][1][filters][0][field]=updated_at
searchCriteria[filter_groups][1][filters][0][value]={{ since }}
searchCriteria[filter_groups][1][filters][0][condition_type]=gt
Page through results until items is empty - Magento returns up to pageSize per call.
Step 3: Loop Over Orders
Wrap the rest of the workflow in a Loop node iterating over {{ orders.items }}. For each order, optionally call get-order on the same connector if the list response doesn't include all the line-item detail you need.
Step 4: Resolve or Create the NetSuite Customer
Add a Connector node calling netsuite run-suiteql with:
SELECT id FROM customer WHERE email = '{{ order.customer_email }}'
Use a Condition node on the result count. If the customer doesn't exist, call create-customer with the Magento billing address. Either way, capture the NetSuite customer internal id in nsCustomerId.
Step 5: Transform Line Items and Create the Sales Order
Use a Transform node to flatten configurable products (keep the simple child SKU, drop the parent) and look up the NetSuite item internal id per line. Then call netsuite create-record with type salesOrder:
{
"entity": { "id": "{{ nsCustomerId }}" },
"otherrefnum": "{{ order.increment_id }}",
"trandate": "{{ order.created_at }}",
"item": {
"items": [
{ "item": { "id": "{{ line.nsItemId }}" }, "quantity": {{ line.qty_ordered }}, "rate": {{ line.price }} }
]
}
}
Step 6: Stamp Back and Notify on Failure
Store the returned NetSuite internal id back on the Adobe Commerce order as a comment via raw-rest-request so support can cross-reference. Wrap the create-record call in a Condition on success - on failure, route to slack send-message with the Magento order number and error.
Tips
- Configurable products in Magento have a parent SKU plus a simple child SKU. Push only the simple child to NetSuite or you'll get duplicate inventory movement.
- Pre-cache the SKU-to-NetSuite-item map in MongoDB or MySQL and look it up locally rather than hitting NetSuite once per line.
- Set per-node retries on the NetSuite step - Adobe Commerce occasionally returns the same order twice in overlapping windows, and NetSuite's natural-key check on
otherrefnumwill reject the duplicate cleanly.
Common Pitfalls
- Tax lines - Adobe Commerce reports tax per line and at order level. NetSuite expects either inclusive or exclusive prices, not both. Pick one and stick to it.
- Bundle products - Bundles in Magento expand to their child SKUs on the order. Make sure your Transform step traverses
parent_item_idcorrectly. - Status drift - Filtering on
status = processingmisses orders that briefly enterholded. Either widen the filter or run a daily reconciliation pass.
Testing
Pick one real Adobe Commerce order and run the workflow manually with the loop hard-limited to that single order id. Open the resulting NetSuite sales order in the UI and check entity, item lines, quantities, prices, and the stored otherrefnum match exactly. Only then enable the schedule.