> For the complete documentation index, see [llms.txt](https://docs.coupler.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.coupler.io/sources/category/sales/netsuite.md).

# NetSuite

Connect Oracle NetSuite to Google Sheets, BigQuery, and BI tools via Coupler.io. Export NetSuite records or run custom SuiteQL queries automatically.

NetSuite (Oracle NetSuite) is a cloud ERP that unifies accounting, order management, inventory, and CRM in one system. Connecting NetSuite to Coupler.io lets you export standard and custom records, or run your own SuiteQL queries, into spreadsheets, BI tools, or databases on a schedule — without building a custom integration.

## Why connect NetSuite to Coupler.io?

* **Automate sales and financial reporting** — Schedule regular exports of sales orders, invoices, vendor bills, and other records instead of running manual saved searches.
* **Query exactly what you need** — Use the SuiteQL data type to pull custom joins, filters, or aggregations that a single record type can't provide.
* **Build custom dashboards** — Export NetSuite data to Looker Studio, Power BI, or Google Sheets for reporting NetSuite doesn't offer natively.
* **Combine with other sources** — Merge NetSuite data with e-commerce, marketing, or support data for a complete view of the business.
* **Flexible destinations** — Export to AI tools, Google Sheets, Excel, BigQuery, Looker Studio, Power BI, or other supported destinations.

## Prerequisites

Before connecting, make sure you have:

* **Administrator access** to your NetSuite account, needed to enable features and create the integration and token records below
* **Token-Based Authentication** and **REST Web Services** enabled (Setup → Company → Enable Features → SuiteCloud tab)
* An **Integration record** with Token-Based Authentication enabled (Setup → Integration → Manage Integrations → New) — this gives you a **Consumer Key** and **Consumer Secret**
* An **Access Token** created for the role you want Coupler.io to use (Setup → Users/Roles → Access Tokens → New) — this gives you a **Token Key** and **Token Secret**
* Your **NetSuite Account ID** (Realm) — found under Setup → Company → Company Information, or in your NetSuite URL

{% hint style="warning" %}
NetSuite only shows the Consumer Secret and Token Secret once, at the moment you create them. Copy all five values (Realm, Consumer Key, Consumer Secret, Token Key, Token Secret) before leaving the page — if you lose them, you'll need to create a new access token.
{% endhint %}

## Quick start

{% hint style="success" %}
Start with the **Objects** data type and the **Invoice** entity, leaving **Start date** and **Window in days** at their defaults. Run it once to confirm the connection and see the fields available, then switch to **SuiteQL** if you need a custom join or filter.
{% endhint %}

## How to connect

NetSuite uses token-based authentication (TBA) — you enter credentials generated in NetSuite rather than signing in through a redirect.

{% hint style="info" %}
See [How to Connect](/sources/category/sales/netsuite/how-to-connect.md) for the full walkthrough of generating your Realm, Consumer Key/Secret, and Token Key/Secret in NetSuite, including the required role and feature setup.
{% endhint %}

{% stepper %}
{% step %}
In NetSuite, enable **Token-Based Authentication** and **REST Web Services** (Setup → Company → Enable Features → SuiteCloud), then create an **Integration record** (Setup → Integration → Manage Integrations → New) with Token-Based Authentication turned on. Note the **Consumer Key** and **Consumer Secret** NetSuite generates.
{% endstep %}

{% step %}
Create an **Access Token** for the role you want Coupler.io to use (Setup → Users/Roles → Access Tokens → New). Note the **Token Key** and **Token Secret**.
{% endstep %}

{% step %}
In Coupler.io, create a new data flow and select **NetSuite** as a source.\
Enter your **Realm** (Account ID), **Consumer Key**, **Consumer Secret**, **Token Key**, and **Token Secret**, then click **Connect**. For a sandbox account, append the sandbox suffix to the Realm, e.g. `1234567_SB1`.
{% endstep %}

{% step %}
Choose a **Data type**: **Objects** to select a standard or custom NetSuite record type, or **SuiteQL** to write a custom query.
{% endstep %}

{% step %}
**For Objects:** select an **Object** (e.g., Invoice, Vendor Bill, Customer) and adjust **Start date** or **Window in days** if needed.
{% endstep %}

{% step %}
**For SuiteQL:** enter your query in the **SuiteQL** field.
{% endstep %}

{% step %}
Choose your destination and run the data flow.
{% endstep %}
{% endstepper %}

## NetSuite data overview

Coupler.io's NetSuite source offers two data types: **Objects**, which pulls standard or custom NetSuite records through the REST Record API, and **SuiteQL**, which runs a custom query you write yourself.

## Objects

{% hint style="info" %}
The list of available objects is fetched live from your NetSuite account's REST Record API metadata catalog, so it reflects exactly the standard and custom record types enabled for your account and role — not a fixed list. Below are common examples grouped by area.
{% endhint %}

#### Transactions

| Object                          | Description                                                            |
| ------------------------------- | ---------------------------------------------------------------------- |
| **Invoice**                     | Customer invoices with line items, tax, and payment terms              |
| **Sales Order**                 | Sales orders with customers, items, quantities, and fulfillment status |
| **Purchase Order**              | Purchase orders with vendors, line items, and receiving status         |
| **Vendor Bill**                 | Payables from suppliers with line items and due dates                  |
| **Journal Entry**               | General ledger entries with debits, credits, and posting accounts      |
| **Credit Memo**                 | Credit memos reducing amounts owed by customers                        |
| **Vendor Credit**               | Credits reducing amounts owed to suppliers                             |
| **Item Fulfillment**            | Shipment records against sales orders                                  |
| **Item Receipt**                | Receiving records for purchased or transferred inventory               |
| **Expense Report**              | Employee expense reports with line items and reimbursement status      |
| **Deposit / Cash Sale / Check** | Cash and payment transactions                                          |

#### Lists and setup records

| Object                                     | Description                                                |
| ------------------------------------------ | ---------------------------------------------------------- |
| **Account**                                | Chart of accounts, including types, numbers, and hierarchy |
| **Subsidiary**                             | Multi-entity records for NetSuite OneWorld accounts        |
| **Location / Department / Classification** | Segment values used for reporting and transaction tagging  |
| **Currency / Currency Rate**               | Currency definitions and exchange rates                    |
| **Term**                                   | Payment terms and due-date rules                           |
| **Accounting Period**                      | Fiscal periods with open/closed status                     |

#### Entities and items

| Object                                        | Description                                              |
| --------------------------------------------- | -------------------------------------------------------- |
| **Employee**                                  | Employee records with job and payroll information        |
| **Contact**                                   | Contact records linked to customers and partners         |
| **Vendor**                                    | Vendor records with payment details and purchase history |
| **Inventory Item / Assembly Item / Kit Item** | Stocked, manufactured, and bundled items                 |
| **Service Sale/Resale/Purchase Item**         | Service items without inventory tracking                 |

This is a representative subset — a typical NetSuite account exposes 100+ standard record types, plus any custom record types you've created.

#### Entity parameters

| Parameter          | Purpose                                                                                                     |
| ------------------ | ----------------------------------------------------------------------------------------------------------- |
| **Object**         | The record type to export. Options load from your account; you can also type a custom record's internal ID. |
| **Start date**     | Export only records with a last-modified date on or after this date.                                        |
| **Window in days** | Splits the sync into date windows of this size (default 30) when paging through a record type.              |

{% hint style="info" %}
**Start date** and **Window in days** only apply to record types that expose a last-modified field (`lastModifiedDate` for standard records, `lastmodified` for most custom records). Record types without one of these fields are synced in full on every run.
{% endhint %}

## SuiteQL

SuiteQL is NetSuite's SQL-like query language. Choose the **SuiteQL** data type and write a query against NetSuite's record tables — useful when you need a join across records, a calculated field, or filters that aren't exposed as Object parameters.

```sql
SELECT id, tranid, entity, trandate, total
FROM transaction
WHERE type = 'CustInvc'
AND trandate >= TO_DATE('2026-01-01', 'YYYY-MM-DD')
```

{% hint style="warning" %}
SuiteQL runs as a full data pull on every run — there's no Start date or incremental option for this data type. NetSuite also caps SuiteQL results at 100,000 rows per query; narrow your `WHERE` clause or aggregate in the query if you hit this limit.
{% endhint %}

See NetSuite's [SuiteQL documentation](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_156257770590.html) for table and field references and query syntax.

## Use cases by role

{% tabs %}
{% tab title="Finance / Accounting" %}
Export Invoice, Vendor Bill, and Journal Entry objects to build AR/AP aging and GL reporting outside NetSuite's native reports. Use Start date to pull only recently modified transactions for daily refreshes.
{% endtab %}

{% tab title="Sales / Revenue Ops" %}
Export Sales Order and Customer-related records to track pipeline and bookings alongside CRM data. Use SuiteQL to join sales orders with items or customers for a single flattened export.
{% endtab %}

{% tab title="Operations / Inventory" %}
Export Inventory Item, Item Fulfillment, and Item Receipt objects to monitor stock levels and fulfillment performance. Combine with Purchase Order data for supply chain visibility.
{% endtab %}

{% tab title="IT / Admin" %}
Use SuiteQL to pull custom record types or fields not exposed as a standard Object, and scope the Access Token's role to only the records a given data flow needs.
{% endtab %}
{% endtabs %}

## Platform-specific notes

* **Token scope determines what you see** — The Access Token is tied to a specific NetSuite role. If an object doesn't appear, or returns a permission error, the role behind your token doesn't have access to it.
* **Objects fetch full record detail per row** — For each object, Coupler.io first lists matching records, then requests each one individually with sub-resources expanded. Large objects with many records take longer than the row count alone suggests.
* **Records without a last-modified field sync in full each run** — Some standard and most custom record types don't expose `lastModifiedDate`/`lastmodified`, so Start date has no effect on them and every run re-pulls the entire record type.

## NetSuite common issues

### Connection Issues

<details>

<summary>Connection fails right after entering credentials</summary>

This usually means one of the five credential fields (Realm, Consumer Key, Consumer Secret, Token Key, Token Secret) is incorrect, or Token-Based Authentication / REST Web Services aren't enabled on the account.

**Fix:**

1. Confirm **Token-Based Authentication** and **REST Web Services** are enabled under Setup → Company → Enable Features → SuiteCloud.
2. Confirm the Integration record has Token-Based Authentication turned on, and the Access Token is active and assigned to the correct role.
3. Re-check the Realm value — see the next issue for the correct format.

</details>

<details>

<summary>Realm (Account ID) format is rejected or connects to the wrong environment</summary>

The Realm must match your NetSuite account ID exactly. Production accounts use the numeric ID alone (e.g., `1234567`); sandbox accounts append a suffix (e.g., `1234567_SB1`). Entering a hostname or URL instead of the account ID will fail.

**Fix:** Use just the account ID, with the sandbox suffix if applicable. You can find it under Setup → Company → Company Information, or in the domain of your NetSuite URL.

</details>

<details>

<summary>Lost the Consumer Secret or Token Secret</summary>

NetSuite only displays the Consumer Secret and Token Secret once, when they're generated. If you didn't save them, there's no way to retrieve them afterward.

**Fix:** Create a new Access Token (Setup → Users/Roles → Access Tokens → New) and reconnect the source in Coupler.io with the new Token Key and Token Secret.

</details>

### Permission Errors

<details>

<summary>403 error or "insufficient permission" for a specific object</summary>

The role assigned to your Access Token doesn't have permission to view that record type in NetSuite.

**Fix:** In NetSuite, edit the role used for the Access Token (Setup → Users/Roles → Manage Roles) and grant view permission for the record type, or create a token under a role that already has broader access.

</details>

<details>

<summary>Error reading an Admin-only record</summary>

Some record types are restricted to the Administrator role in NetSuite. If the Access Token's role isn't Administrator, requests for these records fail.

**Fix:** Use an Access Token created under the Administrator role for objects that require it, or skip that object if broader access isn't appropriate for your integration.

</details>

### SuiteQL Issues

<details>

<summary>SuiteQL query returns "Invalid search query" error</summary>

NetSuite rejected the query — usually due to a syntax error, an unknown table/column name, or a reference to a field that doesn't exist on that record.

**Fix:** Check the exact error detail returned (Coupler.io surfaces NetSuite's own message), and confirm table and field names against NetSuite's SuiteQL documentation. Test the query in NetSuite's SuiteQL query tool if you're unsure it's valid.

</details>

<details>

<summary>SuiteQL query fails because it exceeds 100,000 rows</summary>

NetSuite's REST API caps SuiteQL results at 100,000 rows per query. Queries that would return more fail instead of returning a partial result.

**Fix:** Narrow the query with a tighter `WHERE` clause (e.g., a date range), or aggregate/summarize in the query itself rather than pulling raw rows. There's no way to paginate past this limit through the REST API.

</details>

### Data Gaps

<details>

<summary>Start date doesn't seem to filter a particular object</summary>

The Start date and Window in days parameters only apply to record types that expose a last-modified field (`lastModifiedDate` or `lastmodified`). Record types without one of these fields don't support incremental filtering and are synced in full on every run.

**Fix:** This is expected for those record types — there's no incremental option available for them via the Objects data type. Use SuiteQL with a date filter in the `WHERE` clause if you need to scope the export.

</details>

<details>

<summary>An object returns no data or fewer records than expected</summary>

If the object type doesn't exist or isn't accessible in your account, NetSuite returns an error that Coupler.io logs without failing the entire data flow — so the object silently returns no rows instead of an obvious error.

**Fix:** Verify the object name against the ones available in your account's metadata catalog (shown in the Object dropdown when creating the data flow), and confirm the token's role has access to it.

</details>

## NetSuite FAQ

<details>

<summary>Does NetSuite use OAuth login in Coupler.io?</summary>

No. NetSuite uses token-based authentication (TBA). Instead of signing in through a redirect, you generate a Consumer Key, Consumer Secret, Token Key, and Token Secret in NetSuite, then enter them along with your Realm (Account ID) directly in Coupler.io.

</details>

<details>

<summary>What's the difference between Objects and SuiteQL?</summary>

**Objects** pulls a standard or custom NetSuite record type as a single table — one row per record, with fields matching that record's schema. **SuiteQL** runs a SQL-like query you write yourself, letting you join across records, add calculated fields, or apply filters that Object parameters don't expose.

Use Objects for straightforward record exports. Use SuiteQL when you need data shaped across multiple records or fields not available through a single Object.

</details>

<details>

<summary>Which NetSuite records can I export?</summary>

Any standard or custom record type your NetSuite account and Access Token role have access to — the Object list in Coupler.io loads live from your account's metadata catalog. Common examples include Invoice, Sales Order, Purchase Order, Vendor Bill, Journal Entry, Customer-related entities, and inventory items. See [Data Overview](#netsuite-data-overview) for a fuller breakdown by category.

</details>

<details>

<summary>Why doesn't Start date filter some of my objects?</summary>

Start date (and Window in days) only work for record types that expose a last-modified field — `lastModifiedDate` for standard records, `lastmodified` for most custom records. Record types without one of these fields don't support incremental filtering and are synced in full every run.

</details>

<details>

<summary>Is there a row limit on SuiteQL queries?</summary>

Yes. NetSuite's REST API caps SuiteQL results at 100,000 rows per query — a query that would return more fails instead of paginating past the limit. Narrow your `WHERE` clause or aggregate in the query itself to stay under it.

</details>

<details>

<summary>How do I connect to a sandbox instead of production?</summary>

Append your sandbox suffix to the Realm value, for example `1234567_SB1` instead of `1234567`. Everything else (Consumer Key, Consumer Secret, Token Key, Token Secret) is generated the same way, but you'll need a separate Integration record and Access Token created in the sandbox account.

</details>

<details>

<summary>Why am I getting a permission error on an object I know exists?</summary>

The Access Token is tied to a specific NetSuite role, and that role may not have view permission for the record type you're requesting — even if your own user account can see it in the NetSuite UI. Grant the role access to that record type, or create a token under a role that already has it.

</details>

<details>

<summary>What happens if I lose my Consumer Secret or Token Secret?</summary>

NetSuite only displays these values once, when they're generated — there's no way to retrieve them later. You'll need to create a new Access Token in NetSuite and reconnect the source in Coupler.io with the new credentials.

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.coupler.io/sources/category/sales/netsuite.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
