Chapter 10.1

Integration Strategy

Plan your integration architecture: point-to-point vs. middleware, iPaaS options, patterns, and error handling strategies.

Integration Architecture Overview

Every NetSuite implementation involves integrations—whether connecting to e-commerce platforms, CRM systems, banks, or third-party applications. A well-planned integration strategy prevents data silos, reduces manual work, and ensures system reliability.

INTEGRATION ARCHITECTURE PATTERNS
═══════════════════════════════════════════════════════════════

POINT-TO-POINT
───────────────────────────────────────────────────────────────
  ┌─────────┐         ┌─────────┐
  │ System  │────────►│NetSuite │
  │    A    │◄────────│         │
  └─────────┘         └─────────┘
       │                   │
       │                   │
       ▼                   ▼
  ┌─────────┐         ┌─────────┐
  │ System  │────────►│ System  │
  │    B    │         │    C    │
  └─────────┘         └─────────┘

  Pros: Simple, direct, lower initial cost
  Cons: Spaghetti architecture, hard to maintain at scale

HUB AND SPOKE (iPaaS/Middleware)
───────────────────────────────────────────────────────────────
  ┌─────────┐     ┌─────────┐     ┌─────────┐
  │ System  │     │ System  │     │ System  │
  │    A    │     │    B    │     │    C    │
  └────┬────┘     └────┬────┘     └────┬────┘
       │              │              │
       └──────────────┼──────────────┘
                      │
                      ▼
              ┌───────────────┐
              │   iPaaS/      │
              │   Middleware  │
              │   (Celigo,    │
              │   Boomi, etc.)│
              └───────┬───────┘
                      │
                      ▼
              ┌───────────────┐
              │   NetSuite    │
              └───────────────┘

  Pros: Centralized monitoring, reusable connectors, scalable
  Cons: Higher cost, additional system to manage
                        

Integration Method Comparison

Method Use Case Volume Complexity
CSV Import Batch data loads, migrations Low-Medium Low
SuiteTalk SOAP Legacy systems, complex operations Medium-High High
SuiteTalk REST Modern integrations, mobile apps Medium-High Medium
RESTlets Custom endpoints, complex logic Any Medium-High
iPaaS (Celigo, etc.) Multiple systems, complex flows Any Medium
SuiteAnalytics Connect BI tools, reporting extracts Read-only Low-Medium

Integration Patterns

Real-Time vs. Batch

Pattern When to Use Examples
Real-Time (Synchronous) Immediate response required Price checks, inventory availability
Near Real-Time (Async) Quick updates, no immediate response Order creation, customer updates
Batch (Scheduled) High volume, non-time-sensitive Daily inventory sync, GL exports
Event-Driven Triggered by specific actions Order shipped → update e-commerce

Data Flow Patterns

COMMON DATA FLOW PATTERNS
═══════════════════════════════════════════════════════════════

MASTER DATA SYNC (Bidirectional)
───────────────────────────────────────────────────────────────
  E-Commerce ◄────► Customers ◄────► NetSuite
                    Products

  Challenge: Conflict resolution (which system wins?)
  Solution: Define system of record per entity type

ONE-WAY PUSH
───────────────────────────────────────────────────────────────
  E-Commerce ─────► Orders ─────► NetSuite

  Simple, clear ownership, no conflict resolution needed

PULL/POLLING
───────────────────────────────────────────────────────────────
  NetSuite ◄───── Polling ◄───── External System
  (status)        (every 5 min)

  External system requests updates on schedule

EVENT-DRIVEN (Webhook)
───────────────────────────────────────────────────────────────
  NetSuite ─────► Webhook ─────► External System
  (on save)       (immediate)

  NetSuite pushes immediately when event occurs
                        

Authentication Methods

Method Description Recommendation
Token-Based Authentication (TBA) Consumer/Token key pairs Preferred for server-to-server
OAuth 2.0 Standard OAuth flow Preferred for user-facing apps
User Credentials Email/Password Deprecated—avoid

Error Handling Strategy

ERROR HANDLING FRAMEWORK
═══════════════════════════════════════════════════════════════

ERROR CATEGORIES
───────────────────────────────────────────────────────────────
1. TRANSIENT ERRORS (retry)
   - Network timeouts
   - Rate limit exceeded
   - Temporary service unavailability
   → Strategy: Exponential backoff retry

2. DATA ERRORS (fix and retry)
   - Validation failures
   - Missing required fields
   - Invalid references
   → Strategy: Log, alert, queue for review

3. SYSTEM ERRORS (escalate)
   - Authentication failures
   - Permission denied
   - API changes
   → Strategy: Alert immediately, stop processing

RETRY PATTERN
───────────────────────────────────────────────────────────────
Attempt 1: Immediate
Attempt 2: Wait 1 second
Attempt 3: Wait 5 seconds
Attempt 4: Wait 30 seconds
Attempt 5: Wait 2 minutes
→ After 5 failures: Move to dead letter queue

MONITORING REQUIREMENTS
───────────────────────────────────────────────────────────────
• Success/failure counts by integration
• Average processing time
• Queue depth (pending records)
• Error rate trending
• Alerts for threshold breaches
                        

iPaaS Comparison

Platform NetSuite Focus Strengths
Celigo High (NetSuite partner) Pre-built connectors, integrator.io
Dell Boomi Medium Enterprise scale, broad connector library
Workato Medium User-friendly, strong automation
MuleSoft Medium Enterprise APIs, Salesforce integration
Tray.io Low-Medium Flexible workflows, developer-friendly
Consultant Insight

Start simple. Point-to-point integrations are fine for 2-3 connections. Only move to iPaaS when you have 4+ integrations or need advanced features like data transformation, error handling, and monitoring. The iPaaS monthly cost often exceeds the development savings unless you truly need the capability.

Integration Planning Checklist

Inventory all systems requiring integration
Define data ownership (system of record per entity)
Map data fields between systems
Determine real-time vs. batch requirements
Select integration method per connection
Design error handling and alerting
Plan authentication and security
Estimate governance unit consumption
Chapter 10.2

SuiteTalk SOAP

SOAP web services for NetSuite integration: authentication, operations, and best practices.

SuiteTalk SOAP Overview

SuiteTalk SOAP is NetSuite's original web services API. While the REST API is now preferred for new integrations, SOAP remains important for legacy systems and complex operations not yet available in REST.

Feature SOAP REST
Protocol XML-based SOAP JSON over HTTP
Maturity 20+ years, fully featured Newer, growing coverage
Learning Curve Steeper (WSDL, namespaces) Lower (standard REST)
Custom Records Full support Full support
Saved Searches Full support Via SuiteQL
Asynchronous Yes (native) Limited

WSDL and Endpoints

SUITETALK SOAP ENDPOINTS
═══════════════════════════════════════════════════════════════

WSDL URL:
https://<ACCOUNT_ID>.suitetalk.api.netsuite.com/wsdl/v2024_2_0/netsuite.wsdl

ENDPOINT URL:
https://<ACCOUNT_ID>.suitetalk.api.netsuite.com/services/NetSuitePort_2024_2

ACCOUNT ID FORMAT:
───────────────────────────────────────────────────────────────
Production:  TSTDRV1234567
Sandbox:     TSTDRV1234567_SB1
Development: TSTDRV1234567_DEV

FINDING YOUR ACCOUNT ID:
Setup → Company → Company Information → Account ID
                        

Authentication Setup

Token-Based Authentication (TBA)

TBA SETUP PROCESS
═══════════════════════════════════════════════════════════════

1. CREATE INTEGRATION RECORD
   Setup → Integration → Manage Integrations → New
   ├── Name: "My Integration"
   ├── State: Enabled
   ├── Token-Based Authentication: Checked
   └── → Save → Note Consumer Key & Secret

2. CREATE ACCESS TOKEN
   Setup → Users/Roles → Access Tokens → New
   ├── Application: "My Integration"
   ├── User: Integration user
   ├── Role: Integration role
   └── → Save → Note Token ID & Secret

SOAP HEADER WITH TBA:
───────────────────────────────────────────────────────────────
<tokenPassport>
  <account>TSTDRV1234567</account>
  <consumerKey>consumer_key_here</consumerKey>
  <token>token_id_here</token>
  <nonce>random_string</nonce>
  <timestamp>unix_timestamp</timestamp>
  <signature algorithm="HMAC-SHA256">signature</signature>
</tokenPassport>
                        

Common Operations

Operation Description Use Case
get Retrieve single record by ID Fetch customer details
getList Retrieve multiple records by IDs Batch fetch orders
add Create new record Create sales order
update Modify existing record Update customer address
upsert Add or update based on external ID Sync from external system
delete Remove record Delete draft order
search Query records with criteria Find open invoices
asyncAddList Bulk add asynchronously Import 10,000 records

Search Operations

SOAP SEARCH EXAMPLE
═══════════════════════════════════════════════════════════════

<search>
  <searchRecord xsi:type="TransactionSearchBasic">
    <type operator="anyOf">
      <searchValue>_salesOrder</searchValue>
    </type>
    <status operator="anyOf">
      <searchValue>_salesOrderPendingFulfillment</searchValue>
    </status>
    <tranDate operator="within">
      <searchValue>2025-01-01T00:00:00</searchValue>
      <searchValue2>2025-12-31T23:59:59</searchValue2>
    </tranDate>
  </searchRecord>
</search>

SEARCH TYPES:
───────────────────────────────────────────────────────────────
Basic:     Simple criteria on main record
Joined:    Include related record criteria
Advanced:  Use saved search definition
                        

Governance and Limits

SOAP Concurrency Limits
  • Concurrent requests: Based on SuiteCloud license tier
  • Records per request: 200 for add/update, 1000 for search results
  • Request timeout: 15 minutes
  • Rate limiting: Requests may be throttled under load

Best Practices

SOAP Integration Best Practices
  • Use external IDs: Enable upsert operations and avoid duplicate lookups
  • Batch operations: Use addList/updateList instead of individual calls
  • Async for large volumes: Use asyncAddList for bulk operations
  • Handle pagination: Search results may require multiple pages
  • Cache WSDL locally: Avoid re-downloading on every request
  • Implement retry logic: Handle transient failures gracefully
Consultant Insight

SOAP is verbose but powerful. For new integrations, prefer REST unless you need features only available in SOAP (like certain async operations or complex saved search execution). When working with legacy SOAP integrations, prioritize moving to TBA authentication if still using user credentials—it's more secure and doesn't count against concurrent user limits.

Chapter 10.3

SuiteTalk REST

Modern REST API for NetSuite: record operations, SuiteQL, OAuth 2.0, and integration patterns.

REST API Overview

SuiteTalk REST provides a modern, JSON-based API for NetSuite integration. It follows REST conventions and is easier to use than SOAP for most common operations.

API Endpoints

REST API BASE URLS
═══════════════════════════════════════════════════════════════

RECORD API:
https://<ACCOUNT_ID>.suitetalk.api.netsuite.com/services/rest/record/v1

QUERY API (SuiteQL):
https://<ACCOUNT_ID>.suitetalk.api.netsuite.com/services/rest/query/v1

METADATA:
https://<ACCOUNT_ID>.suitetalk.api.netsuite.com/services/rest/record/v1/metadata-catalog

EXAMPLES:
───────────────────────────────────────────────────────────────
GET customer:     GET /customer/123
Create customer:  POST /customer
Update customer:  PATCH /customer/123
Delete customer:  DELETE /customer/123
List customers:   GET /customer
                        

Authentication

OAuth 2.0 Setup

OAUTH 2.0 FLOW
═══════════════════════════════════════════════════════════════

1. AUTHORIZATION REQUEST
───────────────────────────────────────────────────────────────
GET https://<ACCOUNT_ID>.app.netsuite.com/app/login/oauth2/authorize.nl
    ?response_type=code
    &client_id=<CLIENT_ID>
    &redirect_uri=<REDIRECT_URI>
    &scope=rest_webservices
    &state=<STATE>

2. TOKEN EXCHANGE
───────────────────────────────────────────────────────────────
POST https://<ACCOUNT_ID>.suitetalk.api.netsuite.com/services/rest/auth/oauth2/v1/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=<AUTH_CODE>
&redirect_uri=<REDIRECT_URI>
&client_id=<CLIENT_ID>
&client_secret=<CLIENT_SECRET>

3. API REQUEST WITH TOKEN
───────────────────────────────────────────────────────────────
GET /services/rest/record/v1/customer/123
Authorization: Bearer <ACCESS_TOKEN>
                        

Token-Based Authentication

TBA HEADER FORMAT
═══════════════════════════════════════════════════════════════

Authorization: OAuth
  realm="ACCOUNT_ID",
  oauth_consumer_key="consumer_key",
  oauth_token="token_id",
  oauth_signature_method="HMAC-SHA256",
  oauth_timestamp="unix_timestamp",
  oauth_nonce="random_string",
  oauth_version="1.0",
  oauth_signature="base64_encoded_signature"
                        

Record Operations

REST RECORD OPERATIONS
═══════════════════════════════════════════════════════════════

CREATE CUSTOMER (POST)
───────────────────────────────────────────────────────────────
POST /services/rest/record/v1/customer
Content-Type: application/json

{
  "companyName": "Acme Corporation",
  "email": "contact@acme.com",
  "subsidiary": {"id": "1"},
  "custentity_external_id": "ACME-001"
}

Response: 201 Created
{
  "id": "12345",
  "links": [...]
}

UPDATE CUSTOMER (PATCH)
───────────────────────────────────────────────────────────────
PATCH /services/rest/record/v1/customer/12345
Content-Type: application/json

{
  "phone": "555-1234",
  "custentity_credit_limit": 50000
}

Response: 204 No Content

GET WITH SUBLISTS
───────────────────────────────────────────────────────────────
GET /services/rest/record/v1/salesOrder/67890?expandSubResources=true

Returns order with line items, addresses, etc.
                        

SuiteQL Queries

SUITEQL VIA REST API
═══════════════════════════════════════════════════════════════

POST /services/rest/query/v1/suiteql
Content-Type: application/json
Prefer: transient

{
  "q": "SELECT id, companyname, email
        FROM customer
        WHERE isinactive = 'F'
        AND datecreated > '2025-01-01'
        ORDER BY companyname"
}

RESPONSE:
{
  "links": [...],
  "count": 150,
  "hasMore": true,
  "offset": 0,
  "totalResults": 1523,
  "items": [
    {"id": "123", "companyname": "Acme Corp", "email": "..."},
    {"id": "124", "companyname": "Beta Inc", "email": "..."},
    ...
  ]
}

PAGINATION:
───────────────────────────────────────────────────────────────
Add to query: FETCH NEXT 1000 ROWS ONLY
Add header: Prefer: respond-async
Next page: Follow "next" link in response
                        

Sublist Operations

WORKING WITH SUBLISTS
═══════════════════════════════════════════════════════════════

ADD LINE TO SALES ORDER
───────────────────────────────────────────────────────────────
POST /services/rest/record/v1/salesOrder/67890/item
Content-Type: application/json

{
  "item": {"id": "100"},
  "quantity": 5,
  "rate": 99.99
}

UPDATE LINE
───────────────────────────────────────────────────────────────
PATCH /services/rest/record/v1/salesOrder/67890/item/1
Content-Type: application/json

{
  "quantity": 10
}

DELETE LINE
───────────────────────────────────────────────────────────────
DELETE /services/rest/record/v1/salesOrder/67890/item/1

GET ALL LINES
───────────────────────────────────────────────────────────────
GET /services/rest/record/v1/salesOrder/67890/item
                        

Error Handling

REST API ERROR RESPONSES
═══════════════════════════════════════════════════════════════

400 BAD REQUEST
───────────────────────────────────────────────────────────────
{
  "type": "https://www.netsuite.com/problems/validation",
  "title": "Invalid field value",
  "status": 400,
  "o:errorDetails": [
    {
      "detail": "Invalid reference key '999' for field 'subsidiary'",
      "o:errorCode": "INVALID_KEY_OR_REF"
    }
  ]
}

429 TOO MANY REQUESTS
───────────────────────────────────────────────────────────────
{
  "type": "https://www.netsuite.com/problems/rate-limiting",
  "title": "Rate limit exceeded",
  "status": 429,
  "o:errorDetails": [
    {
      "detail": "Request rate limit exceeded. Retry after 60 seconds."
    }
  ]
}
                        
REST API Best Practices
  • Use SuiteQL for queries: More flexible than record filtering
  • Expand sublists selectively: Only request what you need
  • Handle pagination: Use offset/limit for large result sets
  • Check for async: Large operations may return 202 Accepted
  • Use external IDs: Enable idempotent operations
Consultant Insight

REST is the future of NetSuite integrations. Start new projects with REST unless you specifically need SOAP features. The REST API's JSON format is easier to debug, and OAuth 2.0 is standard across modern applications. SuiteQL via REST gives you SQL-like flexibility that's often easier than building complex search criteria.

Chapter 10.4

RESTlets

Build custom REST endpoints in NetSuite for complex integration logic and specialized operations.

RESTlet Overview

RESTlets are custom SuiteScript endpoints that respond to HTTP requests. They enable you to build custom APIs within NetSuite, perfect for complex business logic that standard APIs don't cover.

Use RESTlets When Use Standard API When
Complex business logic required Simple CRUD operations
Multiple records in single transaction Single record operations
Custom data transformation Standard field mapping
Aggregate data from multiple sources Single record type queries
Custom authentication/validation Standard authentication

RESTlet Structure

RESTLET SCRIPT TEMPLATE (SuiteScript 2.1)
═══════════════════════════════════════════════════════════════

/**
 * @NApiVersion 2.1
 * @NScriptType Restlet
 */
define(['N/record', 'N/search', 'N/log'], (record, search, log) => {

    /**
     * GET request handler
     * @param {Object} requestParams - URL parameters
     * @returns {Object} Response data
     */
    const get = (requestParams) => {
        try {
            const customerId = requestParams.customerId;

            if (!customerId) {
                return { error: 'customerId is required' };
            }

            // Load customer record
            const customer = record.load({
                type: record.Type.CUSTOMER,
                id: customerId
            });

            return {
                id: customer.id,
                name: customer.getValue('companyname'),
                email: customer.getValue('email'),
                balance: customer.getValue('balance')
            };

        } catch (e) {
            log.error('GET Error', e.message);
            return { error: e.message };
        }
    };

    /**
     * POST request handler
     * @param {Object} requestBody - Request body (JSON parsed)
     * @returns {Object} Response data
     */
    const post = (requestBody) => {
        try {
            const { customerName, email, subsidiary } = requestBody;

            // Validation
            if (!customerName) {
                return { error: 'customerName is required' };
            }

            // Create customer
            const customer = record.create({
                type: record.Type.CUSTOMER
            });

            customer.setValue('companyname', customerName);
            customer.setValue('email', email);
            customer.setValue('subsidiary', subsidiary || 1);

            const customerId = customer.save();

            return {
                success: true,
                customerId: customerId
            };

        } catch (e) {
            log.error('POST Error', e.message);
            return { error: e.message };
        }
    };

    /**
     * PUT request handler
     */
    const put = (requestBody) => {
        // Update logic
    };

    /**
     * DELETE request handler
     */
    const doDelete = (requestParams) => {
        // Delete logic
    };

    return { get, post, put, delete: doDelete };
});
                        

Deployment

RESTLET DEPLOYMENT
═══════════════════════════════════════════════════════════════

1. CREATE SCRIPT RECORD
   Customization → Scripting → Scripts → New
   ├── Type: RESTlet
   ├── Script File: restlet_customer_api.js
   └── Functions: get, post, put, delete

2. CREATE SCRIPT DEPLOYMENT
   ├── Status: Released
   ├── Log Level: Debug (for testing)
   ├── Execute As Role: Integration role
   ├── Audience: Roles that should access
   └── URL: Generated automatically

RESTLET URL FORMAT:
───────────────────────────────────────────────────────────────
https://<ACCOUNT_ID>.restlets.api.netsuite.com/app/site/hosting/restlet.nl
    ?script=<SCRIPT_ID>
    &deploy=<DEPLOY_ID>
    &customerId=123

Or use external URL (if configured)
                        

Authentication

RESTLET AUTHENTICATION
═══════════════════════════════════════════════════════════════

OPTION 1: TOKEN-BASED AUTHENTICATION (TBA)
───────────────────────────────────────────────────────────────
Same OAuth 1.0 header as SuiteTalk REST:

Authorization: OAuth
  realm="ACCOUNT_ID",
  oauth_consumer_key="...",
  oauth_token="...",
  oauth_signature_method="HMAC-SHA256",
  oauth_timestamp="...",
  oauth_nonce="...",
  oauth_version="1.0",
  oauth_signature="..."

OPTION 2: NLAUTH (Not Recommended)
───────────────────────────────────────────────────────────────
Authorization: NLAuth
  nlauth_account=ACCOUNT_ID,
  nlauth_email=user@domain.com,
  nlauth_signature=password,
  nlauth_role=3

Note: NLAuth uses user credentials—prefer TBA for security
                        

Advanced Patterns

RESTLET DESIGN PATTERNS
═══════════════════════════════════════════════════════════════

PATTERN 1: COMPOSITE OPERATIONS
───────────────────────────────────────────────────────────────
// Single API call creates order with items and customer

const post = (requestBody) => {
    const { customer, orderLines, shipAddress } = requestBody;

    // Create or find customer
    let customerId = findCustomerByEmail(customer.email);
    if (!customerId) {
        customerId = createCustomer(customer);
    }

    // Create sales order
    const order = record.create({ type: 'salesorder' });
    order.setValue('entity', customerId);

    // Add lines
    orderLines.forEach((line, index) => {
        order.setSublistValue({
            sublistId: 'item',
            fieldId: 'item',
            line: index,
            value: line.itemId
        });
        order.setSublistValue({
            sublistId: 'item',
            fieldId: 'quantity',
            line: index,
            value: line.quantity
        });
    });

    const orderId = order.save();
    return { success: true, orderId };
};

PATTERN 2: SEARCH AGGREGATION
───────────────────────────────────────────────────────────────
// Combine data from multiple searches into single response

const get = (requestParams) => {
    const customerId = requestParams.customerId;

    return {
        customer: getCustomerDetails(customerId),
        openOrders: getOpenOrders(customerId),
        recentInvoices: getRecentInvoices(customerId),
        creditLimit: getCreditInfo(customerId)
    };
};

PATTERN 3: WEBHOOK RECEIVER
───────────────────────────────────────────────────────────────
// Receive webhooks from external systems

const post = (requestBody) => {
    log.audit('Webhook Received', JSON.stringify(requestBody));

    // Validate webhook signature
    if (!validateSignature(requestBody)) {
        return { error: 'Invalid signature', status: 401 };
    }

    // Queue for processing (avoid timeout)
    const queueRecord = record.create({ type: 'customrecord_webhook_queue' });
    queueRecord.setValue('custrecord_payload', JSON.stringify(requestBody));
    queueRecord.save();

    return { success: true, message: 'Queued for processing' };
};
                        

Governance Considerations

RESTlet Governance
  • Governance units: RESTlets have standard SuiteScript limits (10,000 units)
  • Timeout: 5 minutes for synchronous requests
  • Concurrency: Based on account's SuiteCloud license
  • Response size: 10MB maximum

For long-running operations, queue work and use scheduled scripts to process.

Consultant Insight

RESTlets are your escape hatch when standard APIs don't fit. Common use cases: e-commerce order import with custom logic, inventory availability checks across locations, composite operations that would require multiple API calls. Always add logging and error handling—debugging RESTlets in production without good logs is painful.

Chapter 10.5

CSV Import

Batch data loading via CSV: templates, field mapping, scheduling, and best practices.

CSV Import Overview

CSV Import is NetSuite's built-in tool for batch data loading. It's often the simplest integration method for periodic data transfers that don't require real-time processing.

Import Types

Import Type Description Common Use
Add Create new records only Initial data load
Update Modify existing records Mass updates
Add/Update Upsert based on key field Ongoing sync

Import Process Flow

1
Select Type
2
Upload CSV
3
Map Fields
4
Preview
5
Import

CSV Formatting Rules

CSV FORMATTING REQUIREMENTS
═══════════════════════════════════════════════════════════════

FILE FORMAT
───────────────────────────────────────────────────────────────
• Encoding: UTF-8 (preferred) or Windows-1252
• Delimiter: Comma (,)
• Text qualifier: Double quotes (")
• Line ending: CRLF or LF
• First row: Column headers (required)

FIELD FORMATS
───────────────────────────────────────────────────────────────
Dates:        MM/DD/YYYY or YYYY-MM-DD
Booleans:     T/F, True/False, Yes/No, 1/0
Numbers:      No thousands separator, period decimal
Currency:     No currency symbol, no thousands separator
Multi-select: Values separated by pipe (|)
References:   Internal ID or External ID

EXAMPLE CSV
───────────────────────────────────────────────────────────────
External ID,Company Name,Email,Subsidiary,Is Inactive
CUST-001,Acme Corporation,sales@acme.com,1,F
CUST-002,Beta Industries,info@beta.com,1,F
CUST-003,"Gamma, LLC",contact@gamma.com,2,F

Note: "Gamma, LLC" quoted because contains comma
                        

Field Mapping

FIELD MAPPING STRATEGIES
═══════════════════════════════════════════════════════════════

REFERENCE FIELDS
───────────────────────────────────────────────────────────────
For fields like Customer, Item, Class, etc.:

Option 1: Internal ID
  Column: Customer
  Value:  12345

Option 2: Name/Display Value
  Column: Customer
  Value:  Acme Corporation

Option 3: External ID (recommended)
  Column: Customer : External ID
  Value:  CUST-001

SUBLIST IMPORT (Two-File Method)
───────────────────────────────────────────────────────────────
File 1: Header (Sales Order)
  External ID,Customer,Order Date,Subsidiary
  SO-001,CUST-001,12/01/2025,1
  SO-002,CUST-002,12/02/2025,1

File 2: Lines (Sales Order Items)
  External ID,Item,Quantity,Rate
  SO-001,ITEM-001,10,99.99
  SO-001,ITEM-002,5,149.99
  SO-002,ITEM-001,20,99.99

Import header first, then lines (linked by External ID)

SINGLE-FILE SUBLIST IMPORT
───────────────────────────────────────────────────────────────
Denormalized format (repeat header data):
  External ID,Customer,Item,Quantity,Rate
  SO-001,CUST-001,ITEM-001,10,99.99
  SO-001,CUST-001,ITEM-002,5,149.99
  SO-002,CUST-002,ITEM-001,20,99.99
                        

Saved Import Maps

Save field mappings for repeated imports:

Setting Description
Import Map Name Descriptive name for this mapping
Record Type Customer, Item, Sales Order, etc.
Field Mappings CSV column → NetSuite field
Import Options Add, Update, or Add/Update
Data Handling On error: skip record or abort

Scheduled Imports

AUTOMATED CSV IMPORT
═══════════════════════════════════════════════════════════════

OPTION 1: SCHEDULED IMPORT (Built-in)
───────────────────────────────────────────────────────────────
1. Save import map
2. Go to: Setup → Import/Export → Scheduled CSV Imports
3. Configure:
   - Saved import to use
   - File source: File Cabinet folder
   - Schedule: Daily, Weekly, etc.
   - Email notification on completion

OPTION 2: SUITESCRIPT + N/TASK MODULE
───────────────────────────────────────────────────────────────
const task = require('N/task');

const importTask = task.create({
    taskType: task.TaskType.CSV_IMPORT,
    mappingId: 'custimport_customer_sync',
    importFile: 'SuiteScripts/imports/customers.csv'
});

const taskId = importTask.submit();

OPTION 3: EXTERNAL AUTOMATION
───────────────────────────────────────────────────────────────
1. External system uploads CSV to File Cabinet via REST/SOAP
2. Scheduled script triggers import
3. Results logged/emailed
                        

Error Handling

Common Import Errors
  • Invalid reference: Referenced record doesn't exist—check ID or name
  • Required field missing: Mandatory field not mapped or empty
  • Duplicate key: External ID already exists (for Add imports)
  • Invalid date format: Use MM/DD/YYYY or configure format
  • Permission denied: Import user lacks record access
CSV Import Best Practices
  • Always preview: Review first 10 rows before full import
  • Use external IDs: Enable reliable updates without internal IDs
  • Test in sandbox: Validate import maps before production
  • Limit batch size: 25,000 records max per import recommended
  • Log imports: Keep import files and results for audit
Consultant Insight

CSV Import is underrated. For daily/weekly batch updates from systems that can export CSV (most can), it's often simpler than building API integrations. Use scheduled imports with File Cabinet as the drop zone—external systems FTP files there, NetSuite picks them up automatically. Just ensure good monitoring so you catch failures.

Chapter 10.6

NetSuite AI Connector (MCP)

AI integration capabilities using the Model Context Protocol (MCP) standard.

New in 2025.2: MCP Standard Tools

NetSuite now supports the Model Context Protocol (MCP), enabling AI systems to interact with NetSuite data and operations through standardized interfaces.

MCP Overview

The Model Context Protocol (MCP) is an open standard for connecting AI systems to external data sources and tools. NetSuite's AI Connector implements MCP, allowing AI assistants and agents to query data, create records, and execute business processes.

MCP ARCHITECTURE
═══════════════════════════════════════════════════════════════

┌─────────────────────────────────────────────────────────────┐
│                    AI APPLICATION                            │
│  ┌─────────────────────────────────────────────────────────┐│
│  │  AI Model (Claude, GPT, etc.)                           ││
│  │  "What were last month's top 10 customers by revenue?"  ││
│  └───────────────────────────┬─────────────────────────────┘│
└──────────────────────────────┼──────────────────────────────┘
                               │
                               ▼
┌─────────────────────────────────────────────────────────────┐
│                    MCP CLIENT                                │
│  Translates natural language to MCP tool calls              │
└──────────────────────────────┬──────────────────────────────┘
                               │
                               ▼
┌─────────────────────────────────────────────────────────────┐
│              NETSUITE MCP SERVER                             │
│  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐           │
│  │   Query     │ │   Record    │ │  Workflow   │           │
│  │   Tools     │ │   Tools     │ │   Tools     │           │
│  └─────────────┘ └─────────────┘ └─────────────┘           │
└──────────────────────────────┬──────────────────────────────┘
                               │
                               ▼
┌─────────────────────────────────────────────────────────────┐
│                    NETSUITE                                  │
│  Records, Transactions, Searches, Workflows                  │
└─────────────────────────────────────────────────────────────┘
                        

Available MCP Tools

Tool Category Capabilities Example Use
Query Tools Run saved searches, SuiteQL queries "Show me overdue invoices"
Record Tools Create, read, update records "Create a customer for Acme Corp"
Workflow Tools Trigger workflows, check status "Approve pending purchase orders"
Report Tools Generate financial reports "Generate income statement for Q4"
Analytics Tools Access dashboard KPIs "What's our current DSO?"

Prerequisites

  • NetSuite account: Administrator-level access to configure features, integrations, and roles
  • Paid AI accounts: ChatGPT Plus/Enterprise or Claude Pro/Enterprise
  • Integration record: Must be created and configured in NetSuite
  • Enabled features in NetSuite: Server SuiteScript, OAuth 2.0, REST Web Services

NetSuite Configuration

STEP 1: ENABLE FEATURES
═══════════════════════════════════════════════════════════════
Path: Setup → Company → Enable Features → SuiteCloud subtab

Enable the following features:
✓ Server SuiteScript
✓ OAuth 2.0
✓ REST Web Services


STEP 2: INSTALL SUITEAPP
═══════════════════════════════════════════════════════════════
Location: SuiteApp section (or Customization → SuiteBundler → Search & Install)

Action: Search for "MCP" and install "MCP Standard Tools SuiteApp"


STEP 3: CONFIGURE ROLE
═══════════════════════════════════════════════════════════════
Path: Setup → Users/Roles → Manage Roles

Approach: Clone an existing role (e.g., AP Clerk) or create a new
          least-privilege role

Required Permissions:
├── MCP server connection: Full
└── Login using OAuth 2.0 access token: Full

⚠️  IMPORTANT: Administrator role CANNOT be used for AI connections
                        

Integration Record Setup

CREATE INTEGRATION RECORD
═══════════════════════════════════════════════════════════════
Path: Setup → Integrations → Manage Integrations → New

Fields to Configure:
├── Name: "AI Connector – ChatGPT" (or "AI Connector – Claude")
├── State: Enabled
├── Authentication: OAuth 2.0
└── Redirect URI: Callback URL from AI client

Result: NetSuite generates Client ID and Client Secret
        (Store these securely - Client Secret shown only once!)
                        

OAuth 2.0 Authorization Flow

Step Action Details
1. Authorization Request AI client redirects user User logs into NetSuite and grants consent
2. Authorization Code NetSuite returns code Code sent to Redirect URI
3. Token Exchange AI client requests tokens Sends code, Client ID, Client Secret to token endpoint
4. Tokens Issued NetSuite returns tokens Access Token (API calls), Refresh Token (renewal)
OAUTH 2.0 ENDPOINTS
═══════════════════════════════════════════════════════════════
Replace <ACCOUNT_ID> with your NetSuite account ID

Authorization:
https://<ACCOUNT_ID>.suitetalk.api.netsuite.com/services/rest/auth/oauth2/v1/authorize

Token:
https://<ACCOUNT_ID>.suitetalk.api.netsuite.com/services/rest/auth/oauth2/v1/token

Revoke (to invalidate tokens):
https://<ACCOUNT_ID>.suitetalk.api.netsuite.com/services/rest/auth/oauth2/v1/revoke
                        

Connecting ChatGPT to NetSuite

CHATGPT CONNECTOR SETUP
═══════════════════════════════════════════════════════════════

1. OPEN SETTINGS
   Path: Settings → Apps and Connectors

2. ENABLE DEVELOPER MODE
   Navigate to Advanced Settings and enable Developer Mode if required

3. CREATE CONNECTOR
   Action: Create Connector
   Name: "NetSuite Connector"

4. ENTER DETAILS
   Account ID: Found at Setup → Company → Company Information
   MCP Server URL: Use format from NetSuite AI Connector docs,
                   inserting your Account ID

5. AUTHENTICATE
   Method: OAuth 2.0
   Role: Select your custom MCP role (NOT Administrator)

6. TEST CONNECTION
   Example prompt: "Show me the most recently created vendor"
   Validate results directly in NetSuite
                        

Connecting Claude to NetSuite

CLAUDE CONNECTOR SETUP
═══════════════════════════════════════════════════════════════

1. OPEN SETTINGS
   Path: Settings → Connectors

2. CHOOSE CONNECTOR TYPE
   Option A: Web → NetSuite AI Connector (pre-built)
   Option B: Custom connector (recommended for more control)

3. ENTER DETAILS
   MCP Server URL: Same format as ChatGPT, with your Account ID

4. AUTHENTICATE
   Method: OAuth 2.0
   Role: Select your custom MCP role (NOT Administrator)

5. TEST CONNECTION
   Try: "What customers were created this week?"
   Verify results match NetSuite data
                        

Use Cases

AI-Powered Business Operations
  • Customer Service: "Look up order SO-12345 status"
  • Sales Support: "What's the pricing history for this customer?"
  • Finance: "Generate AR aging report and email CFO"
  • Operations: "What items are below reorder point?"
  • Executive: "Compare this month's revenue to last year"

Testing & Troubleshooting

Issue Cause Solution
Role not visible during auth Missing permissions or assignment Verify MCP permission, role assignment, then re-login
Permission errors on create/update Role has view-only access Grant Create/Edit permissions for target record types
Missing data in results Subsidiary restrictions Verify role has access to all required subsidiaries
Token expired errors Access token lifecycle Implement refresh token logic; re-authenticate if needed
Administrator role rejected Security restriction Create dedicated least-privilege role for AI connections
Data Privacy Controls

Review AI application settings to opt out of training data usage if required by your organization's data policies. Both ChatGPT and Claude offer enterprise plans with data privacy guarantees.

Security Considerations

AI Integration Security Best Practices
  • Least-privilege roles: Create dedicated roles with minimum necessary permissions
  • Role-based access: AI executes with assigned role permissions only
  • Subsidiary scope: Restrict data visibility to assigned subsidiaries
  • Audit logging: All AI operations logged for compliance review
  • Operation approval: Configure which operations need human approval
  • Rate limiting: Prevent excessive AI-initiated operations
  • Data filtering: Restrict sensitive fields from AI access
  • Token security: Store Client Secret securely; implement token refresh

Community Tools & References

In addition to the official SuiteApp, these resources can help with MCP implementations:

Consultant Insight

The MCP integration is transformative for organizations using AI assistants. Start with read-only access (queries and reports) to build trust, then gradually enable write operations with appropriate approval workflows. The biggest value is in repetitive lookup tasks—"What's the status of X?" questions that currently require manual NetSuite navigation. Note that open-source tools like OpenSuiteMCP should be thoroughly vetted before production use.

Chapter 10.7

Common Integrations

Integration patterns for Salesforce, Shopify, Amazon, banking, and payment processors.

E-Commerce Integrations

Shopify Integration

SHOPIFY ↔ NETSUITE DATA FLOWS
═══════════════════════════════════════════════════════════════

PRODUCTS (NetSuite → Shopify)
───────────────────────────────────────────────────────────────
NetSuite Item ─────► Shopify Product
├── Item ID        → SKU
├── Display Name   → Title
├── Description    → Description
├── Base Price     → Price
├── Images         → Images
└── Quantity       → Inventory Level

ORDERS (Shopify → NetSuite)
───────────────────────────────────────────────────────────────
Shopify Order ─────► NetSuite Sales Order
├── Order Number   → External ID
├── Customer Email → Customer (lookup/create)
├── Line Items     → Item lines
├── Shipping       → Shipping item
├── Discounts      → Discount items
└── Payment        → Payment record (if paid)

FULFILLMENT (NetSuite → Shopify)
───────────────────────────────────────────────────────────────
NetSuite Fulfillment ─────► Shopify Fulfillment
├── Tracking Number → Tracking
├── Carrier        → Company
└── Ship Date      → Created At

INVENTORY (NetSuite → Shopify)
───────────────────────────────────────────────────────────────
Frequency: Real-time or every 15 minutes
NetSuite Available Qty → Shopify Inventory Level
                        

Amazon Integration

Data Type Direction Frequency
Product Listings NetSuite → Amazon On change
Inventory NetSuite → Amazon Every 15 min
Pricing NetSuite → Amazon On change
Orders Amazon → NetSuite Every 5 min
Fulfillment NetSuite → Amazon On ship
Returns Amazon → NetSuite Daily

CRM Integrations

Salesforce Integration

SALESFORCE ↔ NETSUITE DATA FLOWS
═══════════════════════════════════════════════════════════════

ACCOUNTS/CUSTOMERS (Bidirectional)
───────────────────────────────────────────────────────────────
Decision: Which system is master?

Option A: Salesforce Master (Common)
  SF Account ─────► NS Customer
  New customers created in Salesforce, synced to NetSuite

Option B: NetSuite Master
  NS Customer ─────► SF Account
  New customers created in NetSuite, synced to Salesforce

Option C: Bidirectional
  Requires conflict resolution rules
  Usually based on "last modified wins" or designated fields

OPPORTUNITIES → SALES ORDERS
───────────────────────────────────────────────────────────────
SF Opportunity (Closed Won) ─────► NS Sales Order
├── Account           → Customer
├── Products          → Items (requires item mapping)
├── Amount            → Total
└── Opportunity ID    → External ID

INVOICES/PAYMENTS → SALESFORCE
───────────────────────────────────────────────────────────────
NS Invoice ─────► SF Invoice Object (custom)
NS Payment ─────► SF Payment Object (custom)
                        

Banking Integrations

BANK INTEGRATION PATTERNS
═══════════════════════════════════════════════════════════════

BANK FEEDS (Transactions Import)
───────────────────────────────────────────────────────────────
Bank ─────► NetSuite Bank Data
├── Method: Direct bank connection or file import
├── Frequency: Daily or multiple times per day
└── Matching: Auto-match to existing transactions

Supported formats: OFX, QFX, CSV, BAI2

POSITIVE PAY (Fraud Prevention)
───────────────────────────────────────────────────────────────
NetSuite Checks ─────► Bank Positive Pay File
├── Check number
├── Amount
├── Payee name
└── Date

Bank verifies checks against file before clearing

ACH/EFT PAYMENTS
───────────────────────────────────────────────────────────────
NetSuite Vendor Payments ─────► NACHA File ─────► Bank
├── Generate NACHA format file
├── Upload to bank portal (manual or automated)
└── Bank processes ACH transactions

LOCKBOX (Customer Payments)
───────────────────────────────────────────────────────────────
Bank Lockbox ─────► Payment File ─────► NetSuite
├── Bank processes customer checks
├── Generates payment data file
├── NetSuite imports and matches to invoices
                        

Payment Processor Integrations

Processor Integration Method Features
Stripe SuiteApp or RESTlet Cards, ACH, subscriptions
PayPal Native integration PayPal payments, e-commerce
Authorize.net SuitePayments Credit card processing
Square iPaaS or custom POS, online payments
Bill.com SuiteApp AP automation, vendor payments

Industry-Specific Integrations

Manufacturing
  • EDI: SPS Commerce, TrueCommerce for customer/vendor EDI
  • PLM: Product Lifecycle Management systems
  • MES: Manufacturing Execution Systems for shop floor
  • Quality: QMS systems for quality tracking
Retail
  • POS: Square, Lightspeed, Shopify POS
  • Marketplaces: Amazon, eBay, Walmart, Etsy
  • Shipping: ShipStation, ShipBob, EasyPost
  • Returns: Loop, Returnly, Happy Returns
Software/SaaS
  • Billing: Stripe Billing, Chargebee, Zuora
  • CRM: Salesforce, HubSpot
  • Support: Zendesk, Intercom, Freshdesk
  • Usage: Product analytics for usage-based billing
Consultant Insight

Before building custom integrations, check the SuiteApp marketplace. Common integrations like Shopify, Salesforce, and major shipping carriers have established connectors that are faster to implement than custom builds. Custom development makes sense when you have unique requirements or need tight control over the integration logic.

Chapter 10.8

E-Invoicing

Electronic invoicing standards, compliance requirements, and NetSuite configuration.

New in 2025.2: North America E-Invoicing

NetSuite now supports e-invoicing for North American markets, expanding beyond existing European and Latin American coverage.

E-Invoicing Overview

E-invoicing (electronic invoicing) is the exchange of invoice documents between trading partners in structured electronic format. Many countries now mandate e-invoicing for B2B and B2G transactions.

Global E-Invoicing Standards

Region Standard Status
European Union Peppol, FatturaPA (Italy) Mandatory (varies by country)
Mexico CFDI 4.0 Mandatory
Brazil NF-e, NFS-e Mandatory
India GST E-Invoice Mandatory above threshold
Saudi Arabia ZATCA E-Invoicing Mandatory
North America Various (emerging) Voluntary/Growing

E-Invoicing Architecture

E-INVOICING FLOW
═══════════════════════════════════════════════════════════════

OUTBOUND (Sending Invoices)
───────────────────────────────────────────────────────────────
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│  NetSuite   │     │  E-Invoice  │     │  Trading    │
│  Invoice    │────►│  Provider   │────►│  Partner    │
└─────────────┘     └─────────────┘     └─────────────┘
      │                   │                   │
      ▼                   ▼                   ▼
   Generate           Convert to           Receive &
   XML/JSON           standard format      validate

INBOUND (Receiving Invoices)
───────────────────────────────────────────────────────────────
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│  Vendor     │────►│  E-Invoice  │────►│  NetSuite   │
│             │     │  Provider   │     │  Vendor Bill│
└─────────────┘     └─────────────┘     └─────────────┘
      │                   │                   │
      ▼                   ▼                   ▼
   Send e-invoice     Validate &          Create bill
                      transform           for approval
                        

NetSuite Configuration

Enable E-Invoicing

  • Enable Electronic Invoicing
  • Configure country-specific settings

E-Invoice Provider Setup

E-INVOICE PROVIDER CONFIGURATION
═══════════════════════════════════════════════════════════════

Setup → Company → Electronic Invoicing → Provider Setup

PROVIDER OPTIONS:
───────────────────────────────────────────────────────────────
• NetSuite E-Invoicing (native)
• Avalara (for supported countries)
• Third-party providers (via integration)

CONFIGURATION:
───────────────────────────────────────────────────────────────
1. Select provider
2. Enter API credentials
3. Map NetSuite fields to e-invoice format
4. Configure document types (invoice, credit memo, etc.)
5. Set up customer/vendor identifiers (VAT, tax ID)
6. Test with sample transactions
                        

Country-Specific Requirements

European Union (Peppol)
PEPPOL REQUIREMENTS
───────────────────────────────────────────────────────────────
Required Fields:
• Seller: Name, Address, VAT ID, Peppol ID
• Buyer: Name, Address, VAT ID, Peppol ID
• Invoice: Number, Date, Due Date, Currency
• Lines: Description, Quantity, Unit, Price, VAT
• Totals: Net, VAT, Gross

Peppol ID Format: Country Code : Identifier
Example: DE:991234567890
                            
Mexico (CFDI 4.0)
CFDI 4.0 REQUIREMENTS
───────────────────────────────────────────────────────────────
• RFC (tax ID) for buyer and seller
• Uso de CFDI (invoice purpose code)
• Forma de Pago (payment method)
• Método de Pago (payment timing)
• Producto/Servicio codes (SAT catalog)
• Unidad de Medida codes
• Digital stamp from PAC (authorized provider)
• Timbrado within 72 hours of transaction
                            

Implementation Checklist

Identify applicable e-invoicing mandates
Select e-invoice provider/approach
Configure customer tax identifiers
Map NetSuite fields to e-invoice format
Configure product/service codes
Test with sandbox transactions
Validate with trading partners
Train users on e-invoice process
Establish error handling procedures
Consultant Insight

E-invoicing compliance is increasingly mandatory globally. Start by understanding which countries require it and by when. For multi-country operations, consider a provider that covers all your jurisdictions to avoid managing multiple integrations. The data quality requirements are strict—clean up customer tax IDs and addresses before going live, as e-invoice rejections create operational headaches.