GoHighLevel resources
How to connect the GoHighLevel API
The official documentation is complete, but it is written for developers. This page walks you through the way in: what you need, in what order, and how to make your first call without losing an afternoon.
Summary
The GoHighLevel API is the set of endpoints that lets another program read and write in your account without going through the interface. Many common tasks, like getting form leads in, get solved without it: start with the section below to see if that is your case. If you do need the API, you need 3 things: a private integration token, the sub-account Location ID, and the API version in the header. The official documentation lives at marketplace.gohighlevel.com/docs.
Updated
Before you start: do you really need the API?
Many people come here to solve something that does not require the API, get a token and end up stuck. Find your case first:
Path A1
You do not code and your client is fine using a GoHighLevel form
This is the short path and it needs no API, no token and no developer. GoHighLevel gives you a code to embed its form on any site (Squarespace, Wix, Shopify, WordPress, Duda) and contacts come in on their own.
In GoHighLevel: Sites, then Forms at the top right. Pick your form or create one with "+ Add Form". Then go to the Integrate tab, top right, and click Copy Embed Code. That code gets pasted into the site.
Official guide to embedding forms on non-HighLevel sitesPath A2
You do not code and the existing form stays as it is
This is the most common case and it is also solved without the API. Instead of you calling GoHighLevel, you make GoHighLevel listen: you create an inbound webhook, which is an address of its own that the form sends the data to. Watch out for the trap: the trigger only STARTS the workflow, it does not create the contact. You have to add the action.
The 5 steps are below, in their own section.
Official guide to the Inbound Webhook triggerPath B
You do not code, and neither path above covers you
Then your job here is to get the credentials and hand over a well-built request. Do steps 1 through 6 (all inside GoHighLevel, no code) and keep two pieces of data: the token and the Location ID.
Give your developer the link to this page, those two pieces of data, and tell them in one sentence what has to happen. With that they have everything they need to start.
Path C
You code, or you will use an AI assistant to write the code
Follow the whole page straight through. And use the shortcut almost nobody sees: in the official documentation, every endpoint has Copy for LLM, Open in Claude and Open in ChatGPT buttons, which hand the assistant the exact specification for that endpoint.
Start with ONE endpoint, not with understanding everything.
The no-code path, in full: connecting a form that already exists
If you picked Path A2, this is everything you have to do. No token, no API, no developer. Step 4 is the one almost everyone skips, and without it the workflow looks configured and does nothing:
- 1
Create the workflow with the trigger
In GoHighLevel: Automation, Workflows, and create a new one. As the trigger pick "Inbound Webhook". A unique URL is generated for that workflow: copy it.
- 2
Send the form data to that URL
This step happens on the website, not in GoHighLevel. Look in your form plugin for an option called Webhook, Webhooks or Send to URL, and paste the URL you copied there. Elementor Forms, WPForms, Gravity Forms and Fluent Forms have it (in several cases only in their paid version). Contact Form 7 does not ship with it: there you need Zapier or Make as a bridge.
- 3
Fill out the form once, as a test
With real data of your own. This is required, not optional: GoHighLevel needs to receive a submission to learn what the fields your form sends are called. Without that test you have nothing to match in the next step.
- 4
Add the action that creates the contact
This is where almost everyone stops halfway. The trigger only starts the workflow: you have to add an action that creates or updates the contact, and match the fields that arrived (name, email, phone) with the contact fields in GoHighLevel.
- 5
Save, publish and check with your own eyes
Save the trigger, publish the workflow, and fill out the form again. Then look for that contact in the sub-account. If it shows up, it works. If it does not, the problem is in step 2 (the URL) or step 4 (the matching), in that order.
If your form plugin cannot send data to a URL, the bridge is Zapier or Make and it is still no-code: Official HighLevel guide to webhooks with Zapier.
Everything after this point is for people who WILL use the API. If the above solved your case, you are done.
What you need besides the token
This is what confuses people most and it almost never gets said: the API does not call itself. A form on a web page cannot talk to GoHighLevel on its own. You need something in the middle, a program running on some server, that receives the form data and makes the call. When you hire someone to "connect the API", that middle piece is what you are paying for.
Six words you will see
- Endpoint
- A GoHighLevel web address that your program talks to.
- Header
- Data that travels with the call, apart from the address: who you are and which version you use.
- Token
- A long password that identifies your integration. Whoever has it, gets in.
- JSON
- The text format the data travels in. It looks like a list of fields and values between braces.
- Terminal
- The text program that already comes with your computer for typing commands. On Mac it is called Terminal, on Windows PowerShell. If you have never opened it, use the interactive documentation instead.
- Error 401
- The response the API gives when it did not like your token: it is either copied wrong, or it lacks the permission you asked for.
- Environment variable
- A place outside the code where the program keeps secrets like your token. If you do not code, keep it in your password manager and that is it.
- Scopes (permissions)
- The list of things your token can do. You check them when you create the integration.
- Labs
- The GoHighLevel section where features that are not on by default get turned on. That is where Private Integrations is switched on if it does not show up.
What an endpoint is, in one sentence
An endpoint is a web address that connects to GoHighLevel. What changes is the method, that is, the intent with which you call that address:
| Method | What it does | Example |
|---|---|---|
GET | Fetches information. Changes nothing. | Read a contact |
POST | Creates something or triggers an action. | Create an opportunity |
PUT | Updates something that already exists. | Change a contact's phone |
DELETE | Deletes. | Remove an appointment |
The URL alone is not enough. GoHighLevel needs to know who is calling and in which sub-account, and that travels in the headers:
What you can do with it
There are hundreds of endpoints. These are the 6 families where almost everyone starts:
Contacts and CRM
Create, read, update and delete contacts, with tags and custom fields.
What it is for: Push a lead in from your own form, sync a list, tag by behavior.
Conversations
SMS, email and calls: send messages, manage threads and read the history.
What it is for: Reply to an SMS from your app, read the conversation before a call.
Calendar and appointments
Book, move and cancel appointments, and read real availability.
What it is for: A bot that confirms appointments, or offers the slot that just opened up.
Opportunities
The pipeline: create opportunities and move them between stages.
What it is for: Move the deal when it is signed, create the opportunity when a qualified lead comes in.
Payments
Charges, subscriptions and transaction data.
What it is for: Mark a contact as a customer when they pay, read active subscriptions.
Webhooks
Real-time alerts for more than 50 events, so you never have to keep asking.
What it is for: React the moment a lead comes in, instead of checking every 5 minutes.
Which of the 3 authentication methods is yours
This is the decision that defines everything else, and getting it wrong here means redoing the work. To automate your account or a client’s, the answer is the private integration:
| Method | Permissions | Version | Expiration | When to use it |
|---|---|---|---|---|
| Private integration (PIT) | Permissions you choose, per integration | API v2.0 | Does not expire; rotated by hand whenever you decide | Automating your account or a client's. It is the recommended one today. |
| API key (legacy) | Unrestricted access to the whole account | API v1.0, unmaintained | Does not expire | Nothing new. It only exists for old integrations that have not migrated yet. |
| OAuth 2.0 | Permissions each account approves on install | API v2.0 | The token expires daily and has to be refreshed | Distributing or selling the integration to third-party accounts. |
Step by step to connect it
- 1
Decide which type of integration you need
There are three ways to authenticate, and picking the wrong one means redoing the work. To automate your account or a client's, the right answer today is a private integration.
- Private integration (recommended): a token you generate from the interface, with permissions you choose. Uses API v2.0.
- API key (legacy): gives unrestricted access to the whole account and runs on v1.0, which is no longer maintained. Do not use it for anything new.
- Marketplace app with OAuth 2.0: for distributing the integration to other people's accounts. Its tokens expire daily and have to be refreshed.
- 2
Open Private Integrations in the agency settings
The menu lives in the agency-level settings, not inside the sub-account. If you do not see it there, it is not broken: the feature is turned on in Labs first.
- Path: Settings (agency settings) and look for Private Integrations in the list.
- If it does not show up: Settings, Labs, and turn the feature on. Then go back to Settings.
- By default every agency admin can create them. To restrict that: Settings, Team, edit the user, Roles & Permissions. Access to agency integrations and sub-account integrations is controlled separately there.
- 3
Create the integration and name it
Click "Create new Integration" and give it a name and a description that say what it is for. Six months from now, with four tokens created, the name is the only thing that will tell you which one you can revoke without breaking anything.
- One token per integration, not one for everything.
- Name it by function, not by tool: "dental appointment confirmation" is more useful than "token 2".
- 4
Pick only the permissions you will use
The scopes step is where you mark what the token can access. Check the minimum. This is the real advantage over the old API keys: a key gives access to everything, this token gives access only to what you checked.
- If your integration only reads contacts, do not give it permission to delete.
- Permissions can be edited later without generating a new token, so start small and widen when you need to.
- 5
Copy the token NOW
The token is shown once and cannot be viewed again. If you close that screen without copying it, there is no recovery: you have to rotate it and start over. Store it in a password manager or an environment variable, never inside the code.
- If you are handing it to a developer, send it through a private channel, never a group chat or email.
- A token that ended up in a repository gets revoked, not hidden: git history keeps it.
- 6
Grab the Location ID from the address bar
Almost every endpoint needs to know which sub-account to work in. Open the sub-account and look at your browser's URL: the Location ID is the string of letters and numbers that comes after /location/.
- app.gohighlevel.com/v2/location/ABC123xyz/dashboard, where ABC123xyz is your Location ID.
- Some agency-level endpoints ask for the Company ID instead of the Location ID.
- 7
Test the call without writing a single line of code
You do not need to install anything or open the terminal to test whether your token works. The official documentation runs the call from the browser, and it is the fastest way to find out whether the problem is the token, the permission or the data. The exact steps are below.
- 8
Put a date on the rotation
HighLevel recommends rotating the token every 90 days. Rotation does not cut service: when you rotate, you get a 7-day window where the old token and the new one both work, so you can update without rushing.
- Path: Settings, Private Integrations, click your integration, and use "Rotate and expire this token later".
- Within those 7 days you can "Cancel rotation" if you need more time, or "Expire Now" once you have updated everything.
- If you think the token leaked, do not wait: use "Rotate and expire this token now", which cuts the old one immediately.
Testing it from the browser, step by step
This is the no-code route. The field and button names are literal, exactly as they appear in the official documentation:
- 1.Open the official documentation and look in the left sidebar for your endpoint family (for example Contacts) and then the endpoint (for example Create Contact).
- 2.In the right panel, in the Auth section, you will see a field that says "Bearer Token". Paste your token there.
- 3.Right below, in Parameters, the "Version" dropdown already has the correct value for that endpoint. Do not change it unless you know why.
- 4.In the Body section there is an editable example JSON. Change the "locationId" to yours and put real data in the other fields.
- 5.Click the blue "Send API Request" button.
- 6.The response appears below, in the RESPONSE section. If the contact was created, open it in GoHighLevel to check with your own eyes.
If you code: the same call in code
Paste these two blocks into a terminal (the command program on your computer), or hand them to whoever will build the integration. They do not go in the browser or inside GoHighLevel.
curl -X GET \
'https://services.leadconnectorhq.com/contacts/?locationId=YOUR_LOCATION_ID' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Version: 2021-07-28' \
-H 'Accept: application/json'curl -X POST \
'https://services.leadconnectorhq.com/contacts/' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Version: 2021-07-28' \
-H 'Content-Type: application/json' \
-d '{
"locationId": "YOUR_LOCATION_ID",
"firstName": "Maria",
"lastName": "Rivera",
"email": "maria@example.com",
"phone": "+13055550123",
"tags": ["web-lead"]
}'If you get a 401 and the token is right
Watch the Authorization header: the marketplace documentation shows the token with the Bearer prefix, and the help article shows it without a prefix. Start with Bearer, which is what the newer doc uses, and if you get a 401 with the right token, try sending it without the prefix before you keep looking.
Replace YOUR_TOKEN and YOUR_LOCATION_ID with your own. The base URL is always https://services.leadconnectorhq.com. Versions available today in the official docs selector: v32023-02-212021-07-282021-04-15.
What changes depending on your plan
Not all plans open the same endpoints, and this is what surprises people most halfway through a project. We use the plan names as HighLevel writes them, not the price, because prices change:
| Access | Plans | What it includes |
|---|---|---|
| Basic API | Starter and Unlimited | Most endpoints: contacts, opportunities, calendars, appointments, forms, conversations. Sub-account level API keys (Location API Keys). |
| Advanced API | Agency Pro | Everything above plus agency-level keys (Agency API Keys) and the OAuth 2.0 endpoints. It is what you need to create sub-accounts, load snapshots or create users through code. |
Usage limits
Burst limit
100 requests every 10 seconds
per Marketplace app, resource or company
Daily limit
200,000 requests per day
per Marketplace app, resource or company
Every response carries headers that tell you how much you have left. A well-built program reads them and slows down on its own, instead of waiting for the API to return an error:
X-RateLimit-Max | The request ceiling for the current window. |
X-RateLimit-Remaining | How many you have left in this window. |
X-RateLimit-Interval-Milliseconds | How many milliseconds the window lasts. |
X-RateLimit-Limit-Daily | Your ceiling for the day. |
X-RateLimit-Daily-Remaining | How many you have left today. |
The 4 mistakes that cost the most time
- Forgetting the Version header. The token is right and the URL is right, but the call fails. It is the first place to look.
- Mixing up Location ID and Company ID. The first is the sub-account, the second the agency. Agency-level endpoints ask for the second.
- Calling an endpoint your plan does not open. Creating sub-accounts or loading snapshots requires the advanced API. It is not a bug on your side.
- Leaving the token in the code. It goes in an environment variable. A token pushed to a repository has to be revoked, not hidden.
Frequently asked questions
What is the GoHighLevel API?
It is the set of web addresses (endpoints) that let another program read and write inside your GoHighLevel account without going through the interface. With it, a contact gets created from your own form, an appointment gets booked from your app, or an AI agent moves an opportunity to another stage. The official documentation lives at marketplace.gohighlevel.com/docs.
Do I need to know how to code to use it?
To use it directly, yes, at least a little. But there is a real middle path: give the official documentation URL to an AI assistant, explain your business, and ask it to build and explain the call for you. HighLevel itself recommends this, and it works better if you start with ONE endpoint instead of trying to understand everything.
What is an endpoint, and what do GET, POST, PUT and DELETE mean?
An endpoint is a URL that connects to GoHighLevel. The method says what it does: GET fetches information, POST creates something or triggers an action, PUT updates something that already exists, and DELETE removes it. Same address, different intent.
What do I need to authenticate?
A token in the Authorization header with the Bearer format, the API version in the Version header, and the Location ID of the sub-account you are going to work in. Some agency-level endpoints ask for the Company ID instead of the Location ID.
What is the difference between a private integration and a Marketplace app?
A private integration uses a token and is for automating your own account or a client of yours. A Marketplace app uses OAuth 2.0, is installed by each account that wants it, and is the path if you are going to distribute or sell the integration to third parties.
Do all plans have the same access?
No. The Starter and Unlimited plans come with the basic API and sub-account level keys. The Agency Pro plan adds the advanced API: agency-level keys and the OAuth 2.0 endpoints, which are the ones that let you create sub-accounts, load snapshots and create users through code.
What are the usage limits?
One hundred requests every ten seconds and 200,000 per day, counted per Marketplace app, resource or company. Every response carries headers that tell you how many you have left, so a well-built program slows itself down before hitting the limit.
Which API version should I use?
For anything new, the latest one available in the documentation's version selector. If you maintain an integration that already works, stay on its version and switch on purpose, not by accident: changing versions can change the shape of the response.
Official sources
This page is an entry guide, not a replacement for the documentation. When you need the exact detail of an endpoint, the source wins:
- Official API documentation
Every endpoint, with a version selector and interactive execution.
- API help article
Differences by plan, usage limits and how to report a bug.
- Developer portal
Marketplace, Slack community and the monthly developer call.
Data verified against those sources on 2026-08-24. GoHighLevel changes its API and its plans: if something does not add up, the official documentation is the one that counts. The documentation walkthrough is adapted from the video «The GHL API is the most powerful feature» by Andrew George.
Keep going with the daily GoHighLevel changes, the GHL resources in the catalog or the AI terms glossary.