NetSuite REST API vs SuiteScript RESTlet — Choosing the Right Interface
- The REST Record API is the default first choice for standard record CRUD — no custom SuiteScript, and as of 2026.1 it also handles same-type bulk writes up to 100 records per call.
- A RESTlet is still required when a record type isn’t on REST, when one call must atomically create more than one linked record, or when custom server-side logic has to run mid-write.
- REST and RESTlet requests draw from the same account-wide concurrency pool — choosing RESTlets does not buy more simultaneous throughput, only a larger per-call governance budget (5,000 units vs 1,000).
- Building everything as a RESTlet by default creates maintenance debt most teams don’t see until month two: every endpoint is a script deployment your team owns, versions, and debugs.
Every new NetSuite WooCommerce integration faces the same early decision: use the REST Record API or build RESTlets? The answer is not the same for every operation, and it changed in 2026.1 — REST gained a same-type batch endpoint that removes one of the reasons teams reached for a RESTlet by default. Getting the choice wrong in either direction still creates maintenance problems: a fragile custom SuiteScript codebase for operations REST now handles natively, or REST calls that hit a genuine coverage or atomicity gap and force a late-stage rewrite.
Contents
- Decision Matrix
- When the REST Record API Is the Right Call
- When to Build a RESTlet
- What 2026.1 Changed: Homogeneous Batch Operations
- The Governance Math: Two Separate Budgets
- Concurrency Is Shared, Not Doubled
- The Hybrid Pattern for Most Integrations
- What It Costs to Change Your Mind Later
Decision Matrix
| Operation | Recommended interface | Why |
|---|---|---|
| Create / read a Sales Order | REST Record API | Fully covered, JSON-native, no SuiteScript needed |
| Read inventory by location across 500 items | SuiteQL via REST | One query beats 500 individual REST calls |
| Bulk-create or update 100 same-type records | REST batch endpoint (2026.1+) | Async, one record type per call, up to 100 records — see below |
| Create SO + Fulfillment Request atomically in one call | RESTlet | Batch is same-type only; REST still can’t link two different record types in one atomic write |
| Apply custom pricing logic on order import | RESTlet | Business logic must run server-side in SuiteScript |
| Update inventory levels from WooCommerce | REST Record API (Inventory Adjustment) | Covered — use PATCH on the InventoryAdjustment record type |
| Retrieve custom record types | RESTlet or REST (if custom records enabled) | Custom records require REST API to be enabled per record type |
Seven operations, three verdicts. For anything not in this table, the flowchart below is the same logic in decision order: coverage first, then atomicity, then bulk shape.
When the REST Record API Is the Right Call
The record type is on the supported list. You need standard CRUD, or a same-type bulk write of 100 records or fewer — not custom business logic. You value lower long-term maintenance cost over initial development flexibility. You are building a new integration from scratch in 2026 (REST is the supported direction; SuiteTalk SOAP is legacy).
When to Build a RESTlet
You need to create multiple related records of different types in a single API call (SO + line items + fulfilment in one transaction — the REST batch endpoint only handles one record type per call). You need to execute NetSuite business logic during the write (pricing engine, approval workflow trigger). The record type is not on the REST API coverage list. You need to return aggregated data from multiple records in a single call — REST Record API is per-record only.
What 2026.1 Changed: Homogeneous Batch Operations
NetSuite’s REST Record API gained a batch endpoint in the 2026.1 release: add, update, delete, or upsert multiple records of the same type in a single REST request, processed asynchronously. Before 2026.1, a bulk import of 500 sales orders meant either 500 individual REST calls or a RESTlet written specifically to loop over a payload — batch operations remove the second option’s main justification for anything that is a single record type.
The constraints matter more than the headline. A batch call is homogeneous — every item in one request is the same record type; you can’t mix sales orders and customers in one call. The ceiling is 100 records per request, so a 500-record import is still five calls, not one. Two headers are mandatory: Prefer: respond-async and a Content-Type of application/vnd.oracle.resource+json; type=collection. An optional X-NetSuite-idempotency-key header lets a retried request match against the original instead of creating duplicates — worth setting on every batch call an integration might resend after a timeout.
POST https://ACCOUNT.suitetalk.api.netsuite.com/services/rest/record/v1/salesOrder
Authorization: /* OAuth 2.0 bearer token */
Prefer: respond-async
Content-Type: application/vnd.oracle.resource+json; type=collection
{
"items": [
{ "entity": { "id": "1204" }, "externalId": "SO-WOO-10231" },
{ "entity": { "id": "1198" }, "externalId": "SO-WOO-10232" }
]
}
What this changes for the decision above: a nightly job that creates or updates 100 or fewer same-type records no longer needs a RESTlet just to avoid dozens of round trips. It still needs one the moment a single call has to touch two different record types, or run logic beyond a straight field-level write.
The Governance Math: Two Separate Budgets
Two different limits govern every NetSuite API call, and advice that conflates them is wrong. The first is per-request script governance: a RESTlet gets 5,000 units to spend inside a single execution — five times the 1,000-unit budget a standard script (a Suitelet, a user event script, a workflow action) gets for the same job. A RESTlet that validates input, looks up related records, applies pricing logic, and writes the result in one call can afford all of that inside one governance budget; the same logic split across a user event script triggered by a plain REST write has to fit in 1,000 units instead, or run in a scheduled script’s 10,000.
The second half of the asymmetry: standard REST record calls don’t consume SuiteScript governance units at all. Governance only enters once a RESTlet, or a script triggered indirectly by a REST write — a user event script firing on record creation, for instance — executes. A REST-only integration with no server-side scripts attached to its target records never touches the governance ceiling; the moment any script fires against those records, it does.
Neither number is about how many requests you can send at once — that’s a separate budget, and it’s shared.
Concurrency Is Shared, Not Doubled
REST web services and RESTlets draw from one account-wide concurrency pool, not two. The base limit is set by service tier, and each SuiteCloud Plus license adds ten more:
| Service tier | Base concurrent requests |
|---|---|
| Standard | 5 |
| Premium | 15 |
| Enterprise | 20 |
| Ultimate | 20 |
| Developer / partner accounts | 5 (fixed) |
Verdict: check the live number at Setup > Integration > Integration Governance before capacity planning — every guide says this because it’s cheaper than guessing.
A request that exceeds the pool is rejected, not queued — the client has to back off and retry; NetSuite does not hold it in line, a rejection behavior covered in more depth in our breakdown of NetSuite’s concurrency rejection handling. This is the detail that breaks the intuitive assumption that switching an integration from REST to RESTlets buys more headroom under load — it doesn’t. A Standard-tier account with five REST integrations already running at their concurrency ceiling gets no more simultaneous capacity by rewriting one of them as a RESTlet; the new RESTlet calls compete for the same five slots, alongside any AI Connector Service traffic the account also runs, a shared-pool consequence detailed in our 2026 NetSuite development roundup. What a RESTlet call gets instead is a bigger governance budget per call, and the ability to do more work inside that one call — which is why the real lever for throughput is fewer, batched calls, not a different interface.
The Hybrid Pattern for Most Integrations
Most production WooCommerce-to-NetSuite integrations end up using three interfaces deliberately: REST Record API for order creation and customer reads (simple, low-maintenance), REST’s batch endpoint for same-type bulk inventory or price updates (added 2026.1 — previously this was RESTlet territory), a RESTlet reserved for calls that genuinely need custom logic mid-write (a SKU-to-item lookup combined with a conditional write, or a multi-record atomic create), and SuiteQL for reporting queries. Designing the split deliberately at the start prevents the messy refactor where everything was built as RESTlets and the team is now maintaining a dozen custom scripts a single 2026.1 REST call could have replaced.
What It Costs to Change Your Mind Later
Every interface choice made under deadline pressure eventually needs revisiting, and the retrofit cost is not symmetric. Moving a RESTlet endpoint to the REST Record API means deleting a script deployment, updating the integration’s target URL and auth header shape, and re-testing every caller against REST’s standard error envelope — a RESTlet’s error response is whatever the script author wrote, and callers built against that custom shape break silently against REST’s structured error object if nobody updates them.
Moving the other direction — replacing a REST call with a RESTlet — is cheaper technically; a RESTlet can wrap the same REST calls internally while adding the missing logic. But it adds a maintenance surface with no counterpart on the REST side: a script deployment to version, a script owner to name, and a debug session in the NetSuite Debugger or SuiteCloud IDE the moment it misbehaves in production.
The cheapest fix is neither retrofit: default to REST for anything the coverage list and the 2026.1 batch endpoint already handle, and reserve RESTlets for the specific gap — coverage, atomicity, or custom logic — rather than for the whole integration, so the decision above only needs revisiting one operation at a time.
Not sure whether your integration is over-built on RESTlets or under-covered on REST?
An ecommerce sync audit checks which interface each of your NetSuite calls actually needs — coverage, atomicity, and governance, not just what was easiest to ship first.
Get the working checklists
The runbooks and decision checklists from these guides, as printable PDFs — free in the SoftXone guide library.
References
- REST Web Services Supported RecordsOracle NetSuite Help — full list of record types available via the REST Record API.
- SuiteScript 2.1 RESTlet ReferenceOracle NetSuite Help — RESTlet framework, request handling, and deployment.
- RESTlet Governance and SecurityOracle NetSuite Help — the 5,000-unit per-script governance budget for RESTlets.
- Batch OperationsOracle NetSuite Help — the 2026.1 homogeneous batch endpoint, headers, and the 100-record ceiling.
- Concurrency Governance Limits Based on Service Tiers and SuiteCloud Plus LicensesOracle NetSuite Help — the account concurrency table by service tier.
- Using SuiteQLOracle NetSuite Help — SuiteQL capabilities and access paths, including REST.
Frequently asked questions
When is the REST Record API the right choice?
For standard record operations where built-in behaviour matches your needs and you want no server-side code to maintain — including same-type bulk writes of 100 records or fewer through the 2026.1 batch endpoint.
When should I build a RESTlet instead?
When the record type isn’t on REST’s coverage list, when one call needs to atomically create more than one linked record of different types, or when custom business logic has to run during the write.
Can I use both?
Yes. A hybrid is the practical default: REST for standard records and same-type bulk writes, RESTlets for operations that genuinely need custom work or cross-record atomicity.
Does the 2026.1 batch endpoint replace RESTlets for bulk operations?
Only for same-type writes of 100 records or fewer per call. It doesn’t create linked records of different types atomically, and it can’t run custom logic mid-write — both are still a RESTlet’s job.
Does switching from REST to a RESTlet give my integration more concurrent request capacity?
No. REST and RESTlet requests draw from the same account-wide concurrency pool. A RESTlet buys a larger per-call governance budget and custom-logic capability, not more simultaneous throughput.

Leave a Reply