One of the biggest strengths in NetSuite as an ERP is the possibility of customization. And one of the most important avenues for customization is the possibility to integrate with external systems. NetSuite exposes a sophisticated REST interface that allows to create, update, and delete almost any record type and leverages the power of SuiteQL for more complex queries.
But there could be times when more sophisticated business logic needs to be triggered from a system outside NetSuite. That’s where RESTlets come in.
There are many SuiteScript types, each one offering unique possibilities and characteristics. You must be familiar with Suitelets allowing you to create custom pages within the NetSuite instance, or User Event Scripts modifying the behavior of forms upon submit.
A RESTlet is a SuiteScript that you make available for other applications to call. It can be called from either an external application or from another script within NetSuite. A RESTlet executes only when it is called and in some cases, returns a value to the calling application. The main advantage is that, when the RESTlet is running, it has complete access to all of the NetSuite instance and can run custom code and logic. Regular REST calls are useful for basic CRUD operations, a RESTlet opens the door to custom validations, data manipulation or any business logic you could think of.
Because RESTlets can be called from within other SuiteScripts, they have other interesting functionalities as well. You could write logic inside a Suitelet that calls a RESTlet and deploys the returning HTML, or hides certain components depending on the call response. It’s not necessary to connect to NetSuite from an external system to leverage the possibilities RESTlets offer.
RESTlets are created and deployed exactly the same as any other SuiteScript. You can create the logic in your SuiteApp project and deploy it to your Test Drive instance using SuiteCloud Developer Tools. The script and deployment records are standard. When you save a script deployment record for a RESTlet, the system automatically generates a URL that can be used to call the RESTlet. Because a RESTlet executes only when it is called, this information is critical for using the RESTlet.
RESTlets receive metadata information on the call itself, such as the HTTP method used to invoke it. Supported methods are DELETE, GET, POST, or PUT. Depending on which method you use, you may be required to embed input for the RESTlet within the URL, or you may be required to submit arguments in a request body. Additionally, for the call to be successful, your RESTlet script must contain an entry point that corresponds with the method you use to make the call.
Entry points are functions stored in variables that need to be called like the HTTP method they respond to.
For example:
// Restlet entry point
const post = function (requestBody) {
// This is your business logic
return returnValue;
}
The function gets called passing parameters depending on the method type. For POST and PUT calls, the requestBody is passed, for GET and DELETE calls, the RequestParams are passed:
const get = function (requestParams)
Apart from the data in the call, a Content-Type Header can be passed to specify how the request body will be formatted. When a Content-Header is required but is missing, the request fails with an HTTP error code reading 415: Unsupported Media Type.
The following are suggested Content-Type headers:
application/json – used for RESTlets that require request bodies that map values to fields.
application/xml – used for RESTlets that are invoked through the GET method.
text/plain – used for RESTlets that require limited or simple input.
The module N/scriptTypes/restlet in SuiteScript 2.x has the function createResponse that can be used to create the response object for the RESTlet call.
createResponse({
content: // This is your response content
contentType: // Content-Type corresponding to the call header
});
If your RESTlet returns data, take note of the following:
If the data has the same format as the request body, the response data follows that format.
If you want your RESTlet data to have a different format than the request body, you must specify it using restlet.createResponse(options).
If your RESTlet does not have a request body, the default return format is plain text.
Once the RESTlet has been called and the code is running, you have access to all of SuiteScript’s modules and features, including the context of the NetSuite instance. The structure of the RESTlet needs to be the same as any other SuiteScript type, starting with the SuiteScript definition commented:
/**
* @NApiVersion 2.1
* @NScriptType Restlet
*/
followed by the define syntax and a list of the modules used. Remember to add N/scriptTypes/restlet for the response functions.
define(['N/scriptTypes/restlet', 'N/query'], function (restlet, query) {
}
Finally, inside the define function, the specific methods for the HTTP call types have to be returned:
return { post };
So, the complete syntax of a RESTlet would look like this:
/**
* @NApiVersion 2.1
* @NScriptType Restlet
*/
define(['N/scriptTypes/restlet', 'N/query'], function (restlet, query) {
// Restlet entry point
const post = function (requestBody) {
// Business logic
const response = createResponse({
content: // This is your response content
contentType: // Content-Type corresponding to the call header
});
return response;
}
return { post };
});
Three important things to keep in mind:
- When working with RESTlets, you should be aware of governance limitations and security concerns specific to the RESTlet script type.The SuiteScript governance model tracks usage units on two levels: API level and script level. At the API level, RESTlets have the same usage limits as other types of SuiteScripts. At the script level, RESTlets allow 5,000 usage units per script, a limit five times greater than SuiteLets and most other types of SuiteScripts. There is a guarantee of 10MB per string used as RESTlet input or output. In ideal circumstances, you may receive a larger string in an output, however, the 10MB size is the guarantee.
- RESTlets require authentication and calls are processed synchronously. The way to provide login credentials for a RESTlet varies according to whether the RESTlet is called from an external client or from a client hosted by NetSuite, such as a client SuiteScript. Starting at 2021.1 either the three-step TBA authorization flow or the OAuth 2.0 should be used for RESTlet integrations.
- The OPTIONS, HEAD, TRACE, PATCH, and CONNECT HTTP methods are not available for RESTlets. This may not be an important limitation for most applications, but keep in mind in case the external integration requires a specific use case.
