Skip to main content
Creates one sales order in the workspace’s own NetSuite account with a single 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_idrequired. NetSuite internal id of the customer (match_identifier from a lookup on customer). Never the name.
  • line_itemsrequired, max 500. Each: item_id (required, internal id from a lookup on item), 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_*). Flat custcol_* keys on a line are accepted too.
  • tran_date, ship_dateYYYY-MM-DD; empty tran_date means 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), or ship_address_list_id (one of the customer’s saved addresses). Giving two is a validation error.
  • Bill-to, optional: billing_address or bill_address_text. NetSuite defaults it from the customer.
  • custom_fields — header custbody_* values for this order: plain value for text/number/date/checkbox, {"id": "…"} for list fields. Overrides the configured defaults key by key. Flat custbody* / cseg* keys at the top level are accepted too; an explicit custom_fields entry wins over a flat key with the same name, and a flat key set to null means “unset” and is dropped.
Fixed defaults (group Fixed defaults; pin per agent so the model cannot contradict them):
  • 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_statusA Pending Approval (default) or B Pending Fulfillment.
Configuration only:
  • custom_fields_defaults — JSON object of custbody_* values applied to every order, e.g. {"custbody_order_source": {"id": "3"}}.
  • line_custom_fields_defaults — JSON object of custcol_* values applied to every line.
  • duplicate_checknone (default) or other_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_num is 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 in warnings any 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 resolved location_id goes: 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), or both. A line’s own location_id always 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* or cseg* 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 missing customer_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 no other_ref_num while duplicate_check is 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.
Which of these the platform retries: configuration and validation errors, the duplicate refusal and any NetSuite 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.