NetSuite M2M OAuth
Guide a developer from zero to a verified NetSuite OAuth 2.0 Client Credentials connection while explaining what each credential and trust relationship does.
This is a workflow skill, not a general OAuth reference. Move through setup one checkpoint at a time and verify each checkpoint before advancing.
Scope
Use this skill for NetSuite OAuth 2.0 Client Credentials (Machine to Machine) authentication for:
- REST Web Services —
rest_webservices - RESTlets —
restlets - SuiteAnalytics Connect —
suite_analytics
Do not use this skill for:
- OAuth 2.0 Authorization Code Grant
- Token-Based Authentication (TBA)
- SOAP web services
- browser/user-login flows
- NetSuite AI Connector Service authentication
If the user is configuring the NetSuite AI Connector Service, stop this workflow and explain that NetSuite's current integration-record rules require the Client Credentials (Machine to Machine) Grant to be cleared for that scope. Use the appropriate AI Connector/authentication guidance instead.
Relationship to Oracle skills
When Oracle's SuiteCloud Agent Skills are installed, treat them as authoritative platform guidance.
In particular, netsuite-sdf-safe-guide may provide current OAuth and security guidance. Do not duplicate or override it.
This skill owns the interactive M2M workflow:
- explain the trust model
- identify the required NetSuite configuration
- create the certificate-backed mapping
- build a JWT client assertion
- exchange the assertion for an access token
- make a safe authenticated request
- troubleshoot the failing stage when verification does not succeed
Operating style
Walk the user through the process rather than dumping every step at once.
For each checkpoint:
- Explain what is being configured and why it exists.
- Act by giving the exact NetSuite UI action or local development action.
- Verify the smallest non-secret result that proves the checkpoint is complete.
- Continue only when the current checkpoint is understood or verified.
Use information already available in the workspace before asking the user for it.
When generating code, inspect the existing project language, package manager, environment-variable conventions, and HTTP/JWT libraries first. Prefer existing dependencies over introducing a new stack.
Security rules
Never ask the user to paste any of these into chat:
- private key contents
- access tokens
- client secrets
- production secrets from a secret manager
Do not print, log, commit, or echo JWT assertions or access tokens unless the user explicitly needs a redacted diagnostic representation.
Prefer:
- a local private-key file outside the repository
- a secrets manager or deployment secret store
- environment variables for identifiers and configuration
.gitignoreprotection for any local credential material
If a private key is found inside the repository, call that out immediately and recommend removing it from version control and rotating the credential if it may have been exposed.
Do not use Administrator as the integration role merely to make authentication succeed. Use the least-privileged role that supports the integration's required operations.
Mental model
Before setup, make sure the user understands this chain:
Integration Record
= which application is connecting
|
| client ID (`iss`)
v
Application identity
Entity + Role
= who the application acts as
and what that identity may do
Public X.509 certificate
= uploaded to NetSuite
NetSuite uses it to verify signatures
Private key
= stays with the external application
the application uses it to sign assertions
Certificate ID
= generated by the NetSuite M2M mapping
used as JWT header `kid`
Signed JWT client assertion
= short-lived proof that the client controls
the private key for the configured mapping
|
| POST to token endpoint
v
Access token
= short-lived Bearer credential used for API calls
Reinforce this distinction when confusion appears:
JWT client assertion != NetSuite access token.
The client assertion proves the application's identity to the token endpoint. The access token is what NetSuite returns after successful authentication and what the client sends as Authorization: Bearer <token> to protected resources.
Client Credentials does not use an interactive user login. It is a machine-to-machine flow.
Checkpoint 1 — Identify the target
Determine the resource the application needs to access.
Map it to the OAuth scope:
| Target | Scope |
|---|---|
| REST Web Services | rest_webservices |
| RESTlet | restlets |
| SuiteAnalytics Connect | suite_analytics |
If more than one supported target is required, use only the scopes that are actually needed.
Also establish:
- production, sandbox, or Release Preview
- the entity that the application should act as
- the role it should use
- whether this is a new integration or troubleshooting an existing one
Do not request credentials yet.
Checkpoint 2 — Confirm account prerequisites
Guide the user through the applicable prerequisites.
OAuth 2.0 feature
NetSuite UI:
Setup > Company > Enable Features > SuiteCloud > Manage Authentication > OAuth 2.0
The OAuth 2.0 feature must be enabled.
For RESTlets, NetSuite also requires Client SuiteScript and Server SuiteScript to be enabled.
For REST Web Services, confirm the REST Web Services feature and the role permissions needed for the intended REST operations.
Integration role
The role used by the M2M mapping must have:
Log in Using OAuth 2.0 Access Tokens
The role must also have the record, transaction, list, setup, or analytics permissions required by the integration itself.
Explain the difference between these two permissions when relevant:
OAuth 2.0 Authorized Applications Managementis an administrative/setup permission.Log in Using OAuth 2.0 Access Tokensallows the mapped identity to access RESTlets, REST Web Services, or SuiteAnalytics Connect with OAuth 2.0.
Account-specific URLs
Do not invent or manually normalize the account-specific domain, especially for sandbox or Release Preview accounts.
Have the user confirm it in:
Setup > Company > Company Information > Company URLs
Use the SuiteTalk/REST Web Services account-specific domain shown by NetSuite for the token endpoint.
Treat the domain as configuration rather than hard-coding assumptions about account-ID formatting.
Checkpoint complete when the required features, role, and account-specific domain are known.
Checkpoint 3 — Create or verify the Integration Record
Open or create the NetSuite Integration Record for the external application.
Under OAuth 2.0:
- enable Client Credentials (Machine to Machine) Grant
- enable only the required supported scopes
- do not enable unrelated scopes merely for troubleshooting
- save the integration
Capture the Client ID securely.
Explain:
Client ID = application identity
JWT `iss` = Client ID
The Client Credentials token exchange uses the certificate-signed client assertion. Do not design this workflow around sending the client secret to the token endpoint.
Do not ask the user to paste the Client ID or Client Secret into chat. Prefer a local environment variable or secret configuration.
Checkpoint complete when the Integration Record supports Client Credentials and the required scope.
Checkpoint 4 — Generate the key pair and certificate
Explain the split first:
public certificate -> NetSuite
private key -> external application only
NetSuite's current M2M certificate requirements support X.509 public certificates with RSA or EC keys and a maximum certificate validity of two years. Prefer a shorter operational lifetime with a planned rotation process.
If the project has no existing certificate standard, an ES256-compatible certificate can be generated with OpenSSL using Oracle's documented pattern:
openssl req \
-new \
-x509 \
-newkey ec \
-pkeyopt ec_paramgen_curve:prime256v1 \
-pkeyopt ec_param_enc:named_curve \
-nodes \
-days 365 \
-out public.pem \
-keyout private.pem
Before running a command that writes credential material into the current workspace, choose a safe destination and confirm it will not be committed.
After generation, verify without exposing secret material:
openssl x509 -in public.pem -noout -subject -issuer -dates
If RSA-PSS is required by the user's platform, use a NetSuite-supported RSA size and a matching PS* JWT algorithm rather than changing algorithms independently.
Checkpoint complete when:
- a public X.509 certificate exists
- the corresponding private key is stored safely
- the selected JWT algorithm matches the key type
Checkpoint 5 — Create the NetSuite M2M mapping
NetSuite UI:
Setup > Integration > Manage Authentication > OAuth 2.0 Client Credentials (M2M) Setup
Create a new mapping and select:
- Entity
- Role
- Application — the Integration Record
- Certificate — upload the public certificate only
Save the mapping.
Explain the trust relationship:
Application + Entity + Role + Certificate = M2M identity
Record the resulting Certificate ID securely as configuration.
Explain:
Certificate ID = JWT header `kid`
Never upload the private key to NetSuite.
If the integration record does not appear in the Application list, first verify that Client Credentials (Machine to Machine) Grant is enabled on that Integration Record.
Checkpoint complete when the mapping exists and the Certificate ID is known.
Checkpoint 6 — Build the local configuration
Prefer environment variables or the project's existing secret/configuration mechanism.
Use names appropriate to the project. A clear generic model is:
NETSUITE_TOKEN_URL
NETSUITE_CLIENT_ID
NETSUITE_CERTIFICATE_ID
NETSUITE_PRIVATE_KEY_PATH
NETSUITE_SCOPE
NETSUITE_RESOURCE_BASE_URL
Construct NETSUITE_TOKEN_URL from the confirmed account-specific SuiteTalk domain, using the current NetSuite token path:
/services/rest/auth/oauth2/v1/token
Do not commit real values to .env.example. Examples must use placeholders.
For RESTlets, remember that the protected RESTlet resource URL may use the account-specific RESTlets domain even though the M2M token endpoint is documented on the account-specific SuiteTalk domain.
Checkpoint complete when the application can load configuration without printing secrets.
Checkpoint 7 — Create the JWT client assertion
Use a maintained JWT library supported by the project's language/runtime. Do not hand-roll Base64url encoding or cryptographic signing.
JWT header
Use:
{
"typ": "JWT",
"alg": "ES256",
"kid": "<CERTIFICATE_ID>"
}
alg is an example. It must match the certificate/key type. NetSuite currently supports PS256, PS384, PS512, ES256, ES384, and ES512 for the client assertion.
JWT payload
Use the required NetSuite claims:
{
"iss": "<CLIENT_ID>",
"scope": ["rest_webservices"],
"aud": "<EXACT_TOKEN_URL>",
"iat": 0,
"exp": 0
}
Populate:
isswith the Integration Record Client IDscopewith the required NetSuite M2M scope or scopesaudwith the exact token endpoint being callediatwith current Unix time in secondsexpwith a short future Unix time
NetSuite requires exp to be less than 60 minutes after iat. Prefer a short assertion lifetime, such as about five minutes, unless the project's requirements justify something else.
A unique jti may be added if the implementation/library uses one, but do not invent additional required claims that NetSuite does not require.
Before sending the assertion, decode its header and payload locally without printing the signature or secret key and verify:
kidequals the Certificate ID from the mappingissequals the Integration Record Client IDalgmatches the private keyscopematches the Integration Record scopeaudexactly matches the token endpointiatandexpare Unix seconds, not milliseconds- local system time is accurate
Checkpoint complete when the assertion can be generated and its non-secret claims are correct.
Checkpoint 8 — Exchange the assertion for an access token
POST to the confirmed token endpoint with:
Content-Type: application/x-www-form-urlencoded
Form fields:
grant_type=client_credentials
client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
client_assertion=<SIGNED_JWT>
Use the project's existing HTTP client when possible.
Do not log the request body because it contains the signed client assertion.
A successful response contains:
{
"access_token": "<REDACTED>",
"expires_in": 3600,
"token_type": "Bearer"
}
Explain that NetSuite M2M access tokens are currently valid for 60 minutes. There is no interactive refresh-token workflow here; when the access token expires, create a fresh client assertion and run the Client Credentials token exchange again.
Store/cache the access token only as long as needed and never commit it.
Checkpoint complete when NetSuite returns an access token.
Checkpoint 9 — Verify with a safe authenticated operation
Do not declare success merely because the token endpoint returned 200.
Make one non-destructive authenticated request appropriate to the selected target.
For HTTP APIs, send:
Authorization: Bearer <ACCESS_TOKEN>
Prefer a read-only operation such as metadata lookup, a permitted record GET, or a RESTlet GET that is known not to mutate data.
Do not create, update, delete, post, transform, or trigger business transactions merely to test authentication.
For SuiteAnalytics Connect, verify by opening the intended connection and running the smallest harmless query supported by the user's environment.
The workflow is complete only when:
- the token exchange succeeds
- the access token is accepted by the intended NetSuite service
- the read-only verification succeeds with the mapped role
Completion summary
At the end, summarize the resulting configuration without exposing secrets:
Target: REST Web Services | RESTlet | SuiteAnalytics Connect
Environment: production | sandbox | Release Preview
Scope: <scope>
Integration Record: configured
Entity/Role: configured
Certificate mapping: configured
Private key: stored locally/secret manager, not shared
JWT assertion: generated successfully
Token exchange: successful
Read-only API test: successful
Status: M2M authentication verified
If anything remains unverified, say exactly which checkpoint is incomplete. Do not report the integration as working until the final authenticated read-only verification succeeds.
Additional resources
- Troubleshooting and common mistakes: references/troubleshooting.md
- Oracle docs and version notes: references/oracle-docs.md