Guides / n8n × HubSpot / Authentication

HubSpot OAuth app vs private app token: which authentication should you use?

Choose between a HubSpot OAuth app and a private app token with a practical decision guide, request examples, scopes, rotation, and rollout checks.

Advertisement
Short answer: Use a private app token when one HubSpot account controls the integration and an administrator can manage the app. Use OAuth when your product is installed into multiple customer accounts, needs per-account consent, or must keep each customer’s authorization separate. Do not treat a private-app token as a portable customer credential. Private-app request: OAuth request after the authorization-code exchange: The API call is similar; the lifecycle around the token is not.

When should you choose a private app?

Choose a private app for an internal automation, a one-company data pipeline, a controlled agency deployment, or a service owned by one HubSpot administrator. The account owner creates the app, selects scopes, and copies an access token into a server-side secret manager. This model is operationally simple because there is no install screen or callback route to maintain.

It is still an application credential. Give it only the read and write scopes used by the integration. A contact synchronizer usually does not need every CRM, marketing, or settings scope. Separate development and production apps so a test token cannot accidentally modify a live portal.

When should you choose OAuth?

Choose OAuth for a SaaS product, marketplace integration, public connector, or agency product that connects independent HubSpot accounts. The customer authorizes your app, HubSpot redirects back to your callback, and your service stores an access token and refresh token associated with that installation. Each portal gets its own credential record.

OAuth also makes ownership clearer. The customer can uninstall or revoke the app without handing your team a shared master token. Your application must handle consent, callback validation, token refresh, uninstall events, and scope changes. That is more code, but it is the correct boundary for multi-tenant software.

Advertisement

Compare the two models before coding

Ask four questions. How many HubSpot accounts will use the integration? Who is allowed to authorize it? Does the integration need customer-by-customer revocation? Who rotates the credential? One account, one administrator, and one operational owner normally points to a private app. Many accounts and customer consent point to OAuth.

Do not decide from the word “private.” A private app is not the same as a private OAuth client. The deciding factor is the installation model, not whether your business is public.

OAuth callback checklist

Register an exact redirect URI and keep separate values for local, staging, and production. Generate a state value for every authorization attempt and verify it on callback. Exchange the authorization code on the server, never in browser JavaScript. Store the portal ID, token expiry, refresh token, granted scopes, app ID, and installation timestamp.

Refresh before expiry and update the stored token atomically. If a refresh fails, mark the installation as requiring reauthorization rather than retrying the same invalid token forever. Treat an uninstall or revoked grant as a state change in your database.

Example authorization shape:

Use the scopes your app actually needs; the example is illustrative, not a universal scope set.

https://app.hubspot.com/oauth/authorize
  ?client_id=CLIENT_ID
  &scope=crm.objects.contacts.read%20crm.objects.contacts.write
  &redirect_uri=https%3A%2F%2Fexample.com%2Foauth%2Fhubspot%2Fcallback
  &state=RANDOM_NONCE

Private-app rollout checklist

Create the app in the target portal, name it after the service, and document its owner and purpose. Start with read scopes and run a read-only smoke test. Add write scopes only after the request body and object mapping are verified. Copy the token once into a secret manager, redact it from logs, and record a rotation date.

Deploy the token through configuration rather than hard-coding it in workflow JSON. Restart workers that cache environment variables. Test one read, one controlled write, and one association if the workflow uses relationships. Confirm the app is attached to the intended portal before any production write.

Common failure patterns

A 401 normally means the token is absent, malformed, expired, revoked, or sent to the wrong host. A 403 often means the token is valid but lacks a scope or portal access. A 404 can be a wrong object route, record ID, or retired endpoint. A 429 is a usage-limit problem. Changing from OAuth to a private token will not fix a bad property name or deprecated endpoint.

If a private token works in curl but fails in a connector, inspect the connector’s credential type. It may send the value as a query parameter, overwrite the Authorization header, or use a cached credential. If OAuth works for one customer but not another, compare granted scopes, installation state, portal ID, and token refresh timestamps.

Warning: never put a private-app token, OAuth client secret, or refresh token in a browser bundle, URL, public workflow export, screenshot, or issue. Revoke exposed credentials immediately.

A migration path when the choice is wrong

Moving an internal integration from OAuth to a private app means removing the consent dependency and replacing per-portal token storage with one controlled secret. Moving a multi-tenant product from a private token to OAuth requires a tenant credential table, consent route, callback, refresh handling, uninstall handling, and a cutover plan. Do not switch auth headers alone.

Run both paths in shadow mode if the integration is business-critical. Compare records by stable HubSpot IDs, not by response order. Disable writes in the shadow client. Once every installation has a valid credential, route reads and then writes through the new model. Keep an audit trail of which credential produced each mutation.

Manual QA test matrix

For a private app, test a missing token, valid read scope, missing read scope, valid write scope, wrong portal, revoked token, and rotated token. For OAuth, test a cancelled consent screen, mismatched state, expired code, refresh success, refresh failure, uninstall, and a customer with fewer scopes than expected.

Inspect that logs contain portal ID and correlation ID but not access or refresh tokens. Verify that retries do not create duplicate contacts or deals. Check that a token refresh cannot overwrite a newer token with an older response. Confirm that revocation changes the installation state and presents a useful reauthorization message.

The installation boundary is the deciding test

Ask whether an administrator can safely rotate one credential without affecting unrelated customers. If yes, a private app may fit an internal portal. If every customer needs a separate grant, uninstall path, or consent record, OAuth is the stronger boundary. Document this decision before coding because changing only the Authorization header later leaves the wrong token storage and lifecycle design in place.

Where these facts come from

Advertisement
Advertisement