Skip to main content

Oracle NetSuite

NetSuite is Oracle's cloud business management suite, covering ERP and financials, CRM, and ecommerce.

This connector reads NetSuite record types through SuiteTalk REST Web Services. It discovers streams at runtime from the account's record metadata catalog, so the streams you see depend on the account rather than on a fixed list.

Prerequisites​

  • An Oracle NetSuite account with administrator access, so you can enable features and create integrations, roles, and access tokens.
  • Token-based authentication credentials: realm (account ID), consumer key, consumer secret, token ID, and token secret.

The connector authenticates with token-based authentication (OAuth 1.0a, HMAC-SHA256). It doesn't support OAuth 2.0. Oracle has announced that as of NetSuite 2027.1 you can't create new token-based authentication integrations, although existing integrations keep working. See Preparing for Token-based Authentication (TBA) End of Support.

Setup guide​

Step 1: Create NetSuite account​

  1. Create account on Oracle NetSuite
  2. Confirm your Email

Step 2: Setup NetSuite account​

Step 2.1: Obtain Realm info​

  1. Login into your NetSuite account
  2. Go to Setup » Company » Company Information
  3. Copy your Account ID (Realm). It should look like 1234567 for the Production env. or 1234567_SB2 - for a Sandbox

Step 2.2: Enable features​

  1. Go to Setup » Company » Enable Features
  2. Click on SuiteCloud tab
  3. Scroll down to SuiteScript section
  4. Enable checkbox for CLIENT SUITESCRIPT and SERVER SUITESCRIPT
  5. Scroll down to Manage Authentication section
  6. Enable checkbox TOKEN-BASED AUTHENTICATION
  7. Scroll down to SuiteTalk (Web Services)
  8. Enable checkbox REST WEB SERVICES
  9. Save the changes

Step 2.3: Create Integration (obtain Consumer Key and Consumer Secret)​

  1. Go to Setup » Integration » Manage Integrations » New
  2. Fill the Name field (we recommend to put airbyte-rest-integration for a name)
  3. Make sure the State is enabled
  4. Enable checkbox Token-Based Authentication in Authentication section
  5. Save changes
  6. After that, Consumer Key and Consumer Secret will be showed once (copy them to the safe place)

Step 2.4: Setup Role​

  1. Go to Setup » Users/Roles » Manage Roles » New
  2. Fill the Name field (we recommend to put airbyte-integration-role for a name)
  3. Scroll down to Permissions tab
  4. Click on Setup and add both REST Web Services and Log in using Access Tokens. REST web services rejects every request from a role that lacks these two permissions, whatever else the role can read. See Prerequisites and Setup for REST Web Services.
  5. On the same Setup subtab, add the remaining dropdown entities with either full or view access level.
  6. Click on Transactions and add all the dropdown entities with either full or view access level.
  7. Click on Reports and add all the dropdown entities with either full or view access level.
  8. Click on Lists and add all the dropdown entities with either full or view access level.

The role decides which record types you can actually read, but it doesn't shape the stream list: a record type the role can't read still appears as a stream, and syncing it logs an INSUFFICIENT_PERMISSION error and returns no records. Revisit these permissions when you rename or customize a record type in NetSuite.

Step 2.5: Setup User​

  1. Go to Setup » Users/Roles » Manage Users
  2. In column Name click on the user’s name you want to give access to the airbyte-integration-role
  3. Then click on Edit button under the user’s name
  4. Scroll down to Access tab at the bottom
  5. Select from dropdown list the airbyte-integration-role role which you created in step 2.4
  6. Save changes

Step 2.6: Create Access Token for role​

  1. Go to Setup » Users/Roles » Access Tokens » New
  2. Select an Application Name
  3. Under User select the user you assigned the airbyte-integration-role in the step 2.4
  4. Inside Role select the one you gave to the user in the step 2.5
  5. Under Token Name you can give a descriptive name to the Token you are creating (we recommend to put airbyte-rest-integration-token for a name)
  6. Save changes
  7. After that, Token ID and Token Secret will be showed once (copy them to the safe place)

Step 2.7: Summary​

You have copied next parameters

  • Realm (Account ID)
  • Consumer Key
  • Consumer Secret
  • Token ID
  • Token Secret Also you have properly Configured Account with Correct Permissions and Access Token for User and Role you've created early.

Step 3: Set up the source connector in Airbyte​

  1. In the left navigation bar, click Sources. In the top-right corner, click + new source.
  2. On the source setup page, select NetSuite from the Source type dropdown and enter a name for this connector.
  3. Enter your Realm (Account Id), Consumer Key, Consumer Secret, Token Key (Token Id), and Token Secret.
  4. Enter a Start Date as YYYY-MM-DDTHH:mm:ssZ, for example 2017-01-25T00:00:00Z. Incremental streams read from this point on their first sync, plus a lookback of up to a day. See How incremental syncs work.
  5. Optionally set Object Types to the API names of the record types you want, such as customer or salesorder. Leave it empty to expose every record type in the account's metadata catalog.
  6. Optionally set Window in Days. The default is 30.
  7. Click Set up source.

Object Types​

When Object Types is empty, the connector lists the account's whole metadata catalog and fetches a schema for every record type in it. Large accounts can expose hundreds of record types, and each one costs a schema request during discovery. Naming the record types you actually need keeps setup and schema refreshes short.

Use the API name of the record type, in lowercase, as it appears in the REST API browser, not the label shown in the NetSuite UI. The connection test requests a single record of the first type you list, so a bad name there fails setup with an HTTP error. A bad name further down the list isn't tested: it produces a warning and no stream when schemas are fetched. Setup also fails with a Duplicate record type message if the same name appears twice in the list.

Window in Days​

Window in Days controls how many days of history each incremental request covers. The connector walks from the cursor date to today in windows of this size, so a smaller window means more requests, each returning fewer records. Use a positive number: nothing validates the field, and a value of zero or less leaves the window unable to advance. Lower it if a stream holds a lot of changes per day and requests time out or return too much data at once. NetSuite times out any request that runs longer than 15 minutes.

Supported sync modes​

The NetSuite source connector supports the following sync modes:

  • Full Refresh
  • Incremental

Supported streams​

The connector generates one stream per record type, so the stream list depends on your configuration rather than on a fixed catalog. Set Object Types and you get exactly the record types you named; leave it empty and the connector reads the account's whole metadata catalog. The token's role doesn't narrow the list either way, only what each stream can actually return. See Setup guide » Step 2.4 and Step 2.5.

Schemas come from the account's metadata catalog, which means custom fields and customized record types are included. Every field is typed as nullable because NetSuite schemas don't declare nullability. Occasionally the catalog returns a record type with no fields at all; the connector refetches that schema a few times, then logs a warning and leaves the stream out of the catalog.

Sync mode support is per stream and depends on the record type's own fields:

Record type hasCursor fieldSync modes
lastModifiedDatelastModifiedDateFull refresh, incremental
lastmodified (typical of custom records)lastmodifiedFull refresh, incremental
Neither fieldNoneFull refresh only

How incremental syncs work​

NetSuite can't sort records in a response, so the connector filters each request to a date range instead of paging through an ordered result set. Two consequences are worth knowing before you plan downstream pipelines:

  • Requests are day-granular, even though records aren't. NetSuite's record query filter accepts bare dates only, and it resolves them in the account's own time zone. To avoid missing records on accounts behind UTC, the connector opens each sync's first window 12 hours before the stored cursor and then truncates to a date. Expect a sync to re-request records it has already read near the cursor. Records older than the stored cursor timestamp are dropped before they're emitted, so the overlap doesn't duplicate data. The first sync of a stream has no cursor to compare against, so it emits everything the widened first window returns — which can include records changed up to a day before your Start Date.
  • The connector detects your account's date format. NetSuite expects date literals in the format the account prefers. The connector tries MM/DD/YYYY, YYYY-MM-DD, DD/MM/YYYY, and DD.MM.YYYY in that order, and reissues the same request under the next format when NetSuite rejects one. You don't need to configure this, but the accepted format isn't remembered between syncs, so every sync logs a warning for each format it has to discard.

Performance considerations​

The connector reads each record individually: it lists record IDs for a date window, then requests each record with expandSubResources=true to get its sublists. A sync therefore costs roughly one API call per record, plus one call per page of IDs. Streams with many records are slow for that reason, not because of rate limiting.

NetSuite governs REST concurrency at the account level, and that limit is shared with SOAP web services and RESTlets. Syncing several NetSuite streams or connections at once competes with your other integrations for the same threads. See Web Services and RESTlet Concurrency Governance.

Troubleshooting​

A record type is missing from the stream list​

A record type is left out of the catalog only when the metadata catalog returns no fields for it. The discovery log says schema is not available for that record type; retry discovery later.

If you set Object Types, only the record types you listed are considered, so remove the field or add the record type to it.

A stream syncs successfully but returns no records​

This is usually a permissions problem rather than an empty record type, because the stream list doesn't reflect what the role can read. Check the sync logs for the stream's name:

  • INSUFFICIENT_PERMISSION: the token's role lacks access to that record type. Add it under Setup » Users/Roles » Manage Roles.
  • USER_ERROR: NetSuite refused to load individual records. This usually means a workflow locks them; see Records locked by a workflow are skipped.

Records locked by a workflow are skipped​

A NetSuite workflow can include a Lock Record action. While a record sits in a workflow state with that action, NetSuite refuses to load it through web services and returns HTTP 400 with the error code USER_ERROR. The record still appears in the ID list, so the connector requests it and then has to skip it.

Starting in version 0.1.29, the connector counts these skipped records per stream:

  • When a stream skips at least one record, the sync logs a warning like Stream journalentry: 25 of 100 records skipped due to USER_ERROR (records locked by user-defined workflows) and continues, as long as no more than half of the records requested so far were skipped. The records that NetSuite did return are emitted normally.
  • When more than half of the records requested for a stream so far are skipped, the sync fails with Stream journalentry has incomplete data. Failing is deliberate: it stops a sync from reporting success while most of a stream's data is missing.

Earlier versions dropped these records without any message, so a stream could appear complete while being mostly empty.

To sync the locked records, change the workflow rather than the connector. Adjust the Lock Record action so it doesn't run for web services requests, for example by narrowing its execution context or condition, or move the records out of the locking state. After you change the workflow, run the sync again. If you can't change the workflow, set Object Types to an explicit list of the record types you want, leaving out the affected one. Don't just clear the field: an empty Object Types means every record type in the account, which brings the locked one back.

Setup fails right after you enter credentials​

The connection check reads a single record. With Object Types set, it reads the first record type in your list; otherwise it reads contact. A failure here usually means the role is missing the REST Web Services or Log in using Access Tokens permission, the realm doesn't match the account, or the token belongs to a different user or role than the one you granted access to.

Use the realm exactly as NetSuite shows it, for example 1234567 for production or 1234567_SB2 for a sandbox. Sandbox refreshes invalidate tokens, so create new ones after each refresh.

Incremental syncs re-read the same records​

This is expected. See How incremental syncs work.

IP allow list​

If you use Airbyte Cloud and your organization restricts access to specific IPs, add the Airbyte Cloud IP addresses to your allow list.

Reference​

Config fields reference

Field
Type
Property name
string
consumer_key
string
consumer_secret
string
realm
string
start_datetime
string
token_key
string
token_secret
array<string>
object_types
integer
window_in_days

Changelog​

Expand to review
VersionDatePull RequestSubject
0.1.292026-09-1679191Emit warning and fail sync when >50% of records are silently skipped due to NetSuite workflow locks (USER_ERROR)
0.1.282026-08-2079654Fix incremental sync permanently dropping records modified between the sync time and account-local midnight; retry a rejected date format on the same slice instead of skipping it
0.1.272025-10-1467787Update dependencies
0.1.262025-10-0767429Update dependencies
0.1.252025-09-3066934Update dependencies
0.1.242025-09-2466623Update dependencies
0.1.232025-09-0965813Update dependencies
0.1.222025-08-2365215Update dependencies
0.1.212025-08-1661055Update dependencies
0.1.202025-08-1263698Add support for german date format in NetSuite input
0.1.192025-05-2560581Update dependencies
0.1.182025-05-1160086Update dependencies
0.1.172025-05-0459481Update dependencies
0.1.162025-04-2759091Update dependencies
0.1.152025-04-2058531Update dependencies
0.1.142025-04-1357860Update dependencies
0.1.132025-04-0657301Update dependencies
0.1.122025-03-2956692Update dependencies
0.1.112025-03-2256060Update dependencies
0.1.102025-03-0855455Update dependencies
0.1.92025-03-0655207Add support for additional date format in Netsuite input
0.1.82025-03-0154821Update dependencies
0.1.72025-02-2254363Update dependencies
0.1.62025-02-1853853Update dependencies
0.1.52025-02-0853243Update dependencies
0.1.42025-02-0542857Migrate connector to Poetry
0.1.32023-01-2121645Minor issues fix, Setup Guide corrections for public docs
0.1.12022-09-2817304Migrate to per-stream state
0.1.02022-09-2116093Initial Alpha release