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
- Create account on Oracle NetSuite
- Confirm your Email
Step 2: Setup NetSuite account
Step 2.1: Obtain Realm info
- Login into your NetSuite account
- Go to Setup » Company » Company Information
- Copy your Account ID (Realm). It should look like 1234567 for the
Productionenv. or 1234567_SB2 - for aSandbox
Step 2.2: Enable features
- Go to Setup » Company » Enable Features
- Click on SuiteCloud tab
- Scroll down to SuiteScript section
- Enable checkbox for
CLIENT SUITESCRIPTandSERVER SUITESCRIPT - Scroll down to Manage Authentication section
- Enable checkbox
TOKEN-BASED AUTHENTICATION - Scroll down to SuiteTalk (Web Services)
- Enable checkbox
REST WEB SERVICES - Save the changes
Step 2.3: Create Integration (obtain Consumer Key and Consumer Secret)
- Go to Setup » Integration » Manage Integrations » New
- Fill the Name field (we recommend to put
airbyte-rest-integrationfor a name) - Make sure the State is
enabled - Enable checkbox
Token-Based Authenticationin Authentication section - Save changes
- After that, Consumer Key and Consumer Secret will be showed once (copy them to the safe place)
Step 2.4: Setup Role
- Go to Setup » Users/Roles » Manage Roles » New
- Fill the Name field (we recommend to put
airbyte-integration-rolefor a name) - Scroll down to Permissions tab
- Click on Setup and add both
REST Web ServicesandLog 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. - On the same Setup subtab, add the remaining dropdown entities with either
fullorviewaccess level. - Click on Transactions and add all the dropdown entities with either
fullorviewaccess level. - Click on Reports and add all the dropdown entities with either
fullorviewaccess level. - Click on Lists and add all the dropdown entities with either
fullorviewaccess 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
- Go to Setup » Users/Roles » Manage Users
- In column
Nameclick on the user’s name you want to give access to theairbyte-integration-role - Then click on Edit button under the user’s name
- Scroll down to Access tab at the bottom
- Select from dropdown list the
airbyte-integration-rolerole which you created in step 2.4 - Save changes
Step 2.6: Create Access Token for role
- Go to Setup » Users/Roles » Access Tokens » New
- Select an Application Name
- Under User select the user you assigned the
airbyte-integration-rolein the step 2.4 - Inside Role select the one you gave to the user in the step 2.5
- Under Token Name you can give a descriptive name to the Token you are creating (we recommend to put
airbyte-rest-integration-tokenfor a name) - Save changes
- 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
- In the left navigation bar, click Sources. In the top-right corner, click + new source.
- On the source setup page, select NetSuite from the Source type dropdown and enter a name for this connector.
- Enter your Realm (Account Id), Consumer Key, Consumer Secret, Token Key (Token Id), and Token Secret.
- Enter a Start Date as
YYYY-MM-DDTHH:mm:ssZ, for example2017-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. - Optionally set Object Types to the API names of the record types you want, such as
customerorsalesorder. Leave it empty to expose every record type in the account's metadata catalog. - Optionally set Window in Days. The default is 30.
- 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 has | Cursor field | Sync modes |
|---|---|---|
lastModifiedDate | lastModifiedDate | Full refresh, incremental |
lastmodified (typical of custom records) | lastmodified | Full refresh, incremental |
| Neither field | None | Full 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, andDD.MM.YYYYin 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
Changelog
Expand to review
| Version | Date | Pull Request | Subject |
|---|---|---|---|
| 0.1.29 | 2026-09-16 | 79191 | Emit warning and fail sync when >50% of records are silently skipped due to NetSuite workflow locks (USER_ERROR) |
| 0.1.28 | 2026-08-20 | 79654 | Fix 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.27 | 2025-10-14 | 67787 | Update dependencies |
| 0.1.26 | 2025-10-07 | 67429 | Update dependencies |
| 0.1.25 | 2025-09-30 | 66934 | Update dependencies |
| 0.1.24 | 2025-09-24 | 66623 | Update dependencies |
| 0.1.23 | 2025-09-09 | 65813 | Update dependencies |
| 0.1.22 | 2025-08-23 | 65215 | Update dependencies |
| 0.1.21 | 2025-08-16 | 61055 | Update dependencies |
| 0.1.20 | 2025-08-12 | 63698 | Add support for german date format in NetSuite input |
| 0.1.19 | 2025-05-25 | 60581 | Update dependencies |
| 0.1.18 | 2025-05-11 | 60086 | Update dependencies |
| 0.1.17 | 2025-05-04 | 59481 | Update dependencies |
| 0.1.16 | 2025-04-27 | 59091 | Update dependencies |
| 0.1.15 | 2025-04-20 | 58531 | Update dependencies |
| 0.1.14 | 2025-04-13 | 57860 | Update dependencies |
| 0.1.13 | 2025-04-06 | 57301 | Update dependencies |
| 0.1.12 | 2025-03-29 | 56692 | Update dependencies |
| 0.1.11 | 2025-03-22 | 56060 | Update dependencies |
| 0.1.10 | 2025-03-08 | 55455 | Update dependencies |
| 0.1.9 | 2025-03-06 | 55207 | Add support for additional date format in Netsuite input |
| 0.1.8 | 2025-03-01 | 54821 | Update dependencies |
| 0.1.7 | 2025-02-22 | 54363 | Update dependencies |
| 0.1.6 | 2025-02-18 | 53853 | Update dependencies |
| 0.1.5 | 2025-02-08 | 53243 | Update dependencies |
| 0.1.4 | 2025-02-05 | 42857 | Migrate connector to Poetry |
| 0.1.3 | 2023-01-21 | 21645 | Minor issues fix, Setup Guide corrections for public docs |
| 0.1.1 | 2022-09-28 | 17304 | Migrate to per-stream state |
| 0.1.0 | 2022-09-21 | 16093 | Initial Alpha release |