The quick answer
POST an invoice to /services/rest/record/v1/invoice with the customer in an entity reference object and the item lines in item.items. A successful synchronous create returns HTTP 204 and a Location header. GET that location, then compare the saved invoice's customer, lines and balance with your request.
The terminal shown here is a local API exercise. It illustrates request and response shapes and opens a matching example invoice. It does not contact your NetSuite account. Person and operating-company names are fictional.
Before you start
Enable Accounts Receivable and REST Web Services, and use authorized authentication with a role that can create and view invoices. The example assumes an access token is already available; it does not show authentication setup. Keep tokens in your own secure environment.
Use customer and item internal IDs that exist in your account. Check invoice metadata, the selected form, role and account configuration for required fields. Depending on the account, these can include subsidiary, location, posting period, A/R account, tax fields and custom fields. Posting period may default from the date. OneWorld subsidiaries must be compatible with the customer and items. REST tax handling depends on SuiteTax and account configuration; do not assume that omitting tax fields creates a zero-tax invoice. Legacy tax behavior is not supported by REST. A date alone does not guarantee an open posting period.
This example bills Harbor Equipment Ltd. for three units of Inspection Service at 140.00 each, in a local configuration with no tax, discount or shipping charge. The line amount and invoice total are 420.00. Verify your saved result; pricing rules, currency and scripts can change amounts.
01. Inspect the request error
Inspect invoice.json before running the POST. The customer ID is 418, and item ID 826 is the service. The starting payload incorrectly wraps entity in an array. A customer is a single reference. The item lines are a collection, so item.items remains an array.
The local example runs this request after REST is set to the account-specific service root and TOKEN holds authorized authentication:
curl -i -X POST "$REST/invoice" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" --data @invoice.json
Run the POST only after substituting your own account context. The local response is HTTP 400, followed by an explanation that entity must be a reference object. In a real account, the precise error text can differ; read its error details rather than treating every 400 as the same problem.
02. Correct the reference and create
Replace the array with an object, keeping the item collection intact:
{
"entity": {"id":"418"},
"tranDate": "2026-10-15",
"memo": "October service visit",
"item": {"items": [
{"item":{"id":"826"}, "quantity":3, "rate":140}
]}
}
Use a minimal writable payload. An existing invoice's response can help you understand the schema, but copying its totals, paid amounts and other calculated fields into a new request can introduce invalid values. Add your account's mandatory fields explicitly.
Run the same POST again. The local example returns HTTP 204 and a Location ending in invoice/84001. Location identifies internal ID 84001; the example transaction number is INV84001. Internal ID and invoice number are separate identifiers and need not share a numeric suffix. An empty response body is expected for this synchronous create. Use the returned ID instead of assuming the next invoice number.
03. Retrieve the saved invoice
GET the URL returned in Location. If it is relative, resolve it against the same account-specific REST host. The example requests expanded item details with expandSubResources=true:
curl -s "$REST/invoice/84001?expandSubResources=true" \
-H "Authorization: Bearer $TOKEN"
Use the internal ID from your own Location response. Expansion changes the retrieval representation, not how the invoice was created.
Check INV84001, customer Harbor Equipment Ltd., memo October service visit, total 420, and amount remaining 420. The item collection shows the same service, quantity 3, rate 140, and amount 420. The response is verification data; the POST did not send a hardcoded invoice total.
04. Verify the invoice in NetSuite
Open the invoice using the local example's record link. For a real request, find the same transaction number in NetSuite's invoice list.
Check INV84001, the customer, the 10/15/2026 date and the memo. In the local example, the invoice is Open. Its Summary shows Subtotal 420.00, Tax Total 0.00, Total 420.00 and Amount Due 420.00.
Scroll to Items. In the local example, the single row shows Inspection Service, Quantity 3, Rate 140.00 and Amount 420.00. If the response or UI differs, investigate the saved record and its account defaults before retrying the POST; an unexamined retry can create another invoice.
Common questions
Why does invoice creation return Invalid content in the request body?
A malformed field value can cause this error. In this example, entity was an array where the API expects a single reference object. Validate the request against your account's invoice metadata and inspect the error details; other invalid or required fields can produce similar failures.
Why is the successful POST response empty?
A successful synchronous record creation returns HTTP 204 with a Location header. Retrieve that URL to inspect the invoice. An empty body does not mean the invoice was not created.
Can I create an invoice without a sales order?
Yes. A standalone invoice needs a valid customer, at least one valid billable line, and any account-required transaction fields. POST directly to the invoice record endpoint. Transforming a sales order into an invoice is a separate operation with source transaction and billing eligibility rules.
Should I send subtotal and total in the request?
Start with the writable fields required to create the transaction and its lines. NetSuite calculates amounts using pricing, tax and other account rules. Read and verify the saved totals rather than treating copied calculated fields as proof of the result.
Will three units at 140 always create a 420 invoice?
The pre-tax line calculation is 420. The invoice total can change because of taxes, discounts, shipping, rounding, currency, pricing or account automation. The example assumes none of those changes the amount.