---
title: NetSuite
slug: netsuite
docTags: 
createdAt: 2026-09-15T18:42:22.327Z
---

NetSuite is a cloud ERP that manages finance, inventory, and orders for most enterprise brands. Chord ingests NetSuite's general ledger, transaction, and item master data so you can model per-order COGS, landed costs, inventory movements, and revenue attribution alongside the rest of your stack. Chord reads exclusively via SuiteQL, an SQL interface to NetSuite's data, using Token-Based Authentication (OAuth 1.0a).

## What Chord ingests from NetSuite

Chord pulls 21 datasets from your NetSuite account. Each dataset becomes its own table in your Chord Snowflake schema.

- **Account.** Chart of accounts: account number, name, type, balance, and hierarchy.
- **Account type.** Account classification lookup (e.g. Income, Expense, Bank, Fixed Asset).
- **Accounting period.** Fiscal calendar: period name, start/end date, closed flag per accounting book.
- **Classification.** Classification segment lookup (aka segments or classes in older NetSuite configs).
- **Customer.** Customer records: name, identifier, email, billing/shipping address, tax ID, stage.
- **Department.** Department segment lookup.
- **Employee.** Employee records (full sync per run, useful for payroll joins).
- **Entity.** Unified bridge spanning customer, vendor, and employee records: name, type, primary address.
- **Item.** Item catalog: SKU, description, item type, cost, pricing, costing method, custom fields.
- **Subsidiary.** Legal entity / subsidiary lookup (critical for OneWorld accounts).
- **Transaction status.** Transaction-status lookup, scoped per transaction type (e.g. Pending, Billed, Closed).
- **Vendor.** Vendor records: name, identifier, email, address, tax ID, payment terms.
- **Aggregate item location.** On-hand and available quantity per item and location. Aggregates multiple quantity types (committed, on order, backordered). Use this for inventory snapshot reporting.
- **Inventory item locations.** Per-location quantity detail: on hand, committed, backordered, on order. Use this for supply-chain planning.
- **Assembly item locations.** Per-location quantity detail for assembly (parent) items.
- **Item location availability.** Available quantity per item and location.
- **Transaction.** Transaction header spanning all types: sales orders, invoices, cash sales, credit memos, vendor bills, purchase orders, item fulfillments, payment applications, and inventory adjustments. Merged incrementally on last modified date. Includes custom fields.
- **Transaction line.** Transaction line detail: quantity, rate, amount, GL account mappings, custom fields. One row per line per transaction. Merged incrementally (cursor is the parent transaction's last modified date).
- **Transaction accounting line.** General ledger posting detail per transaction line and accounting book: account, debit/credit amounts, posting date. This is the source for realized COGS and revenue attribution. Merged incrementally.
- **Transaction shipping address.** Shipping address snapshot per transaction. Merged incrementally.
- **Transaction billing address.** Billing address snapshot per transaction. Merged incrementally.

## Generate a NetSuite API credential set

You'll need five values from your NetSuite account: Account ID, Consumer Key, Consumer Secret, Token ID, and Token Secret. All five must be copied from NetSuite together at the time of creation or rotation. Chord uses them to sign OAuth 1.0a requests to the SuiteQL endpoint. Token-Based Authentication (TBA) is the only supported flow. OAuth 2.0 is not available.

:::hint{type="warning"}
**Heads up:** only NetSuite account administrators or users with the "Setup" permission for Integration and Access Tokens can create these credentials. If your role doesn't include it, ask a NetSuite admin to either generate the credential set for you or grant your user the required permissions first.
:::

**1. Enable required features in NetSuite.**

Log in to NetSuite as an administrator.

1. Go to **Setup → Company → Enable Features**.
2. Click the **SuiteCloud** tab.
3. In the **SuiteScript** section, check **Client and Server** (if not already enabled).
4. In the **Manage Authentication** section, check **Token-Based Authentication** (if not already enabled).
5. In the **SuiteTalk (Web Services)** section, check **REST Web Services** (if not already enabled).
6. Click **Save**.

**2. Create an integration record to get Consumer Key and Consumer Secret.**

1. Go to **Setup → Integration → Manage Integrations → New**.
2. Fill in Name: something like `Chord data sync`.
3. Check **Token-Based Authentication** (if not already checked).
4. Uncheck **Authorization Code Grant Credential Flow** (Chord signs requests directly and does not use callbacks).
5. Click **Save**.
6. On the confirmation page, you'll see **Consumer Key** and **Consumer Secret**. Copy both values immediately. They are shown only once.

**3. Create an access token to get Token ID and Token Secret.**

1. Go to **Setup → Users/Roles → Access Tokens → New**.
2. Select the Integration: pick the integration record you just created (e.g. `Chord data sync`).
3. Select the User: the integration user who will own this token (e.g. a dedicated service account).
4. Select the Role: the integration role you'll grant with the permissions below.
5. Click **Save**.
6. On the confirmation page, you'll see **Token ID** and **Token Secret**. Copy both values immediately. They are shown only once and cannot be revealed later.

**4. Grant required permissions to the integration role.**

1. Go to **Setup → Users/Roles → Manage Roles** and click the integration role you selected above.
2. Click the **Permissions** subtab.

Grant the following Setup permissions:

- **Log in using Access Tokens** → Full
- **REST Web Services** → Full

Grant the following Reports permission:

- **SuiteAnalytics Workbook** → Edit. This permission is critical for SuiteQL queries. REST Web Services alone is not sufficient.

Grant the following Lists permissions (View level):

- **Customers** → View
- **Items** → View
- **Vendors** → View
- **Subsidiaries** → View
- **Accounts** → View
- **Departments** → View
- **Classes** → View
- **Locations** → View
- **Accounting Periods** → View
- **Inventory** → View

Grant the following Transactions permissions (View level):

- **Sales Orders** → View
- **Invoices** → View
- **Cash Sales** → View
- **Credit Memos** → View
- **Customer Payments** → View
- **Item Fulfillments** → View
- **Vendor Bills** → View
- **Purchase Orders** → View
- **Item Receipts** → View
- **Adjust Inventory** → View

3. Click **Save**.

**5. For OneWorld accounts, ensure all-subsidiary access.**

If your NetSuite account uses multiple subsidiaries (OneWorld):

1. Go to **Setup → Users/Roles → Manage Roles** and click the integration role.
2. Under the **Subsidiary Restrictions** setting, choose **All** (or **Selected** with all target subsidiaries checked). If left at the default **User Subsidiary**, Chord will silently ingest only the integration user's assigned subsidiary and miss all others.
3. Go to **Setup → Users/Roles → Manage Users**, click the integration user, and confirm under **Subsidiary Restrictions** that they also have access to **All** target subsidiaries.
4. Click **Save**.

## Connect the credential set in Chord

1. Open Chord Hub and go to **Data Sources → Add Source**.
2. Pick **NetSuite** from the data source list.
3. Enter your Account ID in the **Account ID** field. Format: production = `1234567`, sandbox = `1234567_SB1` (underscore before the SB suffix, not hyphen).
4. Paste the Consumer Key you copied into the **Consumer Key** field.
5. Paste the Consumer Secret you copied into the **Consumer Secret** field.
6. Paste the Token ID you copied into the **Token ID** field.
7. Paste the Token Secret you copied into the **Token Secret** field.
8. Click **Save**. Chord will make a test SuiteQL query against your NetSuite account to confirm all five values are correct and the integration role has the required permissions. This validation happens immediately on save.
9. If validation passes, the first sync kicks off automatically. Subsequent syncs run on your tenant's standard ingestion schedule. If validation fails, you'll see an error message with details on what's missing or misconfigured (see troubleshooting below).

## Troubleshooting

**The credential validation failed with a 400 error. What does the error detail text say?**
NetSuite returns HTTP 400 with status `INVALID_PARAMETER` for both authentication failures and permission problems. The error message body contains a detail field that tells you which one. Look for one of these two messages:

- **"SuiteAnalytics Workbook feature has been disabled"** → The feature is turned off account-wide. Fix: Go to **Setup → Company → Enable Features**, click the **SuiteCloud** tab, and check **Analytics** in the SuiteAnalytics section. Save and retry the Chord validation.
- **"Your current role does not have permission to perform this action"** → The feature is on, but the integration role is missing the SuiteAnalytics Workbook permission. Fix: Go to **Setup → Users/Roles → Manage Roles**, click the integration role, click **Permissions**, find **Reports**, and grant **SuiteAnalytics Workbook → Edit**. Save and retry the Chord validation.

These two failures look identical from the HTTP status code alone, but the detail text tells you which one you're facing and where to fix it.

**The validation failed with&#x20;**`INVALID_LOGIN`**, but my credentials look right to me. What's the most likely cause?**
The most common cause (especially if this credential was working before) is that you rotated your access token or consumer credentials but didn't update all five fields in Chord at the same time. NetSuite returns `INVALID_LOGIN` whenever the signature doesn't match, whether the cause is a typo, a revoked token, or (most commonly) a partial update. The error text itself won't tell you which, so check for a partial update first. When you regenerate a token in NetSuite, you get new Token ID and Token Secret values. When you regenerate consumer credentials, you get new Consumer Key and Consumer Secret values. If you paste only some of the new values into Chord while others remain stale, the OAuth signature will fail. The signature requires all five pieces to match exactly as they stand together in NetSuite at that moment. Updating four fields and leaving one stale breaks the connection. Always copy all five values fresh from NetSuite (Account ID, Consumer Key, Consumer Secret, Token ID, Token Secret) and paste them all into Chord at once, then save. Chord validates all five together immediately on save.

**I copied the values but validation still fails. Should I check for hidden whitespace?**
Yes. Consumer Key, Consumer Secret, Token ID, and Token Secret are long strings that are easy to copy with leading or trailing whitespace, which breaks the signature. Paste each field into Chord, then manually check that there are no spaces at the very start or end of the value. NetSuite's credential display pages sometimes add whitespace when you select the text. Clear it before pasting. If you're still stuck, generate fresh credentials in NetSuite and retry. You may have copied partially or with an invisible character.

**Do NetSuite TBA tokens expire?**
No. Access tokens remain valid indefinitely unless you explicitly revoke or regenerate them in NetSuite. If a working credential suddenly fails, check that the token has not been revoked under **Setup → Users/Roles → Access Tokens**. Also check that the integration user and role have not been disabled. TBA tokens do not time out, but they break if the user account or the role is deactivated.

**How do I rotate the credential set?**

1. In NetSuite, regenerate the access token: go to **Setup → Users/Roles → Access Tokens**, click the token, and click **Regenerate Token**. This produces a new Token ID and Token Secret.
2. At the same time, go to **Setup → Integration → Manage Integrations**, click your integration record, and regenerate the Consumer Key and Consumer Secret: click **Regenerate Credentials**.
3. Copy all five values: Account ID (unchanged), plus the new Consumer Key, Consumer Secret, Token ID, and Token Secret.
4. In Chord, open the same NetSuite credential entry, paste all five values (replacing what's there), and click **Save**. Chord validates the new set immediately on save.
5. Once validation passes and the next sync runs cleanly, you can delete the old token and integration record in NetSuite.

**I'm only seeing data from one subsidiary but we have multiple. What's happening?**
This is a OneWorld scope issue. By default, the integration role's **Subsidiary Restrictions** are set to **User Subsidiary**, which silently filters all SuiteQL responses to only that subsidiary. NetSuite returns no error for out-of-scope rows. It just excludes them. Check the role and integration user's **Subsidiary Restrictions** (as described in step 5 of the credential setup above) and set them to **All** to access every subsidiary. Then kick off a new Chord sync.

***

**Need help?** If you hit a credential, permission, or connectivity issue you can't resolve, reach out to [help@chord.co](mailto\:help@chord.co) with the exact error message (or screenshot). We'll trace the request against your NetSuite account and tell you what's missing or misconfigured.
