← All posts

GoHighLevel OAuth vs Private Integration Token: Which Should You Use?

Hamza Lamhidra
GoHighLevel OAuth vs Private Integration Token comparison for secure API authentication, server-to-server access, app installation, and multi-customer integrations.

Compare GoHighLevel OAuth 2.0 and Private Integration Tokens (PITs), including scopes, token refresh, multi-location apps, security, and when to use each.

GoHighLevel supports two main authorization models for modern API integrations: Private Integration Tokens (PITs) and OAuth 2.0.

Both can provide scoped access to the HighLevel API, but they solve different integration problems.

A Private Integration Token is usually the simpler choice when the integration is internal, controlled by your own team, and only needs direct server-to-server access to a specific HighLevel account or location.

OAuth 2.0 becomes the better choice when customers need to connect their own HighLevel accounts, when an application is installed across multiple agencies or sub-accounts, or when you need a proper installation and authorization lifecycle.

A useful starting point is:

Situation

Better Starting Point

Internal script for your own HighLevel account

Private Integration Token

Private backend integration for one client/location

Private Integration Token

Internal reporting or synchronization

Private Integration Token

App installed by many HighLevel customers

OAuth

Marketplace-style integration

OAuth

Users authorize their own HighLevel account

OAuth

Installation across many independent sub-accounts

OAuth

App needs an installation lifecycle

OAuth

The decision is not about which authentication model is more advanced.

It is about who owns the integration, who authorizes it, how many accounts it needs to serve, and how credentials must be managed over time.

let's talk

What Is a GoHighLevel Private Integration Token?

A Private Integration Token, commonly called a PIT, is a scoped credential generated directly inside HighLevel.

It can be sent as a Bearer token when calling supported HighLevel APIs.

The architecture is simple:

Your backend
      ↓
Private Integration Token
      ↓
HighLevel API

Unlike OAuth, a PIT does not require a customer-facing authorization flow.

You create the Private Integration, select the permissions it needs, generate the token, store it securely, and use it from your application.

Conceptually:

Generated manually
      ↓
Scoped permissions
      ↓
Static credential
      ↓
No OAuth consent flow
      ↓
No access-token refresh flow

That simplicity is exactly why PITs can be useful for internal integrations.

When a Private Integration Token Makes Sense

A PIT can be a strong fit for:

For example:

Internal reporting service
        ↓
PIT
        ↓
HighLevel Location
        ↓
Read CRM data

If one company owns both the application and the HighLevel environment, there may be little value in building OAuth authorization, callbacks, refresh-token storage, and installation management.

In that case, OAuth would add infrastructure without solving an actual business problem.

For this system I used Private Integration Tokens rather than OAuth. The integration is a backend I control that drives outbound calls and SMS sequences through the HighLevel API on behalf of the accounts it serves. There is no external customer who installs the app and authorizes it themselves; the integration and the HighLevel environments are managed together, so a PIT per location gives the backend the direct server-to-server access it needs.

OAuth would have added an authorization flow, redirect handling, token exchange, refresh-token storage, and installation records, none of which solve a problem this integration has. Nobody needs to click "connect my HighLevel account," so the entire OAuth installation lifecycle would be infrastructure without a purpose. The honest tradeoff is that PIT does not onboard many independent third-party customers cleanly, since each location's token is provisioned rather than self-authorized. That is a real limit of the approach, but for a controlled integration where the same team manages the accounts and the backend, the scoped PIT is the simpler credential and OAuth's lifecycle would be complexity without benefit.

What Is GoHighLevel OAuth 2.0?

OAuth solves a different problem.

Instead of an administrator manually generating a token and giving it to the application, a HighLevel user authorizes the application through an installation flow.

Conceptually:

HighLevel user
      ↓
Install / Authorize App
      ↓
Authorization Code
      ↓
Your application
      ↓
Exchange code for tokens
      ↓
Access Token + Refresh Token
      ↓
HighLevel API

The application defines the permissions it needs, redirects the user through authorization, receives an authorization code, and exchanges that code for tokens.

The important difference is ownership.

With a PIT:

Developer/admin creates credential
→ integration uses credential

With OAuth:

User installs app
→ user grants access
→ app receives authorization
→ app manages that installation

OAuth is therefore much better suited to software that other HighLevel users need to connect themselves.

When OAuth Makes Sense

OAuth is the natural fit when:

For example:

Client A ──authorize──┐
                     │
Client B ──authorize──┼→ Your application
                     │        ↓
Client C ──authorize──┘   tenant-specific tokens
                              ↓
                         HighLevel API

That is fundamentally different from storing one manually generated token in server configuration.

Private Integration vs OAuth: The Main Differences

Private Integration Token

OAuth 2.0

Credential creation

Generated manually in HighLevel

Generated through OAuth authorization

Customer consent flow

No

Yes

Access model

Static credential

Access + refresh token lifecycle

Best fit

Internal/controlled integrations

Installable/multi-customer applications

Scopes

Yes

Yes

Manual setup

Yes

Automated after OAuth flow is built

Multi-client authorization

Difficult to manage manually

Natural fit

Marketplace/app lifecycle

Limited fit

Designed for it

Token refresh logic

Not required

Required

Credential rotation

Operational/manual

OAuth lifecycle

Internal server-to-server use

Strong fit

Often unnecessary complexity

A useful question is:

Who is expected to authorize this integration?

If the answer is:

“Our own team for our own HighLevel environment.”

a PIT may be enough.

If the answer is:

“Every agency or customer that connects our product.”

OAuth is usually the better architecture.

Private Integration Is Not the Same as a Private OAuth App

The terminology can be confusing.

A Private Integration Token and a private OAuth application are not the same thing.

A private OAuth app still uses OAuth:

Private OAuth App
      ↓
OAuth authorization flow
      ↓
Access + refresh tokens

A Private Integration uses a PIT:

Private Integration
      ↓
Generate PIT
      ↓
Static Bearer credential

So there are two separate decisions:

How is API access authorized?
→ PIT or OAuth

How is an OAuth app distributed?
→ Private or Public

Do not confuse those two concepts.

Private Integration Tokens Are Not the Old HighLevel API Keys

Another common source of confusion is older HighLevel API tutorials.

A modern Private Integration Token is not simply a renamed legacy API key.

The safer mental model is:

Private Integration Token
→ modern scoped API authorization

Legacy API key
→ older authentication model

This matters because older examples may use authentication patterns, endpoints, or assumptions that should not be copied into a new production integration.

For a new HighLevel integration, start with the current authorization model rather than treating old API-key tutorials as the source of truth.

Authentication is only one part of the system. For the complete production pattern, see GoHighLevel API integration architecture

Scopes Matter With Both PIT and OAuth

Choosing a PIT does not mean giving the application unrestricted API access.

Both PIT and OAuth integrations should use only the permissions required by the application.

A safer design starts with the integration requirement:

Business requirement
        ↓
Required API operations
        ↓
Minimum required scopes
        ↓
Credential

For example, if an internal reporting tool only needs to read contacts, there is no reason to give it unrelated write permissions.

This reduces the impact of:

Scopes are part of the security architecture.

Missing Scope vs Invalid Credential

When an API request fails, distinguish between:

The token is invalid

and:

The token is valid
but does not have the required permission

Those are different failures.

Refreshing or replacing a valid credential will not fix a missing scope.

The application needs the correct authorization scope for the operation it is attempting.

A HighLevel API call started returning a permission error when I added a new operation the integration hadn't used before. The failure looked like an auth error, but the credential was valid and working for every other call, which was the tell: this wasn't an expired or wrong token, it was a missing scope. A credential that authenticates fine for reads but fails on one specific operation points at permissions, not identity.

I identified it by separating the two failure types the API can return: an invalid credential fails everywhere, while a missing scope fails only on the operation that needs it. Since the token worked elsewhere, refreshing or replacing it would have fixed nothing. The fix was in the Private Integration settings: the scope for that operation hadn't been enabled, so I added it and re-saved, and the call succeeded. No credential value was ever exposed in the process, since the scope is configured in HighLevel's interface, not in the token itself.

OAuth Requires a Token Lifecycle

One of the biggest differences between PIT and OAuth appears after installation.

A PIT is a static credential until it is rotated or revoked.

OAuth access tokens expire.

That means OAuth requires an ongoing token-management process.

Conceptually:

OAuth installation
      ↓
Access Token
Refresh Token
      ↓
API requests
      ↓
Access Token expires
      ↓
Refresh
      ↓
New Access Token
New Refresh Token
      ↓
Persist both

That final step is important.

When HighLevel returns a new access token and refresh token, the application should persist the new credential state.

Do not design the integration around:

refresh
↓
save new access token
↓
keep using old refresh token forever

The authentication store should treat the refreshed credentials as a new token pair.

A useful state transition is:

Current:
accessToken A
refreshToken A

        ↓ refresh

New:
accessToken B
refreshToken B

        ↓

Persist B + B

Token management is therefore part of the application architecture, not just an API request detail.

Do Not Refresh Every Time You Receive a 401

Another common mistake is treating every:

401 Unauthorized

as proof that the OAuth access token expired.

A 401 can also come from:

So avoid this logic:

any 401
→ refresh token

A better model is:

401
 ↓
inspect authentication failure
 ↓
token expired?
 ├── Yes → refresh → persist new token pair → retry
 └── No  → investigate actual authentication problem

Otherwise an application can repeatedly refresh tokens while hiding the real configuration problem.

Private Integration Tokens Have a Different Lifecycle

PITs avoid the OAuth access-token refresh process.

But a static credential still needs operational management.

A safe rotation process looks like this:

PIT A in production
      ↓
Generate replacement credential
      ↓
Update application
      ↓
Verify production traffic
      ↓
Retire PIT A

The important point is:

Static does not mean permanent.

A PIT should still have procedures for:

If a token becomes exposed, it should be replaced rather than treated as permanent infrastructure.

Rotating a PIT without downtime relies on the old and new tokens being valid at the same time. The procedure is to generate a replacement Private Integration in HighLevel while the existing one is still active, deploy the new token to the credential store, confirm live traffic is authenticating on it, and only then revoke the old token. Because both credentials work during the overlap, there is no moment where in-flight requests fail. The old token is retired only after the new one is proven in production. No token value is exposed in the process, since the credential lives in the secret store and never in source control or logs.

Store Tokens as Secrets, Not Source Code

Whether the integration uses PIT or OAuth, the credentials are secrets.

Do not commit them into Git.

Do not print them in logs.

Do not include them in screenshots.

Do not paste them into public tickets, chat messages, or documentation.

A production architecture should separate:

Application code

from:

Authentication secrets

For OAuth, secrets can include:

For PIT, the token itself is sensitive.

The storage technology depends on the application, but the security requirement remains the same:

The application should be able to retrieve its credentials without unnecessarily exposing them to developers, logs, repositories, users, or unrelated tenants.

HighLevel credentials are treated as secrets, not configuration. Each location's token is stored in a dedicated secret store rather than in source control, loaded at runtime and keyed by location so the backend retrieves only the credential for the account it is acting on. Tokens never appear in logs, in the repository, or in the request payloads themselves. The store is the single place credentials live, which keeps rotation and revocation to one boundary rather than scattered copies.

Single-Location Integrations Are Where PIT Is Most Attractive

Consider an internal integration for one HighLevel Location:

Internal application
        ↓
PIT
        ↓
Location A

The company controls:

There is no external user who needs to click:

“Connect my HighLevel account.”

Building OAuth in this case might require:

without solving an actual business requirement.

That is exactly where PIT simplicity becomes valuable.

OAuth Becomes More Valuable as the Installation Model Expands

Now consider a product used by many independent HighLevel customers:

Your application
      │
      ├── Client A / Location A
      ├── Client B / Location B
      ├── Client C / Location C
      └── Client D / Location D

A PIT-based onboarding process might require every customer to:

  1. create a Private Integration;
  2. select the correct scopes;
  3. generate a token;
  4. send the token to your team or application;
  5. repeat the process when credentials change.

That may work technically.

But it becomes operationally awkward.

OAuth changes the onboarding flow:

Client
 ↓
Connect HighLevel
 ↓
Review requested permissions
 ↓
Authorize
 ↓
Application receives installation context

This is why OAuth scales better as a product authorization flow.

The advantage is not that OAuth is more impressive technically.

The advantage is that customers can authorize the application through a standardized installation process.

Agency-Level and Location-Level Context Still Matter

Authentication does not remove HighLevel's account hierarchy.

Your application still needs to know which:

the credential belongs to.

In a multi-location architecture, token context is part of tenant isolation.

Conceptually:

Incoming operation
      ↓
locationId
      ↓
installation record
      ↓
correct credential context
      ↓
HighLevel API

The production rule is:

An operation for Client A should never execute with Client B's credential.

Avoid a design where the application stores one global OAuth token and uses it as a fallback for unrelated locations.

Authentication state should remain associated with the installation that created it.

This is especially important when one application manages many HighLevel accounts.

A candid note on a real limitation. This integration currently authenticates with a single Private Integration Token loaded from the environment. The code supports per-location tokens (it looks for a location-specific token first), but in practice one token has served the system while it operates against a single account. That is fine for one controlled location, but it is not a multi-tenant isolation model: a shared credential with a fallback is exactly what you should not carry into a system serving many independent locations, because an unmatched location silently uses the wrong token instead of failing. The correct design, and the direction this moves as more locations are added, is a distinct credential per location selected by locationId, with no fallback: if a location's token can't be resolved, the operation fails rather than borrowing another location's access.

When Does PIT Become the Wrong Abstraction?

PIT simplicity has a boundary.

Some warning signs are:

At that point, the problem is no longer simply:

“How can our backend authenticate?”

The real question becomes:

How should customers securely install and authorize our application?

That is where OAuth becomes the better abstraction.

When Is OAuth Unnecessary Complexity?

The opposite mistake also happens.

OAuth should not be added simply because it is the more familiar standard for third-party applications.

Consider:

One company
One backend
One controlled HighLevel account
No external installers
No public application

That environment may not need:

OAuth consent
redirect handling
authorization-code exchange
refresh logic
installation database

A scoped PIT may be easier to implement and maintain.

The best architecture is not the one with the most authentication infrastructure.

It is the one that fits the ownership and installation model.

Common GoHighLevel Authentication Mistakes

Using a PIT for a Product Customers Need to Install

The API may work correctly, but customer onboarding becomes manual.

If independent customers need to connect their HighLevel accounts themselves, OAuth is usually a cleaner authorization boundary.

Building OAuth for One Internal Script

OAuth can work, but the installation and refresh infrastructure may provide no useful value.

A PIT may be enough.

Requesting Every Available Scope

More access does not make an integration better.

Request the minimum permissions required for the application.

Storing One OAuth Token Globally

This is dangerous in multi-location systems.

Credential state should remain associated with the correct HighLevel installation and account context.

Saving the New Access Token but Not the New Refresh Token

OAuth refresh is a state transition.

When new token values are returned, persist the new credential state correctly.

Treating Every 401 as Token Expiry

Inspect the authentication error first.

Do not refresh automatically when the actual problem is a missing, invalid, or revoked credential.

Treating PIT as Ordinary Configuration

A static token is still a secret.

Store and rotate it accordingly.

Following Legacy API-Key Tutorials

Modern PITs and older API keys are not the same authentication model.

Do not build a new production integration from an outdated authentication example.

GoHighLevel OAuth vs Private Integration: Decision Guide

A practical decision tree looks like this:

Who needs to authorize the integration?
        ↓

Only your own controlled environment?
       / \
     Yes  No
      ↓    ↓
Do customers      Customers need
need an install   to authorize your app
experience?             ↓
   / \                 OAuth
 No   Yes
 ↓      ↓
PIT   OAuth

Choose a Private Integration Token When

A PIT is usually a good starting point when:

Choose OAuth When

OAuth is usually a better fit when:

Neither model is universally better.

They serve different integration models.

Can You Start With PIT and Move to OAuth Later?

Yes.

For some products, that is a sensible evolution.

An early prototype may use:

Development
    ↓
PIT
    ↓
HighLevel API

because the initial goal is to validate:

If the integration later becomes a product that customers install, the authorization layer can evolve:

Internal prototype
      ↓
PIT
      ↓
Validate integration
      ↓
Multi-customer product
      ↓
OAuth installation model

What matters is recognizing when the product itself has changed.

Do not keep stretching an internal credential model after the integration becomes a customer-facing application.

A Production Authentication Architecture

A small internal PIT integration may only need:

Application
      ↓
Secure secret storage
      ↓
PIT
      ↓
HighLevel API

A multi-customer OAuth integration requires more:

HighLevel installation
        ↓
Authorization Code
        ↓
Token exchange
        ↓
Installation record
        ↓
Access Token
Refresh Token
Scopes
Location / Company context
        ↓
Secure token storage
        ↓
API client
        ↓
HighLevel API

That additional complexity is justified because OAuth solves additional problems:

Do not copy the complexity of the second architecture into the first unless those requirements actually exist.

Authentication model where an event's locationId resolves a per-location credential from a secret store; a found token calls the HighLevel API for that location, a missing token fails the operation with no fallback.
The target multi-tenant model: each event's locationId resolves the credential for that specific location, and if no token is found the operation fails rather than borrowing another location's access. A shared or fallback credential is the pattern to avoid, because an unmatched location silently acts against the wrong account.

GoHighLevel Authentication Production Checklist

Before shipping the integration, confirm:

The right authentication model should make the integration safer and easier to operate, not simply more complicated.

Need Help Choosing the Right GoHighLevel Authentication Architecture?

Authentication problems often begin long before an API request returns 401.

The important decisions include:

Hamza can review the integration and choose the smallest authentication architecture that safely matches the real use case.

For an internal tool, that may be a scoped Private Integration Token.

For a product installed by many HighLevel users, that may require a complete OAuth installation and token-management architecture.

Need help designing the authorization model? Work with a GoHighLevel developer for secure integrations

Book a free workflow audit

30 minutes. We look at your two or three most critical workflows and I tell you which ones are actually at risk. No pitch deck.

GoHighLevel OAuth vs Private Integration Token: Which Should You Use? — hamzaautomations.com