A fulfillment tool may need inventory by item and location, with a lot number for some products. The listIssueInventoryNumber example queries those records through the NetSuite SuiteQL REST endpoint.
Updated listIssueInventoryNumber
The snippet below instantiates a NetSuite REST client and adds light-touch normalization for lot numbers while keeping the interface identical to the original helper. Review its inputs, query construction, and account-specific assumptions before adapting it to your application. (Import moment and your IssueInventoryNumberByLotNumberResponse interface alongside this helper.)
const netsuiteApi = new NetsuiteRest({
consumer_key: process.env.NETSUITE_CUSTOMER_KEY,
consumer_secret_key: process.env.NETSUITE_SECRET_KEY,
token: process.env.NETSUITE_TOKEN,
token_secret: process.env.NETSUITE_TOKEN_SECRET,
realm: process.env.NETSUITE_ACCOUNT_ID,
base_url: process.env.NETSUITE_API_URL,
})
interface IssueInventoryNumberByLotNumberResponse {
id: string
lotnumber: string
itemid: string
itemnumber: string
itemname: string
quantityavailable: string
locationid: string
}
function listIssueInventoryNumber(
itemNumber: string,
locationId: number,
lotNumber?: string
): Promise<IssueInventoryNumberByLotNumberResponse[]> {
const normalizeLotNumber = (lotNumberToNormalize: string) => {
try {
// example if dates are passed in as 01/01/2025, we need to normalize it to 01/01/25
const isDate = moment(lotNumberToNormalize, 'MM/DD/YYYY').isValid()
if (isDate) {
return moment(lotNumberToNormalize, 'MM/DD/YYYY').format('MM/DD/YY')
}
return lotNumberToNormalize
} catch (error) {
return lotNumberToNormalize
}
}
let query = lotNumber
? `
SELECT inventoryNumber.Id AS id, inventorynumber.inventorynumber AS lotNumber, inventorynumber.item AS itemId, item.itemid AS itemNumber,
item.displayname AS itemName, ItemInventoryBalance.quantityAvailable AS quantityAvailable, ItemInventoryBalance.location AS locationId,
FROM inventorynumber
INNER JOIN ItemInventoryBalance ON ItemInventoryBalance.inventoryNumber = inventoryNumber.Id
INNER JOIN item ON inventorynumber.item = item.id
WHERE (inventorynumber.inventorynumber LIKE '%${lotNumber}%' or inventorynumber.inventorynumber LIKE '%${normalizeLotNumber(lotNumber)}%') and item.itemid = '${itemNumber}' and ItemInventoryBalance.location = ${locationId}
`
: `
SELECT '' AS id, '' AS lotNumber, iteminventorybalance.item AS itemId, item.itemid AS itemNumber,
item.displayname AS itemName, ItemInventoryBalance.quantityAvailable AS quantityAvailable, ItemInventoryBalance.location AS locationId,
FROM ItemInventoryBalance
INNER JOIN item ON item.id = iteminventorybalance.item
WHERE item.itemid = '${itemNumber}' and iteminventorybalance.location = ${locationId}
`
return netsuiteApi
.request({
path: `query/v1/suiteql`,
method: 'POST',
body: JSON.stringify({
q: query,
}),
})
.then((response) => response.data?.items || [])
.catch((error) => {
const response = error && error.response
const errorMessage = (response && response.body) || error
return Promise.reject(errorMessage)
})
}
How the helper works
- NetSuite authentication:
NetsuiteRestis configured with token-based credentials pulled from environment variables, which keeps secrets out of source control while enabling deployments across multiple accounts. - Optional lot search: When you pass a
lotNumber, the helper searches by both the raw value and a normalized date-style variant so you can capture inventory tied to dates such as expiration lots. - Non-lot inventory: Skip the
lotNumberargument to pull available quantity for standard items that do not rely on lot tracking; the query automatically falls back toItemInventoryBalance.
Querying the NetSuite SQL (SuiteQL) endpoint
All of the heavy lifting runs through NetSuite's SQL-like API at query/v1/suiteql. This REST endpoint accepts Oracle-flavoured SQL inside the q property of the POST body and returns a JSON payload with an items array. The query joins inventorynumber, iteminventorybalance, and item in one request.
To control query size and support pagination:
- Limit your columns to only what the UI needs, especially when you are rendering product detail pages or headless commerce listings.
- Add deterministic ordering (for example,
ORDER BY itemNumber, lotNumber) when you plan to paginate or cache responses.
Using the helper in your application
- Instantiate a NetSuite REST client with token-based authentication or OAuth 1.0.
- Call
listIssueInventoryNumberwith the item number and location ID you need to inspect. - Include a
lotNumberto return per-lot availability; omit it to fetch inventory for non-lot items. - Surface the resulting
quantityAvailabledata in dashboards, customer experiences, or internal planning tools.
More NetSuite SuiteQL examples
This inventory helper is part of a broader NetSuite SuiteQL series:
- NetSuite SuiteQL Examples for E-commerce Integrations
- Query NetSuite Sales Orders and Line Items with SuiteQL
- Track NetSuite Item Fulfillments and Shipping Packages with SuiteQL
- Find Partially Fulfilled Sales Orders in NetSuite with SuiteQL
If the question is not how to read inventory but which system should own on-hand, reservations, availability, and the Shopify projection, see Shopify + NetSuite Inventory Sync: Choosing the Source of Truth.

