A developer's honest guide to NetSuite APIs
If you've landed here, you're probably trying to connect something to NetSuite. Maybe it's a custom application, maybe it's syncing data with another platform, or maybe you're just exploring what's possible. Either way, you've got options — and they're not all created equal.
NetSuite has accumulated several API approaches over the years, each with different strengths. The good news: for most new projects, the path is clear. The REST API is modern, well-documented, and handles the majority of use cases. Start there unless you have a specific reason not to.
The overview below shows when each API type makes sense, but don't let the table fool you into thinking they're equivalent choices. REST is the default; the others exist for specific scenarios.
| API Type | Best For | Protocol | Authentication |
|---|---|---|---|
| SuiteTalk REST | Modern integrations, mobile apps | REST/JSON | OAuth 2.0, TBA |
| SuiteTalk SOAP | Legacy systems, complex transactions | SOAP/XML | TBA |
| RESTlets | Custom endpoints, specific business logic | REST/JSON | TBA, OAuth 2.0 |
| SuiteAnalytics Connect | BI tools, data extraction | ODBC/JDBC | User credentials |
SuiteTalk REST API
The REST API is where you should start. Introduced in 2019 and continuously expanded, it covers most standard record types and operations with clean JSON payloads and sensible endpoint patterns. If you've worked with modern REST APIs elsewhere, this will feel familiar.
Base URL Structure
https://{accountId}.suitetalk.api.netsuite.com/services/rest/record/v1/{recordType}
Example for a customer record:
https://1234567.suitetalk.api.netsuite.com/services/rest/record/v1/customer/123
Common Operations
GET a record:
curl -X GET \
'https://1234567.suitetalk.api.netsuite.com/services/rest/record/v1/customer/123' \
-H 'Authorization: Bearer {access_token}' \
-H 'Content-Type: application/json'Create a record (POST):
curl -X POST \
'https://1234567.suitetalk.api.netsuite.com/services/rest/record/v1/customer' \
-H 'Authorization: Bearer {access_token}' \
-H 'Content-Type: application/json' \
-d '{
"companyName": "Acme Corp",
"email": "contact@acme.com",
"subsidiary": {"id": "1"}
}'Update a record (PATCH):
curl -X PATCH \
'https://1234567.suitetalk.api.netsuite.com/services/rest/record/v1/customer/123' \
-H 'Authorization: Bearer {access_token}' \
-H 'Content-Type: application/json' \
-d '{
"email": "newemail@acme.com"
}'Search/Query (SuiteQL):
curl -X POST \
'https://1234567.suitetalk.api.netsuite.com/services/rest/query/v1/suiteql' \
-H 'Authorization: Bearer {access_token}' \
-H 'Content-Type: application/json' \
-H 'Prefer: transient' \
-d '{
"q": "SELECT id, companyname, email FROM customer WHERE isinactive = '\''F'\'' ORDER BY id"
}'Supported Record Types
The REST API supports most standard and custom record types:
- Transactions: Sales Orders, Purchase Orders, Invoices, Payments, etc.
- Entities: Customers, Vendors, Employees, Contacts
- Items: Inventory Items, Service Items, Non-Inventory Items
- Custom Records: Any custom record type you've created
- Sublists: Line items on transactions
Check the NetSuite REST API Browser for the complete list.
Authentication Methods
Token-Based Authentication (TBA)
TBA is required for all production integrations. It uses OAuth 1.0 with four credentials:
- Consumer Key (from integration record)
- Consumer Secret (from integration record)
- Token ID (from access token)
- Token Secret (from access token)
Setup Steps:
- Create an Integration Record (Setup > Integration > Manage Integrations > New)
- Enable Token-Based Authentication
- Create an Access Token for the integration
- Generate the OAuth signature for each request
Example OAuth 1.0 Header:
OAuth oauth_consumer_key="abc123",
oauth_token="def456",
oauth_signature_method="HMAC-SHA256",
oauth_timestamp="1234567890",
oauth_nonce="randomstring",
oauth_version="1.0",
oauth_signature="calculated_signature"
OAuth 2.0 (REST API)
For the REST API, OAuth 2.0 with Client Credentials flow is also supported:
# Get access token
curl -X POST \
'https://1234567.suitetalk.api.netsuite.com/services/rest/auth/oauth2/v1/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials&client_id={client_id}&client_secret={client_secret}'SuiteTalk SOAP API
The SOAP API is the original NetSuite API, still widely used for complex transactions and legacy integrations.
WSDL Location
https://webservices.netsuite.com/wsdl/v2024_1_0/netsuite.wsdl
Example SOAP Request (Get Customer)
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns="urn:messages_2024_1.platform.webservices.netsuite.com">
<soap:Header>
<ns:tokenPassport>
<ns:account>1234567</ns:account>
<ns:consumerKey>abc123</ns:consumerKey>
<ns:token>def456</ns:token>
<ns:nonce>random</ns:nonce>
<ns:timestamp>1234567890</ns:timestamp>
<ns:signature algorithm="HMAC-SHA256">signature</ns:signature>
</ns:tokenPassport>
</soap:Header>
<soap:Body>
<ns:get>
<ns:baseRef internalId="123" type="customer"
xsi:type="ns:RecordRef"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</ns:get>
</soap:Body>
</soap:Envelope>When to Use SOAP vs REST
| Use SOAP When | Use REST When |
|---|---|
| Complex transactions with many sublists | Simple CRUD operations |
| Batch operations (addList, updateList) | Modern applications/mobile |
| Integration with legacy systems | You prefer JSON over XML |
| Specific operations not in REST API | SuiteQL queries needed |
RESTlets (Custom API Endpoints)
RESTlets are SuiteScript 2.x scripts that expose custom REST endpoints. They're perfect for:
- Custom business logic not available via standard APIs
- Aggregating data from multiple record types
- Transforming data before/after NetSuite operations
- Building microservices that interact with NetSuite
Basic RESTlet Structure
/**
* @NApiVersion 2.1
* @NScriptType Restlet
*/
define(['N/record', 'N/search'], (record, search) => {
// Handle GET requests
const get = (requestParams) => {
const customerId = requestParams.customerId;
const customerRecord = record.load({
type: record.Type.CUSTOMER,
id: customerId
});
return {
id: customerRecord.id,
name: customerRecord.getValue('companyname'),
email: customerRecord.getValue('email'),
balance: customerRecord.getValue('balance')
};
};
// Handle POST requests
const post = (requestBody) => {
const newCustomer = record.create({
type: record.Type.CUSTOMER
});
newCustomer.setValue('companyname', requestBody.name);
newCustomer.setValue('email', requestBody.email);
const customerId = newCustomer.save();
return { success: true, customerId };
};
return { get, post };
});Deploying a RESTlet
- Upload the script to File Cabinet
- Create a Script Record (Customization > Scripting > Scripts > New)
- Create a Script Deployment
- Note the External URL — this is your API endpoint
SuiteQL: SQL-like Queries
SuiteQL allows SQL-like queries against NetSuite data via the REST API. It's faster and more flexible than saved searches for data extraction.
Example Queries
Basic query:
SELECT id, companyname, email, balance
FROM customer
WHERE isinactive = 'F'
ORDER BY balance DESC
LIMIT 100Join tables:
SELECT
t.id,
t.tranid,
t.trandate,
c.companyname as customer_name,
t.total
FROM transaction t
JOIN customer c ON t.entity = c.id
WHERE t.type = 'SalesOrd'
AND t.trandate >= '2026-01-01'
ORDER BY t.trandate DESCAggregate:
SELECT
BUILTIN.DF(subsidiary) as subsidiary_name,
COUNT(*) as order_count,
SUM(total) as total_revenue
FROM transaction
WHERE type = 'SalesOrd'
AND trandate >= '2026-01-01'
GROUP BY subsidiaryRate Limits & Best Practices
API Rate Limits
- Concurrent requests: 10 per account (REST/SOAP)
- Request timeout: 5 minutes
- Payload size: 10 MB max
- SuiteQL results: 1000 rows per page (use offset for pagination)
Best Practices
-
Use bulk operations — addList/updateList in SOAP, or batch requests to minimize API calls
-
Implement retry logic — Handle 429 (rate limit) and 503 (service unavailable) with exponential backoff
-
Cache reference data — Don't fetch the same subsidiary/location/item repeatedly
-
Use SuiteQL for reads — Faster than loading records individually
-
Filter at source — Apply filters in your queries rather than fetching everything
-
Handle pagination — Use
offsetandlimitfor large result sets -
Monitor governance — RESTlets and SuiteScript have governance limits
-
Use async for heavy operations — Map/Reduce scripts for batch processing
Error Handling
try {
const response = await fetch(endpoint, options);
if (response.status === 429) {
// Rate limited - wait and retry
await sleep(retryAfter);
return retry(endpoint, options);
}
if (!response.ok) {
const error = await response.json();
throw new Error(`NetSuite API Error: ${error.title} - ${error.detail}`);
}
return response.json();
} catch (error) {
console.error('API call failed:', error);
throw error;
}Integration Patterns
Direct API Integration
Best for:
- Simple, single-direction data flows
- Low volume (< 1000 records/day)
- Technical teams comfortable with API development
iPaaS (Celigo, Boomi, n8n)
Best for:
- Complex multi-system integrations
- High volume or real-time sync
- Non-technical teams managing integrations
- Pre-built connectors (Shopify, Salesforce, etc.)
We offer Celigo implementation services and n8n integration services for complex integration needs.
Middleware/Custom Service
Best for:
- Heavy data transformation
- Complex business logic
- High-volume batch processing
- Custom retry and error handling
Tools & Resources
Official Resources
Development Tools
- Postman — NetSuite collection available
- SuiteCloud IDE — Eclipse-based IDE for SuiteScript
- SDF CLI — Command-line deployment tool
Libraries
- netsuite-rest (Node.js) — Community REST API client
- netsuite (Python) — Python client for SOAP API
- NetSuiteClient (.NET) — .NET SOAP client
Wrapping up: choosing your approach
After years of building NetSuite integrations, our default recommendation is straightforward: start with the REST API. It handles CRUD operations cleanly, supports SuiteQL for efficient data extraction, and follows modern API conventions that your developers will find familiar.
When standard endpoints aren't enough — when you need custom business logic, data aggregation, or transformations that don't fit the standard patterns — that's when RESTlets earn their place. They require SuiteScript knowledge and deployment overhead, but they give you full control over what your endpoint does.
The SOAP API is legacy territory. We still encounter it in older integrations, and some batch operations work better through SOAP, but there's rarely a reason to choose it for new development.
For complex integration scenarios — multiple systems, high volumes, non-technical teams managing the flows — consider an iPaaS platform like Celigo or n8n. The development overhead is lower, and you get monitoring, error handling, and retry logic out of the box.
Need Help with NetSuite Integrations?
We specialize in NetSuite integrations — from simple API connections to complex multi-platform orchestrations. Whether you need a custom RESTlet, an iPaaS implementation, or a full integration architecture review, we can help.

BrokenRubik
NetSuite Development Agency
Expert team specializing in NetSuite ERP, SuiteCommerce development, and enterprise integrations. Oracle NetSuite partner with 10+ years of experience delivering scalable solutions for mid-market and enterprise clients worldwide.
Get More Insights Like This
Join our newsletter for weekly tips, tutorials, and exclusive content delivered to your inbox.
Related Articles
How BrokenRubik uses NetSuite to support tariff-affected businesses
How BrokenRubik helps tariff-affected businesses navigate complexity through tailored NetSuite architecture, automation, and cross-border integrations.
How to add any Library to a backend script
Step-by-step guide to bundling and using external JavaScript libraries in NetSuite backend scripts with Rollup for advanced SuiteScript functionality.
Make the most of SuiteWorld 2025 with BrokenRubik
Get ready for SuiteWorld 2025 with BrokenRubik: key trends, insights, and strategies to make the most of NetSuite’s flagship event.
BrokenRubik