Use the NetSuite integration to connect Shapes to your NetSuite account via OAuth 2.0. You'll create a machine-to-machine (client credentials) connection in NetSuite, upload the Shapes certificate, and copy four values back into the Shapes connect wizard. This takes about 10 minutes and requires NetSuite administrator access.
Before You Start
NetSuite administrator access — you'll be creating an integration record and a certificate mapping.
The SuiteCloud / OAuth 2.0 features enabled under Setup > Company > Enable Features > SuiteCloud.
The Shapes connect wizard open in another tab — that's where you download the certificate and enter the values you collect below.
Step 1 — Create an OAuth 2.0 Integration Record
In NetSuite, go to Setup > Integration > Manage Integrations > New.
Give it a name (e.g. Shapes).
Enable the OAuth 2.0 section and select the Client Credentials (machine-to-machine) grant.
Turn off TBA and any user-based flows — Shapes connects machine-to-machine.
Save the record, then copy the Client ID (consumer key) and Client Secret (consumer secret).
Heads up: NetSuite shows the Client Secret only once, at creation. Copy it now and keep it somewhere safe — if you lose it you'll have to regenerate it.
Step 2 — Download & Upload the Shapes Certificate
In the Shapes connect wizard, step 1, click Download to save the Shapes public certificate (shapes-netsuite-certificate.pem).
In NetSuite, go to Setup > Integration > OAuth 2.0 Client Credentials (M2M) Setup.
Click Create New and upload the certificate you just downloaded.
Pick the Entity and Role that has the permissions Shapes should use, and select the integration record from Step 1.
Save, then copy the Certificate ID that NetSuite generates for the mapping.
The certificate is what lets Shapes prove who it is. If it isn't uploaded and mapped to a role, the connection will fail with an invalid_grant error.
Step 3 — Find Your Account ID
Your NetSuite account ID is shown under Setup > Company > Company Information (the Account ID field). It looks like 1234567, or 1234567_SB1 for a sandbox account.
Step 4 — Enter the Four Values Back in Shapes
Back in the Shapes connect wizard, step 2, paste the values you collected:
Field | What to enter |
Account ID | Your NetSuite account ID from Setup > Company > Company Information (e.g., 1234567 or 1234567_SB1 for a sandbox). |
Client ID | The Client ID (consumer key) from the OAuth 2.0 integration record you created in Step 1. |
Client Secret | The Client Secret shown when you created the integration record. NetSuite only shows it once. |
Certificate ID | The Certificate ID NetSuite generated when you uploaded the Shapes certificate and mapped it to a role in Step 2. |
Click Connect. Shapes validates the credentials against NetSuite right away and tells you if anything's off.
What Data Syncs
The NetSuite integration is bidirectional and field-mapped: changes made on either side reconcile to the other, field by field, per your configured mapping.
Unlike webhook-based integrations, NetSuite doesn't offer real-time push for HR data — Shapes syncs on a scheduled poll (periodic, configurable cadence). Expect changes to reconcile within minutes to a few hours, not instantly. Set this expectation with your team up front.
Fields kept in sync between Shapes and NetSuite:
First / last name
Job title
Department
Location
Manager
Start date
Termination date
Subsidiary
Salary currency
Custom fields (configurable)
If the Connection Fails
Common errors and what they mean:
invalid_grant — the certificate isn't uploaded/mapped to a role, or the Certificate ID doesn't match. Re-check Step 2.
invalid_client — the Client ID or Client Secret is wrong. Re-copy them from the integration record (regenerate the secret if needed).
invalid_request — usually a malformed Account ID. Confirm it matches Company Information exactly.
The wizard shows the exact reason NetSuite returned, so you can match it to the list above.
If data looks stale or out of sync:
Confirm the poll is still running — credentials can expire silently, which stops syncing without an obvious error.
Remember that a change made right after a poll runs won't show up until the next cycle — this isn't a bug, it's the expected latency for a polling integration.
