Already using API Key (hapi). Should I convert to 0Auth for server-to-hubspot integration?


We have production servers that update contacts, and we're using the hapikey param for authentication to hubspot. Is the hapikey something that should be discouraged because of security? Is 0Auth appropriate for a headless back-end server application that doesn't have a UI, and only has configuration? Would 0Auth allow us to have different access rights to contacts for production vs. development environments?


Hi @brian-voicebase, I would say that we definitely recommend switching to OAuth since OAuth is inherently much more secure since it a. doesn't grant access to everything like a hapikey would b. requires a user to go through a flow to install it to a portal and grant access to that application. OAuth is certainly encouraged, but using your hapikey isn't necessarily a bad thing either as long as nobody else can gain access to it.

In terms of using OAuth on a backend system, this should be possible to do programmatically - the user would just need to grant access to the application initially in the portal. You'd then generate tokens that expire every 6 hours from the refresh token given by the initial OAuth setup.

OAuth uses different scopes that are required by an application to work, and cross checks them with the portal's and user's given parcels to grant access to different tools. You could conceivably create 2 applications - one for testing and one for production - but OAuth doesn't inherently allow you to do this in one fell swoop.

A really great example of how to handle OAuth was published just yesterday. It links to a github project that shows how to handle OAuth programmatically:


I just picked this feature up again, so sorry for my delayed response. If we use the OAuth workflow, then we need an actual user to signup and get the “refresh” token using a web interface? Then, the “refresh" token is saved in the backend application, which then uses the saved refresh token to get the “access” token. The access token is then used to make actually API calls. How much time is the “refresh” token good for? I see in your documentation that a “token” is good for 6 hours by default. Which token is that? Am I getting this correct?


Hi @brian-voicebase, no worries!

we need an actual user to signup and get the “refresh” token using a web interface? Then, the “refresh" token is saved in the backend application, which then uses the saved refresh token to get the “access” token.

Yeah you got that almost all right. One thing, though, is that you don't have to have the user get the refresh token by themselves, you can programmatically do this type of thing with redirects and passing data from one page to another to get them to select their account, but overall, yes you are correct with the overall steps it takes for OAuth to work. To test, though, I'd recommend doing all steps manually.

The access token is then used to make actually API calls.

Correct again, the access token is the token you need to make the calls, and the access token expires every 6 hours. The refresh token doesn't expire unless you kill it manually:

Let me know if I can clarify anything


Cool. We will only have two users - one for production and one for testing. The testing user will have less privilege. We can just do this all manually to get the "refresh" tokens. Thanks for clarifying that the "refresh" tokens last forever. In some systems, they only last for 6 months, and that's a problem.

Now, I can't figure out how to create an app. We have a workflow with the webhooks, but I think I need an application to get the CLIENT_ID and CLIENT_SECRET values. How do you create an application from the website? Out hubspot website UI doesn't look like the one on this page:



hi @brian-voicebase, you'll first need to create a Developer Portal to create an application:


Okay. I found that. Now, is the developer portal app automatically connected to our hubspot account? Our account has the "automation==>workflow" that I'm interested in.


The application must be created first, then you would go through the OAuth flow using the information about your particular application and install it into either a Test or Live Production Portal. When you finish all steps of OAuth, the application is installed. You can then make requests using the access tokens to the parts of the product you're looking to test out.

As I mentioned, you can test out OAuth in either your live, production account that you pay for, or you can test it out with a Test account which you can find within your developer account at the top navigation by clicking "Testing". The advantage of a test account is you have dummy information already and will not mess up data in your live account, and all test portals come pre-installed with Enterprise features, so you can make requests to almost any of the API endpoints.


I get that the application must be created first. But, not sure how this relates to our main account’s workflow webhook.

I’m trying to run your Node.js OAuth 2.0 Quickstart right now. I’m having trouble with the "yarn start”, so I’m installing apple Xcode first. I hope that works. This is the error I get on yarn install:
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

I also get this on yarn start:

yarn start

yarn run v1.12.3

$ node index.js


throw err;


Error: Cannot find module 'dotenv'

at Function.Module._resolveFilename (internal/modules/cjs/loader.js:603:15)

at Function.Module._load (internal/modules/cjs/loader.js:529:25)

at Module.require (internal/modules/cjs/loader.js:658:17)

at require (internal/modules/cjs/helpers.js:22:18)

at Object.<anonymous> (/Users/brianmcglothlen/workspace/oauth-quickstart-nodejs/index.js:1:63)

at Module._compile (internal/modules/cjs/loader.js:722:30)

at Object.Module._extensions..js (internal/modules/cjs/loader.js:733:10)

at Module.load (internal/modules/cjs/loader.js:620:32)

at tryModuleLoad (internal/modules/cjs/loader.js:560:12)

at Function.Module._load (internal/modules/cjs/loader.js:552:3)

error Command failed with exit code 1.

Finally, I just want to make sure OAuth is going to work for us using webhooks in our main production account’s workflow, and also calling an update API. This is for our backend production server, to stay synchronized with Hubspot. This isn’t a customer application that customers use.

Thanks for your help,



Hi @brian-voicebase, if you're getting that yarn error, you need to make sure that yarn is installed buy running yarn --version in your terminal, or install the project via node with npm install. To check if Node is installed you can run node --version. Read more about yarn here:

Thanks for the clarification on your intentions. In this case, the webhook - app relationship is that webhooks are set up for a HubSpot app, not individual portals. Any portals (likely just your own production portal) that install your app (by going through the OAuth flow) will be subscribed to any webhook subscriptions set up for the app. You'd still need to set up your webhook in your HubSpot App in your developer portal, then go through the OAuth flow to install that app to your portal so that you can subscribe to a change, creation or deletion in your paid portal.


Thanks for your help with this issue. I used npm instead of yarn, and I was able to start and get an “access” token using the example nodejs app. I see that it asked me which "portal" I wanted access to, so that seems to be the “relationship” I was wondering about. I’m inside of the hubspot “application” trying to set up a webhook for contact creation and trying to figure out how to call the update contact API, but still have questions.

Is there an example of how to configure the hubspot application to use our production portal so I’m just getting contact creation and update web hook notifications, and calling the update contact API? I see there are boxes to check on the “Details” application page regarding access to contacts and web flows, and it looks like there’s a list of web hook subscriptions. But, no expose update contact API. Do I just enable the Contacts and Workflows checkboxes, and create a web hook subscriptions with a unique URL, and I’ll automatically be hooked up to the development portal?

Thanks again for your help.



Here's another quick one. I'm getting this error now when I call http://localhost:3000/install

Uh oh!

Insufficient scopes were provided. Please contact the integrator.

Not sure why I'm getting this now.


Hi @brian-voicebase thanks for providing more info - hope I can shed light on what's going on and what you're going to want to do here. If you're looking to test out Webhooks, what you need set up is the following:

  1. In the production portal that you're looking to test your subscription to a contact creation, you must install your custom application following the steps 1-4 here: While the OAuth Quickstart app is great to see the ins and outs of OAuth, using webhooks requires you to have access to the Developer Portal that is requesting these scopes. Since you don't have access to our QuickStart App, I would recommend you walk through the steps from the article I linked above.
  2. Once you've gone through the OAuth flow and the app is installed in your production account, you can then set up your webhooks in your dev portal. Webhooks only work on accounts that have your application installed.
  3. I'd recommend something like Request Bin ( to test out your webhooks, unless you already have a live link that you can use to test this out.

Apologies for the roundabout way to get here, but testing out the OAuth quickstart app won't help you get webhooks installed.


Thanks for the information, and I will look at this more carefully. As I look into the “Application” UI, I have another higher level question about whether what we’re doing is even a good idea.

I have an image I can show you, but I’m not sure this is the right place to attach it.

The point is we’re trying to avoid using 2 separate hubspot accounts. We’d like to share a single hubspot account for both production and development. We’re only trying to share a single account, because the lower cost accounts (i.e. free) don’t support workflows and webhooks. The account for production needs secure authorization, so our developers in the development servers cannot see the production credentials and can’t access the production contacts. What we’d like to do is have 2 different sets of workflows and contacts, or at least prevent being able to update the production credentials from the development environment. We also rely on a workflow to update contacts in our backend server via a webhook.

That said, is using a Hubspot OAuth protected Application going to solve the above problem? How do other customers achieve having both a production contact list and development one with webhooks, so they have a development sandbox? I don’t want to implement all of this just to find out that what we’re trying to do is foolish, and we should have done something else. Who can I speak to on the phone about this? I feel a phone conversation might make this go a lot smoother.




Hi @brian-voicebase,

  1. Developer Accounts and Production Accounts are always separate. They cannot be merged.
  2. At the end of the day, in order to use Webhooks you must have an application in a HubSpot Developer Account and that application must be installed into a production portal.

Looking over your responses, I do see you're also talking about workflows. Are you just using the webhooks action on a workflow? - example:

If so, there's no authentication (neither OAuth nor api key) required to use that in a workflow.


I’m looking at my production account underneath the automation tab, and I see “Workflows”. I can see the same page you have attached. However, I don’t see an existing “application”. I’m still not understanding this. Can we get on a call? I entered a support ticket yesterday. Can I get some phone support?


Hi @brian-voicebase, what I'm saying is that we may have had a miscommunication. HubSpot has a Webhooks API and a Webhook action within Workflows. They are completely separate functionalities. That's my fault for not picking up on it sooner, but from what you were speaking about with OAuth, it looked like you were trying to utilize the Webhooks API, which does require an application. Webhook actions within Workflows in your production account does not require an application to set up. What is your support ticket #? You should have received a reply within ~10 hours.

I cannot hop on a call with you at the moment due to the nature of the work we do here in the forums and within HubSpot internally. You can call into Support at any time you'd like, however.


Support ticket is 2144960. I started this whole thing by calling a long time ago, but was directed to the forums because the question was too technical for the person I was talking to. I’m still not getting my answer to a higher level question, and that question is can I restrict some users from updating production contacts, but allow other users to update production contacts. I’m not sure that this solution would even work.


hi @brian-voicebase, I think the main point of confusion is that I'm not clear on what part of the product you're getting stuck on. If we take a step back from OAuth/hapikeys/apps/dev portals, please let me confirm that what you're looking to do is restrict, within HubSpot, who is able to update contacts and who is not? If so, are you looking for User Permissions:

I don't know where your API key and OAuth fits into all of this, but please help me understand by explaining clearly your issue.

If I scroll up to the beginning of our conversation after knowing what I know now, I think continuing to use your API key for a backend process is perfectly fine. An OAuth application can be installed once to an account, so in all of this context, OAuth wouldn't give permissions one way or another to different users, but OAuth is just more secure. See Derek's reply from April 19th here: This hub doesn't have access to some HubSpot features that are required by this integration. Please contact the integrator

I don't really understand where webhooks come into play in all of this, so please detail your process and where you're getting hung up.


Hi Connor,

I think I made a breakthrough here. Here’s my understanding of what I’ve done so far (please correct me and check my names for Hubspot things):

  1. I created a user and gave specific permissions to that user just for the following Hubspot application.
  2. I created a Hubspot application in the developer area. I was careful to select ONLY select only the scopes that would be entered on the URL passed to hubspot later by the OAuth Quickstart app (otherwise I would get an error).
  3. I entered my clientId and clientSecret from the above application to the OAuth Quickstart javascript application configuration file.
  4. I used the OAuth Quickstart javascript application to register/add my application created above to my production portal/account. The above user is logged in and I get back the 0Auth access token to use in my backend server application. I’m still a little fuzzy on why my external javascript application tells the account portal to add the application instead of the account portal adding the application, and this is initially what I didn’t understand. I was also confused about why I got Brian Halligan displayed as a user. I guess he’s your CEO, and it’s a demo of sorts to show I have access to a contact. But, it has nothing to do with the registration here and it confused me because it wasn’t my user account.
  5. The crux for me here is the User I used to register the application has the authorization here. This means I give the user permissions to access contacts, etc. from our account.
  6. Also, I think I would need to implement “Teams” to give the user access to a subset of contacts in my account portal which I found here:
  7. Does it make sense to separate "developer" contacts into a separate Team and limit access to contacts using a user who only has access to that Team? I don’t have a good understanding whether this is a smart move or not. I don't fully understand the purpose of teams in the greater scope of what Hubspot thinks teams are useful for.

Please let me know if this makes sense.