verification
use it
# add to stunt.yaml
services:
netsuite:
adapter: embedded:netsuite-style
# then
$ stunt upThe embedded: source extracts this adapter from the binary — no git clone, fully offline.
how to mock the NetSuite SuiteTalk REST API locally
Install stunt, paste the service block above into stunt.yaml, run stunt up — then point your client at localhost instead of NetSuite SuiteTalk REST API. It works offline, keeps state across requests and restarts, and every response is synthetic: the route shapes, status codes, pagination, and webhook delivery follow the real NetSuite SuiteTalk REST API 1.0 surface — the data is fake, the behavior is real.
backing stores
customerssalesOrdersinvoicesitemsemployeesvendors
api surface (9)
generated from the adapter manifest — exactly what boots, nothing more
9 routes
POST/services/rest/query/v1/suiteql
POST/services/rest/v1/suiteql
GET/services/rest/record/v1/metadata-catalog
GET/services/rest/record/v1/{recordType}
POST/services/rest/record/v1/{recordType}
GET/services/rest/record/v1/{recordType}/{id}
PATCH/services/rest/record/v1/{recordType}/{id}
DELETE/services/rest/record/v1/{recordType}/{id}
POST/services/rest/record/v1/{recordType}/{id}/!transform/{target}
VM-verified behaviors (38)
- ✓a request without Authorization is 401 INVALID_LOGIN in the o: envelope
- ✓TBA without oauth_signature is rejected: the signature's presence is the gate
- ✓TBA, NLAuth and Bearer all pass the structural gate
- ✓every route family sits behind the gate
- ✓create answers 204 No Content with the record's URL in Location
- ✓internal ids are numeric strings minted past the seed range
- ✓the created record reads back verbatim under its id
- ✓POST with a seen externalId is an upsert: the existing record's Location, no duplicate
- ✓DELETE answers 204 and the record is gone afterwards
- ✓unknown ids and unknown record types are distinct 404 codes
- ✓a transaction record without entity is 400 USER_ERROR naming the field
- ✓entity references resolve by id or refName against stored customers
- ✓a dangling entity reference is 400 INVALID_KEY_OR_REF
- ✓customerPayment demands both customer and payment
- ✓a body that is not a JSON object is 400 INVALID_REQUEST
- ✓PATCH merges the sent fields into the stored record and answers 204
- ✓numeric patches round-trip through the collection as floats
- ✓an id in the PATCH body cannot move the record
- ✓PATCH on an unknown record id or type is a 404
- ✓a malformed PATCH body is 400 INVALID_REQUEST
- ✓the list envelope is items/count/hasMore/links with a self link
- ✓limit windows the page and hasMore adds a next link with the following offset
- ✓following the next link returns the tail and clears hasMore
- ✓an offset past the end is an empty page, not an error
- ✓q filters and orderBy sorts before paging
- ✓an unparseable q is 400 INVALID_SEARCH_PARAMETER, not silent unfiltered rows
- ✓the metadata catalog lists the record types the parameterized routes serve
- ✓SuiteQL returns the FROM table's live rows in the query envelope
- ✓created records are visible to SuiteQL
- ✓SQL LIMIT/OFFSET window the page and mint a next link
- ✓limit/offset query params page when the SQL has no clauses
- ✓unknown tables, FROM-less and missing statements are 400 INVALID_REQUEST
- ✓the /services/rest/v1/suiteql alias runs the same handler
- ✓a salesOrder bills into an invoice dated today, due in 30 days
- ✓the invoice settles into a customerPayment and flips its source to Paid in Full
- ✓the clock drives trandate
- ✓request-body fields override the mapped defaults
- ✓impossible chains, unknown sources and dangling overrides use NetSuite's real codes
Not implemented (4)
- No creditMemo, purchaseOrder, vendorBill, journalEntry, or cashSale records
- No sublist child resources (e.g. salesOrder/{id}/item/{line})
- No per-record-type metadata catalog (metadata-catalog/{recordType})
- No file cabinet, blob upload, or REST analytics endpoints
Differs from the real API (3)
- TBA/NLAuth/Bearer only structurally checked; OAuth 1.0a HMAC not validated
- SuiteQL matches only the FROM table; WHERE and ORDER BY clauses are ignored
- Duplicate-externalId create returns the stored record without updating it
want more of the NetSuite SuiteTalk REST API surface? adapters are YAML + Starlark — the authoring guide covers adding routes, fixtures, and state machines. Open an issue for anything big first, or just file a PR — merged routes ship in the next release.