NetSuite REST Connector
API Documentation
Section titled “API Documentation”The NetSuite REST API Browser documents the record endpoints, and the SuiteQL reference documents the query language this connector uses to pull tabular data.
How Authentication Works
Section titled “How Authentication Works”The connector signs in with OAuth 2.0 client credentials using a PS256 JWT client assertion — there is no interactive login and no refresh token. You generate an RSA key pair, upload the public certificate to NetSuite, and give PlaidCloud the matching private key plus three ids. On each pull PlaidCloud builds and signs a short-lived assertion, exchanges it for an access token, and calls the REST API.
NetSuite-Side Setup
Section titled “NetSuite-Side Setup”Do this in NetSuite before creating the PlaidCloud connection. It requires an administrator and is on the critical path.
1. Enable the feature
Section titled “1. Enable the feature”Enable OAuth 2.0 and SuiteTalk (SOAP and REST Web Services) under Setup > Company > Enable Features > SuiteCloud.
2. Create the RSA key pair
Section titled “2. Create the RSA key pair”Generate a 2048-bit (or larger) RSA key pair with a PS256-capable digest. For example, with OpenSSL:
openssl genrsa -out plaidcloud_netsuite.pem 2048openssl rsa -in plaidcloud_netsuite.pem -pubout -out plaidcloud_netsuite_public.pemKeep the private key (plaidcloud_netsuite.pem) secret — it goes into PlaidCloud, never into NetSuite.
3. Upload the public certificate → certificate id
Section titled “3. Upload the public certificate → certificate id”Under Setup > Integration > OAuth 2.0 Client Credentials (M2M) Setup, map the public certificate to an integration, an entity, and a role. NetSuite returns a certificate id for the uploaded public key — this is the JWT kid, and it is not a secret. Record it.
4. Create the integration record → client id
Section titled “4. Create the integration record → client id”Under Setup > Integration > Manage Integrations > New, create an integration with OAuth 2.0 enabled and the Client Credentials grant selected. NetSuite issues a client id (consumer key). Record it. There is no client secret in the client-credentials + assertion flow.
5. Role and permissions
Section titled “5. Role and permissions”Assign the role used in the M2M mapping a set of permissions that covers what you will read:
- REST Web Services (Setup) — required for any REST call.
- SuiteAnalytics Workbook — required if your SuiteQL touches analytics/workbook data.
- Log in using OAuth 2.0 Access Tokens — required for the token exchange.
- Record-level view permissions on every record type your queries read (transactions, accounts, entities, and so on).
6. Account id
Section titled “6. Account id”Find your account id under Setup > Company > Company Information (the Account ID field). It drives the API host:
| Environment | Account id form | API host |
|---|---|---|
| Production | 1234567 |
1234567.suitetalk.api.netsuite.com |
| Sandbox | 1234567_SB1 |
1234567-sb1.suitetalk.api.netsuite.com |
PlaidCloud derives the host from the account id automatically (lowercasing and turning _ into -). Enter the account id exactly as NetSuite shows it, including the _SB1 suffix for a sandbox.
Configuration
Section titled “Configuration”Create the connection with the NetSuite connection type (not the generic REST type — only the NetSuite kind derives the host and injects the SuiteQL paging behavior). These fields appear on the form:
Identification
Section titled “Identification”| Field | Type | Description |
|---|---|---|
| Name | Text | Display name for this connection. |
| Alias | Text (multi-line) | Optional alias or notes about the connection. |
| Is active | Toggle | Whether the connection is enabled. Disable to pause without deleting. |
| Db read only | Toggle | Restrict the connection to read-only operations. |
| Access type | Select | Read-only, write-only, or read-write access level for this connection. |
NetSuite Credentials
Section titled “NetSuite Credentials”| Field | Type | Description |
|---|---|---|
| Oauth2 client id | Text | The client id from the integration record (step 4). |
| Netsuite certificate id | Text | The certificate id (JWT kid) returned when you uploaded the public certificate (step 3). Not a secret. |
| Netsuite account id | Text | The account id (step 6), for example 1234567 or 1234567_SB1. |
| Netsuite private certificate | Text (PEM) | The private key (step 2), pasted as a full multi-line PEM block. Stored encrypted and never returned in cleartext. |
Pulling Data with SuiteQL
Section titled “Pulling Data with SuiteQL”NetSuite’s record API only returns {id, links} per row, so PlaidCloud pulls tabular data with SuiteQL through the REST Request step. Configure the step against the NetSuite connection:
- Method —
POST - Endpoint —
/services/rest/query/v1/suiteql(the literal path; the host comes from the connection) - Body — the query as JSON:
{"q": "SELECT ... FROM ... ORDER BY internalid"}
Don’t Hand-Configure Paging or Headers
Section titled “Don’t Hand-Configure Paging or Headers”For a NetSuite connection the step auto-injects the SuiteQL specifics:
Prefer: transientandContent-Type: application/jsonheaders.- Offset pagination against the response’s
items/hasMorefields, at the service-fixed page size.
Leave the Pagination & Parsing controls and these headers alone — the connection sets them. Set only your Endpoint, Body, and the columns (below).
Type the Amount and Date Columns
Section titled “Type the Amount and Date Columns”SuiteQL returns every value as a JSON string ("1234.56", "2026-01-15", "T"). Define the output columns manually with their real types — Currency/Decimal for amounts, Date/Datetime for dates, Boolean for "T"/"F" flags — and PlaidCloud coerces the strings into typed columns on the way into the table. Empty strings map to null. (Automatic schema guessing does not apply the connection’s service config, so it can’t do this for you — define the columns yourself.)
Known Limitations
Section titled “Known Limitations”| Limitation | What it means |
|---|---|
| Manual columns required | Schema auto-guess doesn’t apply the NetSuite service config, so define amount/date/boolean columns and their types by hand. |
| Paging is service-fixed | The pagination mode, paths, and page size are set by the connection and are not adjustable on the step. |
| Full-table replace only | Every pull re-extracts the whole result — there is no incremental/delta path. A scheduled pull re-reads the entire table each run, so keep your WHERE clause to the slice you need. |
| Multi-currency / subsidiary | On transaction/transactionline, amount is in the transaction’s own currency. A naive cross-subsidiary SUM(amount) is consolidation-wrong — select consolidated or exchange-rate-converted fields when totaling across subsidiaries. |
| Response envelope | The exact response envelope and the accepted scope/role are confirmed at live cutover; the connector is built to NetSuite’s documented shape. |
Example Queries
Section titled “Example Queries”Financial — GL transaction lines for a period, typed and ordered:
SELECT tl.transaction AS transaction_id, t.trandate AS tran_date, a.acctnumber AS account_number, tl.subsidiary AS subsidiary_id, tl.foreignamount AS amountFROM transactionline tlJOIN transaction t ON t.id = tl.transactionJOIN account a ON a.id = tl.expenseaccountWHERE t.trandate BETWEEN TO_DATE('2026-01-01', 'YYYY-MM-DD') AND TO_DATE('2026-01-31', 'YYYY-MM-DD')ORDER BY tl.transaction, tl.idOperational — open sales orders by customer:
SELECT so.tranid AS order_number, so.entity AS customer_id, so.trandate AS order_date, so.status AS order_statusFROM transaction soWHERE so.type = 'SalesOrd' AND so.status = 'SalesOrd:B'ORDER BY so.id