Deploy your first customer portal →
SuitePortal/NetSuite ORM

Connector API

Low-level API reference for the NetSuite HTTP connector.

The suiteportal package exposes the low-level HTTP client and SuiteQL executor. You typically don't need these directly — createClient wraps them — but they're available for advanced use cases.

NetSuiteClient

The core HTTP client with automatic authentication, retries, and rate limiting. Supports both TBA (OAuth 1.0a) and OAuth 2.0 M2M.

import { NetSuiteClient } from 'suiteportal';

const client = new NetSuiteClient({
  authType: 'tba',
  accountId: '1234567_SB1',
  consumerKey: '...',
  consumerSecret: '...',
  tokenId: '...',
  tokenSecret: '...',
});
import { NetSuiteClient } from 'suiteportal';

const client = new NetSuiteClient({
  authType: 'oauth2',
  accountId: '1234567_SB1',
  clientId: '...',
  certificateId: '...',
  privateKey: fs.readFileSync('./private.pem', 'utf8'),
  // algorithm: 'ES256',  // default
  // scopes: ['restlets', 'rest_webservices'],  // default
});

With OAuth 2.0, the client automatically handles token exchange and refresh. Tokens are cached in memory and refreshed 5 minutes before expiry.

Constructor Options

All options shared between both auth types:

OptionDefaultDescription
timeout30000Request timeout in milliseconds
concurrency5Max concurrent requests
maxRetries3Retry attempts for retryable failures
requestsPerSecond(disabled)Proactive rate limit (token bucket)
burstSizerequestsPerSecondToken bucket burst capacity
baseUrl(derived)Override the API base URL (testing)

request

Make an authenticated request to any NetSuite REST endpoint:

const response = await client.request<ResponseType>({
  method: 'GET',
  path: '/services/rest/record/v1/customer/123',
});
// response.status, response.headers, response.data

destroy

Release resources (cancel pending token bucket timers):

client.destroy();

executeSuiteQL

Execute a SuiteQL query and return the first page:

import { executeSuiteQL } from 'suiteportal';

const result = await executeSuiteQL(client, 'SELECT id FROM customer', {
  limit: 100,  // default: 1000
  offset: 0,   // default: 0
});

result.items;        // SuiteQLRow[]
result.hasMore;      // boolean
result.totalResults; // number | undefined

executeSuiteQLPaginated

Auto-paginate through all results:

import { executeSuiteQLPaginated } from 'suiteportal';

const allRows = await executeSuiteQLPaginated(client, 'SELECT id FROM customer', {
  pageSize: 1000,   // default: 1000
  maxRows: 10000,   // default: unlimited
});

REST Record Operations

CRUD helpers for the REST Record API (/services/rest/record/v1):

import {
  createRecord,
  updateRecord,
  deleteRecord,
  getRecord,
} from 'suiteportal';

createRecord

const record = await createRecord(client, 'customer', {
  companyname: 'Acme Corp',
  email: 'hello@acme.com',
});
// POST /services/rest/record/v1/customer
// Returns the created record

updateRecord

const record = await updateRecord(client, 'customer', 123, {
  email: 'new@acme.com',
});
// PATCH /services/rest/record/v1/customer/123
// Returns the updated record

deleteRecord

await deleteRecord(client, 'customer', 123);
// DELETE /services/rest/record/v1/customer/123
// Returns void (204 No Content)

getRecord

const record = await getRecord(client, 'customer', 123);
// GET /services/rest/record/v1/customer/123
// Returns the full record

Error Types

All errors extend NetSuiteError:

import { NetSuiteError, AuthError, RateLimitError, TimeoutError } from 'suiteportal';

try {
  await client.request({ ... });
} catch (error) {
  if (error instanceof AuthError) {
    // 401/403 — bad credentials
  } else if (error instanceof RateLimitError) {
    // 429 — too many requests
    error.retryAfterMs; // suggested wait time
  } else if (error instanceof TimeoutError) {
    // Request timed out
  }
}

With OAuth 2.0 M2M, a 401 response automatically clears the cached token. The next request will trigger a fresh token exchange.

Config Helpers

import { deriveBaseUrl, getRealm, isOAuth2Config } from 'suiteportal';

deriveBaseUrl('1234567_SB1');
// → 'https://1234567-sb1.suitetalk.api.netsuite.com'

getRealm('1234567_SB1');
// → '1234567_SB1'

isOAuth2Config({ authType: 'oauth2', ... });
// → true

On this page