Articles in this section

Sync orders from Shopify to NetSuite

The Order module imports orders and associated customer information from Shopify into NetSuite. This template uses the Shopify Admin GraphQL API to retrieve orders with delta-based pagination, enabling efficient polling for changes since the last flow run.

Orders are synced into NetSuite as either a Sales Order or a Cash Sale, depending on the order source, fulfillment status, and your configuration. The routing decision is made automatically by the flow's router step based on the settings you configure.

The module includes the following flows:

  1. Shopify order to NetSuite sales order or cash sale (add): the primary order flow

  2. Shopify order to NetSuite order (cash sale or sales order) - Exchanges: for exchange orders created through Shopify's native returns workflow

  3. Shopify order transaction to NetSuite custom transaction record (add): syncs payment transaction data

  4. Shopify order transaction to NetSuite customer deposit (add): creates Customer Deposit records for prepaid orders

Prerequisite settings

Before running the order flows, make sure that you configure the following in the Settings:

  • Financial status to filter orders: Select which Shopify financial statuses to include (for example, PAID, AUTHORIZED). Orders not matching the selected statuses are not exported.

  • Fulfillment status to filter orders: Select which Shopify fulfillment statuses to include (for example, UNFULFILLED, PARTIAL).

  • Filter order by: Choose Last updated time (recommended) or Creation time. Determines the delta field used for incremental export.

  • Lag for the next flow run (minutes): Number of minutes to subtract from the previous run timestamp. Helps ensure orders reach the required financial status before export. For example, a value of 5 re-checks orders from 5 minutes before the last successful run.

  • Sync POS orders into NetSuite as sales orders: When enabled, all POS orders are imported as Sales Orders. When disabled (default), POS orders with fulfillmentStatus = FULFILLED are imported as Cash Sales.

  • Sync orders as cash sales when fulfillment service is external:Enable if Shopify is integrated with external fulfillment services (e.g., Amazon FBA, Shipwire). Such orders are imported as Cash Sales.

  • Assign NetSuite order status as Pending Approval: When enabled, high-risk Shopify orders (risk level = HIGH) are set to Pending Approval status in NetSuite. All other orders use Pending Fulfillment status.

  • Sync records in local currency: When enabled, orders are synced using Shopify's presentment (local) currency amounts. When disabled, shop currency amounts are used.

  • Item ID Map for Discounts: When using the discount settings (NetSuite discount item to track Shopify cart discounts and NetSuite discount item to track Shopify line discounts), create corresponding Item ID Map records in NetSuite to map Shopify discounts to NetSuite items. Missing mappings can cause a value_lookup_failed error. For more information, see Create Item ID Map for Shopify discounts.

  • Payment methods mapping: Maps Shopify payment gateway names to NetSuite payment method internal IDs. Configure a default value for unmatched gateways.

  • Shipping methods mapping: Maps Shopify shipping method names to NetSuite ship method internal IDs. Configure a default value for unmatched shipping methods.

For detailed information, see Configure order and customer sync settings.

Important

Run the Shopify products to item ID map flow and the Shopify customer to NetSuite customer flow before enabling the order flow. If item ID mappings are not in place, the order import will fail for any line item whose Shopify Variant ID is not written to the corresponding NetSuite item record.

Shopify order to NetSuite sales order or cash sale (add)

This is the primary order integration flow. It exports new and updated orders from your Shopify store using the GraphQL orders query and imports them into NetSuite as Sales Orders or Cash Sales.

How the flow works

  • Get orders from Shopify (Export): Uses the GraphQL orders(first, query, after) query with delta-based pagination. Orders are filtered by financial status and either the last updated time or the creation time, depending on your Filter order by setting. The flow subtracts the Lag for the next flow run value (in minutes) from the previous run timestamp to prevent missing orders that have not yet reached the correct financial status.

  • Get customer info from Shopify (Lookup): For each order, retrieves the customer's address history from Shopify using the GraphQL customer(id) { addressesV2(first: 5) } query. This enriches the customer record with up to five addresses before it is created or updated in NetSuite.

  • Get metafields from Shopify (Lookup): Retrieves order-level metafields using the GraphQL order.metafields(first, after) query. A postResponseMap hook transforms the metafield data before it is mapped to NetSuite fields.

  • Get order fulfillment info from Shopify (Lookup): Retrieves fulfillment order details using the GraphQL order.fulfillmentOrders(first: 250) query. Returns the assigned location and delivery method for each line item. This step is required for buy-online-pick-up-in-store (BOPIS) orders and for routing line-level location data to NetSuite.

  • Post customer to NetSuite (Import): Creates customer records in NetSuite by mapping Shopify customer details (name, email, phone, and addresses). Uses lookups to determine subsidiaries and prevent duplicate records before creating the customer.

  • Cash Sale or Sales Order (Router): The flow routes each order to one of two branches using first-matching-branch logic.

    • Post cash sales to NetSuite: sourceName = "pos" AND fulfillmentStatus = "FULFILLED" AND Sync POS orders into NetSuite as sales orders is disabled. Also triggers when the order uses an external fulfillment service, and Sync orders as cash sales when the fulfillment service is external is enabled.

    • Post orders to NetSuite: fulfillmentStatus = "UNFULFILLED" OR the order is not a POS order OR Sync POS orders into NetSuite as sales orders is enabled.

    • Orders that match neither branch will generate an error. If you see unexpected routing, verify your order's sourceName and fulfillmentStatus and check the relevant settings.

How line items are processed

The order pre-save script processes each line item before it is imported into NetSuite:

  • Items where currentQuantity > 0 are included. Items with zero quantity (cancelled or removed line items) are excluded.

  • Line-level and cart-level discounts are calculated separately and mapped to the configured NetSuite discount items.

  • Shipping cost, shipping discounts, and duties are mapped to their respective NetSuite line items.

  • Tax amounts are calculated per line item and per shipping line. The Sync sales tax to NetSuite setting controls whether NetSuite's built-in tax calculation is overwritten.

  • Custom Shopify items (items with no associated Shopify product or variant) are mapped to the NetSuite item to track Custom Shopify Items setting.

  • If Sync records in local currency is enabled, the flow uses presentmentMoney amounts (the currency shown to the customer at checkout). Otherwise, shopMoney (the store's currency) is used.

How customer records are handled

The order flow automatically creates or looks up the customer in NetSuite as part of each order import:

  • If a customer is found in NetSuite by email, the flow uses the existing customer record and does not update it. Updates to customer data (addresses, custom fields, metafields) are handled by the Shopify customer to NetSuite customer (add or update) flow.

  • If no customer is found, a new customer record is created in NetSuite with the minimum fields: first name, last name, email, shipping and billing addresses, subsidiary, and currency.

    Note

    If you want customer records to include all custom metafields defined in your Shopify store, run the Shopify customer to NetSuite customer (add or update) flow before enabling the order flow. If the order flow runs first, customer records are created with only the minimum fields.

High-risk orders: If the order's risk assessments include a riskLevel = "HIGH", the flow marks the order as high-risk. You can configure how high-risk orders are handled using the Assign NetSuite order status as Pending Approval setting. When enabled, high-risk orders are set to Pending Approval status in NetSuite rather than the default Pending Fulfillment status.

Shopify order to NetSuite order (cash sale or sales order) - Exchanges

This flow handles exchange orders created through Shopify's native Returns API. When a customer initiates a return with an exchange in Shopify, Shopify creates a new exchange order linked to the original order. This flow exports those exchange orders and creates corresponding Sales Orders or Cash Sales in NetSuite.

How the flow works

  • Post exchange orders to NetSuite: Creates the exchange Sales Order in NetSuite with mapped item, pricing, and customer details.

  • Post customer deposit to NetSuite (upsell): Creates a customer deposit when the exchange involves an additional payment (upsell scenario).

  • Post exchange invoice to NetSuite: Generates an invoice for the exchange Sales Order.

  • Post credit memo to NetSuite: Creates a credit memo for the returned items associated with the exchange.

  • Post customer refund to NetSuite (downsell): Processes refunds when the exchange results in a lower order value (downsell scenario).

  • Get credit memo status from NetSuite: Retrieves the credit memo status to ensure it is eligible for refund or payment application.

  • Get exchange invoice status from NetSuite: Retrieves the invoice status to determine if payment can be applied.

  • Post customer payment to NetSuite: Applies payments to the exchange invoice and/or credit memo as required.

  • Post exchange cash sales to NetSuite: Creates the exchange as a Cash Sale in NetSuite.

  • Post customer payment to NetSuite (upsell): Records payment for upsell exchanges.

  • Post cash refund to NetSuite: Processes refunds for downsell scenarios.

  • Sales Order: The original NetSuite order's record type is salesorder

  • Cash Sale: The original NetSuite order's record type is cashsale

  1. Get exchange orders from Shopify (Export): Uses the GraphQL orders(first, query, after) query filtered by exchange-specific tags. Returns exchange orders created since the last flow run using delta pagination.

  2. Lookups - returns, metafields, fulfillment orders, original order lines: Retrieves returns, order-level metafields, fulfillment order assignments, and the original NetSuite order's line items to match exchange line items to the original NetSuite transaction.

  3. Sales Order or Cash Sale (Router): Exchange Order Router - first matching branch

The exchange order is created in NetSuite using the same record type as the original order. This ensures that the billing and refund flows process exchange orders correctly.

Note

If the ShopifyOrderId on the NetSuite fulfillment record contains a hyphen (for example, 1234567890-1), the script strips the suffix before processing. This is the standard format used for exchange order IDs.

Shopify order transaction to NetSuite custom transaction record (add)

This flow synchronizes Shopify order transactions to NetSuite custom transaction records. It exports new and updated transaction data from Shopify using a GraphQL query and creates corresponding custom transaction records in NetSuite for tracking payments, authorizations, and refunds.

How the flow works

  1. Get order transactions from Shopify (Export): Uses a GraphQL query (delta-based) to retrieve order transactions, including payment, authorization, capture, and refund details. The export uses pagination to process large datasets and ensures only new or updated transactions since the last run are retrieved.

  2. Find Order (Lookup): For each transaction, looks up the corresponding NetSuite order using the Shopify order ID. This ensures that each transaction is correctly linked to the appropriate NetSuite Sales Order or Cash Sale.

  3. Post order transactions to NetSuite custom records (Import): Creates custom transaction records in NetSuite for each Shopify transaction. Supports multiple transactions per order (one-to-many) and prevents duplicate records using lookup logic.

Shopify order transaction to NetSuite customer deposit (add)

This flow creates Customer Deposit records in NetSuite when payment is captured at checkout in Shopify. It is used when your billing configuration is set to Shopify at sale (payment captured in Shopify when the order is placed).

How the flow works

  • Exports order transactions from Shopify using saved search customsearch_celigo_shopify_trans_to_ns).

  • Only transactions with a status of Captured are considered.

  • Creates one Customer Deposit per payment method used on the order.

  • The deposit is linked to the NetSuite Sales Order via the order ID.

Note

When using this flow, ensure that the Payment Method field on the NetSuite Sales Order is not populated by the order flow's field mappings. NetSuite only allows creating Customer Deposit records for a Sales Order when the Payment Method field is empty.

Important

POS cash sale orders picked up by customer deposit flow: Some Shopify POS transactions use a source_name value other than pos (for example, checkout_one). When this happens, the flow may attempt to create a Customer Deposit for a POS order that was imported as a Cash Sale, which will fail because Cash Sales do not have a related Sales Order. To work around this issue, add an input filter on the Post customer deposit to NetSuite import step to exclude records where record.device_id is not empty.

Known limitations

  • The order flow only syncs fully placed orders. Draft orders must be completed in Shopify before they are exported.

  • Items on a Shopify order where currentQuantity = 0 (cancelled or removed line items) are excluded from the import.

  • If an order has no customer assigned in Shopify, the flow will error with: "Shopify order [name] does not have a customer assigned."

  • The on-demand sync setting (Shopify order IDs) accepts up to 5 comma-separated Shopify order IDs for manual re-sync.

Scheduling guidance

  • Primary order flow: schedule every 15 minutes for near-real-time sync.

  • Transaction and customer deposit flows: schedule to run after the primary order flow in each cycle.

  • Exchange flow: enable after the returns flows are stable, as the returns module creates exchange orders.