NetSuite Document:
https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/index.html
Authentication
We will use the OAuth 2.0 (https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_157771281570.html#Getting-Started-with-OAuth-2.0)
How to setup OAuth 2.0
- User setup Feature (Setup > Company > Enable Features) Role (Setup > Users/Roles > Manage Roles) Create Integration Records for Applications to Use OAuth 2.0.
- Authorized Process (https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_158074210415.html#OAuth-2.0-Authorization-Code-Grant-Flow)
- GET Request to the Authorization Endpoint Request: https://<accountID>.app.netsuite.com/app/login/oauth2/authorize.nl
response_type: always code.
client_id: get when the integration record created
redirect_uri: value input when create the integration record
scope: value check when create the integration record (restlets, rest_webservices, suite_analytics, or all of them)
state: 22 and 1024 characters (ex: ykv2XLx1BpT5Q0F3MRPHb94j)
code_challenge (optional):
code_challenge_method (optional):
prompt (optional):
Consent Screen Display for user authorizes.
POST Request to the Token Endpoint => response: access_token and refresh_token.
- GET Request to the Authorization Endpoint Request: https://<accountID>.app.netsuite.com/app/login/oauth2/authorize.nl
How to refresh token
POST Request: https://<accountID>.suitetalk.api.netsuite.com/services/rest/auth/oauth2/v1/token
grant_type: always refresh_token
refresh_token: The value of the refresh_token parameter is in JSON Web Token (JWT) format.
Revoke token
POST Request: https://<accountID>.suitetalk.api.netsuite.com/services/rest/auth/oauth2/v1/revoke.
Other way to Authenticate
- OAuth 2.0 Client Credentials Flow: https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_162730264820.html#OAuth-2.0-Client-Credentials-Flow
- Token-based Authentication:
Overview: https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_4247337262.html#Getting-Started-with-Token-based-Authentication
User setup: https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_4247337262.html#Getting-Started-with-Token-based-Authentication
Authorized Process: https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_156337186044.html#The-Three-Step-TBA-Authorization-Flow
POST Header: https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_1534941295.html#subsect_1520631056
How to setup Token-based Authentication (use in Simplify).
- Feature (Setup > Company > Enable Features).

- Create integration (Setup > Integration > Manage Integrations > New).
Warning: The system displays the client ID and client secret only the first time you save the integration record. - If you are an administrator: Generate access token as administrator.


Warning: The system displays the Token Id and Token Secret only the first time you save the record. - If you aren't an administrator: Set up roles: Role (Setup > Users/Roles > Manage Roles > Permissions tab):
Transactions: Find Transaction - full, Sales Order - full Reports: SuiteAnalytics Workbook Setup: Log in using Access Tokens, REST Web Services.
Set up user : User (Setup > Users/Roles > Manage Users ): Add this role for the user.
Set up user : User (Setup > Users/Roles > Manage Users ): Add this role for the user.
Generate an access token for the user (Setup > Users/Roles > Access Tokens > New).
Push data to NetSuite
Prerequisites and Setup
Some feature/permision need to be enable from user side: Feature.
- REST Web Services feature.
- SuiteAnalytics Workbook feature.
Permissions:
- REST Web Services.
- Log in using Access Tokens.
- SuiteAnalytics Workbook.
List Rest Api
https://system.netsuite.com/help/helpcenter/en_US/APIs/REST_API_Browser/record/v1/2024.1/index.html
Action: Create new sales orders
POST https://demo123.suitetalk.api.netsuite.com/services/rest/record/v1/salesOrder
{ "entity": "Customer", "email": "test@mail.com", "status": { "id": "A" , ...}, ... }
(Full list request body: https://system.netsuite.com/help/helpcenter/en_US/APIs/REST_API_Browser/record/v1/2024.1/index.html#/definitions/salesOrder)
Orther operations
Note: We need to map the correct item ID to create a NetSuite sales order. We have three functions for processing IDs

Pull data from NetSuite
Trigger: Pull sales order
We will use SuiteScript to pull data from NetSuite.
What are SuiteScript
SuiteScript is NetSuite's server-side JavaScript-based scripting language that allows developers to customize and extend the functionality of NetSuite's cloud-based business management platform. SuiteScript enables developers to create customizations, automate business processes, and integrate NetSuite with external systems.
Process to apply SuiteScript:
https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_1503717063.html
- Setup > Company > Enable Features
- SuiteCloud > Client SuiteScript
- Server SuiteScript > I Agree
- Save
Step 2: Create the Script File Step 3: Upload the Script File to NetSuite.
- Documents > File > SuiteScripts > Add File
Step 4: Create a Script Record and Script Deployment Record
- Customization > Scripting > Scripts > New
Step 5: Test the Script
SuiteScript for "webhook"
User Event Script execute when users perform certain actions on records. We will use this to receive data (https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_4387799721.html).
Step 1 : Create a new script: Customization > Scripting > Scripts > New







This is the script content:
/**
* @NApiVersion 2.x
* @NScriptType UserEventScript
*/
define(['N/https', 'N/log', 'N/runtime'], function(https, log, runtime) {
function afterSubmit(context) {
log.error({
title: 'Sending Data',
details: context
});
if (context.type === context.UserEventType.EDIT || context.type === context.UserEventType.CREATE || context.type === context.UserEventType.APPROVE) {
var salesOrder = context.newRecord;
var accountId = runtime.getCurrentScript().getParameter({name: 'custscript_account_id'}) || runtime.accountId;
var postUrl = 'https://42bf-113-165-167-193.ngrok-free.app/api/webhooks/netsuite';
try {
var response = https.post({
url: postUrl,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: salesOrder.id,
actionTarget: "updated-sales-order",
accountId: accountId
})
});
} catch (error) {
log.error({
title: 'Error Sending Data',
details: error.message
});
}
if (context.type === context.UserEventType.CREATE) {
try {
var response = https.post({
url: postUrl,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: salesOrder.id,
actionTarget: "created-sales-order",
accountId: accountId
})
});
} catch (error) {
log.error({
title: 'Error Sending Data',
details: error.message
});
}
}
}
}
return {
afterSubmit: afterSubmit
};
});
Code explain: https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_1510274245.html Depending on the payload or http.post to determine user, data...
Trigger: Pull item fulfillment:
similar to pull sales order This is the script content:
/**
* @NApiVersion 2.x
* @NScriptType UserEventScript
*/
define(['N/https', 'N/log', 'N/runtime'], function(https, log, runtime) {
function afterSubmit(context) {
if (context.type === context.UserEventType.EDIT || context.type === context.UserEventType.CREATE) {
var item = context.newRecord;
var accountId = runtime.getCurrentScript().getParameter({ name: 'custscript_account_id' }) || runtime.accountId;
var postUrl = 'https://42bf-113-165-167-193.ngrok-free.app/api/webhooks/netsuite';
try {
var response = https.post({
url: postUrl,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: item.id,
actionTarget: "updated-item-fulfillment",
accountId: accountId
})
});
} catch (error) {
log.error({
title: 'Error Sending Data',
details: error.message
});
}
if (context.type === context.UserEventType.CREATE) {
try {
var response = https.post({
url: postUrl,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: item.id,
actionTarget: "created-item-fulfillment" ,
accountId: accountId
})
});
} catch (error) {
log.error({
title: 'Error Sending Data',
details: error.message
});
}
}
}
}
return {
afterSubmit: afterSubmit
};
});
Trigger: Pull invoice:
similar to pull sales order This is the script content:
/**
* @NApiVersion 2.x
* @NScriptType UserEventScript
*/
define(['N/https', 'N/log', 'N/runtime'], function(https, log, runtime) {
function afterSubmit(context) {
log.error({
title: 'Sending Data',
details: context
});
if (context.type === context.UserEventType.EDIT || context.type === context.UserEventType.CREATE) {
var invoice = context.newRecord;
var accountId = runtime.getCurrentScript().getParameter({name: 'custscript_account_id'}) || runtime.accountId;
var postUrl = 'https://42bf-113-165-167-193.ngrok-free.app/api/webhooks/netsuite';
try {
var response = https.post({
url: postUrl,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: invoice.id,
actionTarget: "updated-invoice",
accountId: accountId
})
});
} catch (error) {
log.error({
title: 'Error Sending Data',
details: error.message
});
}
if (context.type === context.UserEventType.CREATE) {
try {
var response = https.post({
url: postUrl,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: invoice.id,
actionTarget: "created-invoice" ,
accountId: accountId
})
});
} catch (error) {
log.error({
title: 'Error Sending Data',
details: error.message
});
}
}
}
}
return {
afterSubmit: afterSubmit
};
});
Trigger: Pull inventory item
POST https://demo123.suitetalk.api.netsuite.com/services/rest/query/v1/suiteql
header: Prefer: transient
data:
{
"q": "SELECT top 10 * FROM item WHERE itemtype='InvtPart'"
}
Business
Sales order
List status
- Pending Approval: The sales order has been created but is awaiting approval from the relevant authority.
- Pending Fulfillment: The sales order has been approved but is awaiting fulfillment.
- Partially Fulfilled: The sales order has been partially fulfilled, and the remaining items are pending fulfillment.
- Pending Billing/Partially Fulfilled: The sales order has been approved and partially fulfilled and is pending billing for a portion of the order.
- Pending Billing: The sales order has been fully fulfilled and is awaiting the creation of an invoice.
- Billed: The order has been fully billed.
- Cancelled: The sales order has been cancelled irreversibly.
How to fulfillment (change the status of a sales order to Pending Billing):
Go to Transactions > Sales > Enter Sales Orders > List > view an item.
If the status is "Pending Approval"* -> you need to Approve the order -> after approve -> the status changes to "Pending Fulfillment".

If the status is "Pending Fulfillment", you can fulfill the order.
Items to fulfill need to available in inventory by location.



Check again the status.
How to create an invoice based on a sales order (change the status of a sales order to Billed):
When the status is "Pending Billing" -> you can create an invoice.

How to add available quantity of an item:
- Step 1: Add an Inventory Cost Revaluations: Transactions > Inventory > Revalue Inventory Cost > New

- Step 2: Add an Inventory Adjustment: Transactions > Inventory > Adjust Inventory > New
Enter require value.

Then config Inventory Detail.
