Back to Nodes

NetSuite

Last updated Mar 18, 2026

n8n community node for Oracle NetSuite by SolutionLab - REST API, SuiteQL, Restlets, and Polling Triggers with OAuth 2.0 Client Credentials (M2M/JWT/PS256)

18 Weekly Downloads
145 Monthly Downloads

Included Nodes

NetSuite
NetSuite Trigger

Description

n8n-nodes-netsuite-v2

![npm version](https://www.npmjs.com/package/n8n-nodes-netsuite-v2)
![npm downloads](https://www.npmjs.com/package/n8n-nodes-netsuite-v2)
![License: MIT](https://opensource.org/licenses/MIT)
![n8n community node](https://docs.n8n.io/integrations/community-nodes/)
![Built by SolutionLab](https://solutionlabtech.com)

A production-grade n8n community node for Oracle NetSuite, built by SolutionLab (Avishai Asaf). Connects to the NetSuite REST API using OAuth 2.0 Client Credentials with Certificate (Machine-to-Machine / JWT PS256) – the most secure, fully automated authentication method available for server-to-server integrations.

3 resources. 11 operations. Polling triggers. SuiteQL templates. Zero user interaction required for authentication.

Why This Node?

Standard NetSuite integrations in n8n rely on OAuth 2.0 Authorization Code flow, which requires a browser-based login, manual token refresh, and session management. This creates fragile automations that break when tokens expire or when running in headless environments.

This node was built by SolutionLab to solve three specific production bottlenecks:

Fully Automated M2M Authentication

OAuth 2.0 Client Credentials with Certificate eliminates all user interaction. The node constructs a JWT, signs it with PS256 (RSASSA-PSS + SHA-256), and exchanges it for an access token – entirely in the background. Tokens are cached per credential and automatically refreshed with a 5-minute safety buffer before expiry. No browser sessions. No token expiry surprises. No manual intervention.

Robust Certificate Handling

Real-world NetSuite certificate integrations frequently fail on PEM format edge cases – especially when private keys are pasted through web UIs, environment variables, or secret managers. This node normalizes every variant automatically:

  • Standard multi-line PEM with proper 64-character line breaks
  • Single-line keys with escaped n characters
  • Raw base64 content without BEGIN/END headers
  • Keys with PRIVATE KEY, RSA PRIVATE KEY, or EC PRIVATE KEY headers
  • Enterprise API Coverage with Automatic Pagination

    SuiteQL queries and REST Record listings automatically paginate through all results when “Return All” is enabled. NetSuite’s structured error responses (o:errorDetails, o:errorCode) are parsed and surfaced as readable messages instead of raw HTTP errors.

    Enterprise Features

    REST Record Operations

    Full CRUD operations on any NetSuite record type via the SuiteTalk REST API.

    | Operation | Method | Description |
    |———–|——–|————-|
    | Create | POST | Create a record with a JSON body |
    | Get | GET | Retrieve a single record by internal ID |
    | Get Many | GET | List records with filtering, field selection, and sub-resource expansion |
    | Update | PATCH | Partial update – only the fields you include are modified |
    | Upsert | PUT | Create or update a record by external ID – ideal for syncing data from external systems |
    | Delete | DELETE | Remove a record by internal ID |

    Dynamic Record Types – The record type dropdown is populated automatically from NetSuite’s metadata catalog (/services/rest/record/v1/metadata-catalog). If the catalog is unavailable, the node falls back to 20 common record types including Customer, Contact, Invoice, Sales Order, Purchase Order, Journal Entry, and more.

    Get Many Pagination – Enable “Return All” to automatically follow NetSuite’s rel:next pagination links until all records are retrieved. When disabled, a single page of results is returned up to the configured limit.

    Additional Options:

    | Option | Available On | Type | Description |
    |——–|————-|——|————-|
    | Fields | Get | String | Comma-separated list of field names to return (reduces payload size) |
    | Expand Sub-Resources | Get | Boolean | Include sublists and line items in the response |

    > Tip: Need to filter records or select specific fields? Use the SuiteQL resource — it supports full SQL-like queries with WHERE clauses, JOINs, and field selection.

    SuiteQL

    Execute SQL-like queries against your NetSuite data using Oracle’s SuiteQL syntax.

  • Query Templates – Start with built-in templates for common queries (Active Customers, Recent Sales Orders, Open Invoices, Inventory Levels, Employee Directory, Vendor Bills) or write your own
  • Automatic Pagination – When “Return All” is enabled, the node paginates through results using NetSuite’s hasMore flag and offset-based pagination
  • Configurable Limit – When “Return All” is disabled, returns up to the specified limit (default: 1000)
  • Transient Preferences – Requests include the Prefer: transient header for optimized response handling
  • Restlet Operations

    Call custom SuiteScript Restlet deployments with full HTTP method support.

    | Method | Body | Use Case |
    |——–|——|———-|
    | GET | No | Retrieve data from a custom endpoint |
    | POST | JSON | Submit data or trigger server-side logic |
    | PUT | JSON | Update resources via a custom endpoint |
    | DELETE | No | Remove resources via a custom endpoint |

    Each request requires a Script ID and Deploy ID. Additional query string parameters can be passed as key-value pairs. The Restlet URL is constructed as:

    https://{accountId}.restlets.api.netsuite.com/app/site/hosting/restlet.nl?script={scriptId}&deploy={deployId}
    

    Platform Capabilities

  • Token Caching – Access tokens are cached per accountId:consumerKey pair in a module-level store. Tokens are reused across workflow executions within the same n8n process and refreshed automatically 5 minutes before expiry.
  • PEM Normalization – Handles four input variants (multi-line, escaped newlines, single-line, raw base64) and rebuilds the key with proper 64-character line formatting.
  • Structured Error Parsing – NetSuite REST API error responses are parsed to extract o:errorDetails and o:errorCode fields, providing specific error codes and messages instead of generic HTTP status text.
  • Native Token Exchange – The JWT-to-token exchange uses Node.js native https instead of n8n’s HTTP request helper, avoiding URL encoding issues with the client_assertion parameter.
  • Polling Triggers

    The NetSuite Trigger node monitors your NetSuite data for changes and starts workflows automatically. It uses SuiteQL to poll for records that have been created or modified since the last check.

    | Event | Behavior |
    |——-|———-|
    | Record Created | Triggers when new records are created (uses datecreated field) |
    | Record Updated | Triggers when existing records are modified, excluding newly created records |
    | Record Created or Updated | Triggers on any change (uses lastmodifieddate field) |

    Key capabilities:

  • Dynamic record type dropdown – Same metadata catalog integration as the main node
  • Configurable date fields – Override datecreated and lastmodifieddate for custom records that use different field names
  • Additional filters – Narrow polling scope with SuiteQL WHERE clause fragments (e.g., AND subsidiary = 1)
  • Field selection – Return only the fields you need instead of SELECT *
  • Automatic pagination – Handles large result sets across multiple pages
  • Structured error handling – NetSuite error codes are parsed and surfaced clearly
  • > Polling interval: Configured in the n8n workflow settings (default: every minute). The trigger establishes a baseline on first activation and only fires for records changed after that point.

    Installation

    Community Nodes (Recommended)

    1. In n8n, go to Settings > Community Nodes
    2. Enter n8n-nodes-netsuite-v2
    3. Click Install
    4. Restart n8n if prompted

    Manual Installation

    cd ~/.n8n/custom
    npm install n8n-nodes-netsuite-v2
    

    Then restart n8n.

    > Compatibility: Requires n8n with n8n-workflow >= 2.12.0.

    Quick Start

    1. Install the node via Settings > Community Nodes > n8n-nodes-netsuite-v2
    2. Configure credentials — follow the NetSuite Setup below to create an M2M integration and certificate
    3. Create your first workflow — drag the NetSuite node onto the canvas, select Resource: SuiteQL, pick “Active Customers” template, and execute

    That’s it — you’ll see your NetSuite customer list in under 5 minutes.

    NetSuite Setup – Prerequisites

    Before configuring the node in n8n, complete the following steps in your NetSuite account. Administrator access is required for initial setup.

    Step 1: Create an Integration Record

    Navigate to Setup > Integration > Manage Integrations > New.

    | Setting | Value |
    |———|——-|
    | Name | e.g., “n8n Automation” |
    | Client Credentials (M2M) Grant | Enabled |
    | Authorization Code Grant | Disable (not used) |
    | Token-Based Authentication | Not required |

    Click Save, then copy the Consumer Key. The Consumer Secret is not used in the M2M flow.

    Step 2: Generate a Certificate Key Pair

    Generate an RSA key pair using OpenSSL (4096-bit recommended):

    Generate private key

    openssl genrsa -out private.pem 4096

    Generate public certificate (valid for 365 days)

    openssl req -new -x509 -key private.pem -out public.pem -days 365

    > Security: Keep private.pem secure. Its contents will be pasted into the n8n credential form. Never commit private keys to version control.

    Step 3: Configure OAuth 2.0 Client Credentials Mapping

    Navigate to Setup > Integration > OAuth 2.0 Client Credentials (M2M) Setup and click Create New.

    | Field | Description |
    |——-|————-|
    | Entity | The user or employee associated with API calls |
    | Role | The role that determines API permissions (see Step 4) |
    | Integration | The integration record created in Step 1 |

    Upload the public certificate (public.pem) from Step 2, then click Save.

    Copy the Certificate ID – this is the kid value used in the JWT header for token signing.

    Step 4: Configure Role Permissions

    The role selected in Step 3 must have the following permissions based on which resources you plan to use:

    | Resource | Required Permission | Navigation Path |
    |———-|———————|—————–|
    | REST Records (SuiteTalk) | REST Web Services | Setup > REST Web Services |
    | SuiteQL | SuiteAnalytics Workbook | Reports > SuiteAnalytics Workbook |
    | Restlets | SuiteScript | Setup > SuiteScript |
    | All Resources | Log in using Access Tokens | Setup > Log in using Access Tokens |

    > Tip: For initial testing, use the Administrator role. For production, create a custom role with only the minimum required permissions.

    Step 5: Find Your Account ID

    Navigate to Setup > Company > Company Information. Your Account ID is displayed at the top of the page.

  • Production accounts: 1234567
  • Sandbox accounts: 1234567_SB1
  • The node automatically normalizes the Account ID for API URLs (converts to lowercase and replaces underscores with hyphens).

    Credential Configuration

    When creating a new NetSuite Client Credentials (Certificate) credential in n8n, fill in the following fields:

    | Field | Description | Where to Find |
    |——-|————-|—————|
    | Account ID | Your NetSuite Account ID | Setup > Company > Company Information |
    | Consumer Key | Integration consumer key | Integration Record (Step 1) |
    | Certificate ID | Certificate ID (JWT kid claim) | M2M Setup page (Step 3) |
    | Certificate Private Key (PEM) | Full contents of your private key file | private.pem from Step 2 |

    Private Key Format

    Paste the entire contents of your private.pem file, including the -----BEGIN PRIVATE KEY----- and -----END PRIVATE KEY----- lines.

    The node handles multiple formats automatically:

  • Standard multi-line PEM
  • Single-line with escaped n characters
  • Raw base64 without headers
  • Keys with PRIVATE KEY, RSA PRIVATE KEY, or EC PRIVATE KEY headers
  • Testing the Connection

    Click Test in the n8n credential form to verify the connection. The test performs a full authentication cycle (JWT creation, token exchange) and calls GET /services/rest/record/v1/metadata-catalog with the Prefer: transient header. If the test passes, all four credential fields are valid and the certificate is correctly mapped in NetSuite.

    Usage

    Record Operations

    Select Resource: Record to perform CRUD operations on NetSuite records.

    #### Create a Record

    Select Operation: Create, choose the record type, and provide a JSON body:

    {
      "companyname": "Acme Corp",
      "email": "contact@acme.com",
      "subsidiary": { "id": "1" }
    }
    

    #### Get a Record

    Select Operation: Get, choose the record type, and enter the Record ID (internal ID).

    Use Additional Options to control the response:

  • Fields: companyname,email,phone – return only specific fields
  • Expand Sub-Resources: include sublists and line items in the response
  • #### Get Many Records

    Select Operation: Get Many and choose the record type.

  • Enable Return All to automatically paginate through all matching records
  • Set a Limit when Return All is disabled to control the page size
  • For filtering or field selection, use the SuiteQL resource which supports full SQL-like WHERE clauses
  • #### Update a Record

    Select Operation: Update, choose the record type, enter the Record ID, and provide the fields to update:

    {
      "email": "new-email@acme.com",
      "phone": "555-0100"
    }
    

    The update uses HTTP PATCH – only the fields you include will be modified.

    #### Delete a Record

    Select Operation: Delete, choose the record type, and enter the Record ID.

    SuiteQL Queries

    Select Resource: SuiteQL and Operation: Execute.

    Enter your query using SuiteQL syntax:

    SELECT id, companyname, email
    FROM customer
    WHERE isinactive = 'F'
    

    SuiteQL supports JOIN operations for cross-table queries:

    SELECT t.tranid, t.trandate, c.companyname
    FROM transaction t
    JOIN customer c ON t.entity = c.id
    WHERE t.type = 'SalesOrd'
    

    Options:

  • Return All – When enabled, automatically paginates through all results using offset-based pagination. When disabled, returns up to the specified Limit.
  • Limit – Maximum number of results per page (default: 1000). Only visible when Return All is disabled.
  • Restlet Operations

    Select Resource: Restlet to call custom SuiteScript Restlet deployments.

    | Field | Description |
    |——-|————-|
    | Script ID | The numeric script ID of the Restlet deployment |
    | Deploy ID | The deployment ID (default: 1) |
    | Operation | HTTP method: GET, POST, PUT, or DELETE |
    | Body (JSON) | Request body for POST and PUT operations |
    | Additional Parameters | Extra query string parameters (key-value pairs) |

    Example POST body for a custom Restlet:

    {
      "action": "createRecord",
      "recordType": "customrecord_project",
      "values": {
        "name": "New Project",
        "custrecord_status": "1"
      }
    }
    

    Trigger Setup

    Add a NetSuite Trigger node as the first node in your workflow.

    1. Select the Record Type to monitor (e.g., Customer, Sales Order, Invoice)
    2. Choose the Event type: Created, Updated, or Created or Updated
    3. Optionally specify Return Fields (e.g., id, companyname, email) to reduce payload size
    4. Optionally add Additional Filters to narrow the scope (e.g., AND subsidiary = 1)

    The trigger polls NetSuite at the interval configured in your workflow settings. On first activation, it records the current timestamp as a baseline – only records changed after activation will trigger the workflow.

    #### Upsert a Record

    Select Operation: Upsert, choose the record type, specify the External ID Field (default: externalid) and its Value, then provide the fields:

    {
      "companyname": "Acme Corp",
      "email": "contact@acme.com",
      "subsidiary": { "id": "1" }
    }
    

    If a record with the given external ID exists, it will be updated. Otherwise, a new record is created. This is ideal for syncing data from external systems.

    Common Workflow Examples

    These are popular workflows built with this connector. For implementation help, contact SolutionLab.

    NetSuite → Google Sheets Daily Sync
    Schedule a daily SuiteQL query (e.g., open invoices) and write results to a Google Sheet for reporting.

    Shopify Order → NetSuite Sales Order
    Use a Shopify trigger to capture new orders, then create NetSuite sales orders with customer lookup and item mapping.

    Daily Invoice Aging Report via Email
    Run “Open Invoices” SuiteQL template on a schedule, format as HTML table, and send via email to your finance team.

    CRM Contact Sync
    Use the polling trigger to detect new NetSuite customers, then sync to HubSpot, Salesforce, or your CRM of choice.

    Inventory Alerts
    Poll inventory levels with SuiteQL and send Slack alerts when stock falls below threshold.

    Professional Services & Support

    This node is developed and maintained by SolutionLab, a team that specializes in NetSuite integrations, SuiteScript development, and n8n workflow automation.

    Free vs Professional

    | Capability | Free (this connector) | Professional (SolutionLab) |
    |—|—|—|
    | Record CRUD + Upsert | Included | — |
    | SuiteQL queries with templates | Included | — |
    | Restlet invocation (all HTTP methods) | Included | — |
    | Polling triggers | Included | — |
    | Real-time webhook triggers | — | Custom SuiteScript User Event Script deployment |
    | Bulk create/update/delete | — | Custom Restlet scripts for batch operations |
    | Line item manipulation | — | Complex transaction workflows (invoices, sales orders with lines) |
    | Multi-subsidiary configuration | — | NetSuite role, permission, and subsidiary setup |
    | Custom field mapping & data transformation | — | Integration consulting and architecture |

    What We Build

  • NetSuite ↔ E-commerce sync – Real-time inventory, order, and customer sync with Shopify, WooCommerce, and custom platforms
  • Automated invoicing & payment processing – End-to-end order-to-cash automation with GL journal entries
  • Multi-system ERP integration – NetSuite as the hub connecting CRM, warehouse, and logistics systems
  • Custom SuiteScript Restlets – Purpose-built API endpoints for complex business logic that REST API can’t handle
  • Real-time NetSuite triggers – User Event Scripts that push events to n8n webhooks in sub-second latency
  • Contact

    Book a consultation | avishai@solutionlabtech.com | LinkedIn

    How Authentication Works

    This section details the OAuth 2.0 Client Credentials with Certificate flow as implemented in this node.

    JWT Construction

    The node builds a JSON Web Token with the following structure:

    Header:

    {
      "alg": "PS256",
      "typ": "JWT",
      "kid": ""
    }
    

    Payload:

    {
      "iss": "",
      "scope": ["restlets", "rest_webservices"],
      "iat": 1710000000,
      "exp": 1710003600,
      "aud": "https://.suitetalk.api.netsuite.com/services/rest/auth/oauth2/v1/token"
    }
    

    | Claim | Description |
    |——-|————-|
    | iss | The Consumer Key from the Integration Record |
    | scope | Fixed scopes: restlets and rest_webservices |
    | iat | Issued-at timestamp (current Unix time in seconds) |
    | exp | Expiration timestamp (issued-at + 3600 seconds) |
    | aud | The token endpoint URL (also the audience) |
    | kid | The Certificate ID from the M2M Setup page |

    JWT Signing

    The JWT is signed using PS256 (RSASSA-PSS with SHA-256):

  • Algorithm: crypto.sign('sha256', signingInput, { key, padding: RSAPKCS1PSSPADDING, saltLength: RSAPSSSALTLENDIGEST })
  • The signing input is base64url(header).base64url(payload)
  • The signature is base64url-encoded and appended: header.payload.signature
  • Token Exchange

    The signed JWT is exchanged for an access token via HTTP POST:

    POST https://.suitetalk.api.netsuite.com/services/rest/auth/oauth2/v1/token
    Content-Type: application/x-www-form-urlencoded

    granttype=clientcredentials &clientassertiontype=urn:ietf:params:oauth:client-assertion-type:jwt-bearer &client_assertion=

    The token exchange uses Node.js native https.request instead of n8n’s HTTP helper to avoid URL encoding issues with the client_assertion parameter.

    Token Caching

    Cache Key:   {accountId}:{consumerKey}
    Storage:     Module-level Map (persists across workflow executions within the same n8n process)
    Refresh:     300 seconds (5 minutes) before token expiry
    

    When a cached token is still valid (more than 5 minutes until expiry), it is reused without making a new token exchange request. This minimizes API calls to the NetSuite token endpoint.

    Authentication Hooks

    Two hooks ensure the Bearer token is attached to every outgoing request:

    1. Pre-Authentication – Runs before each httpRequestWithAuthentication call, exchanges credentials for a token, and stores it for the authenticate hook
    2. Authenticate – Injects the Authorization: Bearer header into the request. Falls back to a direct token exchange if pre-authentication was skipped (e.g., during credential testing)

    Troubleshooting

    Error Reference

    | Error Message | Cause | Solution |
    |—————|——-|———-|
    | NetSuite credential error: Account ID is empty | Account ID field not filled in | Enter your Account ID from Setup > Company > Company Information |
    | NetSuite credential error: Consumer Key is empty | Consumer Key field not filled in | Enter the Consumer Key from the Integration Record |
    | NetSuite credential error: Certificate ID is empty | Certificate ID field not filled in | Enter the Certificate ID from the M2M Setup page |
    | NetSuite credential error: Certificate Private Key is empty | Private Key field not filled in | Paste the full contents of your private.pem file |
    | JWT signing failed (PS256) | Invalid PEM format or unsupported key type | Verify the key is RSA. Run openssl rsa -check -in private.pem to validate. Ensure the full PEM content including BEGIN/END lines is pasted. |
    | Token exchange failed (HTTP 400) | Mismatched credentials or key pair | Verify the Consumer Key matches the Integration Record. Verify the Certificate ID from M2M Setup. Ensure the private key corresponds to the uploaded public certificate. |
    | Token exchange failed (HTTP 401) | M2M grant not enabled or mapping inactive | Verify the Integration Record has “Client Credentials (M2M) Grant” enabled. Verify the M2M Setup mapping is active. |
    | Token exchange network error | DNS resolution failure or network issue | Check the Account ID format. Verify network connectivity to *.suitetalk.api.netsuite.com. |
    | Token response is not valid JSON | Unexpected response from token endpoint | The NetSuite token endpoint may be temporarily unavailable. Retry after a few minutes. |
    | Token response missing access_token | Token endpoint returned an unexpected payload | Verify the M2M Setup is complete and active. Check that the Integration Record is not disabled. |
    | HTTP 403 on API calls | Insufficient role permissions | Add the required permissions to the role mapped in M2M Setup (see Step 4 in Prerequisites). |

    Debugging Steps

    1. Start with the credential test – Click “Test” in the n8n credential form. The error message indicates exactly which step failed: input validation, JWT signing, token exchange, or the API call itself.

    2. Verify the key pair matches – The private key pasted into n8n must correspond to the public certificate uploaded to NetSuite. Both must be generated from the same OpenSSL key pair.

    3. Check the M2M Setup status – Navigate to Setup > Integration > OAuth 2.0 Client Credentials (M2M) Setup in NetSuite and confirm your mapping shows as active.

    4. Sandbox accounts – If using a sandbox, your Account ID includes _SB1 (or similar suffix). The node normalizes this automatically – no manual formatting required.

    What’s New in v0.3.0

  • Polling Triggers — Monitor NetSuite records for creation/modification with the new NetSuite Trigger node
  • 6 SuiteQL Templates — Built-in queries for customers, sales orders, invoices, inventory, employees, and vendor bills
  • Improved Error Messages — Contextual help for common HTTP errors (400, 401, 403, 404) with troubleshooting guidance
  • Input Validation — Record ID and External ID checks prevent cryptic API errors
  • Pagination Safety — Maximum iteration limits prevent runaway loops
  • AI Agent Support — Use the NetSuite node as a tool in n8n AI Agent workflows

No breaking changes from v0.2.x. See CHANGELOG.md for full details.

Contributing

Clone the repository

git clone https://github.com/avishaiasaf/n8n-netsuite-node-v2.git cd n8n-nodes-netsuite-v2

Install dependencies

npm install

Build

npm run build

Lint

npm run lint

Submit issues and pull requests via GitHub.

License

MIT