Contents11 sections ↓
NetSuite development platform: an honest API guide
Where is the NetSuite API documentation? NetSuite's official API reference is split across a few places: the SuiteTalk REST API Browser (record types, fields, and operations for REST), the Records Browser (the SOAP schema), the SuiteScript API reference, and the Connect Browser for SuiteAnalytics — all hosted in the Oracle NetSuite Help Center. This guide is the practical companion to those references: which API to use for what, how authentication actually works, and the integration patterns the official docs leave out.
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.
Authentication changes in NetSuite 2027.1. Three of them land in the same release. NLAuth authentication for RESTlets stops working (existing integrations on the IssueToken endpoint are the exception). You can no longer create new integrations that use token-based authentication (TBA), for SOAP, REST or RESTlets; existing TBA integrations keep working until support ends, tentatively in 2028.2. And new integrations that use the OAuth 2.0 authorization code grant flow must send PKCE parameters. Build new integrations on REST web services with OAuth 2.0. Separately, 2026.2 changed SuiteQL's default sort order for transaction queries, so re-validate any code that assumes result ordering. Details by release in our NetSuite 2026 release notes hub.
| API Type | Best For | Protocol | Authentication |
|---|---|---|---|
| SuiteTalk REST | Modern integrations, mobile apps | REST/JSON | OAuth 2.0 (TBA for existing integrations) |
| SuiteTalk SOAP | Existing integrations only | SOAP/XML | TBA — no new integrations from 2027.1 |
| RESTlets | Custom endpoints, specific business logic | REST/JSON | OAuth 2.0 (TBA for existing integrations; NLAuth ends in 2027.1) |
| SuiteAnalytics Connect | BI tools, data extraction | ODBC/JDBC | OAuth 2.0, TBA, 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
OAuth 2.0 (use this for new integrations)
OAuth 2.0 is Oracle's preferred method, and from NetSuite 2027.1 it is the only option for new integrations. It works with REST web services, RESTlets and SuiteAnalytics Connect. It isn't supported for SOAP web services.
There are two flows:
- Authorization code grant: a user signs in to NetSuite and approves access. Use it when a person is behind the integration. From 2027.1, new integrations on this flow must send PKCE parameters, whether the client is public or confidential.
- Client credentials (machine-to-machine): no user interaction. You upload a certificate to NetSuite and sign each token request with its private key. Use it for server-to-server integrations.
Client credentials token request:
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' \
-d 'client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer' \
-d 'client_assertion={signed_jwt}'The client_assertion is a JWT signed with the certificate's private key. Its header carries the certificate ID NetSuite gave you as kid; its payload carries the integration's client ID as iss, the scopes (restlets, rest_webservices), the token endpoint as aud, and issued-at and expiry times. The access token that comes back is valid for 60 minutes; when it expires, request a new one.
Token-Based Authentication (TBA) — existing integrations only
TBA signs every request with OAuth 1.0, using four credentials: a consumer key and secret from the integration record, and a token ID and secret from an access token tied to a user and role. From NetSuite 2027.1 you can't create new TBA integrations, through either the IssueToken endpoint or the three-step authorization flow. Existing ones keep working until support ends, tentatively in 2028.2. Don't start new work on TBA; plan the move to OAuth 2.0 for the integrations you already run. The SuiteScript 2.1 requirement lands in the same 2028.2 release, so on our SuiteScript 2.1 migration projects we inventory the scripts and the integrations that call them together.
To see which integrations sign in with TBA, open the Login Audit Trail (Setup > Users/Roles > User Management > View Login Audit Trail), check Use Advanced Search, and add the Token-based Application Name and Token-based Access Token Name fields to the results.
NLAuth — ends in 2027.1
NLAuth sends a user's email and password in the Authorization header of a RESTlet call. NetSuite stopped accepting it for new RESTlets in 2021.1, and in 2027.1 every integration that still uses it stops working; existing integrations on the IssueToken endpoint are the only exception. Search your scripts and middleware for the string NLAuth and move what you find to OAuth 2.0.
Building on the NetSuite API?
SuiteTalk, RESTlets, SuiteScript 2.x — we build production-grade integrations that your team can actually maintain. Code reviews included.
Scope my projectSuiteTalk SOAP API
The SOAP API is the original NetSuite API, still found in many older integrations. Oracle is retiring it: 2025.2 is the last planned endpoint, no new SOAP integrations can be built from 2027.1 (SOAP requires TBA), and every SOAP endpoint is disabled in 2028.2. Use this section to maintain what you have, not to start something new.
WSDL Location
https://webservices.netsuite.com/wsdl/v2025_2_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_2025_2.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>Why older integrations used SOAP, and why REST is the default now
| Why older integrations used SOAP | Why REST is the default now |
|---|---|
| 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: one pool per account, shared by SOAP, REST and RESTlet requests: 5 for Standard, 15 for Premium, 20 for Enterprise and Ultimate service tiers, plus 10 for each SuiteCloud Plus license
- Over the limit: REST web services return HTTP 429; RESTlets return HTTP 400 with
SSS_REQUEST_LIMIT_EXCEEDED - Request timeout: requests that run longer than 15 minutes time out
- 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 (REST over the concurrency limit), RESTlet
SSS_REQUEST_LIMIT_EXCEEDEDand 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, but from 2027.1 you can't build a new SOAP integration at all, and Oracle disables every SOAP endpoint in 2028.2. If you run one, put its move to REST on the roadmap now.
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.
What clients ask before signing
Sebastian · BrokenRubik
Replies by email within 24 hours
Sebastian
Stuck on a script, a query or an API call? Paste the error and a developer will reply with what we'd check first.

Joaquin Vigna
Co-Founder & CTO
Co-founder and Chief Technology Officer at BrokenRubik with 12+ years of experience in software architecture and NetSuite development. Leads technical strategy, innovation initiatives, and ensures delivery excellence across all projects.
