Package Information
Documentation
n8n-nodes-netsuite-v2
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. 10 operations. Polling triggers. 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
\ncharacters - Raw base64 content without BEGIN/END headers
- Keys with
PRIVATE KEY,RSA PRIVATE KEY, orEC PRIVATE KEYheaders
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 |
| 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 nine common record types: Customer, Employee, Invoice, Item, Journal Entry, Purchase Order, Sales Order, Vendor, and Vendor Bill.
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 (available on Get and Get Many):
| Option | Type | Description |
|---|---|---|
| Fields | String | Comma-separated list of field names to return (reduces payload size) |
| Expand Sub-Resources | Boolean | Include sublists and line items in the response |
| Query Filter | String | Filter expression to narrow results (Get Many only) |
SuiteQL
Execute SQL-like queries against your NetSuite data using Oracle's SuiteQL syntax.
- Automatic Pagination - When "Return All" is enabled, the node paginates through results using NetSuite's
hasMoreflag 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: transientheader 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:consumerKeypair 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:errorDetailsando:errorCodefields, providing specific error codes and messages instead of generic HTTP status text. - Native Token Exchange - The JWT-to-token exchange uses Node.js native
httpsinstead of n8n's HTTP request helper, avoiding URL encoding issues with theclient_assertionparameter.
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
datecreatedandlastmodifieddatefor 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)
- In n8n, go to Settings > Community Nodes
- Enter
n8n-nodes-netsuite-v2 - Click Install
- 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.
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.pemsecure. 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
\ncharacters - Raw base64 without headers
- Keys with
PRIVATE KEY,RSA PRIVATE KEY, orEC PRIVATE KEYheaders
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
- Use the Query Filter additional option to narrow results (e.g.,
email IS NOT NULL) - Set a Limit when Return All is disabled to control the page size
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.
- Select the Record Type to monitor (e.g., Customer, Sales Order, Invoice)
- Choose the Event type: Created, Updated, or Created or Updated
- Optionally specify Return Fields (e.g.,
id, companyname, email) to reduce payload size - 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.
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": "<certificateId>"
}
Payload:
{
"iss": "<consumerKey>",
"scope": ["restlets", "rest_webservices"],
"iat": 1710000000,
"exp": 1710003600,
"aud": "https://<accountId>.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: RSA_PKCS1_PSS_PADDING, saltLength: RSA_PSS_SALTLEN_DIGEST }) - 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://<accountId>.suitetalk.api.netsuite.com/services/rest/auth/oauth2/v1/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=<signedJwt>
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:
- Pre-Authentication - Runs before each
httpRequestWithAuthenticationcall, exchanges credentials for a token, and stores it for the authenticate hook - Authenticate - Injects the
Authorization: Bearer <token>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
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.
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.
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.
Sandbox accounts - If using a sandbox, your Account ID includes
_SB1(or similar suffix). The node normalizes this automatically - no manual formatting required.
Professional Services & Support
This node is developed and maintained by SolutionLab, a team that specializes in NetSuite integrations, SuiteScript development, and n8n workflow automation.
If your requirements go beyond what this node provides out of the box, SolutionLab offers:
- Custom NetSuite Integration Development - Tailored integrations between NetSuite and third-party systems, including complex data mappings and business logic
- SuiteScript & Restlet Development - Server-side and client-side SuiteScript development for custom NetSuite functionality, including Restlet endpoints for external system access
- n8n Workflow Design & Deployment - End-to-end workflow architecture, from initial design through production deployment and monitoring
- Real-Time NetSuite Triggers - For sub-second event-driven workflows, SolutionLab can deploy custom User Event Scripts in your NetSuite account that push events to n8n webhooks in real time. This eliminates polling latency for time-critical integrations.
- Production Support & Troubleshooting - Ongoing support for NetSuite integrations, including performance optimization and issue resolution
Contact: avishai@solutionlabtech.com | LinkedIn | solutionlabtech.com
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

