Building REST Integrations with SuiteScript 2.0
Table of contents
One of the most common tasks in a NetSuite implementation is integrating with external systems. Whether it’s syncing orders to a warehouse, pushing invoices to a third-party accounting tool, or pulling data from a CRM, you’ll eventually need to call an external REST API from SuiteScript.
Here’s a pattern I’ve settled on after doing this repeatedly.
The Basic Shape
SuiteScript 2.0 provides the https module for making outbound HTTP requests. The core call looks like this:
/**
* @NApiVersion 2.1
* @NScriptType ScheduledScript
*/
define(['N/https', 'N/log'], function(https, log) {
function execute(context) {
var response = https.get({
url: 'https://api.example.com/v1/orders',
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'application/json'
}
});
if (response.code === 200) {
var data = JSON.parse(response.body);
processData(data);
} else {
log.error('API Error', response.code + ' - ' + response.body);
}
}
return { execute: execute };
});
Handling Authentication
Most modern APIs use OAuth 2.0 or API keys. For API keys, store them in a Script Parameter (not hardcoded). Go to Customization > Scripting > Scripts > [Your Script] > Parameters and add a string parameter for the key.
Then access it in the script:
define(['N/https', 'N/runtime', 'N/log'], function(https, runtime, log) {
function execute(context) {
var script = runtime.getCurrentScript();
var apiKey = script.getParameter({ name: 'custscript_api_key' });
// use apiKey in your headers
}
});
This keeps credentials out of source code and lets you change them without a deployment.
Sending Data (POST)
For sending data outbound:
var payload = JSON.stringify({
order_id: '12345',
status: 'shipped',
tracking: 'JD014600006321'
});
var response = https.post({
url: 'https://api.example.com/v1/shipments',
headers: {
'Authorization': 'Bearer ' + apiKey,
'Content-Type': 'application/json'
},
body: payload
});
Governance Limits
NetSuite caps outbound HTTP calls per script execution. For Scheduled Scripts, you have 5,000 units per execution — each HTTP call costs 10 units. That means you can make at most 500 calls per run.
If you need to process more records, batch them or use Map/Reduce scripts, which reset governance per stage.
Error Handling and Retries
External APIs fail. Network timeouts happen. Build in logging and consider a retry queue (store failed records in a custom record and re-process them in the next scheduled run).
try {
var response = https.post({ /* ... */ });
if (response.code >= 400) {
logFailure(recordId, response.code, response.body);
}
} catch (e) {
log.error('Request failed', e.message);
logFailure(recordId, 'EXCEPTION', e.message);
}
This is just the foundation. OAuth flows, pagination, and webhook receivers each deserve their own post. Those are coming.