GHL Private API — backend.leadconnectorhq.com
The Discovery
Codex found it via Playwright. Logged into GHL in a real browser, dumped storage state JSON (cookies + localStorage), then replayed requests programmatically. The app talks to backend.leadconnectorhq.com — not the documented services.leadconnectorhq.com / rest.gohighlevel.com public API.
This endpoint exposes everything the UI can do, including things the public API explicitly does not: workflow CRUD, trigger editing, action insertion, version control.
Why It Matters
Public API can't create or modify workflows. You clone by hand in the UI, every sub-account, every time. Private API means one-shot workflow replication across 50+ sub-accounts from a script.
How To Use It
1. Capture auth state
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
ctx = browser.new_context()
page = ctx.new_page()
page.goto("https://app.gohighlevel.com")
input("Log in manually, then press Enter...")
ctx.storage_state(path="ghl_auth.json")
2. Replay requests
Open DevTools → Network on the GHL workflow builder. Filter backend.leadconnectorhq.com. Copy as cURL. Convert to requests/httpx with headers + cookies from storage state.
Key headers:
token-id— bearer from localStoragechannel: APPsource: WEB_USERversion: 2021-07-28location-id— target sub-account
3. Workflow endpoints
GET /workflows/?locationId={id}— listGET /workflows/{workflowId}— full definitionPOST /workflows/— createPUT /workflows/{workflowId}— updatePOST /workflows/{workflowId}/publish— publish version
Payload schema mirrors what DevTools shows. Diff two workflows in the UI to learn the field shape.
Risks
- Unofficial. GHL can change or lock it.
- Tokens expire — refresh via storage-state reload.
- Rate limits exist but are undocumented. Throttle to ~1 req/sec.
Lineage
Discovered on stream via Codex (GPT-5 coding harness). Claude Code took over for consistency once the endpoint was mapped.