When it comes to running your AR process on NetSuite, one of the most common tasks you'll do is creating sales orders.
Manually creating sales orders can be tedious - the NetSuite UI is not very straightforward, and there are further complexities that are present only in the API and not on the NetSuite UI application.
However, the complexity of the NetSuite API can be difficult to deal with. It takes a lot of dedicated time (and effort) to set up an API integration and actually automate your NetSuite workflows.
In this guide we'll go through a step-by-step process on how to use the NetSuite API to create sales orders, as well as automation solutions that can make the job easier.
Nanonets automates sales order entry into NetSuite, and sets up seamless 2-way matching with payments in less than 15 minutes!
Understanding Sales Orders in NetSuite
A Sales Order is a transaction between a business and a customer where the customer commits to purchasing products or services. Sales orders are critical for tracking inventory, revenue, and customer payments. NetSuite’s API allows you to create, manage, and fulfill these orders programmatically.
There are four main types of sales orders in NetSuite:
- Standard Sales Order: The default type for regular sales transactions where payment is due upon delivery.
- Standard Sales Order - Cash: Used for sales transactions where payment is made at the time of the sale.
- Standard Sales Order - Invoice: Allows the sale to be invoiced at a later time, often after the product or service has been delivered.
- Standard Sales Order - Progress Billing: Used for large projects that require billing in stages or milestones, as work progresses.
The standard sales order is the most flexible of all of these, and it will give you the most number of options to input as fields. When you create a standard sales order, you basically need to choose these 5-6 fields:
- The customer
- The transaction date (defaulted to the current date)
- The sales order status (Pending Approval or Pending Fulfillment)
- The items/services that you are selling
- The payment terms
- The payment method
However, in many cases, it might be beneficial to use one of the other 3 types of sales orders - especially when you already know in advance what type of sale it is going to be (for eg. a cash sale). The benefit to doing that is that many of the fields will be pre-populated for you, saving time and effort.
Setting up the NetSuite API
Before you can start creating sales orders using the NetSuite API, you'll need to set up your account access and ensure proper authentication.
We have published a separate, detailed guide on setting up the NetSuite API - you can always get started there and then come back here.
In case you already know how to run API calls and just need quick-start instructions for NetSuite authentication, here’s how you can do it:
Obtain Account Credentials:
- Log in to your NetSuite account.
- Navigate to Setup > Company > Enable Features.
- Under the SuiteCloud tab, ensure that REST Web Services and Token-Based Authentication are enabled.
Create an Integration Record:
- Go to Setup > Integration > Manage Integrations > New.
- Fill out the required fields, and note down the Consumer Key and Consumer Secret provided.
Set Up Token-Based Authentication (TBA):
- Navigate to Setup > Users/Roles > Access Tokens > New.
- Select the integration record you created, and generate the Token ID and Token Secret.
With your Account ID, Consumer Key, Consumer Secret, Token ID, and Token Secret, you're now ready to make authenticated API calls to NetSuite.
Creating a Sales Order in NetSuite
The NetSuite API allows you to create Sales Orders programmatically, ensuring seamless integration between systems. Below is a step-by-step guide to creating a Sales Order using NetSuite's REST API in python.
Authentication
Before making any API calls to NetSuite, you need to authenticate using OAuth 1.0. The following Python code uses the requests_oauthlib
library to authenticate the request using your consumer_key
, consumer_secret
, token_key
, and token_secret
.
Here's how you authenticate using OAuth 1.0:
import requests
from requests_oauthlib import OAuth1
# Authentication details
auth = OAuth1('consumer_key', 'consumer_secret', 'token_key', 'token_secret')
Once you're authenticated, you're ready to build your payloads.
Create Sales Order Payload
This is the main payload that sends the sales order data to NetSuite. In this, we are able to define what kind of sales order we are creating. We take 2 examples below from the 4 types of sales orders that we saw earlier.
1. Standard Item-Based Sales Order
If your sales order involves tangible products, here’s how to structure the payload for a standard sales order:
item_payload = {
"entity": {"id": "1234"}, # Customer ID
"trandate": "2024-09-01", # Transaction Date
"duedate": "2024-09-15", # Due Date
"currency": {"id": "1"}, # Currency ID (USD)
"terms": {"id": "1"}, # Payment terms
"item": [
{
"item": {"id": "5678"}, # Item ID
"quantity": 10, # Quantity
"rate": 20.00 # Unit price
}
],
"memo": "Sales order for office supplies"
}
2. Progress Billing Sales Order
For large projects that are billed incrementally, here’s the structure for a progress billing sales order:
progress_billing_payload = {
"entity": {"id": "5678"}, # Customer ID
"trandate": "2024-09-01", # Transaction Date
"duedate": "2024-09-15", # Due Date
"currency": {"id": "1"}, # Currency ID (USD)
"item": [
{
"item": {"id": "service_item_id"}, # Service Item ID
"quantity": 1, # Quantity
"rate": 200.00, # Rate
"percentcomplete": 50 # Percentage complete for progress billing
}
],
"memo": "Consulting services for September"
}
Send POST Request
Once the payload is created, the next step is to send a POST request to the NetSuite API using the authenticated session. Below is the function to handle the request:
def create_sales_order(auth, payload):
url = "https://<account_id>.suitetalk.api.netsuite.com/services/rest/record/v1/salesOrder"
headers = {"Content-Type": "application/json"}
# Send POST request to create the sales order
response = requests.post(url, json=payload, headers=headers, auth=auth)
return response
# Send the sales order creation request
response = create_sales_order(auth, payload)
URL: This is the NetSuite REST API endpoint for creating sales orders. Replace <account_id>
with your actual NetSuite account ID.
Response Handling
Once the POST request is made, the API returns a response. You should check the status of the response and handle it accordingly. If the sales order is created successfully, the response will include details such as the sales order ID and status.
# Response Handling
if response.status_code == 200:
print("Sales Order created successfully:", response.json())
else:
print("Error creating Sales Order:", response.status_code, response.text)
Example of successful Sales Order creation
Once the sales order is created successfully it will show up in the NetSuite UI as below:
Download Full Code:
The core code for posting a sales order using NetSuite remains consistent. However, the payload varies depending on the type of sales order being added. Let's explore how to send a POST request to add various types of sales orders using the NetSuite API.
How to Retrieve Internal IDs in NetSuite
To populate the necessary fields in the payloads (such as itemID
, currencyID
, termsID
, and accountID
), you'll need to use NetSuite's Internal IDs. These IDs correspond to specific entities, items, or terms within your NetSuite account.
You can find these internal IDs through the following steps:
- NetSuite UI: Navigate to the relevant record (e.g., Vendor, Item, or Account) in the NetSuite dashboard and enable "Internal IDs" under
Home -> Set Preferences -> General -> Defaults -> Show Internal IDs
.
- Saved Searches: Navigate to Reports -> Saved Searches -> All Saved Searches in the NetSuite dashboard. Create a new search and select the relevant record type (e.g., Items, Customers). In the Results tab, add the Internal ID field as a column. Running the search will display the internal IDs of the selected records in your results.
- SuiteScript: You can write and deploy a SuiteScript that retrieves internal IDs from records. After deploying the script, you can run it to access internal IDs for use in your API calls. Below an example of a simple SuiteScript to retrieve internal IDs of customers:
/**
* @NApiVersion 2.x
* @NScriptType Suitelet
*/
define(['N/search'], function(search) {
function onRequest(context) {
var customerSearch = search.create({
type: search.Type.CUSTOMER,
columns: ['internalid', 'entityid'] // internal ID and Customer name
});
var searchResult = customerSearch.run();
var customers = [];
searchResult.each(function(result) {
customers.push({
internalId: result.getValue({ name: 'internalid' }),
customerName: result.getValue({ name: 'entityid' })
});
return true; // continue iteration
});
// Send back response as JSON
context.response.write(JSON.stringify(customers));
}
return {
onRequest: onRequest
};
});
With these internal IDs, you can ensure your API calls target the correct records, improving accuracy and efficiency in your sales order creation process.
Handling Sales Order Fulfilment and Payment Scenarios in NetSuite
When creating sales orders in NetSuite, the type of payment terms that you're applying can vary, and will often depend on another variable - when the sales order is getting fulfilled.
There are a few common tasks that you will usually have to do:
- Apply a customer payment to a Sales Order
- Handling discounts and credits
- Transform a Sales Order into an Item Fulfilment
Applying Customer Payments to Sales Orders
Once a sales order is created, customer payments can be applied using this payload:
payment_data = {
"customer": {"id": "customer_id"},
"salesOrder": {"id": "sales_order_id"},
"payment": {
"amount": 500,
"method": {"id": "payment_method_id"} # Payment Method ID (e.g., credit card)
}
}
payment_url = 'https://your_netsuite_instance/rest/customerpayment/v1/'
response = requests.post(payment_url, json=payment_data, auth=auth)
print(response.json())
Applying Discounts or Credits to Sales Orders
To apply discounts or credits to a sales order, update the payload like this:
sales_order_data["discountitem"] = {"id": "discount_id"} # Discount ID
response = requests.post(url, json=sales_order_data, auth=auth)
print(response.json())
Transform a Sales Order into an Item Fulfilment
Once a sales order is ready to be fulfilled, you can transform the sales order into an item fulfillment using the NetSuite API. This process ensures that the items in the sales order are marked as shipped or delivered.
This can be done as a NetSuite transform - i.e., you change the sales order to an item fulfilment.
Here’s an example API call for directly transforming a sales order into item fulfillment:
POST /record/v1/salesOrder/<Sales_Order_id>/!transform/itemFulfillment
{
"inventoryLocation": {
"id" : <location id>
}
...
}
Note that the inventoryLocation field is mandatory when transforming a Sales Order to an Item Fulfillment (you need to specify from where in the inventory you are shipping the items that you just sold).
Common Pitfalls and Troubleshooting
Creating sales orders via the NetSuite API is a powerful way to automate your AR process, but it comes with its challenges. Here are some common pitfalls and how to avoid them:
Pitfall | Solution |
---|---|
Authentication Issues | Double-check your tokens, keys, and permissions. Ensure that Token-Based Authentication (TBA) is correctly set up. |
Missing or Incorrect Fields | Always refer to the NetSuite API documentation to ensure all required fields are included and correctly formatted. |
Data Synchronization Issues | Implement regular GET queries to verify that the data in your system matches what's in NetSuite. Consider using middleware or an integration platform to maintain synchronization. |
Rate Limits | Monitor your API usage and increase the API concurrency within NetSuite to 3 or 4, this usually helps. |
Handling Partial Exports | Implement error handling and logging to identify and address partial exports promptly. |
Create Sales Orders on Netsuite using Nanonets
Nanonets simplifies the process by handling the complexities of API authentication, scope management, and error handling, making it an ideal end-to-end NetSuite automation workflow provider.
By leveraging the AI-powered Nanonets platform, you can automate the entire sales order creation process in NetSuite with minimal human intervention. This ensures faster processing times, improved accuracy, and seamless integration with your existing workflows.
Nanonets intelligently extracts key data from your internal CRM as well as documents, maps it directly into NetSuite, and generates accurate sales orders.
Here’s a demo video showing how you can set up automated NetSuite workflows using Nanonets in under 2 minutes.
Advantages of Using Nanonets:
- Native NetSuite Connection: Handles all the intricate details like API authentication and missing fields.
- Out-of-the-Box Workflows: Simplifies tasks like sales order creation and payment application.
- Accurate Data Extraction: Leverages Gen AI models to extract data from invoices and other documents.
- User and Data Management: Provides features like document storage and management and team collaboration.
- Approval Workflows: Allows for data verification within your team before posting to NetSuite.
By automating the sales order creation process with Nanonets, you can ensure efficiency, accuracy, and scalability in your accounts receivable workflow, leaving the tedious tasks to AI.
For more information, check out the Nanonets documentation.
Nanonets automates sales order and payment entry into NetSuite, plus sets up seamless 2-way, 3-way, and 4-way matching in minutes!
Conclusion
Creating sales orders in NetSuite using the API streamlines your accounts receivable process, from handling multiple items and recurring payments to applying discounts.
But why stop at just manual API calls? Nanonets takes automation a step further. By harnessing AI, Nanonets automates the extraction and input of critical sales order data directly into NetSuite, saving you time and eliminating the risk of human error.