Developer ToolsFree referencePDF, Excel, Word exportNetSuiteAll NetSuite tools

SuiteScript 1.0 to 2.1 API Mapping: nlapi Functions to 2.x Modules

This table maps the nlapi functions and nlobj objects you find in legacy SuiteScript 1.0 code to the SuiteScript 2.x module and method that replaces them. Use it while rewriting a 1.0 script as 2.1, or while reading old code to understand what it does.

Download:
SuiteScript 1.0SuiteScript 2.xModuleGovernance (2.x units)Gotcha
nlapiLoadRecord
record.load({type, id, isDynamic})
N/record
10 transaction, 2 custom record, 5 other
Defaults to standard mode. Pass isDynamic: true if the 1.0 code relied on sourcing as fields were set.
nlapiCreateRecord
record.create({type, isDynamic, defaultValues})
N/record
10 transaction, 2 custom record, 5 other
Initialize values go in defaultValues.
nlapiSubmitRecord
Record.save({enableSourcing, ignoreMandatoryFields})
N/record
20 transaction, 4 custom record, 10 other
Options object replaces positional booleans. Returns the internal ID.
nlapiDeleteRecord
record.delete({type, id})
N/record
20 transaction, 4 custom record, 10 other
Same unit cost as save.
nlapiTransformRecord
record.transform({fromType, fromId, toType, isDynamic})
N/record
10 transaction, 2 custom record, 5 other
Save the returned record to commit it.
nlapiCopyRecord
record.copy({type, id, isDynamic})
N/record
10 transaction, 2 custom record, 5 other
Returns an unsaved record.
nlapiSubmitField
record.submitFields({type, id, values, options})
N/record
10 transaction, 2 custom record, 5 other
Values is an object. Only works on inline-editable body fields; others trigger a full load and save.
nlapiLookupField
search.lookupFields({type, id, columns})
N/search
1
Select fields return an array of {value, text}, not a string.
nlapiAttachRecord
record.attach({record, to, attributes})
N/record
10
record and to are {type, id} objects.
nlapiDetachRecord
record.detach({record, from, attributes})
N/record
10
Mirror of attach.
nlapiVoidTransaction
transaction.void({type, id})
N/transaction
10
Behaviour depends on the Void Transactions Using Reversing Journals preference.
nlapiSearchRecord
search.create({type, filters, columns}).run().getRange({start, end})
N/search
getRange 10 per call; create 0
1.0 returned up to 1000 rows directly. In 2.x use runPaged or getRange in 1000-row pages.
nlapiCreateSearch
search.create
N/search
0
Filters can be filter objects or a filter expression array.
nlapiLoadSearch
search.load({id})
N/search
5
id accepts the customsearch script ID or internal ID.
nlobjSearchFilter
search.createFilter({name, join, operator, values})
N/search
0
Use search.Operator enums, for example search.Operator.ANYOF.
nlobjSearchColumn
search.createColumn({name, join, summary, sort})
N/search
0
Read results with result.getValue(column) or getValue({name, join}).
nlobjSearchResultSet.forEachResult
ResultSet.each(callback)
N/search
10
Return true to continue; stops at 4000 results.
nlapiGetContext
runtime.getCurrentScript(), runtime.getCurrentUser(), runtime.getCurrentSession()
N/runtime
0
Script parameters: runtime.getCurrentScript().getParameter({name}).
nlobjContext.getRemainingUsage
runtime.getCurrentScript().getRemainingUsage()
N/runtime
0
Same idea, different object.
nlapiGetUser
runtime.getCurrentUser().id
N/runtime
0
Property, not a method.
nlapiGetRole
runtime.getCurrentUser().role
N/runtime
0
Returns the internal ID; roleId gives the script ID.
nlapiGetSubsidiary
runtime.getCurrentUser().subsidiary
N/runtime
0
Department and location follow the same pattern.
nlapiScheduleScript
task.create({taskType: task.TaskType.SCHEDULED_SCRIPT, scriptId, deploymentId, params}).submit()
N/task
20 for submit
Map/Reduce uses task.TaskType.MAP_REDUCE.
nlapiYieldScript, nlapiSetRecoveryPoint
No equivalent
N/A
N/A
Redesign long scheduled jobs as Map/Reduce, which yields and resumes automatically.
nlapiSendEmail
email.send({author, recipients, subject, body, attachments, relatedRecords})
N/email
20
relatedRecords replaces the records parameter.
nlapiRequestURL
https.request / https.get / https.post (or http.*)
N/https
10
Response body is response.body, status is response.code.
nlapiResolveURL
url.resolveRecord, url.resolveScript, url.resolveTaskLink, url.resolveDomain
N/url
0
Split by URL type instead of one function with a type string.
nlapiSetRedirectURL
redirect.toRecord, redirect.toSuitelet, redirect.toTaskLink, redirect.redirect
N/redirect
0
Suitelet response redirects can also use response.sendRedirect.
nlapiLogExecution
log.debug, log.audit, log.error, log.emergency
N/log
0
Global log object; the deployment Log Level filters what is stored.
nlapiCreateError
error.create({name, message, notifyOff})
N/error
0
Throw the returned object.
nlapiLoadFile
file.load({id})
N/file
10
id accepts internal ID or File Cabinet path.
nlapiCreateFile
file.create({name, fileType, contents, folder})
N/file
0
Set folder before File.save().
nlapiSubmitFile
File.save()
N/file
20
Returns the file internal ID.
nlapiCreateForm
serverWidget.createForm({title, hideNavBar})
N/ui/serverWidget
0
Added field IDs must start with custpage.
nlapiCreateList
serverWidget.createList({title})
N/ui/serverWidget
0
Suitelet only.
nlapiCreateAssistant
serverWidget.createAssistant({title})
N/ui/serverWidget
0
Suitelet only.
nlapiDateToString, nlapiFormatCurrency
format.format({value, type: format.Type.DATE | CURRENCY})
N/format
0
Uses the user's date and number preferences.
nlapiStringToDate
format.parse({value, type: format.Type.DATE})
N/format
0
Returns a Date object. setValue on date fields expects Date, not a string.
nlapiXMLToPDF
render.xmlToPdf({xmlString})
N/render
10
Returns a file.File object.
nlapiCreateTemplateRenderer
render.create()
N/render
0
Then setTemplateById or templateContent, addRecord, renderAsPdf.
nlapiGetFieldValue / nlapiSetFieldValue
Record.getValue({fieldId}) / Record.setValue({fieldId, value})
N/record, N/currentRecord
0
Values are typed: checkboxes are booleans, dates are Date objects.
nlapiGetFieldText / nlapiSetFieldText
Record.getText / Record.setText
N/record
0
getText on a standard mode record works only after setText or load.
nlapiGetLineItemValue / nlapiSetLineItemValue
Record.getSublistValue / setSublistValue({sublistId, fieldId, line, value})
N/record
0
Lines are 0-based in 2.x, 1-based in 1.0. Sublist IDs are lower case (item, not Item).
nlapiGetLineItemCount
Record.getLineCount({sublistId})
N/record
0
Use it as the loop bound: lines run from 0 to count - 1.
nlapiSelectNewLineItem / nlapiCommitLineItem
Record.selectNewLine / Record.commitLine({sublistId})
N/record (dynamic), N/currentRecord
0
Dynamic mode only; use setCurrentSublistValue between select and commit.
nlapiFindLineItemValue
Record.findSublistLineWithValue({sublistId, fieldId, value})
N/record
0
Returns a 0-based index or -1.
nlapiGetNewRecord / nlapiGetOldRecord
context.newRecord / context.oldRecord
Entry point context
0
Read-only in afterSubmit; reload to change and save.
nlapiInitiateWorkflow / nlapiTriggerWorkflow
workflow.initiate / workflow.trigger
N/workflow
20
Workflow ID accepts the customworkflow script ID.
nlapiExchangeRate
currency.exchangeRate({source, target, date})
N/currency
10
Source and target accept ISO code or internal ID.

Mappings follow the SuiteScript 1.0 to SuiteScript 2.x API Map in NetSuite help. Governance values are the SuiteScript 2.x unit costs; recheck them in help for your release. 2.1 scripts declare @NApiVersion 2.1 in the JSDoc header.

Get a SuiteScript 1.0 migration estimate

Send us your script list (names, types, line counts) and we will return a reviewed migration order and the scripts that need redesign rather than a rewrite.

Optional. The tool and every export work without this. No spam.

Was this tool useful?

How to use it

Search for the 1.0 function name you are replacing, for example nlapiSubmitField. The 2.x column gives the call and its options object, Module tells you which define dependency to add, and the governance column shows the 2.x unit cost so you can recheck the script's budget. The Gotcha column is where most migration bugs hide: typed values, 0-based line indexes and different return shapes. Work through a script top to bottom, list every distinct nlapi call, and look each one up before you touch the logic. Rows marked No equivalent mean a redesign, not a rename.

SuiteScript 2.1 basics you need for the rewrite

A 2.1 script starts with a JSDoc block containing @NApiVersion 2.1 and @NScriptType (for example UserEventScript or MapReduceScript), then a define call that loads modules such as N/record and N/search and returns the entry points. 2.1 runs on a newer JavaScript engine and accepts ES2019-era syntax such as let, const, arrow functions, destructuring and spread. 1.0 and 2.x APIs cannot be mixed in one file. A 1.0 script record cannot simply point to a 2.1 file; create a new script record, deploy it, test, then set the old deployment to not deployed. Recreate the script parameters on the new script record and value them on the new deployment.

Worked example

A 1.0 user event calls nlapiLookupField('customer', custId, 'creditlimit'), then nlapiSubmitField('salesorder', soId, 'custbody_hold', 'T'). In 2.1 this becomes search.lookupFields({type: search.Type.CUSTOMER, id: custId, columns: ['creditlimit']}).creditlimit, then record.submitFields({type: record.Type.SALES_ORDER, id: soId, values: {custbody_hold: true}}). Note the checkbox is now a boolean true instead of 'T'. If the lookup were a select field, the result would be an array of objects with value and text, so code that compared a string would silently fail. Governance stays the same in this example: 1 unit for the lookup and 10 for submitFields on a transaction.

Common mistakes

The three bugs that show up in almost every migration are 1-based line loops copied into 2.x, so the last line is skipped or line 0 is missed; string dates passed to setValue on a date field, which throws INVALID_FLD_VALUE; and searches that returned 1000 rows in 1.0 now returning nothing because run() was called but getRange or each was not. Also watch nlapiYieldScript loops: there is no yield in 2.x scheduled scripts, so long jobs belong in Map/Reduce. Finally, 2.x context objects differ per entry point, so check context.type against context.UserEventType enums instead of the string 'create'.

  • Loop lines from 0 to getLineCount() - 1
  • Pass Date objects to date fields, booleans to checkboxes
  • Use runPaged for result sets over a few thousand rows

Frequently Asked Questions

Should I migrate SuiteScript 1.0 to 2.0 or 2.1?

Target 2.1 for new work. It uses the same modules as 2.0 but supports modern JavaScript syntax, and Oracle documents new capabilities against 2.x. 1.0 still runs, but Oracle no longer adds new features to it and new APIs are not exposed to it. Migrate the scripts you change most often first.

What replaces nlapiSearchRecord in SuiteScript 2.1?

search.create with type, filters and columns, then run() and either getRange({start: 0, end: 1000}) or each(callback). For more than a few thousand rows use search.runPaged and fetch each page. You can also query with N/query or query.runSuiteQL if SuiteQL is a better fit for the joins you need.

Is there a SuiteScript 2.x equivalent of nlapiYieldScript?

No. Scheduled scripts in 2.x cannot yield and resume. Long-running work should be rewritten as a Map/Reduce script, which splits input into map and reduce stages, manages governance per stage and yields automatically based on the deployment's yield settings.

Can I call SuiteScript 1.0 functions from a 2.1 script?

No. A script file is either 1.0 or 2.x. The nlapi functions are not available in 2.x scripts and 2.x modules are not available in 1.0. During migration you can run both versions side by side as separate script records and deployments, then turn off the old one.

If you want a private AI assistant that reads your legacy SuiteScript and drafts the 2.1 version for your developers to review, running on your own servers, we can set that up.

ArchRay builder
Design the on-prem AI stack for NetSuite: model, GPUs, RAG pipeline, guardrails
See memory, speed and cost as you swap parts, then export the diagram. Free, in your browser.
Open the builder

Keep exploring