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

  1. User setup Feature (Setup > Company > Enable Features) Role (Setup > Users/Roles > Manage Roles) Create Integration Records for Applications to Use OAuth 2.0.
  2. Authorized Process (https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_158074210415.html#OAuth-2.0-Authorization-Code-Grant-Flow)
    1. 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):

    2. Consent Screen Display for user authorizes.

    3. POST Request to the Token Endpoint => response: access_token and refresh_token.

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

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

https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/chapter_1540811107.html#Working-with-Records

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

https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_156257770590.html#subsect_156475078410

 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.