Netsuite HTTP Request using OAUTH1

Describe the issue/error/question

I am trying to connect to Netsuite, but the HTTP Request node specifies:
Authorization URL
Access Token URL
Request Token URL

Is the Suitetalk url the authorization url? (xxxxx…suitetalk.api.netsuite.com)
From what I can see they do not provide the token urls. I do have the Token ID and Token secret, but nowhere to enter them…

Please share the workflow

{
“nodes”: [
{
“parameters”: {
“authentication”: “oAuth1”,
“options”: {}
},
“name”: “HTTP Request”,
“type”: “n8n-nodes-base.httpRequest”,
“typeVersion”: 1,
“position”: [
920,
300
],
“credentials”: {
“oAuth1Api”: {
“id”: “1”,
“name”: “Unnamed credential”
}
}
}
],
“connections”: {}
}

Information on your n8n setup

  • n8n.cloud

@Manuel_Bautista welcome to the community

Can you please share the docs of the API that you are trying to connect to? I could not find it myself, and you seem to need an account to access it but not 100% sure.

I don’t have documentation, but here is my postman example.


I think the postman mechanics is different since here, you need to have the tokens, but in ours, we get the token from the URLs (Request token URL, Authorization Token URL, and Access Token URL). I would guess the URLs are in the docs somewhere.

NetSuite uses its own implementation of OAuth 1.0 which does not call an authorization URL. Unfortunately, there’s not a guide per se, but here are a few excerpts from SuiteAnswers.

Example of how to build the OAuth Header and call another NetSuite API from inside of NetSuite

Example Header

Hi Manuel, did you succeeded integrating netsuite OAuth1 with n8n?

1 Like

Hi all,

Is this the correct NetSuite documentation?

https://system.netsuite.com/help/helpcenter/en_US/APIs/REST_API_Browser/record/v1/2022.2/index.html

I may be taking on a project involving NetSuite’s CRM. Would be my first time working with NetSuite. Before I commit to the project, I would definitely want to be sure NetSuite has a fully built-out API I can use to make the integration. (Main use case would be to push lead/contact data into NetSuite, based on triggers. And nice to have would be to push data back [to n8n] from events within NetSuite.)

Can anyone confirm NetSuite’s API is ready to rock and roll, and that what I would need is possible?

@Manuel_Bautista @RicardoE105

Thank you!

EP

Had a quick look and look to me that they have everything you would need to create the integration

1 Like

A buddy and me are working on this. In the example node there is a part of the credentials file where they specify the authorization and where it belongs in the API call. On a node where you’re generating the authorization like this one, is it advised to generate that in the credential file, or in the node file?

Hello all,

We have published a community node that gives users an easy way to set up HTTP requests to a Netsuite restlet in your n8n workflows.

You can find that here - https://www.npmjs.com/package/@squaregrove/n8n-nodes-nsrestlet

4 Likes

Possible i “up vote” the feature? we are also looking forward for NetSuite’s auth node. But we likely can’t afford the self-host version.

Installing of community node required self-host as per my understanding

update 17 Jul 2024: i managed to create a node program to auth with NetSuite, next step is to build it via javascript, so i dont need to use the hosted n8n. Finger cross

const request = require('request')
const crypto = require('crypto')

// NetSuite specific parameters
const ACCOUNT_ID = 'x'
const COMPANY_URL = 'x.suitetalk.api.netsuite.com'
const REST_SERVICES = '/services/rest'

// OAuth credentials
const CONSUMER_KEY = 'x'
const CONSUMER_SECRET = 'x' // Replace with actual secret
const TOKEN_KEY = 'x'
const TOKEN_SECRET = 'x' // Replace with actual secret

/* */
const request_data = {
    url: `https://${COMPANY_URL}${REST_SERVICES}/query/v1/suiteql`,
    method: 'POST',
}
// const request_data = {
    // url: `https://${COMPANY_URL}${REST_SERVICES}/record/v1/journalentry`,
    // method: 'GET',
    // data: { },
// }


function generateNonce(length = 32) {
    return crypto.randomBytes(length).toString('hex')
}

function generateAuthHeader() {
    const timestamp = Math.floor(Date.now() / 1000).toString()
    const nonce = generateNonce()

    const data = {
        oauth_consumer_key: CONSUMER_KEY,
        oauth_token: TOKEN_KEY,
        oauth_signature_method: 'HMAC-SHA256',
        oauth_timestamp: timestamp,
        oauth_nonce: nonce,
        oauth_version: '1.0'
    }

    const encodedData = Object.keys(data)
        .sort()
        .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`)
        .join('&')

    const baseString = `${request_data.method}&${encodeURIComponent(request_data.url)}&${encodeURIComponent(encodedData)}`
    const signingKey = `${encodeURIComponent(CONSUMER_SECRET)}&${encodeURIComponent(TOKEN_SECRET)}`

    const signature = crypto.createHmac('sha256', signingKey)
        .update(baseString)
        .digest('base64')

    return `OAuth realm="${ACCOUNT_ID}",oauth_consumer_key="${CONSUMER_KEY}",oauth_token="${TOKEN_KEY}",oauth_signature_method="HMAC-SHA256",oauth_timestamp="${timestamp}",oauth_nonce="${nonce}",oauth_version="1.0",oauth_signature="${encodeURIComponent(signature)}"`
}

console.log('Starting authentication process...');

const authHeader = generateAuthHeader()
console.log('Generated Auth Header:', authHeader)

request(
    {
        url: request_data.url,
        method: request_data.method,
        headers: {
            'Authorization': authHeader,
            'Content-Type': 'application/json',
            'Prefer': 'transient'
        },
        body: JSON.stringify({ q: 'SELECT * FROM currency' })
	  //  body: JSON.stringify({}) // if using suiteql, comment this and enable line above
    },
    function(error, response, body) {
        if (error) {
            console.error('Error occurred:', error);
            return;
        }

        console.log('Response Status Code:', response.statusCode);
        console.log('Response Headers:', JSON.stringify(response.headers, null, 2));

        if (response.statusCode === 200) {
            console.log('Request successful!');
            try {
                const data = JSON.parse(body);
                console.log('Response data:', JSON.stringify(data, null, 2));
            } catch (e) {
                console.error('Error parsing response:', e);
                console.log('Raw response body:', body);
            }
        } else {
            console.log('Request failed.');
            console.log('Response Body:', body);
            try {
                const error = JSON.parse(body);
                if (error['o:errorDetails'] && error['o:errorDetails'].length > 0) {
                    console.log('Error message:', error['o:errorDetails'][0].detail);
                    console.log('Error code:', error['o:errorDetails'][0]['o:errorCode']);
                } else {
                    console.log('Unexpected error format:', error);
                }
            } catch (e) {
                console.error('Error parsing error response:', e);
                console.log('Raw error body:', body);
            }
        }
    }
)
1 Like

@weilies_chok
were you able to get this custom NetSuite auth node setup? I’ve been struggling with this for a while and the oAuth2.0 is a pain since it forces you to manually re-authenticate the connection every 7 days.

nope, and i will not consider custom node at the moment. Coz we can’t affort the self-host ver

Ok, so are you just using the oAuth2.0 Connector and going through the reconnect process weekly as well?

1 Like