Developer ToolsFree generatorPDF, Excel, Word exportNetSuite

NetSuite SuiteScript 2.1 RESTlet Skeleton Generator

A RESTlet is the quickest way to give an external system a custom endpoint into NetSuite. The structure is always the same: an annotated define block, a get and a post entry point, and careful error handling. This generator writes that structure for the record type you choose.

Fill in

Generated code
Download:

RESTlet script file

/**
 * @NApiVersion 2.1
 * @NScriptType Restlet
 * @NModuleScope SameAccount
 * @description Work order status lookup
 * @author Integration Team
 * @since 2026-10-20
 */
define(['N/record', 'N/log', 'N/error'], (record, log, error) => {

  const get = (requestParams) => {
    try {
      if (!requestParams || !requestParams.id) {
        throw error.create({ name: 'MISSING_ID', message: 'Query parameter id is required', notifyOff: true });
      }
      const rec = record.load({ type: record.Type.WORK_ORDER, id: requestParams.id, isDynamic: false });
      return {
        success: true,
        id: requestParams.id,
        tranid: rec.getValue({ fieldId: 'tranid' }),
        trandate: rec.getValue({ fieldId: 'trandate' })
      };
    } catch (e) {
      log.error({ title: 'GET work order failed', details: e });
      return { success: false, name: e.name, message: e.message };
    }
  };

  const post = (requestBody) => {
    try {
      if (!requestBody || !requestBody.values) {
        throw error.create({ name: 'MISSING_BODY', message: 'Body must contain a values object', notifyOff: true });
      }
      const rec = record.create({ type: record.Type.WORK_ORDER, isDynamic: true });
      Object.keys(requestBody.values).forEach((fieldId) => {
        rec.setValue({ fieldId: fieldId, value: requestBody.values[fieldId] });
      });
      const newId = rec.save({ enableSourcing: true, ignoreMandatoryFields: false });
      log.audit({ title: 'Created work order', details: newId });
      return { success: true, id: newId };
    } catch (e) {
      log.error({ title: 'POST work order failed', details: e });
      return { success: false, name: e.name, message: e.message };
    }
  };

  return { get, post };
});

Deployment checklist as comments

// 1. Upload the file to the File Cabinet, for example SuiteScripts/restlets/
// 2. Customization > Scripting > Scripts > New, choose the file, create the script record
// 3. Deploy it, set status to Testing, restrict Audience to the integration role
// 4. Call the External URL from the deployment record with OAuth 2.0 or token based authentication
// 5. Move status to Released only after a sandbox test with the same role

This is a skeleton, not production code. Validate the field ids against your record, add input validation, and check governance usage: a RESTlet gets 5,000 units per call. Many real integrations return a standard HTTP error instead of success false, so adapt the error branch to your client.

Planning a NetSuite integration?

Get a short expert review of your endpoint design, roles and governance exposure.

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

How to use the skeleton

Select the record.Type constant, name the two fields you want returned, and copy the script. Save it as a .js file in the File Cabinet, create the script record and deploy it. The generated GET handler loads one record by id. The POST handler creates a record from a values object, which is simple enough to test but not enough for complex transactions with sublists.

  • Replace the field ids with fields that exist on your record
  • Add sublist handling with selectNewLine and commitLine where needed
  • Keep the deployment on Testing until a sandbox call succeeds
  • Limit the audience to the integration role, not all roles

Why 2.1 and these modules

SuiteScript 2.1 supports modern JavaScript syntax such as arrow functions, const and let, which is why the skeleton uses them. N/record handles loading and saving, N/log writes to the execution log, and N/error creates named errors that are easier to filter. Use N/search or N/query when you need to read many records instead of loading each one, because record.load consumes far more governance than a search result.

Authentication and permissions

A RESTlet runs with the permissions of the role attached to the calling token or OAuth client. If the role cannot edit a work order, the POST fails regardless of what the script does. Create a dedicated integration role with only the permissions the endpoint needs, and never reuse an administrator token for a script that accepts external input.

Common mistakes

Frequent problems include returning the whole record object, which is not valid JSON, setting values before the form or subsidiary is known so sourcing misfires, and swallowing errors so the caller sees success. Always log the error details and return a message the caller can act on.

  • Using dynamic mode when standard mode would do
  • Not validating the request body before saving
  • Hard coding internal ids that differ between sandbox and production
  • Deploying to all roles with an open audience

Frequently Asked Questions

What is the governance limit for a RESTlet?

A RESTlet script gets 5,000 governance units per invocation. A record.load or record.save on a transaction costs a noticeable share, so batch work through searches and keep each request small. The execution log shows remaining units when you query it.

Should I use a RESTlet or the REST record API?

Use the standard REST record API when the default record shape is enough, because there is no code to maintain. Use a RESTlet when you need custom logic, a combined response from several records, or a simpler payload than the standard API provides.

Can I use SuiteScript 2.0 instead?

Yes, 2.0 still runs, but 2.1 is the current version and supports modern syntax. Existing 2.0 scripts do not need to be rewritten, though new scripts are usually written in 2.1 to avoid a later migration.

Is the generated code safe to deploy as is?

No. It is a starting point. Add validation, permission thinking, retries on the caller side and tests in a sandbox. Review field ids and mandatory fields for your own forms and customizations before releasing.

If you are building integrations between NetSuite and shop floor or engineering systems, we can review the design and the governance risks with you before you deploy.