Netsuite Integration Guide
Use the Arlyn UpScale touchscreen indicator’s Web API to capture live weights into NetSuite.
Disclaimer:
This integration guide was generated with the assistance of AI and is provided for informational purposes only. While the steps and examples are based on common integration practices, details such as API responses, field names, and configuration options should be verified with your Arlyn UpScale device and NetSuite environment before implementation. Always consult your IT team for production use.
At a glance
- Endpoint: http://<SCALE_IP>:8090/api/1.0/weight
- Common use cases: Inventory receipts, work order completions, QC capture, audit logs
- Best practice: Use a small on-prem “bridge” service that posts to a NetSuite RESTlet (outbound only)
What you’ll get from this guide
- Two integration patterns (recommended push vs. direct pull)
- Exact data model to store readings in NetSuite
- Ready-to-use code snippets (cURL, PowerShell, Python, Node, SuiteScript)
- Hardening & troubleshooting checklist
Quick Start (5 steps)
- Locate the scale’s IP and confirm you can reach the endpoint:
curl http://<SCALE_IP>:8090/api/1.0/weight
- Decide architecture: If your scale is on a private LAN (typical), use On-Prem Bridge → NetSuite (Push).
- Create NetSuite objects: A “Scale Reading” custom record with fields for value, unit, stability, timestamp, etc.
- Deploy RESTlet (SuiteScript 2.1) or Scheduled Script (for pull).
- Run the bridge (Node or Python) and verify readings appear in NetSuite.
Architecture options
Option A (Recommended): On-Prem Bridge → NetSuite (Push)
A lightweight script/service inside your network polls the scale (HTTP port 8090) and POSTs the reading to a NetSuite RESTlet over HTTPS.
Why this is preferred
- Works with private scale IPs; no inbound exposure
- Outbound only firewall rule to NetSuite
- Easier security + simpler networking
You need
- A small VM/PC/Raspberry Pi with network access to the scale
- NetSuite Token-Based Auth (TBA) credentials for the RESTlet
Option B: NetSuite Scheduled Script (Pull)
NetSuite’s script calls your scale directly.
Use only if
- The scale is reachable via public DNS/TLS (not typical)
- You have auth + firewall rules to allow NetSuite data centers
UpScale Web API basics
- Weight endpoint: http://<SCALE_IP>:8090/api/1.0/weight (GET)
- Port: 8090 (HTTP)
- Auth: Often none on internal LAN (confirm your device settings)
- Response: JSON or plain text (verify on your unit)
Typical JSON pattern (example; confirm field names on your device)
{
"Platform": 1,
"Unit": "lb",
"Weight": 128.4,
"Tare": 2.0,
"Gross": false,
"Stable": true
}
Practical tips
- Post only stable readings (use stable flag or a /status endpoint if enabled)
- Normalize units (lb/kg/oz/g) before writing to NetSuite
- Poll every 1–5 seconds for ERP usage (avoid noisy sub-second reads)
- Prefer device UTC timestamps; otherwise stamp on the bridge
NetSuite data model (recommended)
Custom Record: Scale Reading (customrecord_scale_reading)
- Scale (Device) – text or list/record (deviceId or friendly name)
- Timestamp – date/time (UTC preferred)
- Gross Weight – decimal
- Net Weight – decimal
- Unit – text (e.g., lb, kg)
- Stable – checkbox
- Tare – decimal
- Source JSON – long text (raw payload for audit)
Optional: Scale Device (customrecord_scale_device)
- Name, deviceId, location, capacity, last_seen
This structure supports saved searches, dashboards, and linking to transactions.
Step-by-step implementation
1) Network & endpoint check
- Assign/confirm static IP for the UpScale indicator
- Test from a workstation on the same subnet:
curl http://<SCALE_IP>:8090/api/1.0/weight
- Capture the actual keys your device returns
2) Choose integration pattern
- Private LAN: Option A (bridge)
- Publicly reachable device: Option B (pull)
3) NetSuite setup
- Create the Scale Reading custom record + fields listed above
- Deploy RESTlet (for push) or Scheduled Script (for pull)
- Generate TBA credentials for the RESTlet role
4) Deploy bridge (Option A)
- Install Node.js (or Python) on a host that can reach the scale
- Add env vars (scale URL, RESTlet URL, tokens)
- Run under a service manager (PM2/systemd/NSSM), with logging and backoff
5) Verify & tune
- Place a test weight; confirm a new Scale Reading in NetSuite
- Validate unit mapping and stability handling
- Tune polling rate and add thresholds (e.g., “post only if change ≥ 0.05 lb”)
Copy-ready code snippets
cURL (quick test)
curl -s
curl -s http://<SCALE_IP>:8090/api/1.0/weight
PowerShell
Invoke-RestMethod -Method GET -Uri "http://<SCALE_IP>:8090/api/1.0/weight"
Python (read once)
import requests
r = requests.get("http://<SCALE_IP>:8090/api/1.0/weight", timeout=3)
print(r.json())
Node (minimal on-prem bridge)
// Polls the scale and POSTs to a NetSuite RESTlet
const http = require('http');
const https = require('https');
const SCALE_URL = 'http://<SCALE_IP>:8090/api/1.0/weight';
const NETSUITE_URL = 'https://<ACCOUNT>.restlets.api.netsuite.com/app/site/hosting/restlet.nl?script=<ID>&deploy=1';
const HEADERS = {
'Content-Type': 'application/json',
// Add TBA/OAuth1 auth headers here
};
function getScaleWeight() {
return new Promise((resolve, reject) => {
http.get(SCALE_URL, res => {
let data = '';
res.on('data', c => data += c);
res.on('end', () => {
try { resolve(JSON.parse(data)); } catch (e) { reject(e); }
});
}).on('error', reject);
});
}
function postToNetSuite(payload) {
return new Promise((resolve, reject) => {
const body = JSON.stringify(payload);
const req = https.request(NETSUITE_URL, { method: 'POST', headers: { ...HEADERS, 'Content-Length': Buffer.byteLength(body) }}, res => {
let data = '';
res.on('data', d => data += d);
res.on('end', () => resolve({statusCode: res.statusCode, body: data}));
});
req.on('error', reject);
req.write(body); req.end();
});
}
setInterval(async () => {
try {
const reading = await getScaleWeight();
if (reading.stable !== false) {
const payload = {
deviceId: reading.deviceId || 'UPSC-UNKNOWN',
timestamp: reading.timestamp || new Date().toISOString(),
gross: reading.gross,
net: reading.net ?? reading.gross,
unit: reading.unit,
stable: reading.stable === true,
tare: reading.tare ?? 0
};
const resp = await postToNetSuite(payload);
if (resp.statusCode >= 300) console.warn('NetSuite non-2xx', resp.statusCode, resp.body);
}
} catch (e) {
console.error('Bridge error', e.message);
}
}, 2000);
NetSuite RESTlet (SuiteScript 2.1, POST)
/**
* @NApiVersion 2.1
* @NScriptType Restlet
*/
define(['N/record','N/log'], (record, log) => {
const READING = 'customrecord_scale_reading';
return {
post: (data) => {
try {
const id = record.create({type: READING})
.setValue({fieldId:'custrecord_sr_scale', value: data.deviceId})
.setValue({fieldId:'custrecord_sr_timestamp', value: new Date(data.timestamp)})
.setValue({fieldId:'custrecord_sr_gross', value: data.gross})
.setValue({fieldId:'custrecord_sr_net', value: data.net ?? data.gross})
.setValue({fieldId:'custrecord_sr_unit', value: data.unit})
.setValue({fieldId:'custrecord_sr_stable', value: !!data.stable})
.setValue({fieldId:'custrecord_sr_tare', value: data.tare || 0})
.setValue({fieldId:'custrecord_sr_source_json', value: JSON.stringify(data)})
.save();
return { success: true, id };
} catch (e) {
log.error('Scale Reading POST failed', e);
return { success: false, message: e.message };
}
}
};
});
NetSuite Scheduled Script (SuiteScript 2.1, GET)
(Use only if the scale is publicly reachable over HTTPS)
/**
* @NApiVersion 2.1
* @NScriptType ScheduledScript
*/
define(['N/https','N/record','N/log'], (https, record, log) => {
const URL = 'https://scale.example.com:8090/api/1.0/weight';
const READING = 'customrecord_scale_reading';
return {
execute: () => {
try {
const resp = https.get({ url: URL /*, headers: { Authorization:'Basic ...' }*/ });
const data = JSON.parse(resp.body);
record.create({type: READING})
.setValue({fieldId:'custrecord_sr_scale', value: data.deviceId})
.setValue({fieldId:'custrecord_sr_timestamp', value: new Date(data.timestamp)})
.setValue({fieldId:'custrecord_sr_gross', value: data.gross})
.setValue({fieldId:'custrecord_sr_net', value: data.net ?? data.gross})
.setValue({fieldId:'custrecord_sr_unit', value: data.unit})
.setValue({fieldId:'custrecord_sr_stable', value: !!data.stable})
.setValue({fieldId:'custrecord_sr_tare', value: data.tare || 0})
.setValue({fieldId:'custrecord_sr_source_json', value: resp.body})
.save();
} catch (e) { log.error('Scale pull failed', e); }
}
};
});
Security & reliability checklist
- Keep the scale off the public internet; prefer the bridge model
- Open outbound HTTPS to NetSuite only; no inbound ports to the shop floor
- Store tokens in OS key vaults (not in code)
- Add debounce or change threshold to reduce noisy logging
- Monitor with a heartbeat: alert if no readings in X minutes
Troubleshooting
- Can’t reach endpoint: confirm scale IP, port 8090, VLAN/firewall rules
- Unexpected payload: log raw body; map actual field names
- Auth failures to NetSuite: check role permissions, token validity, and correct RESTlet domain
- Unstable readings: post only when stable=true; increase polling interval
Frequently Asked Questions
Can the Arlyn UpScale touchscreen indicator send weight data directly to NetSuite?
Yes. Using the UpScale Web API, you can retrieve weight data from the indicator and record it in NetSuite through a RESTlet or Scheduled Script. Most customers choose the recommended bridge method for security and reliability.
What types of NetSuite transactions can use scale data?
Scale readings can be linked to common NetSuite processes such as inventory receipts, work order completions, quality control checks, and shipping/packing transactions. By creating a custom “Scale Reading” record, you can map the captured values directly to the fields you need.
Do I need to expose my scale to the public internet?
No. The preferred method is to keep the scale on a private LAN and use a lightweight bridge service to securely push data to NetSuite. This avoids the risks and complexity of opening inbound access to plant-floor devices.
Can I integrate multiple scales at once?
Yes. The bridge service can poll a list of IP addresses and post readings from each scale, including the device ID in every payload. This lets you capture data from multiple locations or production lines into a single NetSuite account.
How often should the scale be polled?
For ERP and recordkeeping purposes, polling every 1–5 seconds is typical. Faster intervals are usually unnecessary and can generate noise. You can also configure the bridge to only post new readings when the weight changes beyond a set threshold or when a stable reading is available.
What units of measurement are supported?
The API returns the unit of measurement (such as pounds, kilograms, grams, or ounces) along with the weight. NetSuite can store the raw value, or you can normalize units before sending data if you need a standardized record.
Can I use a cloud iPaaS platform instead of a bridge?
Yes. If your organization already uses middleware such as Celigo, Boomi, MuleSoft, Make, or n8n, you can replicate the bridge pattern within those tools. This is useful if you prefer centralized management of all integrations.
What happens if the scale goes offline?
If the scale is unreachable, the bridge will fail to poll and log an error. You can configure monitoring or alerts to notify you if no readings are received in a given timeframe, ensuring quick troubleshooting.