POST /services/rest/record/v1/salesOrder and returns the new order’s internal id, document number and a link to open it. Display name “NetSuite Create Sales Order”. Off by default.
The tool is generic: everything that differs between NetSuite accounts — custom form, subsidiary, currency, location, custom custbody_* / custcol_* fields — is a value the admin pins on the configured tool, never code. The agent supplies only what changes per order and takes every id from NetSuite Lookup.
Authentication and enablement
Configured tool bound to a NetSuite integration (account id, token id/secret, consumer key/secret — see NetSuite Lookup for where each value comes from). The role behind the token needs permission to create sales orders. REST record writes require SuiteTax; accounts on legacy tax get NetSuite’s error back.Inputs
Per order (agent):customer_id— required. NetSuite internal id of the customer (match_identifierfrom a lookup oncustomer). Never the name.line_items— required, max 500. Each:item_id(required, internal id from a lookup onitem),quantity(required, > 0),rate(unit price; omit to use the item’s price level),amount,description,price_level_id,units_id,location_id,department_id,class_id,tax_code_id,custom_fields(custcol_*). Flatcustcol_*keys on a line are accepted too.tran_date,ship_date—YYYY-MM-DD; emptytran_datemeans today.other_ref_num— the customer’s PO number (NetSuite “PO #”); also the duplicate-check key.memo.- Ship-to, one of:
shipping_address(addressee, attention, addr1, addr2, addr3, city, state, zip, country, phone— a one-off address on this order, the customer’s address book is untouched),ship_address_text(free text when the block cannot be split), orship_address_list_id(one of the customer’s saved addresses). Giving two is a validation error. - Bill-to, optional:
billing_addressorbill_address_text. NetSuite defaults it from the customer. custom_fields— headercustbody_*values for this order: plain value for text/number/date/checkbox,{"id": "…"}for list fields. Overrides the configured defaults key by key. Flatcustbody*/cseg*keys at the top level are accepted too; an explicitcustom_fieldsentry wins over a flat key with the same name, and a flat key set tonullmeans “unset” and is dropped.
custom_form_id(Customization → Forms → Transaction Forms; the form decides invoice / cash sale / progress billing),subsidiary_id,currency_id,location_id,department_id,class_id,terms_id,sales_rep_id,ship_method_id.order_status—APending Approval (default) orBPending Fulfillment.
custom_fields_defaults— JSON object ofcustbody_*values applied to every order, e.g.{"custbody_order_source": {"id": "3"}}.line_custom_fields_defaults— JSON object ofcustcol_*values applied to every line.duplicate_check—none(default) orother_ref_num: before creating, look for a sales order with the same customer and PO number and refuse if one exists, naming it. Recommended for email and upload triggers. With the check on,other_ref_numis required — a check that cannot run is refused, not skipped. Runs of this tool for the same account, customer and PO number are serialised with a Postgres advisory lock (the platform’s shared write-lock repository) held across check and create, so two Agents runs for one PO cannot both create; the check runs again after the create and reports inwarningsany other order for that PO entered outside Agents in the same moment. Any existing sales order counts, including cancelled or closed ones — cancel and re-create a PO in NetSuite, or use a new PO number, if a closed order must be replaced.location_mode— where a resolvedlocation_idgoes:header(default, NetSuite’s own behaviour),lines(on every line that has no location of its own, header left empty — use when fulfilment reads the line location, as a per-line warehouse export does), orboth. A line’s ownlocation_idalways wins.
Output
Flat structured result:sales_order_id, tran_id (document number, e.g. SO-10432), status, total, customer_id, tran_date, other_ref_num, order_status, line_item_count, line_items[], custom_fields, netsuite_url, warnings[], completed_at. The markdown summary lists the lines and links to the order. tran_id, status and total come from a best-effort read-back after the create; if that read fails the order still exists, the fields are empty and warnings says so.
A refused duplicate returns an error result whose structured content carries status: "limitation", limitation_type: "duplicate", tool_name, duplicate: true, existing_sales_order_id, existing_tran_id, customer_id, other_ref_num and netsuite_url. The limitation status tells the platform not to retry: the agent gets the existing order at once and decides what to do.
Limits and side effects
- Creates exactly one sales order per successful call; never updates, cancels or fulfils one.
- Every reference id is validated as digits and every custom-field key as a
custbody*,custcol*orcseg*script id before the payload is built. - Item groups cannot have member lines set on create (NetSuite limitation); attachments are out of scope.
- Logs record line count, order id, status and timing — never the payload or addresses.
Expected errors
NetSuite integration not configured…, missing consumer pair, invalid account id — configuration.validation error: …— a missingcustomer_id/line_items, a name where an id is expected, a bad date, an unknown custom-field key, two ship-to modes at once, or noother_ref_numwhileduplicate_checkis on.Another run is creating a sales order for customer … with PO number "…" right now— another run holds the PO lock; nothing created, retry.A sales order for customer … with PO number "…" already exists: SO-… (id …)— duplicate check hit; nothing created.Could not check for an existing sales order before creating: …— the duplicate query failed; nothing created.NetSuite refused the sales order: create sales order returned HTTP 400: …— NetSuite’s own detail (e.g. “Please enter value(s) for: Subsidiary”, an item not valid for the subsidiary, SuiteTax not enabled); nothing created.
4xx are limitations (status: "limitation") and go straight back to the agent — the same call would fail the same way. The lock being busy, a failed lock, network failures and NetSuite 5xx responses are ordinary errors and are retried.