> ## Documentation Index
> Fetch the complete documentation index at: https://docs.asteragents.com/llms.txt
> Use this file to discover all available pages before exploring further.

# NetSuite

> Connect Oracle NetSuite (SuiteTalk) to your Agents to read and write financial and operational data

## Overview

The [NetSuite](https://www.netsuite.com/) integration connects your agents to your NetSuite account over **SuiteTalk REST** using **Token-Based Authentication (TBA / OAuth 1.0a)**. Agents can run **SuiteQL** reporting queries (joins, aggregates, GL detail) and read records through the REST record API — customers, invoices, sales orders, vendors, the chart of accounts, and any other record the connected role can see. With the gated write tool enabled, agents can also create, update, and delete records.

Whether a given agent can write is a per-agent tool-selection decision — attach only the read tools for a read-only deployment. The **role you connect is the real permission boundary**: a View-only role simply cannot write, no matter which tools are attached.

<Note>
  **Multi-instance.** One Aster organization can hold several NetSuite accounts (e.g. two subsidiaries on separate instances). Connect each one under its own label; tools accept an optional `instance` parameter and default to the org's default instance when omitted.
</Note>

## Prerequisites

* A NetSuite account with the **REST Web Services**, **Token-Based Authentication**, and **SuiteAnalytics Workbook** features enabled
* A NetSuite **admin** to create the integration record, role, and token (steps below)
* An Aster **admin** to connect the integration (the connection is shared org-wide)

## Setup Guide

The one-time NetSuite-side setup is what makes or breaks the connection. Follow the steps in order — in particular, **create the access token last**, after the role's permissions are final.

<Steps>
  <Step title="Enable the required features (NetSuite admin)">
    **Setup → Company → Enable Features**:

    * **SuiteCloud** subtab → check **REST Web Services** and **Token-Based Authentication**.
    * **Analytics** subtab → check **SuiteAnalytics Workbook**.

    <Warning>
      **SuiteAnalytics Workbook is not optional.** Its permission gates the *entire* REST API for a custom role — not just SuiteQL. Without it, every SuiteQL query and every REST record call returns `400 — Your current role does not have permission to perform this action`, even when REST Web Services is already granted. The permission also won't appear in the role editor until this feature is enabled.
    </Warning>
  </Step>

  <Step title="Create an integration record (NetSuite admin)">
    **Setup → Integration → Manage Integrations → New**. Name it (e.g. "Aster Agents Integration"), check **Token-Based Authentication**, and leave the OAuth 2.0 boxes unchecked. On save, NetSuite shows the **Consumer Key** and **Consumer Secret** **once** — copy them now; they cannot be retrieved later.
  </Step>

  <Step title="Create a dedicated role (NetSuite admin)">
    **Setup → Users/Roles → Manage Roles → New**. Grant these permissions:

    | Subtab               | Permission                                                                                  | Level                     |
    | -------------------- | ------------------------------------------------------------------------------------------- | ------------------------- |
    | Setup                | **Log in using Access Tokens**                                                              | Full                      |
    | Setup                | **REST Web Services**                                                                       | Full                      |
    | Reports              | **SuiteAnalytics Workbook**                                                                 | Edit                      |
    | Lists / Transactions | Each record the agent must read (Subsidiary, Customers, Accounts, the transaction types, …) | View (or Full for writes) |

    On OneWorld accounts, set **Subsidiary Restrictions → All** (or all subsidiaries the agent must see). A single-subsidiary role silently returns partial data with no error. Assign the role to a dedicated integration user (**Setup → Users/Roles → Manage Users**).
  </Step>

  <Step title="Create an access token — LAST (NetSuite admin)">
    **Setup → Users/Roles → Access Tokens → New**. Select the integration, the user, and the role, then save. NetSuite shows the **Token ID** and **Token Secret** **once** — copy them now.

    <Warning>
      **Mint the token after the role's permissions are final.** A token created before you finish granting permissions may not pick up later changes — you'll keep seeing "does not have permission" until you issue a fresh token. If in doubt, delete the token and create a new one.
    </Warning>
  </Step>

  <Step title="Find your Account ID (NetSuite admin)">
    **Setup → Company → Company Information → Account ID** (e.g. `1234567`, or `1234567_SB1` for a sandbox). Send Aster the **five values** over a secure channel (never email): Account ID, Consumer Key, Consumer Secret, Token ID, Token Secret.
  </Step>

  <Step title="Connect NetSuite in Aster Agents (Aster admin)">
    Navigate to **Control Hub → Integrations**, locate the **NetSuite** card, click **Connect**, give the instance a **label**, and enter the five values. Aster validates them live (a benign SuiteQL call) and confirms the connection. To add a second NetSuite account, connect again with a different label.
  </Step>

  <Step title="Add tools to your agent (Aster admin)">
    Edit your agent and enable the NetSuite tools it needs — **NetSuite Query** for reporting, plus **Get Record** / **List Records** for record reads, and **Manage Records** only if the agent should write.
  </Step>
</Steps>

## Available Tools

* **NetSuite Query** (`netsuite_query`) — Runs a **SuiteQL** `SELECT` (joins, aggregates, filters) — the primary reporting/KPI workhorse. Read-only by construction; non-`SELECT` statements are rejected. Auto-paginates up to a row cap and **spills large result sets to a CSV attachment** while truncating the inline payload to a token budget.
* **NetSuite Get Record** (`netsuite_get_record`) — Fetches a single record by type and internal id, optionally expanding sub-resources.
* **NetSuite List Records** (`netsuite_list_records`) — Lists/filters a record type via the REST record API, with paging and an optional `q` filter.
* **NetSuite Manage Records** (`netsuite_manage_records`) — **Gated write.** Creates, updates, or deletes records. Attach only to agents that should write; a View-only role safely rejects writes with a 403.

<Note>
  **SuiteQL is the reliable way to filter.** For anything beyond a simple list, prefer `netsuite_query` with a `WHERE` clause — it's more expressive (joins, aggregates) and avoids the encoding quirks of REST query-string filters.
</Note>

## Example Prompts

Once connected, agents can answer questions like:

* "What was total revenue by month for the last quarter, from the GL?" (SuiteQL aggregate)
* "Pull all open invoices over \$10,000 with their due dates." (the full set spills to a CSV the agent can process in Python)
* "Show me sales order SO12345 and its line items."
* "Which vendors did we add this year?"
* *(with the write tool)* "Create a customer record for Acme Corp in the East subsidiary."

## Notes & Limitations

* **Full CRUD, gated by role and tools** — reads and writes are both supported; the connected role's permissions and the tools you attach determine what an agent can actually do.
* **Permissions follow the connected role** — agents only see records the integration role can see. Scope that role to least privilege.
* **SuiteQL page size** — NetSuite caps SuiteQL at 1,000 rows per page; the tool auto-paginates to reach larger totals and spills big pulls to CSV.
* **OneWorld** — set the role's Subsidiary Restrictions to **All** (or every relevant subsidiary), or reads silently return partial data.
* **Account-wide concurrency** — NetSuite rate limits (429) are shared across all of the account's integrations, tier-dependent. Prefer narrow filters over bulk pulls.
* **Sandbox vs. production** — the REST host is derived from the Account ID (`1234567_SB1` → `1234567-sb1.suitetalk.api.netsuite.com`); a sandbox refresh may require re-issuing credentials.

## Security Considerations

* **Org-level connection** — one admin connects once for the whole organization. The Consumer Secret and Token Secret are stored server-side and redacted when the connection is read back in the UI.
* **The role is the boundary** — deploy read-only by connecting a View-only role and not attaching the write tool; a read-only role rejects any write with a 403.
* **Use a dedicated integration user and role** with least privilege, so access can be audited and revoked independently of any person.
* **Grant the NetSuite tools only to agents that need them**, and the write tool only where writes are intended.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Every call returns &#x22;role does not have permission&#x22; (400)">
    * The token authenticated (you got a `400`, not a `401`), but the **role** lacks access. The usual culprit is the missing **SuiteAnalytics Workbook** permission (Reports subtab) — it gates all REST, not just SuiteQL — and its feature must be enabled first.
    * Confirm the role also has **REST Web Services** and **Log in using Access Tokens**, plus a **View** permission on each record type queried.
    * If you added permissions *after* creating the token, **issue a new token** — an existing token may not pick up the new permissions.
  </Accordion>

  <Accordion title="&#x22;Invalid login attempt&#x22; (401) on setup">
    * A `401` is a signature/credential problem. Re-check all five values for stray spaces, and confirm the Account ID matches Company Information exactly (including any `_SB1` sandbox suffix).
    * NetSuite occasionally returns a transient `401` on an otherwise-valid request, especially in the first minutes after a token is created — retry.
  </Accordion>

  <Accordion title="Reads return fewer rows than expected">
    * On OneWorld, the role's **Subsidiary Restrictions** are probably not set to **All** — a subsidiary-scoped role returns partial data with no error.
  </Accordion>
</AccordionGroup>

## Related Tools

* [Run Code](/tools/execute_python) — process large NetSuite result sets (the CSV spillover attachment) with pandas.
