NetSuite Setup
Step-by-step guide to configuring Token-Based Authentication or OAuth 2.0 M2M in NetSuite for SuitePortal.
SuitePortal supports two authentication methods. Choose one based on your needs:
| Method | When to Use |
|---|---|
| Token-Based Auth (TBA) | Quick setup, existing integrations |
| OAuth 2.0 M2M | Certificate-based, no user tokens, recommended for new integrations |
Both methods require enabling a few shared features in NetSuite first.
Shared Prerequisites
Enable Required Features
Navigate to Setup > Company > Enable Features > SuiteCloud and enable:
| Feature | Required | Why |
|---|---|---|
| REST Web Services | Yes | SuitePortal uses the REST Record API for mutations and metadata |
| SuiteQL | Yes | SuitePortal queries NetSuite using SuiteQL |
| SuiteScript | Recommended | Required if you plan to use suiteportal pull to download SuiteScript files |
Save the page after enabling these features.
After a sandbox refresh, these features may be reset. If you get unexpected authentication errors after a refresh, verify they are still enabled.
Create a Role with Required Permissions
The role assigned to your integration must have specific permissions. You can use an existing role or create a new one.
Navigate to Setup > Users/Roles > Manage Roles and edit your role (or create a new one). Under the Permissions subtab, add these:
Setup tab:
| Permission | Level |
|---|---|
| Log in using Access Tokens | Full |
| REST Web Services | Full |
Reports tab:
| Permission | Level |
|---|---|
| SuiteQL | Full |
The REST Web Services permission is critical. Without it, all API calls will return 401 Unauthorized with an INVALID_LOGIN error — even if your credentials are correct.
You may also want to add permissions for the specific record types you plan to query (e.g., Customers, Sales Orders, etc.) under the Transactions, Lists, and Custom Record tabs.
Find Your Account ID
Find your account ID at Setup > Company > Company Information. The Account ID field shows your account identifier.
NETSUITE_ACCOUNT_ID=1234567_SB1Sandbox accounts include a suffix like _SB1. SuitePortal accepts both underscore and hyphen formats (1234567_SB1 or 1234567-sb1) and normalizes automatically.
Now follow the setup for your chosen authentication method:
Token-Based Authentication (TBA)
TBA uses OAuth 1.0a. You'll create an integration record and an access token.
Enable TBA Feature
Navigate to Setup > Company > Enable Features > SuiteCloud and enable:
| Feature | Required |
|---|---|
| Token-Based Authentication | Yes |
Create an Integration Record
Navigate to Setup > Integration > Manage Integrations > New.
| Field | Value |
|---|---|
| Name | SuitePortal (or any name you prefer) |
| State | Enabled |
| Token-Based Authentication | Checked |
Click Save. NetSuite will display your Consumer Key and Consumer Secret. Copy both immediately — they are only shown once.
NETSUITE_CONSUMER_KEY=your_consumer_key_here
NETSUITE_CONSUMER_SECRET=your_consumer_secret_hereIf you reset the consumer credentials later, all existing access tokens for this integration are invalidated. You must create a new access token after resetting.
Create an Access Token
Navigate to Setup > Users/Roles > Access Tokens > New.
| Field | Value |
|---|---|
| Application | Select the integration you created (e.g., SuitePortal) |
| User | Your NetSuite user |
| Role | The role with the permissions above |
Click Save. NetSuite will display your Token ID and Token Secret. Copy both immediately — they are only shown once.
NETSUITE_TOKEN_ID=your_token_id_here
NETSUITE_TOKEN_SECRET=your_token_secret_hereComplete .env for TBA
NETSUITE_AUTH_TYPE=tba
NETSUITE_ACCOUNT_ID=1234567_SB1
NETSUITE_CONSUMER_KEY=abc123...
NETSUITE_CONSUMER_SECRET=def456...
NETSUITE_TOKEN_ID=ghi789...
NETSUITE_TOKEN_SECRET=jkl012...OAuth 2.0 Machine-to-Machine (M2M)
OAuth 2.0 M2M uses the Client Credentials grant with a JWT signed by your private key. No user-specific tokens are needed — identity is determined by the certificate mapping in NetSuite.
Generate a Key Pair
Create an EC P-256 key pair on your local machine. This is the recommended algorithm — you can also use EC P-384, EC P-521, or RSA-PSS (3072+ bit).
openssl req -new -x509 -newkey ec \
-pkeyopt ec_paramgen_curve:prime256v1 \
-nodes -days 365 \
-out public.pem -keyout private.pem \
-subj "/CN=SuitePortal"This creates two files:
public.pem— upload this to NetSuiteprivate.pem— keep this secret, used by SuitePortal to sign JWTs
Maximum certificate validity is 2 years (730 days). You can have up to 5 active certificates per integration.
Create an Integration Record
Navigate to Setup > Integration > Manage Integrations > New.
| Field | Value |
|---|---|
| Name | SuitePortal (or any name you prefer) |
| State | Enabled |
| Client Credentials (Machine to Machine) Grant | Checked |
Under Scope, enable the scopes your integration needs:
| Scope | When to Enable |
|---|---|
| REST Web Services | Always (required for SuitePortal) |
| RESTlets | If your integration calls RESTlets |
| SuiteAnalytics Connect | If using SuiteAnalytics |
Click Save. NetSuite will display your Client ID (also called Consumer Key). Copy it immediately.
NETSUITE_CLIENT_ID=your_client_id_hereCreate the M2M Certificate Mapping
Navigate to Setup > Integration > OAuth 2.0 Client Credentials (M2M) Setup.
Click Create New and configure:
| Field | Value |
|---|---|
| Entity | The NetSuite user/entity to authenticate as |
| Role | The role with the permissions from the prerequisites |
| Application | Select the integration you created |
| Certificate | Upload your public.pem file |
Click Save. NetSuite will display a Certificate ID. Copy it immediately — this is the kid (Key ID) used in the JWT header.
NETSUITE_CERTIFICATE_ID=your_certificate_id_hereWrite down the Certificate ID immediately. It is only displayed once after saving. If you lose it, you'll need to create a new certificate mapping.
Add Your Private Key
Add the contents of private.pem to your .env file. Since .env files don't support multiline values, replace newlines with literal \n:
# Convert the key to a single line
cat private.pem | tr '\n' '\\' | sed 's/\\/\\n/g'Then paste the result:
NETSUITE_PRIVATE_KEY=-----BEGIN EC PRIVATE KEY-----\nMHQCAQEE...base64...==\n-----END EC PRIVATE KEY-----Alternatively, you can load the key from a file in your code when using the programmatic API:
privateKey: fs.readFileSync('./private.pem', 'utf8')Complete .env for OAuth 2.0 M2M
NETSUITE_AUTH_TYPE=oauth2
NETSUITE_ACCOUNT_ID=1234567_SB1
NETSUITE_CLIENT_ID=abc123...
NETSUITE_CERTIFICATE_ID=xyz789...
NETSUITE_PRIVATE_KEY=-----BEGIN EC PRIVATE KEY-----\n...\n-----END EC PRIVATE KEY-----Optional variables:
| Variable | Default | Description |
|---|---|---|
NETSUITE_ALGORITHM | ES256 | Must match your key type (EC → ES256, RSA-PSS → PS256) |
NETSUITE_SCOPES | restlets,rest_webservices | Comma-separated scopes |
Verify Your Connection
Run a quick test to confirm everything is working:
npx suiteportal introspectIf you see your account ID and records being discovered, you're all set.
Troubleshooting
401 Unauthorized / INVALID_LOGIN
This is almost always one of these:
- Role missing REST Web Services permission — the most common issue. Edit the role under Setup > Users/Roles > Manage Roles and add "REST Web Services" with Full access under the Setup permissions tab.
- (TBA) Consumer credentials were reset after the access token was created — create a new access token.
- (OAuth 2.0) Certificate ID is wrong — verify the certificate ID matches the one shown during M2M setup.
- (OAuth 2.0) Private key doesn't match the uploaded certificate — regenerate the key pair and re-upload.
- Sandbox was refreshed — all integrations, tokens, and M2M mappings are wiped. Recreate from scratch.
- Wrong credentials in
.env— double-check all values have no extra whitespace.
OAuth 2.0: invalid_grant
This usually means:
- The JWT
expis more than 60 minutes fromiat - The certificate has expired (check the
-daysvalue used during generation) - The algorithm in your
.envdoesn't match your key type (e.g.,ES256with an RSA key)
Login Audit Trail
To debug authentication failures, check Setup > Users/Roles > User Management > View Login Audit Trail. Look for recent "Failure" entries matching your IP address.
For a detailed comparison of both auth methods and when to use each, see the Authentication guide.