Skip to main content
Elastly reads your catalog, costs, inventory, customers, quotes, and realized sales orders from NetSuite over SuiteTalk REST. Because the sync runs unattended on a schedule, it uses NetSuite’s OAuth 2.0 Client Credentials (machine-to-machine) grant: there’s no browser redirect and no end-user authorize step. Authentication is by certificate, and Elastly generates the key pair for you, so you only download a public certificate and upload it to NetSuite.
Setup is done once by a NetSuite administrator and takes about ten minutes.

What you’ll need

NetSuite administrator access, to enable features, create an integration record, set up a role, and upload the certificate.

Enable the required features

Go to Setup → Company → Enable Features → SuiteCloud. Enable Client SuiteScript, Server SuiteScript, REST Web Services, and OAuth 2.0, accept the SuiteCloud terms, then save.
The SuiteCloud tab with Client SuiteScript, Server SuiteScript, REST Web Services, and OAuth 2.0 all checked.

Enable Features → SuiteCloud. All four must be checked before you save.

Do this first. The OAuth 2.0 login permission you’ll add to the role in a later step does not appear in the permissions list until OAuth 2.0 is enabled here and saved. If you can’t find that permission, this is almost always why.

Create the integration record

Go to Setup → Integration → Manage Integrations → New. Name it (for example “Elastly”), set State to Enabled, then check the following:
  • Client Credentials (Machine to Machine) Grant: required for M2M
  • REST Web Services: required for SuiteTalk REST
  • Leave Authorization Code Grant unchecked
Save. NetSuite shows a Client ID; copy it now.
NetSuite integration record with Client Credentials grant and REST Web Services checked, Authorization Code Grant unchecked, and the Client ID shown.

The integration record. Client ID appears once, right after you save.

M2M has no client secret. Authentication is done with a certificate, which you’ll add in the steps below.

Create a role for the integration

A role in NetSuite is a named bundle of permissions you attach to a user, and it decides what that login is allowed to read. Elastly logs in as a user, and that user’s role determines what Elastly can pull. Create a new, dedicated role for this. Don’t reuse Administrator or another built-in role. Built-in roles are locked, which is also why the OAuth permission won’t appear when you try to add it to them.
1

Create the role

Go to Setup → Users/Roles → Manage Roles → New and name it something like Elastly Integration.
2

Add the Setup permissions

On the Permissions → Setup sub-tab, add:Set the two login permissions to Full and Deleted Records to View.
3

Add the Reports permission

On the Permissions → Reports sub-tab, add SuiteAnalytics Workbook at Edit.Elastly reads your data with SuiteQL, NetSuite’s query language, and NetSuite only runs SuiteQL for roles that have this permission. It lives on the Reports sub-tab, not Setup.
4

Add the Lists permissions

On the Permissions → Lists sub-tab, add View on:
5

Add your custom records

Every custom record you map in Elastly needs its own View permission, for example the record that holds your substitute items, or a contract or agreement record. None of the lists above cover them. Where you grant it depends on the record:
  • Most custom records are set to Use Permission List and don’t appear on the role at all. Go to Customization → Lists, Records, & Fields → Record Types, open the record, and on its Permissions sub-tab add the Elastly Integration role at View.
  • If the record does appear on the role’s Permissions → Custom Record sub-tab, add it there at View instead.
If you don’t map any custom records, skip this step.
6

Add the Transactions permissions

On the Permissions → Transactions sub-tab, add:Grant all of these even if you don’t use some of them yet. A transaction type the role can’t see reads as empty, with no error, so a missing one looks exactly like having no data. Check permissions in Elastly tests each one and names any that are missing.
7

Save and assign the role to a user

Save, then give a user this role. Open the user under Setup → Users/Roles → Manage Users, edit their employee record, and on the Access subtab check Login Access (called Give Access on older accounts) and add the Elastly Integration role. Elastly signs in as this user, so if the role isn’t attached here the token request fails. You’ll select this same user and role in the certificate step below.
Sales Order is required, and its omission fails silently. Elastly’s pricing learns from won, realized Sales Orders. They’re the accept signal and the last-purchase-price source. SuiteQL is permission-sensitive: if the role can’t read Sales Orders, the orders sync fails with an opaque server error (NetSuite reports a missing permission as if the table doesn’t exist), not a clear “access denied”. If orders aren’t syncing, check this permission first.
Test with this role, not Administrator. Administrator has every permission built in, so a connection that works as Administrator proves nothing about this role. If the permission check in Elastly fails on Items, Customers, and every transaction at once with “Your current role does not have permission to perform this action”, the role is missing SuiteAnalytics Workbook.
If your NetSuite account is OneWorld (more than one subsidiary), the role and the user you assign it to only see the subsidiaries they’re granted, and Elastly syncs data only for those. Customers, items, and orders in a subsidiary the role can’t reach are skipped with no error, so the data just looks incomplete later. On the role, grant every subsidiary you want priced (or all of them), and confirm the assigned user has the same access. On a single-subsidiary account there’s nothing to set here.
NetSuite may list a permission under a different name. Even on an account that has never renamed anything, the Transactions permission picker can list the Estimate record as Quotation. If your account renamed records under Setup → Company → Rename Records/Transactions, the picker shows your names, for example Inquiry for Opportunity. Look for the label your team uses for that record; it’s the same permission. Check permissions in Elastly confirms it worked.
If you want Elastly to batch-publish approved recommendations onto your NetSuite quotes (the Elastly Rate column, never the native price), grant Edit (not just View) on Estimate. Sales Order stays View, since write-back only ever updates Estimate lines. View-only on both is enough for read-only pricing intelligence. Check permissions treats the Elastly columns as optional until you first publish prices to NetSuite, and as required from then on.

Generate the certificate in Elastly

In Elastly, open Integrations → Connect → Oracle NetSuite and click Generate & Download. Elastly creates the key pair and downloads a public certificate file, elastly-netsuite.pem. This is a public X.509 certificate (RSA-3072), never a .p12. A .p12 would contain the private key, which always stays inside Elastly.
The private key never leaves Elastly. You only ever download and share the public certificate file.

Upload the certificate in NetSuite

Go to Setup → Integration → Manage Authentication → OAuth 2.0 Client Credentials (M2M) Setup and click Create New. (The administrator doing this needs the OAuth 2.0 Authorized Applications Management permission; a full Administrator role already has it.) Fill in:
  • Entity: the user the integration runs as
  • Role: the role you configured above
  • Application: the integration record (“Elastly”)
  • Certificate: upload elastly-netsuite.pem
Save. NetSuite generates a Certificate ID; copy it.
NetSuite OAuth 2.0 M2M setup with the entity, role, application, and the elastly-netsuite.pem certificate uploaded, showing the Certificate ID.

M2M setup: entity, role, application, and the public certificate. Certificate ID appears after saving.

Redo this M2M certificate setup in each environment, and again after every sandbox refresh. A sandbox and production never share a certificate.
The certificate Elastly generates is valid for two years. The sync runs normally until then, and Elastly emails you a reminder as the expiry date approaches. To renew, open Integrations → Oracle NetSuite in Elastly, generate a fresh certificate, upload it in this same M2M setup screen, and enter the new Certificate ID. It’s the same steps you’re doing now.

Find your Account ID

Your Account ID is under Setup → Company → Company Information (also the subdomain prefix of your NetSuite URL). Production looks like 1234567; sandbox looks like 1234567_SB1.

Finish in Elastly

Back in the Elastly connect dialog, enter your Account ID, Client ID, and Certificate ID, then click Connect to NetSuite. There’s no redirect or authorize step: Elastly requests an access token to verify the setup and starts your first sync.
Elastly's Connect Oracle NetSuite dialog with Account ID, Client ID, and Certificate ID fields.

The three values go into Elastly's connect dialog. Click Connect and the first sync starts.

Access tokens are short-lived (60 minutes) with no refresh token; Elastly re-acquires them automatically, so the scheduled sync keeps running unattended.

See Elastly’s price live inside NetSuite

Everything above sets up the read-only sync that feeds Elastly. The integration can also run the other way: a small script inside NetSuite asks Elastly for the recommended price the moment a line is added to an Estimate, and shows it on the line as an advisory column (the Elastly Rate and its reason) right next to the native rate. Your reps keep working entirely in NetSuite and see Elastly’s number against their own. Elastly never overwrites the rate. The rep decides. This is optional, and it reuses everything the sync already taught Elastly: a line seen live in NetSuite carries the same explainable price the Elastly dashboard would show. Set it up once the first sync has finished. It fails open by design: if Elastly is ever slow or unreachable, the advisory columns simply stay empty and quoting is never blocked. Two scripts do the work. A Suitelet runs on the NetSuite server and holds the only connection to Elastly. A Client Script runs in the rep’s browser and only ever talks to that Suitelet. Your Elastly API key lives in a NetSuite API Secret that only the Suitelet can read, so it never reaches a browser. The Suitelet runs as the logged-in user, so it looks up the customer under that user’s own role, and it tells Elastly which NetSuite employee and role asked. That is what lets Elastly scope a rep to the customers they own.
A note on “Estimate.” Some accounts rename the Estimate record type (commonly to “Quote” or “Quotation”) under Setup → Company → Rename Records/Transactions. If you don’t see “Estimate” as an option anywhere below (in the role permissions, or in the script deployment’s record-type list), look for your account’s renamed label instead. It’s the same underlying record, just displayed differently. To confirm, open any such record and check the browser URL: it still reads .../transactions/estimate.nl?... regardless of the display label.

Before you start

You need a NetSuite administrator, or a custom role with these permissions: Reps need nothing new. The Suitelet runs under their own role, so a rep who can open an Estimate and see its customer gets a price. A rep whose role cannot see the customer gets no price on that record. Download elastly-netsuite.zip from Integrations → NetSuite in Elastly. Unzip it. The folder src/FileCabinet/SuiteScripts/elastly/ holds the two files you upload: The same folder also holds elastly_price_ue.js and elastly_apply_cs.js. They belong to the Apply feature, which Elastly turns on per workspace. Leave them out of this install.
The zip is a complete SuiteCloud (SDF) account customization project. If your team deploys with the SuiteCloud CLI, suitecloud project:deploy creates the line fields, both scripts, their deployments and the empty API Secret in one go. You still set the secret’s value and its script restriction by hand, and you check the Suitelet deployment’s Execute As Role after the deploy.

Create a Sales rep API key in Elastly

In Elastly, go to Settings → API keys and press Create key. Choose the ERP scope, then the Sales rep view. Pick an expiry, name the key (for example NetSuite production), and press Create key. Copy it now. The full key is shown once. The Sales rep view returns the price without margins or minimums. That is all the NetSuite scripts need, and it keeps cost and margin out of NetSuite entirely.
Treat it like a password. If you lose it, revoke it and create a new one. Use separate keys for sandbox and production so you can rotate one without touching the other. The key goes into a NetSuite API Secret in a later step. It never goes into a script parameter.

Add the Elastly line fields

Elastly shows its recommendation on the line through five custom line fields. You only need them if you want Elastly’s price, reason, and status visible on NetSuite quote lines. Quotes you build in Elastly and push to NetSuite work without them: Elastly fills in only the fields your account has. If you want them, create all five now, before the scripts, so they have somewhere to write. NetSuite has no way to import a custom field from a file through the UI, so you create them yourself.
1

Open Transaction Line Fields

Go to Customization → Lists, Records, & Fields → Transaction Line Fields → New (labelled “Transaction Column Fields” in some accounts, the same thing).
2

Set the label, type, and ID

Set the Label and Type from the list below, and for the ID type the value shown, starting with the leading underscore (for example _elastly_rate). NetSuite adds the prefix custcol for you, with no underscore of its own, so it saves as custcol_elastly_rate. Drop the leading underscore and you get custcolelastly_rate, which the script can’t read and nothing warns you about.
3

Set Applies To

On the Applies To subtab check Sale (may show as “Sale Item”), and check Store Value.
4

Set the display type

Make Elastly Rate, Elastly Reason, Elastly Decision ID, and Elastly Status display-only, since they’re Elastly’s to write. Leave Elastly Sales Feedback editable, so the rep can note why they kept, raised, or lowered the price versus Elastly’s rate. Elastly reads that note back to learn.
5

Save, then repeat for all five

Save, then repeat for all five fields.
If a column doesn’t show on the Estimate form after you create it, add it to the line-item grid from the form’s Screen Fields customization.

Upload the Suitelet

Go to Customization → Scripting → Scripts → New and upload elastly_price_sl.js. NetSuite reads the script type and the onRequest entry point from the file. On the script record, set: Then open the Parameters subtab and add one parameter:
The IDs must match exactly. The Client Script finds the Suitelet by the IDs customscript_elastly_price_sl and customdeploy_elastly_price_sl, and the Suitelet reads its base URL from custscript_elastly_base_url. NetSuite prepends customscript, customdeploy, and custscript for you, so type the leading underscore yourself and nothing else. Drop it and you get customscriptelastly_price_sl; type the whole prefix and you get a doubled customscriptcustomscript_elastly_price_sl. Either way nothing runs, and nothing warns you.

Upload the Client Script

Back in Customization → Scripting → Scripts → New, upload elastly_price_cs.js. On the script record, set: Leave every other entry-point checkbox unchecked. The Client Script has no parameters. If you see a parameter asking for an API key, you’re looking at the older script; see Upgrading from the older script.

Create the API Secret

Go to Setup → Company → Preferences → API Secrets and press Create New. Save. The ID prefix works like the others: NetSuite adds custsecret, so type the leading underscore yourself. The Suitelet reads the secret as custsecret_elastly_api_key and nothing else can.
NetSuite can take up to an hour to make a new or changed secret value available to scripts. If a fresh install returns 401 in the Suitelet’s log right after you save the secret, wait and test again before you change anything.

Deploy the Suitelet

Open the Elastly Price Proxy script record, go to Deployments, and add one: Available Without Login must stay unchecked. The Suitelet only answers NetSuite users who are signed in, and that is the whole point of the design. Execute As Role must be Current User so the customer lookup, and the employee and role Elastly receives, are the rep’s own.

Deploy the Client Script

Open the Elastly Pricing script record, go to Deployments, and add one on Estimate: The bundle ships the Estimate deployment. If your reps also price from Sales Order, add a second deployment on that record type the same way, with its own ID.
Deploy order. Because Elastly only fills its advisory columns and never touches the line rate, it coexists with any existing pricing script, so there’s nothing to order and no cost-floor validation to satisfy. Don’t deploy it on Opportunity records, which are typically priced by a server-side script.

Test it

Open a new Estimate (or your account’s renamed equivalent), choose a customer, and add an item: the Elastly Rate column should populate with Elastly’s recommendation within a moment. Change the quantity and it updates. Open an existing Estimate in edit mode and every line gets priced on load. The native rate stays exactly as NetSuite set it. Elastly only advises. Back in Elastly, the key’s row under Settings → API keys now shows a used date.
Each step rules out a specific, real failure mode, not a guess.
  1. Open the browser console (F12) before you test. The Client Script runs in the browser. A load-time error (bad upload, corrupted file) shows up here and nowhere else. An entry titled Elastly request failed means the browser could not reach the Suitelet: the Suitelet’s script or deployment ID is not exactly customscript_elastly_price_sl / customdeploy_elastly_price_sl, its deployment is not Released, or the tester’s role is outside its Audience.
  2. Check the Suitelet deployment’s Execution Log. This is where the server side reports. Elastly request failed here means the call to Elastly itself failed: the secret is not readable by this script (check Restrict to Scripts), the domain restriction does not include app.elastly.io, or the key is revoked or expired (Elastly answers 401).
  3. Confirm the Suitelet’s base URL. custscript_elastly_base_url must have a value on the deployment, starting with https:// and with no trailing slash. Without it the Suitelet answers not_configured and writes nothing.
  4. Confirm the API Secret ID is exactly custsecret_elastly_api_key, not doubled and not missing its underscore, and that it has a value.
  5. Confirm both deployments’ Audience includes your test user’s role. Released status doesn’t matter if the tester isn’t in the Audience list.
  6. Confirm the Suitelet deployment runs as Current User with Available Without Login unchecked. A Suitelet set to run as a fixed role prices under that role’s view of customers, not the rep’s.
  7. Confirm Page Init, Post Sourcing, and Field Changed are checked on the Client Script record, matching the table above.
  8. Check the record itself. The Client Script only asks for a price once the Estimate has a customer, a currency, and an item with a positive quantity. A customer the tester’s role cannot see returns customer_not_visible in the Suitelet log and no price. A currency whose ISO code Elastly does not have returns currency_unavailable.
  9. Isolate Elastly’s script from client scripts in general. Does any other client script you run still work on this record? If yes, the problem is scoped to Elastly’s script. If nothing runs at all, something account- or role-wide is blocking client scripts, a bigger issue than this integration.

Upgrading from the older script

Earlier installs used a single Client Script, elastly_estimate_pricing_cs.js, with the Elastly key in a script parameter named custscript_elastly_api_key. That put the key in every rep’s browser. Elastly now marks such keys Exposed under Settings → API keys and expires them 30 days after the flag is set, so move before then.
1

Install the new scripts

Follow the steps above from Create a Sales rep API key through Deploy the Client Script. Add the one new line field, Elastly Status (_elastly_floor_status); the other four already exist. Create the new key rather than reusing the old one: the old key is a Full-view key, and the Suitelet should carry a Sales rep key.
2

Test the new install

Run the test with the new deployment. Both scripts can be Released at the same time while you check; they write the same columns.
3

Retire the old script

On each deployment of the old script, clear the value of Elastly API key (custscript_elastly_api_key) and uncheck Deployed. Then delete the old script record, which removes its parameters and deployments.
4

Revoke the old key in Elastly

Under Settings → API keys, press Revoke on the key marked Exposed. Don’t use Rotate for this one: rotation mints a replacement with the same Full view, and the Suitelet already has its Sales rep key.
Two-way: write-back. Real-time pricing and price write-back are two separate mechanisms, and it’s worth being precise since they need different permissions. The Suitelet and Client Script above fill the advisory columns in the form your rep already has open, under the rep’s own NetSuite session; they never use Elastly’s integration role or REST API to write, only to read the price, so they need no Edit permission of their own. Price write-back (Elastly batch-publishing approved recommendations onto existing Estimates from the dashboard) is the separate mechanism that needs Edit on Estimate (the optional permission noted in the role step above) to fill the Elastly Rate column. It still never overwrites the native rate, and only ever touches Estimates, not Sales Orders.