Contents11 sections ↓
What is the NetSuite REST API?
The NetSuite REST API — officially named SuiteTalk REST Web Services — is Oracle NetSuite's HTTP/JSON interface for reading and writing records programmatically. It uses standard REST conventions: GET to read, POST to create, PATCH to update, and DELETE to remove records. SuiteQL, NetSuite's SQL-92-based query language, is exposed through the same REST web services, which makes it the single integration surface for most use cases.
NetSuite has offered two web services APIs: SOAP web services and REST web services. Oracle has now put end dates on SOAP, so REST is the only one to build new integrations on.
TL;DR: The NetSuite REST API provides CRUD operations on the record types Oracle lists as supported (custom records included; custom sublists and legacy tax features are not), SuiteQL for queries, and JSON payloads. Authenticate with OAuth 2.0 — from NetSuite 2027.1 you can't create new token-based authentication (TBA) integrations. Your account's metadata catalog at /services/rest/record/v1/metadata-catalog describes every exposed record and field, including your customizations. Concurrency is one pool per account, shared by SOAP, REST and RESTlets: 5, 15 or 20 requests depending on service tier, plus 10 for each SuiteCloud Plus license.
SOAP and TBA end-of-life dates
Oracle has published a timeline for retiring SOAP web services and token-based authentication:
| Release | What changes |
|---|---|
| 2025.2 | The last planned SOAP web services endpoint. |
| 2026.1 | New integrations should use REST web services with OAuth 2.0. |
| 2027.1 | No new SOAP integrations, and no new TBA integrations for SOAP, REST or RESTlets. |
| 2028.2 | All SOAP web services endpoints are disabled. Support for existing TBA integrations tentatively ends. |
If you maintain a SOAP integration or an integration that signs requests with TBA, plan the move to REST web services and OAuth 2.0 now rather than in 2028.
Authentication
OAuth 2.0 (recommended)
OAuth 2.0 is Oracle's preferred authentication method for REST web services and RESTlets. It isn't supported for SOAP web services.
- Enable the features: REST Web Services and OAuth 2.0 (Setup > Company > Enable Features > SuiteCloud).
- Create an integration record with OAuth 2.0 enabled and the grant type you need.
- Give the integration a role with the "REST Web Services" and "Log in using OAuth 2.0 Access Tokens" permissions. Oracle advises against using the Administrator role for integrations.
- Pick the flow:
- Authorization code grant — a user signs in to NetSuite and approves access. Use it when a person is behind the integration.
- Client credentials (machine-to-machine) — no user interaction; the integration authenticates with a certificate you upload to NetSuite. Use it for server-to-server integrations.
- Send the access token in the Authorization header as a Bearer token. Access tokens are valid for 60 minutes.
Token-Based Authentication (TBA) — legacy
TBA signs each request with OAuth 1.0 using a consumer key and secret (from the integration record) plus a token ID and secret (from an access token tied to a user and role). Existing TBA integrations keep working for now, but from NetSuite 2027.1 you can't create new TBA integrations, and support for existing ones tentatively ends in 2028.2. Don't start new work on TBA.
Need a custom NetSuite integration built?
REST web services, RESTlets, SuiteQL and OAuth 2.0 setup, or moving an existing SOAP or TBA integration before the cutoff. NetSuite-only since 2017.
Scope my integrationMaking API requests
Base URL
Example: base URL pattern for all REST API requests
https://{accountId}.suitetalk.api.netsuite.com/services/rest/Replace {accountId} with your NetSuite account ID (e.g., 1234567 or 1234567_SB1 for sandbox).
Record operations (CRUD)
Create a record (POST):
Example: create a new customer record
POST /services/rest/record/v1/customer
Content-Type: application/json
{
"companyName": "Acme Corp",
"email": "info@acme.com",
"subsidiary": {"id": "1"}
}Read a record (GET):
Example: get a single customer by internal ID
GET /services/rest/record/v1/customer/123Returns JSON with the fields the role can access.
Update a record (PATCH):
Example: update specific fields on an existing customer
PATCH /services/rest/record/v1/customer/123
Content-Type: application/json
{
"phone": "555-0123",
"email": "new@acme.com"
}PATCH changes only the fields you send; any omitted field is left unchanged.
Upsert a record by external ID (PUT):
PUT is used for one thing in REST web services: the upsert operation, when the request URL carries an external ID. If a record with that external ID exists it's updated, otherwise it's created.
Example: upsert a customer by external ID
PUT /services/rest/record/v1/customer/eid:CID002
Content-Type: application/json
{
"firstName": "John",
"lastName": "Smith"
}Delete a record (DELETE):
Example: permanently delete a customer record
DELETE /services/rest/record/v1/customer/123Sublists (line items)
Records with sublists (e.g., sales order lines, vendor bill lines) include nested arrays. Custom sublists aren't available through REST web services.
Example: POST body for a sales order with two line items
{
"entity": {"id": "123"},
"item": {
"items": [
{
"item": {"id": "456"},
"quantity": 10,
"rate": 25.00
},
{
"item": {"id": "789"},
"quantity": 5,
"rate": 50.00
}
]
}
}Filtering and querying records
List records with filters:
Example: get all customers whose company name contains "Acme"
GET /services/rest/record/v1/customer?q=companyName CONTAIN "Acme"Collection queries return record IDs and links, not field values. To get the fields, read each record or use SuiteQL.
Pagination:
Example: retrieve the first 100 customer records
GET /services/rest/record/v1/customer?limit=100&offset=0Use limit and offset to page through large result sets. The offset must be a multiple of the limit.
Catch misspelled field names
By default, a field name REST web services doesn't recognize only produces a warning. Send the X-NetSuite-PropertyNameValidation: error header so a typo fails the request instead of being silently ignored.
SuiteQL
SuiteQL is NetSuite's query language, based on SQL-92, and it's available through REST web services, the SuiteScript N/query module and SuiteAnalytics Connect. It enforces the same role-based access restrictions as SuiteAnalytics Workbook.
Endpoint:
Example: run a SuiteQL query to retrieve customers created in 2026
POST /services/rest/query/v1/suiteql?limit=1000&offset=0
Content-Type: application/json
Prefer: transient
{
"q": "SELECT id, companyname, email FROM customer WHERE datecreated >= TO_DATE('2026-01-01', 'YYYY-MM-DD')"
}The Prefer: transient header is required. Results come back 1,000 rows per page by default, up to 100,000 results per query; for larger extracts, Oracle points to SuiteAnalytics Connect.
SuiteQL capabilities
- Joins across related tables
- Aggregate functions (SUM, COUNT, AVG, MAX, MIN)
- GROUP BY and HAVING
- Subqueries and UNION
- Built-in functions (TO_DATE, NVL, CASE)
Two rules that catch people: WITH clauses aren't supported, and dates must be wrapped in TO_DATE() rather than compared as plain strings.
Example queries
Top 10 customers by revenue:
Example: SuiteQL query — top 10 customers by invoiced revenue in 2026
SELECT TOP 10
c.companyname,
SUM(tl.netamount) AS total_revenue
FROM transaction t
JOIN transactionline tl ON t.id = tl.transaction
JOIN customer c ON t.entity = c.id
WHERE t.type = 'CustInvc'
AND t.trandate >= TO_DATE('2026-01-01', 'YYYY-MM-DD')
GROUP BY c.companyname
ORDER BY total_revenue DESCOpen purchase orders by vendor:
Example: SuiteQL query — count and total open purchase orders grouped by vendor
SELECT
v.companyname AS vendor,
COUNT(t.id) AS open_pos,
SUM(t.foreigntotal) AS total_amount
FROM transaction t
JOIN vendor v ON t.entity = v.id
WHERE t.type = 'PurchOrd'
AND t.status = 'PurchOrd:B'
GROUP BY v.companyname
ORDER BY total_amount DESCSuiteQL vs. saved searches
SuiteQL is the better fit when you need:
- Joins the saved search interface doesn't offer
- Subqueries or UNION
- Several levels of aggregation
- Programmatic access for an integration or a large export
Saved searches are better for:
- Scheduled emails and alerts when records change
- Dashboard portlets
- Reports that business users build and adjust themselves
The metadata catalog and the REST API Browser
Your account's metadata catalog is the reference to read before you write integration code:
Example: metadata catalog URL for your NetSuite account
https://{accountId}.suitetalk.api.netsuite.com/services/rest/record/v1/metadata-catalogRequest it with Accept: application/swagger+json to get an OpenAPI 3.0 description. It includes user- and company-specific metadata, so it reflects your account's custom fields and custom records. For each record type it shows the fields with their data types, the sublists, and the operations available.
The REST API Browser is a separate, Oracle-hosted reference for the standard record schema. It's useful for exploring, but it doesn't reflect any one account's customizations — the metadata catalog does.
RESTlets vs. REST API
NetSuite has two REST-related features that are often confused:
REST API (SuiteTalk REST web services): The standard API for CRUD operations on records. No custom code required. Works with the record types Oracle lists as supported, including custom records.
RESTlets: Custom SuiteScript endpoints that you write and deploy. RESTlets handle HTTP requests and can run any business logic, not just CRUD operations.
When to use REST API: Standard operations — create records, read records, update records, query data with SuiteQL.
When to use RESTlets: Custom business logic — calculate pricing, validate data against custom rules, aggregate data across several record types in a single call, or any operation that doesn't map to a simple CRUD action.
Rate limits and performance
Concurrency limits
- One pool per account: the concurrency limit applies to the combined total of SOAP web services, REST web services and RESTlet requests.
- Size: 5 for Standard, 15 for Premium, 20 for Enterprise and Ultimate service tiers, increased by 10 for each SuiteCloud Plus license.
- SuiteQL requests count against the same pool.
What happens over the limit
- REST web services return HTTP 429 with
CONCURRENCY_LIMIT_EXCEEDED. - RESTlets return HTTP 400 with
SSS_REQUEST_LIMIT_EXCEEDED. - Requests that run longer than 15 minutes time out.
Oracle doesn't document a Retry-After header. Retry after a delay, and increase the delay on each attempt.
Performance tips
Use SuiteQL for bulk reads. One SuiteQL query that returns 1,000 rows is one request; reading the same records one by one is a thousand requests against a shared concurrency pool.
Use PATCH for updates. PATCH changes only the fields you send. PUT is reserved for upserts by external ID.
Batch and async operations. The batch endpoint accepts up to 100 records per request and runs asynchronously. For long-running single requests, send Prefer: respond-async to get a 202 and a job URL instead of waiting (async isn't supported in the query service).
Minimize round trips. Use expandSubResources=true to include sublists in a single GET request instead of fetching the record and then each sublist separately.
Cache the metadata catalog. Don't query the metadata catalog on every request — cache it and refresh periodically.
Common error codes and fixes
Understanding the HTTP status codes returned by the REST API speeds up debugging significantly.
| HTTP status | Meaning | Common cause | Fix |
|---|---|---|---|
| 400 Bad Request | Invalid payload or field value | Wrong field name, missing required field, wrong data type | Check the metadata catalog for required fields and field IDs |
| 401 Unauthorized | Authentication failure | Expired access token, wrong client ID, or wrong account | Refresh the token; verify the account ID in the base URL matches the integration |
| 403 Forbidden | Permission denied | Role missing permission for the record type or operation | Add the required permission in Setup > Users/Roles > Roles |
| 404 Not Found | Record does not exist | Wrong internal ID or wrong account (sandbox vs. production) | Confirm the record ID and that you're hitting the right account URL |
| 429 Too Many Requests | Concurrency limit exceeded | More concurrent requests than the account's pool allows | Back off and retry with increasing delays |
| 5xx Server Error | Server-side error | Locked record, scripting conflict, platform issue | Check the error message body; 4xx codes point to the request, 5xx to the server |
Handling 429 errors in code
Example: retry with exponential backoff on 429 responses (Python)
import time
import requests
def request_with_retry(url, headers, max_retries=5):
delay = 2
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
if response.status_code == 429:
time.sleep(delay)
delay *= 2
continue
response.raise_for_status()
return response
raise Exception("Max retries exceeded")REST API vs. SOAP API
| Feature | REST API | SOAP API |
|---|---|---|
| Protocol | HTTP + JSON | SOAP + XML |
| Authentication | OAuth 2.0 (TBA for existing integrations) | TBA only — OAuth 2.0 isn't supported |
| Query language | SuiteQL | Saved search criteria |
| Payload size | Smaller (JSON) | Larger (XML) |
| Schema reference | Metadata catalog (OpenAPI 3.0) | WSDL |
| Custom records | Supported | Supported |
| Bulk operations | SuiteQL, batch | Search, getList |
| Status | Current | Last endpoint 2025.2; no new integrations from 2027.1; disabled in 2028.2 |
Recommendation: Build every new integration on REST web services with OAuth 2.0. If you maintain a SOAP or TBA integration, plan its migration before 2027.1, when new SOAP and TBA integrations can no longer be created.
Sources and references
- Oracle NetSuite Help Center — SuiteTalk REST Web Services (docs.oracle.com). Record operations, the metadata catalog, SuiteQL through REST, async and batch requests.
- Oracle NetSuite Help Center — SuiteQL. Supported syntax, joins, functions, and the limits listed above (no WITH clauses, dates in TO_DATE()).
- Oracle NetSuite Help Center — Web services and RESTlet concurrency governance. Concurrency limits by service tier and SuiteCloud Plus licenses.
- Oracle NetSuite Help Center — OAuth 2.0. Authorization code grant, client credentials (machine-to-machine) flow, and token lifetimes.
- Oracle NetSuite Help Center — SOAP web services and TBA end-of-life notices. The 2025.2 / 2027.1 / 2028.2 timeline.
What clients ask before signing
Get your integration scoped
Tell us what systems you need to connect. We'll recommend the right approach and ballpark the cost.

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.
