If you run integrations against NetSuite, this is the migration you cannot afford to defer. Oracle’s 2026.2 release notes confirm a hard deadline: as of the 2027.1 release, SuiteScript 1.0 is fully removed and NLAuth (the legacy header-based authentication used by many RESTlets) is retired. When that release rolls into your account, any RESTlet still running on 1.0 or authenticating with NLAuth will simply stop responding, and integrations built on top of them will break without warning. This post walks through both halves of the fix in detail: converting the RESTlet code to SuiteScript 2.1, and switching the authentication over to token-based OAuth. Read it carefully and precisely, because a botched cutover on a production integration is expensive.
Why RESTlets on NLAuth are your highest-priority migration
Not all SuiteScript migrations carry the same risk. A User Event script that breaks throws a visible error inside the UI, and someone notices immediately. A RESTlet is different: it is the backbone of your machine-to-machine integrations, the endpoint your iPaaS platform, middleware, or partner systems call all day, often unattended. When it fails, the first sign is usually a silent data gap, a failed sync, or a partner escalation, sometimes days later. Combine that blast radius with a fixed removal date and you have the single most urgent item on your migration backlog.
The 2027.1 deadline is not a soft recommendation. Once your account is upgraded, there is no compatibility shim and no grandfather clause for existing deployments. Plan to complete and validate this work at least one full release cycle early so you have a working, tested integration well before the switch flips.
Part 1 β Convert the RESTlet code
The SS1.0 RESTlet structure
Here is a typical 1.0 RESTlet. It exposes a GET that loads a customer, and a POST that creates a sales order. Note the bare functions, the global nlapi* helpers, and the deployment that maps each function to an HTTP verb.
function getCustomer(request)
{
var id = request.id;
var record = nlapiLoadRecord('customer', id);
return {
id: id,
name: record.getFieldValue('companyname'),
email: record.getFieldValue('email')
};
}
function createOrder(request)
{
nlapiLogExecution('DEBUG', 'createOrder', 'entity=' + request.entity);
var so = nlapiCreateRecord('salesorder');
so.setFieldValue('entity', request.entity);
so.setFieldValue('memo', request.memo);
var soId = nlapiSubmitRecord(so, true);
return { success: true, orderId: soId };
}
Add the 2.1 structure
A 2.1 RESTlet needs the same three structural elements as any other 2.x script, plus an entry point per HTTP verb. Add the JSDoc header with @NApiVersion 2.1 and @NScriptType RESTlet, wrap everything in define() declaring the modules you need, and finish with a return object that maps get, post, put, and delete to your functions. Only include the verbs you actually implement.
/**
* @NApiVersion 2.1
* @NScriptType RESTlet
*/
define(['N/record', 'N/search', 'N/runtime'], (record, search, runtime) => {
const get = (requestParams) => { /* ... */ };
const post = (requestBody) => { /* ... */ };
const put = (requestBody) => { /* ... */ };
const doDelete = (requestParams) => { /* ... */ };
return { get, post, put, delete: doDelete };
});
One subtle trap: delete is a reserved word in JavaScript, so you cannot name a function delete directly. Define it under a safe name like doDelete and alias it in the return object as delete: doDelete.
Convert the nlapi calls to N/record, N/search, N/runtime
Now translate the body. Every global helper maps to a module method that takes a named-argument object. nlapiLoadRecord('customer', id) becomes record.load({ type: record.Type.CUSTOMER, id: id }). Reading a field is rec.getValue({ fieldId: 'companyname' }). Creating is record.create({ type: record.Type.SALES_ORDER }), and saving is rec.save() (options like enableSourcing and ignoreMandatoryFields go in the save call). For any lookups, prefer search.lookupFields or N/search over loading whole records. Logging becomes the built-in log global.
The completed SS2.1 RESTlet
/**
* @NApiVersion 2.1
* @NScriptType RESTlet
*/
define(['N/record', 'N/search', 'N/runtime'], (record, search, runtime) => {
const get = (requestParams) => {
const id = requestParams.id;
const fields = search.lookupFields({
type: search.Type.CUSTOMER,
id: id,
columns: ['companyname', 'email']
});
return {
id: id,
name: fields.companyname,
email: fields.email
};
};
const post = (requestBody) => {
log.debug({
title: 'createOrder',
details: 'entity=' + requestBody.entity
});
const so = record.create({ type: record.Type.SALES_ORDER });
so.setValue({ fieldId: 'entity', value: requestBody.entity });
so.setValue({ fieldId: 'memo', value: requestBody.memo });
const soId = so.save({ enableSourcing: true });
return { success: true, orderId: soId };
};
return { get, post };
});
Upload this file to the File Cabinet, create a new Script record so NetSuite reads the fresh 2.1 JSDoc, and note the new Script ID and Deployment ID from the URL, you will need them for the endpoint later.
Part 2 β Switch from NLAuth to token-based OAuth
What NLAuth is and why Oracle is removing it
NLAuth is the legacy scheme where you pass a NetSuite email, password, account ID, and role directly in an Authorization: NLAuth ... header on every request. It is simple, which is exactly the problem: it puts long-lived user credentials on the wire, it breaks the moment a password changes or two-factor authentication is enforced, and it offers no scoping or revocation. Oracle has been steering integrations toward token-based authentication for years, and 2027.1 finalizes that by removing NLAuth entirely. Going forward, RESTlets authenticate with a cryptographically signed token tied to an integration record, not a human’s login.
Create an Integration Record
In NetSuite go to Setup > Integration > Manage Integrations > New. Give the integration a clear name (for example “Celigo Order Sync”), leave it in State: Enabled, and select the authentication method appropriate for your external system, most RESTlet integrations use Token-Based Authentication. Uncheck the flows you do not need. When you save, NetSuite displays the Consumer Key and Consumer Secret exactly once. Copy both immediately into your secrets manager; they are never shown again, and losing them means recreating the integration.
Generate the Token ID and Token Secret
The consumer pair identifies the application; you still need a token that identifies the user and role. Confirm the Token-Based Authentication feature is enabled under Setup > Company > Enable Features (SuiteCloud tab), and that the “Token-Based Authentication” permission is on the role you will use. Then go to Setup > Users/Roles > Access Tokens > New, choose your Application (the integration you just made), the User, and the Role, and save. NetSuite now shows the Token ID and Token Secret, again, only once. Store all four values together: Consumer Key, Consumer Secret, Token ID, Token Secret.
Update your external system or iPaaS
Wherever your integration lives, swap out the old NLAuth email/password configuration for the four token values. In Celigo integrator.io, edit the NetSuite connection and choose Token-Based Auth, then paste the four values and your account ID. In Boomi, update the NetSuite connector or HTTP client operation to sign requests with the token credentials. In Postman, you will configure the Authorization tab directly, covered next. In every case, also update the endpoint URL to point at the new Script ID and Deployment ID from Part 1.
Test the authenticated call from Postman, step by step
Postman is the fastest way to prove your credentials and endpoint work before touching the real integration. Do this first.
- Create a new request and set the method to GET. Set the URL to your RESTlet endpoint:
https://<accountid>.restlets.api.netsuite.com/app/site/hosting/restlet.nl?script=<scriptId>&deploy=<deployId>&id=123. - Open the Authorization tab and select OAuth 1.0 as the type. This is NetSuite’s token-based signing scheme.
- Fill in Consumer Key, Consumer Secret, Access Token (your Token ID), and Token Secret from Part 2.
- Set the Signature Method to HMAC-SHA256, and in the advanced options set the Realm to your account ID (uppercase, e.g.
1234567_SB1). - Send the request. Add a
Content-Type: application/jsonheader for POST/PUT and put your JSON in the body. - A 200 with your expected payload confirms both the RESTlet and the credentials. A 401 means the signature or token is wrong; a 403 usually means a role permission is missing.
Common OAuth mistakes to avoid
Clock skew. Token-based requests are timestamp-signed, and NetSuite rejects requests whose timestamp drifts too far from server time. If you get intermittent 401s, sync your client’s clock via NTP, this is the number one cause of “it worked yesterday” failures.
Wrong OAuth version in your client. NetSuite’s token-based authentication signs with the OAuth 1.0a signing flow, not the OAuth 2.0 bearer-token flow. If your tool offers both, you must select the 1.0a option (in Postman it is labeled “OAuth 1.0”). Choosing a 2.0 bearer configuration will fail signing every time. If Oracle’s documentation for your specific target release describes a different flow, follow the version stated in the release notes for your account, but for classic RESTlet TBA the signing is 1.0a.
Missing or reused nonce. Each signed request must include a unique nonce (a one-time random string). Most libraries generate this automatically, but hand-rolled signing code sometimes omits it or reuses one, which NetSuite rejects. Confirm your signer produces a fresh nonce per call.
Rollback plan if the cutover fails
Never cut over without an escape hatch. Before the switch, deploy the new 2.1 RESTlet under a new Script and Deployment ID rather than overwriting the old one, so the 1.0 endpoint keeps working in parallel. Keep the old integration configuration saved and disabled rather than deleted. Cut over by pointing your external system at the new endpoint and new token credentials; if anything misbehaves, revert the endpoint URL and auth settings back to the old configuration and you are instantly running again. Only after the new path has run clean in production for a full business cycle should you retire the old RESTlet, and even then, do it before 2027.1 removes it for you. Run the whole rehearsal in a Sandbox account first so the production cutover is your second time through, not your first.
If this feels like a lot, The NetSuite Pro migrates RESTlets as a fixed-fee service.
Discover more from The NetSuite Pro
Subscribe to get the latest posts sent to your email.
Leave a Reply