How Can a NetSuite Button Send JSON to a Suitelet in a POST Body?

Move a JSON snapshot from a query parameter into a POST body. Inspect request.body parsing and distinguish the response from opening a new window.

The quick answer

Use https.requestSuitelet with method https.Method.POST, a JSON.stringify(payload) body, and Content-Type application/json. In the Suitelet, parse context.request.body and validate the input. The response returns to the caller; it does not open a new browser window.

This walkthrough is a local transport exercise. It uses a synthetic Inventory Item page, an external code editor and an N/https stand-in. The item button makes an actual local HTTP request through a bounded source adapter. No account deployment, native execution, authentication, role permissions or payload limit is verified. The original new-window requirement is outside this walkthrough.

Before you start

The prepared Pressure Manifold item has a JSON snapshot with itemId 1452 and 64 readings. Its ASCII JSON body measures 6,483 characters. A hidden client field supplies that snapshot in this example; hidden fields are still client-controlled input.

The button already names the exported sendInspection handler. This guide changes request construction, not button attachment or business-record creation. Oracle's client-button Suitelet request sample documents Client Script usage. https.requestSuitelet describes its internal authenticated/trusted request context. This local exercise does not verify native module execution, authentication, deployment resolution or role behavior in an account. Verify deployment access and authorize the submitted data separately.

01. Observe the rejection

Open the item in View and click Send Inspection. The starting request puts the JSON in urlParams.payload and uses GET. The prepared receiver answers POST required. This is its own application guard, not a native URL-length error. Click OK.

The local receiver rejects GET with its application message POST required.

02. Inspect both sources

Open inspection_client.js in the local Code Editor. The method is GET and the payload is a query parameter. Run local harness executes the actual client and receiver code against module/request stand-ins. It reports 8,559 encoded query characters and 0 body characters for this sample. That is a measurement, not a platform URL-limit test.

The starting client uses GET and puts JSON in urlParams.payload.

Open View inspection_receiver.js. The read-only receiver requires POST and calls JSON.parse(request.body). It checks that itemId is a positive integer and readings is a nonempty array. The count returned later comes from that parsed array. Return to the client source.

The Suitelet example explicitly parses raw request.body as JSON.

03. Change the request

Replace the GET method and urlParams with this request block. Keep scriptId, deploymentId, the exported Client Script handler sendInspection and the existing response-handling code unchanged:

const response = https.requestSuitelet({
  scriptId: 'customscript_inspection_receiver',
  deploymentId: 'customdeploy_inspection_receiver',
  method: https.Method.POST,
  body: JSON.stringify(payload),
  headers: {'Content-Type': 'application/json'}
});

The detail below isolates POST and the serialized body. Enlarge the image to see the complete block, including the content type.

The repaired request uses POST and a serialized JSON body.

04. Run the saved source

Click Save, then Run local exercise. The actual client and receiver bytes execute against local stand-ins. Confirm POST, 0 query characters, 6,483 body characters, and an acknowledgment for 64 readings.

The saved source bytes also update the local attachment used by the item exercise. This is not a NetSuite File Cabinet upload. The source harness and the item's bounded adapter are separate local checks; the item adapter does not evaluate uploaded JavaScript.

The actual source harness measures POST with zero payload query characters and 6483 body characters.

05. Check the response

Reopen Pressure Manifold and click Send Inspection. The adapter now sends an actual local HTTP POST with the prepared JSON body. The local receiver parses that body and computes the acknowledgment: POST accepted: 64 readings; 6483 body characters. The in-page browser-alert stand-in represents window.alert.

The receiver creates no business record. Returning JSON does not open a new window.

The local HTTP receiver acknowledges 64 readings from its parsed body.

06. Reload and repeat

Click OK, reload the item and click Send Inspection again. The same computed acknowledgment confirms retained local source wiring. Dismiss it; the item remains in View.

Reloaded local wiring returns the same computed acknowledgment.

Before account use, add complete row validation, business authorization, application size bounds and error handling. This small receiver only checks the envelope; it is not a production-ready endpoint.

Common questions

Does requestSuitelet open the Suitelet in a new window?

No. It returns a response to the caller. Opening a window or navigating is separate. This walkthrough verifies neither the original new-window flow nor cross-tab state.

How can a later window use a large JSON snapshot?

A separate design can store the snapshot server-side and pass a short, per-request token in the navigation URL. It must validate ownership, expiry and request isolation. If the data can be reconstructed from a record, passing its ID may be enough; that does not preserve an arbitrary snapshot. Neither approach is implemented here. One mutable session slot can be overwritten by concurrent tabs.

Is raw JSON the same as a form POST?

No. A Suitelet reads a raw JSON body from ServerRequest.body, then parses it. Query-string values and parameters from a form-style request are exposed through request.parameters. A JSON body is not converted into those parameters. RESTlets have different JSON handling; do not copy this parsing rule blindly.

How much JSON can I send?

This example measures one 6,483-character ASCII body and establishes no NetSuite maximum. UTF-8 byte counts can differ from JavaScript character counts for other text. Check current API/account constraints and impose an application-specific bound before deployment.

Does the successful local result prove authentication or permissions?

No. Local source and HTTP checks do not verify native module execution, script/deployment resolution, authentication, role access, browser-origin rules or business authorization. A hidden field does not make its contents trustworthy.

Supporting sources