OAuth 1.0 Token-Based Authentication (TBA) Setup Guide
This comprehensive guide walks you through implementing Token-Based Authentication (TBA) in NetSuite, from initial configuration to testing with Postman.
Overview
What is Token-Based Authentication (TBA)?
Token-Based Authentication (TBA) is NetSuite's implementation of OAuth 1.0. It provides secure API access without requiring user passwords.
┌────────────────────────────────────────────────────────────────────────┐
│ TOKEN-BASED AUTHENTICATION COMPONENTS │
├────────────────────────────────────────────────────────────────────────┤
│ │
│ Integration Record ──► Consumer Key + Consumer Secret │
│ │ │
│ ▼ │
│ Access Token ──────► Token ID + Token Secret (per user/role) │
│ │ │
│ ▼ │
│ API Request ───────► OAuth 1.0 Signature (all 4 values) │
│ │
└────────────────────────────────────────────────────────────────────────┘
OAuth 1.0 vs OAuth 2.0
| Aspect | OAuth 1.0 (TBA) | OAuth 2.0 |
|---|---|---|
| Complexity | More complex (signature required) | Simpler (bearer token) |
| Token Expiry | Tokens don't expire | Tokens expire (need refresh) |
| Use Case | Long-running integrations | Modern M2M integrations |
| Setup | Easier initial setup | Requires certificate |
| Postman | Built-in OAuth 1.0 support | Requires JWT generation |
TBA Authentication Flow
Prerequisites
Before starting, ensure you have:
- NetSuite Administrator role or equivalent permissions
- Access to Setup > Company > Enable Features
- Access to Setup > Integration > Manage Integrations
- Postman installed for testing
Step 1: Enable Token-Based Authentication Feature
First, enable TBA in your NetSuite account.
┌──────────────────────────────────────────────────────────────────────────┐
│ ENABLE TBA FEATURE │
└──────────────────────────────────────────────────────────────────────────┘
Navigate to:
Setup → Company → Enable Features → SuiteCloud
Enable:
┌────────────────────────────────────────────────────────────────────┐
│ ☑ Token-Based Authentication │
│ ☑ REST Web Services (for REST API) │
│ ☑ SOAP Web Services (for SOAP API) │
│ ☑ SuiteScript (if using RESTlets) │
└────────────────────────────────────────────────────────────────────┘
Detailed Steps:
- Go to Setup → Company → Enable Features
- Click on the SuiteCloud subtab
- Under Manage Authentication, check:
- ☑ Token-Based Authentication
- Under SuiteTalk (Web Services), check:
- ☑ REST Web Services (if using REST API)
- ☑ SOAP Web Services (if using SOAP API)
- Click Save
You must have the Administrator role to enable these features. Changes take effect immediately.
Step 2: Create Integration Record
The integration record identifies your external application and provides the Consumer Key and Secret.
┌──────────────────────────────────────────────────────────────────────────┐
│ CREATE INTEGRATION RECORD │
└──────────────────────────────────────────────────────────────────────────┘
Navigate to:
Setup → Integration → Manage Integrations → New
Integration Record Configuration
| Field | Value | Notes |
|---|---|---|
| Name | My TBA Integration | Descriptive name for your app |
| State | Enabled | Must be enabled to use |
| Token-Based Authentication | ☑ Checked | Required for TBA |
| TBA: Authorization Flow | ☑ Checked | Enable token management |
| OAuth 2.0 | ☐ Unchecked | Not needed for TBA |
Detailed Steps:
- Go to Setup → Integration → Manage Integrations
- Click New
- Fill in the form:
┌────────────────────────────────────────────────────────────────────────┐
│ INTEGRATION RECORD FORM │
├────────────────────────────────────────────────────────────────────────┤
│ │
│ Name: [My TBA Integration ] │
│ │
│ Description: [Token-Based Auth for external API access ] │
│ │
│ State: [● Enabled ○ Blocked] │
│ │
│ ───────────────────────────────────────────────────────────────── │
│ AUTHENTICATION │
│ ───────────────────────────────────────────────────────────────── │
│ │
│ ☑ Token-Based Authentication │
│ └─ ☑ TBA: Authorization Flow │
│ │
│ ☐ OAuth 2.0 │
│ │
└────────────────────────────────────────────────────────────────────────┘
- Click Save
After Saving - IMPORTANT!
After saving, NetSuite displays your credentials ONLY ONCE:
┌────────────────────────────────────────────────────────────────────────┐
│ ⚠️ SAVE THESE CREDENTIALS IMMEDIATELY │
├────────────────────────────────────────────────────────────────────────┤
│ │
│ Consumer Key: │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0 │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ │
│ Consumer Secret: │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ z9y8x7w6v5u4t3s2r1q0p9o8n7m6l5k4j3i2h1g0f9e8d7c6b5a4z3y2x1w0 │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ │
│ ⚠️ Copy these now! They cannot be retrieved later. │
│ │
└────────────────────────────────────────────────────────────────────────┘
Copy and securely store the Consumer Key and Consumer Secret immediately. They are shown only once and cannot be retrieved later. If lost, you must create a new integration record.
Step 3: Assign Integration to Role
Before users can create access tokens, the integration must be assigned to their role.
┌──────────────────────────────────────────────────────────────────────────┐
│ ASSIGN INTEGRATION TO ROLE │
└──────────────────────────────────────────────────────────────────────────┘
Navigate to:
Setup → Users/Roles → Manage Roles → [Select Role]
Detailed Steps:
- Go to Setup → Users/Roles → Manage Roles
- Click Edit on the role that will use TBA (e.g., Administrator, or a custom role)
- Scroll down to the Setup subtab
- Find the Access Token Management section
- Set permissions:
┌────────────────────────────────────────────────────────────────────────┐
│ ROLE PERMISSIONS - SETUP SUBTAB │
├────────────────────────────────────────────────────────────────────────┤
│ │
│ Permission Level │
│ ───────────────────────────────────────────────────────────────── │
│ Access Token Management [Full ▼] │
│ Log in using Access Tokens [Full ▼] │
│ User Access Tokens [Full ▼] │
│ │
└────────────────────────────────────────────────────────────────────────┘
- Click Save
Alternative: Quick Role Setup
If creating a new role for API access:
| Permission | Level | Purpose |
|---|---|---|
| Access Token Management | Full | Manage access tokens |
| Log in using Access Tokens | Full | Allow API authentication |
| User Access Tokens | Full | Create/view own tokens |
| REST Web Services | Full | Access REST API |
| SuiteQL | Full | Run SuiteQL queries |
Step 4: Create Access Token
Each user who needs API access must create their own access token.
┌──────────────────────────────────────────────────────────────────────────┐
│ CREATE ACCESS TOKEN │
└──────────────────────────────────────────────────────────────────────────┘
Navigate to:
Setup → Users/Roles → Access Tokens → New
Access Token Flow
Detailed Steps:
- Go to Setup → Users/Roles → Access Tokens
- Click New
- Fill in the form:
┌────────────────────────────────────────────────────────────────────────┐
│ ACCESS TOKEN FORM │
├────────────────────────────────────────────────────────────────────────┤
│ │
│ Application: [My TBA Integration ▼] │
│ (Select the integration created in Step 2) │
│ │
│ User: [John Developer ▼] │
│ (Select the user for this token) │
│ │
│ Role: [Administrator ▼] │
│ (Select role - determines permissions) │
│ │
│ Token Name: [API Access - Production ] │
│ (Optional descriptive name) │
│ │
└────────────────────────────────────────────────────────────────────────┘
- Click Save
After Saving - IMPORTANT!
After saving, NetSuite displays the token credentials ONLY ONCE:
┌────────────────────────────────────────────────────────────────────────┐
│ ⚠️ SAVE THESE TOKEN CREDENTIALS IMMEDIATELY │
├────────────────────────────────────────────────────────────────────────┤
│ │
│ Token ID: │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ 1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p7q8r9s0t1u2v3w4x5y6z7a8b9c0d │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ │
│ Token Secret: │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ 9z8y7x6w5v4u3t2s1r0q9p8o7n6m5l4k3j2i1h0g9f8e7d6c5b4a3z2y1x0w │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ │
│ ⚠️ Copy these now! They cannot be retrieved later. │
│ │
└────────────────────────────────────────────────────────────────────────┘
Copy and securely store the Token ID and Token Secret immediately. They are shown only once and cannot be retrieved later. If lost, you must revoke the token and create a new one.
Step 5: Gather All Credentials
At this point, you should have collected 4 credential values:
┌────────────────────────────────────────────────────────────────────────┐
│ TBA CREDENTIALS SUMMARY │
├────────────────────────────────────────────────────────────────────────┤
│ │
│ From Integration Record (Step 2): │
│ ───────────────────────────────────────────────────────────────── │
│ 1. Consumer Key: a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6... │
│ 2. Consumer Secret: z9y8x7w6v5u4t3s2r1q0p9o8n7m6l5k4... │
│ │
│ From Access Token (Step 4): │
│ ───────────────────────────────────────────────────────────────── │
│ 3. Token ID: 1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p... │
│ 4. Token Secret: 9z8y7x6w5v4u3t2s1r0q9p8o7n6m5l4k... │
│ │
│ Account Information: │
│ ───────────────────────────────────────────────────────────────── │
│ 5. Account ID: 1234567 (or 1234567_SB1 for sandbox) │
│ 6. Realm: 1234567 (same as Account ID, no underscore) │
│ │
└────────────────────────────────────────────────────────────────────────┘
Finding Your Account ID
Your Account ID can be found:
- URL: Look at your NetSuite URL -
https://1234567.app.netsuite.com/... - Company Info: Setup → Company → Company Information
For OAuth 1.0, the Realm is your Account ID but without any underscore suffix:
- Account ID:
1234567_SB1→ Realm:1234567 - Account ID:
1234567→ Realm:1234567
Step 6: Test with Postman
Now let's test the TBA authentication using Postman.
Configure OAuth 1.0 in Postman
- Open Postman and create a new request
- Click on the Authorization tab
- Select OAuth 1.0 from the Type dropdown
┌────────────────────────────────────────────────────────────────────────┐
│ POSTMAN AUTHORIZATION SETTINGS │
├────────────────────────────────────────────────────────────────────────┤
│ │
│ Type: [OAuth 1.0 ▼] │
│ │
│ ───────────────────────────────────────────────────────────────── │
│ Add authorization data to: [Request Headers ▼] │
│ │
│ Consumer Key: [your_consumer_key_here ] │
│ Consumer Secret: [your_consumer_secret_here ] │
│ Access Token: [your_token_id_here ] │
│ Token Secret: [your_token_secret_here ] │
│ │
│ Signature Method: [HMAC-SHA256 ▼] │
│ Timestamp: [Auto ] │
│ Nonce: [Auto ] │
│ Version: [1.0 ] │
│ │
│ Realm: [1234567 ] │
│ (Account ID without _SB suffix) │
│ │
└────────────────────────────────────────────────────────────────────────┘
OAuth 1.0 Settings
| Field | Value | Notes |
|---|---|---|
| Type | OAuth 1.0 | Select from dropdown |
| Add auth data to | Request Headers | Required for NetSuite |
| Consumer Key | From Step 2 | Integration consumer key |
| Consumer Secret | From Step 2 | Integration consumer secret |
| Access Token | From Step 4 | Token ID |
| Token Secret | From Step 4 | Token secret |
| Signature Method | HMAC-SHA256 | NetSuite requires SHA256 |
| Realm | Account ID | Without _SB suffix |
NetSuite requires HMAC-SHA256 signature method. Using HMAC-SHA1 will result in authentication errors.
Step 7: Test REST API Call
Test 1: SuiteQL Query
Let's run a simple SuiteQL query to verify authentication.
Request Configuration:
| Setting | Value |
|---|---|
| Method | POST |
| URL | https://{ACCOUNT_ID}.suitetalk.api.netsuite.com/services/rest/query/v1/suiteql |
| Headers | Content-Type: application/json, Prefer: transient |
Request Body:
{
"q": "SELECT id, companyname, email FROM customer WHERE rownum <= 5"
}
Full Request Example:
┌────────────────────────────────────────────────────────────────────────┐
│ POSTMAN REQUEST │
├────────────────────────────────────────────────────────────────────────┤
│ │
│ POST ▼ https://1234567.suitetalk.api.netsuite.com/services/rest/ │
│ query/v1/suiteql │
│ │
│ ───────────────────────────────────────────────────────────────── │
│ Authorization Headers Body ... │
│ ───────────────────────────────────────────────────────────────── │
│ │
│ Headers: │
│ ┌──────────────────────┬────────────────────────────────────────┐ │
│ │ Content-Type │ application/json │ │
│ ├──────────────────────┼────────────────────────────────────────┤ │
│ │ Prefer │ transient │ │
│ └──────────────────────┴────────────────────────────────────────┘ │
│ │
│ Body (raw - JSON): │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ { │ │
│ │ "q": "SELECT id, companyname, email FROM customer │ │
│ │ WHERE rownum <= 5" │ │
│ │ } │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────────────┘
Expected Response (200 OK):
{
"links": [...],
"count": 5,
"hasMore": true,
"items": [
{
"links": [],
"id": "123",
"companyname": "ABC Company",
"email": "contact@abc.com"
},
...
],
"offset": 0,
"totalResults": 1250
}
Test 2: Get Record
Retrieve a specific customer record.
Request Configuration:
| Setting | Value |
|---|---|
| Method | GET |
| URL | https://{ACCOUNT_ID}.suitetalk.api.netsuite.com/services/rest/record/v1/customer/123 |
Expected Response (200 OK):
{
"links": [...],
"id": "123",
"companyName": "ABC Company",
"email": "contact@abc.com",
"phone": "555-1234",
...
}
Complete TBA Flow Diagram
Troubleshooting
Common Errors
Error: "Invalid login attempt"
{
"type": "https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2",
"title": "Unauthorized",
"status": 401,
"o:errorDetails": [
{
"detail": "Invalid login attempt.",
"o:errorCode": "INVALID_LOGIN"
}
]
}
Solutions:
| Check | Solution |
|---|---|
| Consumer Key/Secret | Verify copied correctly from Integration record |
| Token ID/Secret | Verify copied correctly from Access Token |
| Signature Method | Must be HMAC-SHA256 (not SHA1) |
| Realm | Use Account ID without _SB suffix |
| Token Status | Ensure token is not revoked |
Error: "Invalid signature"
{
"o:errorDetails": [
{
"detail": "Invalid signature",
"o:errorCode": "INVALID_SIGNATURE"
}
]
}
Solutions:
- Ensure Signature Method is set to
HMAC-SHA256 - Ensure Add authorization data to is set to
Request Headers - Check that no extra spaces in credentials
- Regenerate the signature (Postman does this automatically)
Error: "Permission denied"
Solutions:
- Check user's role has required permissions
- Verify the Access Token was created with correct role
- Ensure role has access to the record type you're querying
API Endpoints Reference
Common NetSuite REST API Endpoints
| Endpoint | Method | Description |
|---|---|---|
/services/rest/query/v1/suiteql | POST | Run SuiteQL queries |
/services/rest/record/v1/{recordType} | GET | List records |
/services/rest/record/v1/{recordType}/{id} | GET | Get single record |
/services/rest/record/v1/{recordType} | POST | Create record |
/services/rest/record/v1/{recordType}/{id} | PATCH | Update record |
/services/rest/record/v1/{recordType}/{id} | DELETE | Delete record |
URL Format
https://{ACCOUNT_ID}.suitetalk.api.netsuite.com/services/rest/...
| Environment | Account ID Format | Example URL |
|---|---|---|
| Production | 1234567 | https://1234567.suitetalk.api.netsuite.com/... |
| Sandbox | 1234567_SB1 | https://1234567-sb1.suitetalk.api.netsuite.com/... |
Note that sandbox URLs use a hyphen (-sb1) instead of underscore (_SB1) in the subdomain.
Security Best Practices
┌────────────────────────────────────────────────────────────────────────┐
│ TBA SECURITY BEST PRACTICES │
├────────────────────────────────────────────────────────────────────────┤
│ │
│ ✅ DO: │
│ ├─► Store credentials in secure vault (not code) │
│ ├─► Use environment variables for credentials │
│ ├─► Create separate tokens for each application/environment │
│ ├─► Use roles with minimum required permissions │
│ ├─► Regularly audit active tokens │
│ └─► Revoke unused tokens immediately │
│ │
│ ❌ DON'T: │
│ ├─► Hardcode credentials in source code │
│ ├─► Share tokens between applications │
│ ├─► Use Administrator role for integrations │
│ ├─► Commit credentials to version control │
│ └─► Share credentials via email/chat │
│ │
└────────────────────────────────────────────────────────────────────────┘
Token Management
| Action | When to Use |
|---|---|
| Create new token | New application, new environment, new user |
| Revoke token | Security incident, user leaves, app decommissioned |
| Create separate tokens | Each environment (dev, staging, prod) |
Postman Collection Export
Save this as a Postman collection for easy import:
{
"info": {
"name": "NetSuite TBA API",
"description": "NetSuite REST API with Token-Based Authentication",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"auth": {
"type": "oauth1",
"oauth1": [
{ "key": "consumerKey", "value": "{{consumer_key}}", "type": "string" },
{ "key": "consumerSecret", "value": "{{consumer_secret}}", "type": "string" },
{ "key": "token", "value": "{{token_id}}", "type": "string" },
{ "key": "tokenSecret", "value": "{{token_secret}}", "type": "string" },
{ "key": "signatureMethod", "value": "HMAC-SHA256", "type": "string" },
{ "key": "realm", "value": "{{realm}}", "type": "string" },
{ "key": "addParamsToHeader", "value": true, "type": "boolean" }
]
},
"variable": [
{ "key": "base_url", "value": "https://{{account_id}}.suitetalk.api.netsuite.com" },
{ "key": "account_id", "value": "YOUR_ACCOUNT_ID" },
{ "key": "realm", "value": "YOUR_REALM" },
{ "key": "consumer_key", "value": "YOUR_CONSUMER_KEY" },
{ "key": "consumer_secret", "value": "YOUR_CONSUMER_SECRET" },
{ "key": "token_id", "value": "YOUR_TOKEN_ID" },
{ "key": "token_secret", "value": "YOUR_TOKEN_SECRET" }
],
"item": [
{
"name": "SuiteQL Query",
"request": {
"method": "POST",
"header": [
{ "key": "Content-Type", "value": "application/json" },
{ "key": "Prefer", "value": "transient" }
],
"body": {
"mode": "raw",
"raw": "{\n \"q\": \"SELECT id, companyname FROM customer WHERE rownum <= 10\"\n}"
},
"url": {
"raw": "{{base_url}}/services/rest/query/v1/suiteql",
"host": ["{{base_url}}"],
"path": ["services", "rest", "query", "v1", "suiteql"]
}
}
},
{
"name": "Get Customer",
"request": {
"method": "GET",
"url": {
"raw": "{{base_url}}/services/rest/record/v1/customer/123",
"host": ["{{base_url}}"],
"path": ["services", "rest", "record", "v1", "customer", "123"]
}
}
}
]
}
How to Import:
- Copy the JSON above
- In Postman, click Import
- Select Raw Text and paste
- Update the variables with your actual credentials
- Start testing!
Summary
┌────────────────────────────────────────────────────────────────────────┐
│ TBA SETUP CHECKLIST │
├────────────────────────────────────────────────────────────────────────┤
│ │
│ ☑ Step 1: Enable TBA feature in NetSuite │
│ ☑ Step 2: Create Integration Record → Consumer Key/Secret │
│ ☑ Step 3: Configure role permissions for TBA │
│ ☑ Step 4: Create Access Token → Token ID/Secret │
│ ☑ Step 5: Collect all 4 credentials + Account ID │
│ ☑ Step 6: Configure Postman OAuth 1.0 (HMAC-SHA256) │
│ ☑ Step 7: Test API calls │
│ │
│ Required Credentials: │
│ ├─► Consumer Key (from Integration) │
│ ├─► Consumer Secret (from Integration) │
│ ├─► Token ID (from Access Token) │
│ ├─► Token Secret (from Access Token) │
│ └─► Realm (Account ID without suffix) │
│ │
└────────────────────────────────────────────────────────────────────────┘
Related Documentation
- OAuth 2.0 Setup Guide - Modern OAuth 2.0 authentication
- Integration Overview - Overview of integration methods
- RESTlet Script Type - Create custom API endpoints