TypeScript SDK for working with HighLevel API v1 and v2 endpoints. Works with any server-side JS runtime including Node.js, Bun, Cloudflare Workers, etc.
The HighLevel API is constantly evolving, with updated endpoints being added regularly. This package downloads the latest OpenAPI schemas from the HighLevel API Docs on a schedule, then uses the openapi-typescript library to generate the types for each endpoint.
This means that when a new endpoint is added, this package will automatically have support for it. Also, each endpoint has full type safety, and the types are generated from HighLevel's OpenAPI v3 documentation so will always be compatible and up to date.
- NEW Support for Private Integrations
- Fully typed client SDK (using native
fetch) built with openapi-fetch - OAuth2 helpers for working with HighLevel's OAuth2 implementation
- Scopes builder for easily adding the appropriate scopes to your app
- Webhooks client with typed responses
- Support for both v1 (legacy API keys) and v2 (OAuth & Private Integrations)
- API v2 Documentation (OAuth & Private Integrations)
- API v1 Documentation (Legacy API Keys)
bun add @gnosticdev/highlevel-sdk
# or
pnpm add @gnosticdev/highlevel-sdk
# or
npm add @gnosticdev/highlevel-sdkThe HighLevel client uses the v2 API by default (see below for v1 client). It can be created with different configurations:
-
Basic Client: Without built-in authentication.
const client = createHighLevelClient() // or pass in the client config const client = createHighLevelClient()
-
Client with OAuth: Requires OAuth configuration.
// The first argument is always the client config, so pass an empty object if you don't need it const client = createHighLevelClient({}, 'oauth', { clientId: 'your-client-id', clientSecret: 'your-client-secret', redirectUri: 'http://localhost:3000/callback', accessType: 'Sub-Account', scopes: ['contacts.readonly'] })
-
Client with Private Integration: Requires private integration configuration.
const client = createHighLevelClient({}, 'integration', { privateToken: process.env.HIGHLEVEL_PRIVATE_TOKEN!, accessType: 'Agency', scopes: ['saas/company.write', 'saas/company.read'] })
The SDK uses openapi-fetch under the hood, which returns both data and error properties for type-safe error handling.
import { createHighLevelClient } from "@gnosticdev/highlevel-sdk"
// Create client with OAuth2 support
const client = createHighLevelClient({}, 'oauth', {
clientId: process.env.HIGHLEVEL_CLIENT_ID!,
clientSecret: process.env.HIGHLEVEL_CLIENT_SECRET!,
redirectUri: 'http://localhost:3000/oauth/callback',
accessType: 'Sub-Account',
scopes: ['contacts.readonly'],
// Optional: store tokens in your database
storageFunction: async (tokenData) => {
await db.saveTokenResponse({
access_token: tokenData.access_token,
expiresAt: tokenData.expiresAt,
refresh_token: tokenData.refresh_token,
locationId: tokenData.locationId,
userId: tokenData.userId,
})
return tokenData
}
})
// Example: Get contacts with error handling
const { data, error } = await client.contacts.GET('/contacts/', {
params: {
query: {
locationId: '1234567890',
query: 'John Doe',
limit: 10,
},
},
})
if (error) {
console.error('Error fetching contacts:', error.message)
// Handle error appropriately
return
}
// Type-safe response data
console.log(data.contacts)The OAuth client is available on the HighLevelClient instance when created with OAuth configuration:
// Generate authorization URL
const authUrl = client.oauth.getAuthorizationUrl()
// Exchange auth code for token
const token = await client.oauth.exchangeToken(authCode)
// Get access token (automatically refreshes if expired)
const accessToken = await client.oauth.getAccessToken()The v1 client requires an API key and automatically adds the authorization header to all requests.
import { createHighLevelV1Client } from "@gnosticdev/highlevel-sdk"
const v1Client = createHighLevelV1Client({
apiKey: process.env.HIGHLEVEL_API_KEY!
})
const { data, error } = await v1Client.GET('/v1/contacts', {
params: {
query: {
locationId: '1234567890',
}
// No need to add Authorization header - it's added automatically
}
})
if (error) {
console.error('Error fetching contacts:', error)
return
}
console.log(data.contacts)The SDK includes a typed client for handling HighLevel webhooks. This provides type safety and validation for incoming webhook payloads:
import { createWebhooksClient } from "@gnosticdev/highlevel-sdk/webhooks"
const webhooks = createWebhooksClient()
// Example: Hono route handler for Contact Create webhook
app.post('/webhooks/contact-create', async (ctx) => {
const { data, error } = await webhooks.ContactCreate.POST({
body: ctx.req.body
})
if (error) {
console.error('Invalid webhook payload:', error)
return res.status(400).json(error)
}
// data is fully typed based on the webhook type
console.log('Contact created:', data)
res.status(200).end()
})
// Example: Handle App Installation webhook
app.post('/webhooks/app-install', async (req, res) => {
const { data, error } = await webhooks.AppInstall.POST({
body: req.body
})
if (error) {
console.error('Invalid app install payload:', error)
return res.status(400).json(error)
}
// Handle new app installation
const { locationId, userId, companyId } = data
await db.saveNewInstallation({ locationId, userId, companyId })
res.status(200).end()
})
Available webhook types include:
- AppointmentCreate
- AppInstall
- ContactCreate
- ContactUpdate
- NoteCreate
- NoteUpdate
- OpportunityCreate
- UserCreate
- And more...
The webhooks client provides full type safety and validation for all webhook payloads defined in the HighLevel API.
#### Webhook Signature Verification
For webhook signature verification and payload decryption, see the [Webhook Payload Decryption documentation](./docs/decrypt-payload.md). Note that signature verification code uses Node.js's `crypto` module and is not included in the SDK to maintain compatibility with all runtimes (Cloudflare Workers, Bun, etc.).
### Endpoint Types
If you just want to get types for the API endpoints, you can use them like this:
```ts
import type * as Locations from "@gnosticdev/highlevel-sdk/types/locations"
// Example: the response type for the `GET /locations/{locationId}` endpoint
type LocationCustomValues =
NonNullable<Locations.operations['get-custom-values']['responses']['200']['content']['application/json']['customValues']>
const customValues: LocationCustomValues = [{
fieldKey: 'contact.lead_source',
id: 'lead_source_id',
locationId: 'my_location_id',
name: 'Lead Source',
value: 'Google',
}]You can create a custom client using the createClient function from openapi-fetch with specific endpoint types from this package. This is useful when you only need a subset of the API endpoints or want to create a more focused client.
import { createClient } from "@gnosticdev/highlevel-sdk"
import type * as CustomMenus from "@gnosticdev/highlevel-sdk/types/custom-menus"
// Create a client with only custom menu endpoints
type CustomMenuPaths = CustomMenus.paths
const client = createClient<CustomMenuPaths>({
headers: {
Authorization: 'Bearer 12345',
Version: '2021-07-28'
}
})
// Use the client with full type safety
const { data, error } = await client.GET('/custom-menus/', {
params: {
query: {
locationId: '1234567890'
}
}
})
if (error) {
console.error('Error:', error)
return
}
console.log(data)You can also combine multiple endpoint types to create a client with a custom set of endpoints:
import { createClient } from "@gnosticdev/highlevel-sdk"
import type * as CustomMenus from "@gnosticdev/highlevel-sdk/types/custom-menus"
import type * as Contacts from "@gnosticdev/highlevel-sdk/types/contacts"
// Combine multiple endpoint types
type CustomMenuPaths = CustomMenus.paths & Contacts.paths
const client = createClient<CustomMenuPaths>({
headers: {
Authorization: 'Bearer 12345',
Version: '2021-07-28'
}
})Note: The createClient function is exported from this package and is the same openapi-fetch client. Headers passed in the config will be used as default headers for all requests, but you can override them per-request in the params.header option.
The SDK provides several module exports for better organization and tree-shaking:
// Main client
import { createHighLevelClient } from "@gnosticdev/highlevel-sdk"
// OAuth specific functionality
import { OAuthClient } from "@gnosticdev/highlevel-sdk/oauth"
// Scopes builder
import { ScopesBuilder } from "@gnosticdev/highlevel-sdk/scopes"
// V1 API client
import { createHighLevelV1Client } from "@gnosticdev/highlevel-sdk/v1"
// Webhooks client
import { createWebhooksClient } from "@gnosticdev/highlevel-sdk/webhooks"
// Types
import type * as Locations from "@gnosticdev/highlevel-sdk/types/locations"-
Once you have added your scopes to your app, you can collect them from the dev console on your app's settings page in the Highlevel Marketplace:
/** * Navigate to your apps' setting page - `https://marketplace.highlevel.com/app-settins/<your-app-id>/auth` * Press cmd + J on keyboard */ $$('.n-tag__content') .map((scope) => scope.textContent.trim()) .toSorted()
-
Copy the resulting array
-
Create a new ScopesBuilder instance and paste the scopes to it.
const client = createHighLevelClient({}, 'oauth', { clientId: 'your-client-id', clientSecret: 'your-client-secret', redirectUri: 'http://localhost:3000/callback', scopes: [ 'locations.write', 'contacts.readonly', // ... your scopes here ] })
Check out our example projects in the examples directory:
examples/bun-auth: Example of OAuth2 authentication flow using Bun and Hono- More examples coming soon!
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.